From bc3a11097f673ce3c2e8ba500014f16402839e53 Mon Sep 17 00:00:00 2001 From: Nick Rosbrook Date: Fri, 21 Mar 2025 15:14:20 -0400 Subject: [PATCH] login: add polkit example rules for allowing root to ignore inhibitors The semantics of strong inhibitors require that POLKIT_ALWAYS_QUERY always be set when checking if we can allow blocking inhibitors to be ignored on shutdown, reboot, etc. With the default polkit rules and policy, users may experience a situation where users in the sudo group are authorized to run: systemctl reboot --check-inhibitors=no but the root user is not authorized. Instead, the following error is given: Call to Reboot failed: Interactive authentication required. While this is correct according to the semantics of strong inhibitors, it is confusing. To help the situation, provide example polkit rules that allow root to perform these actions. Finally, when root receives SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED when calling e.g. systemctl reboot, print a message explaining that this is due to the current polkit policy, and point to the new example rule. Related: https://github.com/systemd/systemd/issues/36786 --- meson.build | 1 + ...ogind-root-ignore-inhibitors.rules.example | 20 +++++++++++++++++++ src/login/meson.build | 2 ++ src/systemctl/systemctl-logind.c | 6 ++++++ 4 files changed, 29 insertions(+) create mode 100644 src/login/10-systemd-logind-root-ignore-inhibitors.rules.example diff --git a/meson.build b/meson.build index 48d4f0027c0..57e26dfed6d 100644 --- a/meson.build +++ b/meson.build @@ -259,6 +259,7 @@ conf.set_quoted('MODPROBE_DIR', modprobedir) conf.set_quoted('MODULESLOAD_DIR', modulesloaddir) conf.set_quoted('PKGSYSCONFDIR', pkgsysconfdir) conf.set_quoted('POLKIT_AGENT_BINARY_PATH', bindir / 'pkttyagent') +conf.set_quoted('POLKIT_RULES_DIR', polkitrulesdir) conf.set_quoted('PREFIX', prefixdir) conf.set_quoted('PREFIX_NOSLASH', prefixdir_noslash) conf.set_quoted('RANDOM_SEED', randomseeddir / 'random-seed') diff --git a/src/login/10-systemd-logind-root-ignore-inhibitors.rules.example b/src/login/10-systemd-logind-root-ignore-inhibitors.rules.example new file mode 100644 index 00000000000..ff79172cdff --- /dev/null +++ b/src/login/10-systemd-logind-root-ignore-inhibitors.rules.example @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT-0 +// +// This config file is installed as part of systemd. +// It may be freely copied and edited (following the MIT No Attribution license). +// +// This example can be enabled by symlinking this file to +// /etc/polkit-1/rules.d/10-systemd-logind-root-ignore-inhibitors.rules + +// Allow the root user to ignore inhibitors when calling reboot etc. +polkit.addRule(function(action, subject) { + if ((action.id == "org.freedesktop.login1.power-off-ignore-inhibit" || + action.id == "org.freedesktop.login1.reboot-ignore-inhibit" || + action.id == "org.freedesktop.login1.halt-ignore-inhibit" || + action.id == "org.freedesktop.login1.suspend-ignore-inhibit" || + action.id == "org.freedesktop.login1.hibernate-ignore-inhibit") && + subject.user == "root") { + + return polkit.Result.YES; + } +}); diff --git a/src/login/meson.build b/src/login/meson.build index 86879b47237..b7448439336 100644 --- a/src/login/meson.build +++ b/src/login/meson.build @@ -150,4 +150,6 @@ if enable_logind install_dir : dbussystemservicedir) install_data('org.freedesktop.login1.policy', install_dir : polkitpolicydir) + install_data('10-systemd-logind-root-ignore-inhibitors.rules.example', + install_dir : polkitrulesdir) endif diff --git a/src/systemctl/systemctl-logind.c b/src/systemctl/systemctl-logind.c index 0df669f484e..4acd32832cf 100644 --- a/src/systemctl/systemctl-logind.c +++ b/src/systemctl/systemctl-logind.c @@ -109,6 +109,12 @@ int logind_reboot(enum action a) { } if (r >= 0) return 0; + if (geteuid() == 0 && sd_bus_error_has_name(&error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED)) + return log_error_errno(r, + "The current polkit policy does not allow root to ignore inhibitors without authentication in order to %s.\n" + "To allow this action, a new polkit rule is needed.\n" + "See " POLKIT_RULES_DIR "/10-systemd-logind-root-ignore-inhibitors.rules.example.", + action_table[a].verb); if (!sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD) || a == ACTION_SLEEP) return log_error_errno(r, "Call to %s failed: %s", actions[a], bus_error_message(&error, r)); -- 2.47.3