run: split out polkit ops into separate .c file

Let's shorten an already very long .c file, by splitting it apart a bit.

Splitting out the polkit code is relatively easy, since it does not
touch any of the arg_xyz variables.
This commit is contained in:
Lennart Poettering
2026-07-18 00:01:47 +02:00
parent bb3fcd73ce
commit 9793dde16e
5 changed files with 306 additions and 282 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ executables += [
executable_template + {
'name' : 'systemd-run',
'public' : true,
'sources' : files('run.c'),
'sources' : files('run.c', 'run-polkit.c'),
},
]
+291
View File
@@ -0,0 +1,291 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <unistd.h>
#include "sd-bus.h"
#include "alloc-util.h"
#include "bus-error.h"
#include "bus-polkit.h"
#include "bus-util.h"
#include "fd-util.h"
#include "pidfd-util.h"
#include "process-util.h"
#include "run-polkit.h"
#include "user-util.h"
int polkit_check_authorization(sd_bus *bus, PolkitFlags flags, char **ret_tmpauthz_id) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
pid_t pid;
_cleanup_close_ int pidfd = -EBADF;
_cleanup_free_ char *tmpauthz_id = NULL;
int is_authorized, is_challenge;
int r;
assert(bus);
r = sd_bus_message_new_method_call(bus, &m,
"org.freedesktop.PolicyKit1",
"/org/freedesktop/PolicyKit1/Authority",
"org.freedesktop.PolicyKit1.Authority",
"CheckAuthorization");
if (r < 0)
return bus_log_create_error(r);
pid = getpid_cached();
/* Polkit requires pidfd to honor temporary authorizations */
pidfd = pidfd_open(pid, 0);
if (pidfd < 0)
return log_debug_errno(errno, "pidfd_open failed: %m");
r = sd_bus_message_append(m, "(sa{sv})s", "unix-process", 4, "pid", "u", (uint32_t) pid,
"start-time", "t", UINT64_C(0), "uid", "i", (uint32_t) geteuid(), "pidfd", "h", pidfd,
"org.freedesktop.systemd1.manage-units");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append(m, "a{ss}us", /* details = */ 0, (uint32_t) flags, /* cancel_id = */ NULL);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_call(bus, m, /* usec = */ 0, &error, &reply);
if (r < 0)
return log_error_errno(r, "Failed to check authorization: %s", bus_error_message(&error, r));
r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
if (r < 0)
return bus_log_parse_error(r);
r = sd_bus_message_read(reply, "bb", &is_authorized, &is_challenge);
if (r < 0)
return bus_log_parse_error(r);
r = sd_bus_message_enter_container(reply, 'a', "{ss}");
if (r < 0)
return bus_log_parse_error(r);
for (;;) {
const char *key, *value;
r = sd_bus_message_enter_container(reply, 'e', "ss");
if (r < 0)
return bus_log_parse_error(r);
if (r == 0)
break;
r = sd_bus_message_read(reply, "ss", &key, &value);
if (r < 0)
return bus_log_parse_error(r);
if (streq(key, "polkit.temporary_authorization_id")) {
r = free_and_strdup(&tmpauthz_id, value);
if (r < 0)
return log_oom();
}
r = sd_bus_message_exit_container(reply);
if (r < 0)
return bus_log_parse_error(r);
}
r = sd_bus_message_exit_container(reply); /* a{ss} */
if (r < 0)
return bus_log_parse_error(r);
r = sd_bus_message_exit_container(reply); /* (bba{ss}) */
if (r < 0)
return bus_log_parse_error(r);
if (ret_tmpauthz_id && is_authorized)
*ret_tmpauthz_id = TAKE_PTR(tmpauthz_id);
return is_authorized;
}
int polkit_revoke_temporary_authorization_by_id(sd_bus *bus, const char *id) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(bus);
assert(id);
r = sd_bus_message_new_method_call(bus, &m,
"org.freedesktop.PolicyKit1",
"/org/freedesktop/PolicyKit1/Authority",
"org.freedesktop.PolicyKit1.Authority",
"RevokeTemporaryAuthorizationById");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append(m, "s", id);
if (r < 0)
return bus_log_create_error(r);
log_debug("Revoking temporary authorization %s", id);
r = sd_bus_call(bus, m, /* usec = */ 0, &error, /* ret_reply= */ NULL);
if (r < 0)
return log_error_errno(r, "Failed to revoke temporary authorization %s: %s",
id, bus_error_message(&error, r));
return 0;
}
static int check_polkit_subject_for_uid(sd_bus_message *m) {
const char *kind = NULL;
uid_t uid = UID_INVALID;
int r;
r = sd_bus_message_enter_container(m, 'r', "sa{sv}");
if (r < 0)
return bus_log_parse_error(r);
r = sd_bus_message_read(m, "s", &kind);
if (r < 0)
return bus_log_parse_error(r);
r = sd_bus_message_enter_container(m, 'a', "{sv}");
if (r < 0)
return bus_log_parse_error(r);
for (;;) {
const char *key, *contents;
char type;
r = sd_bus_message_enter_container(m, 'e', "sv");
if (r < 0)
return bus_log_parse_error(r);
if (r == 0)
break;
r = sd_bus_message_read(m, "s", &key);
if (r < 0)
return bus_log_parse_error(r);
r = sd_bus_message_peek_type(m, &type, &contents);
if (r < 0)
return bus_log_parse_error(r);
if (streq(key, "pid")) {
if (*contents != SD_BUS_TYPE_UINT32)
return bus_log_parse_error(SYNTHETIC_ERRNO(EINVAL));
r = sd_bus_message_skip(m, "v");
if (r < 0)
return bus_log_parse_error(r);
} else if (streq(key, "start-time")) {
if (*contents != SD_BUS_TYPE_UINT64)
return bus_log_parse_error(SYNTHETIC_ERRNO(EINVAL));
r = sd_bus_message_skip(m, "v");
if (r < 0)
return bus_log_parse_error(r);
} else if (streq(key, "uid")) {
if (*contents != SD_BUS_TYPE_INT32)
return bus_log_parse_error(SYNTHETIC_ERRNO(EINVAL));
r = sd_bus_message_read(m, "v", "i", &uid);
if (r < 0)
return bus_log_parse_error(r);
} else if (streq(key, "pidfd")) {
if (*contents != SD_BUS_TYPE_UNIX_FD)
return bus_log_parse_error(SYNTHETIC_ERRNO(EINVAL));
r = sd_bus_message_skip(m, "v");
if (r < 0)
return bus_log_parse_error(r);
} else {
r = sd_bus_message_skip(m, "v");
if (r < 0)
return bus_log_parse_error(r);
}
r = sd_bus_message_exit_container(m);
if (r < 0)
return bus_log_parse_error(r);
}
r = sd_bus_message_exit_container(m); /* a(sa{sv}) */
if (r < 0)
return bus_log_parse_error(r);
r = sd_bus_message_exit_container(m); /* (a(sa{sv})) */
if (r < 0)
return bus_log_parse_error(r);
return uid_is_valid(uid) && uid == geteuid();
}
int polkit_revoke_temporary_authorizations(sd_bus *bus) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const char *session_id = NULL;
int r;
assert(bus);
session_id = getenv("XDG_SESSION_ID");
if (!session_id)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "XDG_SESSION_ID is not set");
r = sd_bus_message_new_method_call(bus, &m,
"org.freedesktop.PolicyKit1",
"/org/freedesktop/PolicyKit1/Authority",
"org.freedesktop.PolicyKit1.Authority",
"EnumerateTemporaryAuthorizations");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append(m, "(sa{sv})", "unix-session", 1, "session-id", "s", session_id);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_call(bus, m, /* usec = */ 0, &error, &reply);
if (r < 0)
return log_error_errno(r, "Failed to enumerate temporary authorizations: %s",
bus_error_message(&error, r));
r = sd_bus_message_enter_container(reply, 'a', "(ss(sa{sv})tt)");
if (r < 0)
return bus_log_parse_error(r);
for (;;) {
const char *id = NULL, *action_id = NULL;
r = sd_bus_message_enter_container(reply, 'r', "ss(sa{sv})tt");
if (r < 0)
return bus_log_parse_error(r);
if (r == 0)
break;
r = sd_bus_message_read(reply, "ss", &id, &action_id);
if (r < 0)
return bus_log_parse_error(r);
if (streq(action_id, "org.freedesktop.systemd1.manage-units")) {
r = check_polkit_subject_for_uid(reply);
if (r < 0)
return r;
if (r > 0) {
r = polkit_revoke_temporary_authorization_by_id(bus, id);
if (r < 0)
return r;
}
} else {
r = sd_bus_message_skip(reply, "(sa{sv})");
if (r < 0)
return bus_log_parse_error(r);
}
r = sd_bus_message_skip(reply, "tt");
if (r < 0)
return bus_log_parse_error(r);
r = sd_bus_message_exit_container(reply);
if (r < 0)
return bus_log_parse_error(r);
}
r = sd_bus_message_exit_container(reply);
if (r < 0)
return bus_log_parse_error(r);
return 0;
}
+8
View File
@@ -0,0 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "forward.h"
int polkit_check_authorization(sd_bus *bus, PolkitFlags flags, char **ret_tmpauthz_id);
int polkit_revoke_temporary_authorization_by_id(sd_bus *bus, const char *id);
int polkit_revoke_temporary_authorizations(sd_bus *bus);
+5 -281
View File
@@ -4,7 +4,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/mount.h>
#include <sys/pidfd.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -57,6 +56,7 @@
#include "pretty-print.h"
#include "process-util.h"
#include "ptyfwd.h"
#include "run-polkit.h"
#include "runtime-scope.h"
#include "signal-util.h"
#include "special.h"
@@ -873,11 +873,11 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
arg_slice_inherit = true;
break;
OPTION('k', "reset-timestamp", NULL, "Revoke temporary authorization"):
OPTION('k', "reset-timestamp", NULL, "Revoke temporary authorization in polkit"):
arg_reset_timestamp = true;
break;
OPTION('K', "remove-timestamp", NULL, "Revoke all temporary authorizations for this user session"):
OPTION('K', "remove-timestamp", NULL, "Revoke all temporary authorizations for this user session in polkit"):
arg_remove_timestamp = true;
break;
@@ -2975,282 +2975,6 @@ static bool shall_make_executable_absolute(void) {
return true;
}
static int polkit_check_authorization(sd_bus *bus, PolkitFlags flags, char **ret_tmpauthz_id) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
pid_t pid;
_cleanup_close_ int pidfd = -EBADF;
_cleanup_free_ char *tmpauthz_id = NULL;
int is_authorized, is_challenge;
int r;
assert(bus);
r = sd_bus_message_new_method_call(bus, &m,
"org.freedesktop.PolicyKit1",
"/org/freedesktop/PolicyKit1/Authority",
"org.freedesktop.PolicyKit1.Authority",
"CheckAuthorization");
if (r < 0)
return bus_log_create_error(r);
pid = getpid_cached();
/* Polkit requires pidfd to honor temporary authorizations */
pidfd = pidfd_open(pid, 0);
if (pidfd < 0)
return log_debug_errno(errno, "pidfd_open failed: %m");
r = sd_bus_message_append(m, "(sa{sv})s", "unix-process", 4, "pid", "u", (uint32_t) pid,
"start-time", "t", UINT64_C(0), "uid", "i", (uint32_t) geteuid(), "pidfd", "h", pidfd,
"org.freedesktop.systemd1.manage-units");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append(m, "a{ss}us", /* details = */ 0, (uint32_t) flags, /* cancel_id = */ NULL);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_call(bus, m, /* usec = */ 0, &error, &reply);
if (r < 0)
return log_error_errno(r, "Failed to check authorization: %s", bus_error_message(&error, r));
r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
if (r < 0)
return bus_log_parse_error(r);
r = sd_bus_message_read(reply, "bb", &is_authorized, &is_challenge);
if (r < 0)
return bus_log_parse_error(r);
r = sd_bus_message_enter_container(reply, 'a', "{ss}");
if (r < 0)
return bus_log_parse_error(r);
for (;;) {
const char *key, *value;
r = sd_bus_message_enter_container(reply, 'e', "ss");
if (r < 0)
return bus_log_parse_error(r);
if (r == 0)
break;
r = sd_bus_message_read(reply, "ss", &key, &value);
if (r < 0)
return bus_log_parse_error(r);
if (streq(key, "polkit.temporary_authorization_id")) {
r = free_and_strdup(&tmpauthz_id, value);
if (r < 0)
return log_oom();
}
r = sd_bus_message_exit_container(reply);
if (r < 0)
return bus_log_parse_error(r);
}
r = sd_bus_message_exit_container(reply); /* a{ss} */
if (r < 0)
return bus_log_parse_error(r);
r = sd_bus_message_exit_container(reply); /* (bba{ss}) */
if (r < 0)
return bus_log_parse_error(r);
if (ret_tmpauthz_id && is_authorized)
*ret_tmpauthz_id = TAKE_PTR(tmpauthz_id);
return is_authorized;
}
static int revoke_temporary_authorization_by_id(sd_bus *bus, const char *id) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(bus);
assert(id);
r = sd_bus_message_new_method_call(bus, &m,
"org.freedesktop.PolicyKit1",
"/org/freedesktop/PolicyKit1/Authority",
"org.freedesktop.PolicyKit1.Authority",
"RevokeTemporaryAuthorizationById");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append(m, "s", id);
if (r < 0)
return bus_log_create_error(r);
log_debug("Revoking temporary authorization %s", id);
r = sd_bus_call(bus, m, /* usec = */ 0, &error, /* ret_reply= */ NULL);
if (r < 0)
return log_error_errno(r, "Failed to revoke temporary authorization %s: %s",
id, bus_error_message(&error, r));
return 0;
}
static int check_polkit_subject_for_uid(sd_bus_message *m) {
const char *kind = NULL;
uid_t uid = UID_INVALID;
int r;
r = sd_bus_message_enter_container(m, 'r', "sa{sv}");
if (r < 0)
return bus_log_parse_error(r);
r = sd_bus_message_read(m, "s", &kind);
if (r < 0)
return bus_log_parse_error(r);
r = sd_bus_message_enter_container(m, 'a', "{sv}");
if (r < 0)
return bus_log_parse_error(r);
for (;;) {
const char *key, *contents;
char type;
r = sd_bus_message_enter_container(m, 'e', "sv");
if (r < 0)
return bus_log_parse_error(r);
if (r == 0)
break;
r = sd_bus_message_read(m, "s", &key);
if (r < 0)
return bus_log_parse_error(r);
r = sd_bus_message_peek_type(m, &type, &contents);
if (r < 0)
return bus_log_parse_error(r);
if (streq(key, "pid")) {
if (*contents != SD_BUS_TYPE_UINT32)
return bus_log_parse_error(SYNTHETIC_ERRNO(EINVAL));
r = sd_bus_message_skip(m, "v");
if (r < 0)
return bus_log_parse_error(r);
} else if (streq(key, "start-time")) {
if (*contents != SD_BUS_TYPE_UINT64)
return bus_log_parse_error(SYNTHETIC_ERRNO(EINVAL));
r = sd_bus_message_skip(m, "v");
if (r < 0)
return bus_log_parse_error(r);
} else if (streq(key, "uid")) {
if (*contents != SD_BUS_TYPE_INT32)
return bus_log_parse_error(SYNTHETIC_ERRNO(EINVAL));
r = sd_bus_message_read(m, "v", "i", &uid);
if (r < 0)
return bus_log_parse_error(r);
} else if (streq(key, "pidfd")) {
if (*contents != SD_BUS_TYPE_UNIX_FD)
return bus_log_parse_error(SYNTHETIC_ERRNO(EINVAL));
r = sd_bus_message_skip(m, "v");
if (r < 0)
return bus_log_parse_error(r);
} else {
r = sd_bus_message_skip(m, "v");
if (r < 0)
return bus_log_parse_error(r);
}
r = sd_bus_message_exit_container(m);
if (r < 0)
return bus_log_parse_error(r);
}
r = sd_bus_message_exit_container(m); /* a(sa{sv}) */
if (r < 0)
return bus_log_parse_error(r);
r = sd_bus_message_exit_container(m); /* (a(sa{sv})) */
if (r < 0)
return bus_log_parse_error(r);
return uid_is_valid(uid) && uid == geteuid();
}
static int revoke_temporary_authorizations(sd_bus *bus) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const char *session_id = NULL;
int r;
assert(bus);
session_id = getenv("XDG_SESSION_ID");
if (!session_id)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "XDG_SESSION_ID is not set");
r = sd_bus_message_new_method_call(bus, &m,
"org.freedesktop.PolicyKit1",
"/org/freedesktop/PolicyKit1/Authority",
"org.freedesktop.PolicyKit1.Authority",
"EnumerateTemporaryAuthorizations");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append(m, "(sa{sv})", "unix-session", 1, "session-id", "s", session_id);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_call(bus, m, /* usec = */ 0, &error, &reply);
if (r < 0)
return log_error_errno(r, "Failed to enumerate temporary authorizations: %s",
bus_error_message(&error, r));
r = sd_bus_message_enter_container(reply, 'a', "(ss(sa{sv})tt)");
if (r < 0)
return bus_log_parse_error(r);
for (;;) {
const char *id = NULL, *action_id = NULL;
r = sd_bus_message_enter_container(reply, 'r', "ss(sa{sv})tt");
if (r < 0)
return bus_log_parse_error(r);
if (r == 0)
break;
r = sd_bus_message_read(reply, "ss", &id, &action_id);
if (r < 0)
return bus_log_parse_error(r);
if (streq(action_id, "org.freedesktop.systemd1.manage-units")) {
r = check_polkit_subject_for_uid(reply);
if (r < 0)
return r;
if (r > 0) {
r = revoke_temporary_authorization_by_id(bus, id);
if (r < 0)
return r;
}
} else {
r = sd_bus_message_skip(reply, "(sa{sv})");
if (r < 0)
return bus_log_parse_error(r);
}
r = sd_bus_message_skip(reply, "tt");
if (r < 0)
return bus_log_parse_error(r);
r = sd_bus_message_exit_container(reply);
if (r < 0)
return bus_log_parse_error(r);
}
r = sd_bus_message_exit_container(reply);
if (r < 0)
return bus_log_parse_error(r);
return 0;
}
static int polkit_validate(sd_bus *bus) {
PolkitFlags flags = POLKIT_ALWAYS_QUERY;
int r;
@@ -3333,7 +3057,7 @@ static int run(int argc, char* argv[]) {
return r;
if (arg_remove_timestamp) {
r = revoke_temporary_authorizations(bus);
r = polkit_revoke_temporary_authorizations(bus);
if (r < 0)
return r;
if (arg_validate)
@@ -3347,7 +3071,7 @@ static int run(int argc, char* argv[]) {
if (r < 0)
return r;
if (r > 0 && tmpauthz_id) {
r = revoke_temporary_authorization_by_id(bus, tmpauthz_id);
r = polkit_revoke_temporary_authorization_by_id(bus, tmpauthz_id);
if (r < 0)
return r;
}
+1
View File
@@ -35,6 +35,7 @@ typedef enum OutputFlags OutputFlags;
typedef enum OutputMode OutputMode;
typedef enum PagerFlags PagerFlags;
typedef enum PatternCompileCase PatternCompileCase;
typedef enum PolkitFlags PolkitFlags;
typedef enum RemoveFlags RemoveFlags;
typedef enum ResolveSupport ResolveSupport;
typedef enum TPM2Flags TPM2Flags;