From: Lennart Poettering Date: Mon, 13 Jul 2026 21:47:34 +0000 (+0200) Subject: run: split out polkit ops into separate .c file X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9793dde16e690d4af0756a3396f91109980dafac;p=thirdparty%2Fsystemd.git 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. --- diff --git a/src/run/meson.build b/src/run/meson.build index 832edcdbc41..01a09c48ff6 100644 --- a/src/run/meson.build +++ b/src/run/meson.build @@ -4,7 +4,7 @@ executables += [ executable_template + { 'name' : 'systemd-run', 'public' : true, - 'sources' : files('run.c'), + 'sources' : files('run.c', 'run-polkit.c'), }, ] diff --git a/src/run/run-polkit.c b/src/run/run-polkit.c new file mode 100644 index 00000000000..0b400f0bc75 --- /dev/null +++ b/src/run/run-polkit.c @@ -0,0 +1,291 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include + +#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; +} diff --git a/src/run/run-polkit.h b/src/run/run-polkit.h new file mode 100644 index 00000000000..120633da730 --- /dev/null +++ b/src/run/run-polkit.h @@ -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); diff --git a/src/run/run.c b/src/run/run.c index 85256a2b1b1..696274d2a06 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -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; } diff --git a/src/shared/forward.h b/src/shared/forward.h index f314b6c2181..38c8dc03e5a 100644 --- a/src/shared/forward.h +++ b/src/shared/forward.h @@ -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;