nspawn: start polkit agent while we do polkit operations

Let's make sure unpriv nspawn can acquire privs even when invoked
outside of a desktop environment that has a polkit agent registered.
This commit is contained in:
Lennart Poettering
2025-05-23 12:17:47 +02:00
parent b5bd717fcd
commit ac8c558629
2 changed files with 21 additions and 1 deletions

View File

@@ -1857,6 +1857,7 @@ After=sys-subsystem-net-devices-ens1.device</programlisting>
<xi:include href="standard-options.xml" xpointer="no-pager" />
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
<xi:include href="standard-options.xml" xpointer="no-ask-password" />
</variablelist>
</refsect2>
</refsect1>

View File

@@ -93,6 +93,7 @@
#include "parse-util.h"
#include "path-util.h"
#include "pidref.h"
#include "polkit-agent.h"
#include "pretty-print.h"
#include "process-util.h"
#include "ptyfwd.h"
@@ -246,6 +247,7 @@ static ImagePolicy *arg_image_policy = NULL;
static char *arg_background = NULL;
static bool arg_privileged = false;
static bool arg_cleanup = false;
static bool arg_ask_password = true;
STATIC_DESTRUCTOR_REGISTER(arg_directory, freep);
STATIC_DESTRUCTOR_REGISTER(arg_template, freep);
@@ -339,6 +341,7 @@ static int help(void) {
" --settings=BOOLEAN Load additional settings from .nspawn file\n"
" --cleanup Clean up left-over mounts and underlying mount\n"
" points used by the container\n"
" --no-ask-password Do not prompt for password\n"
"\n%3$sImage:%4$s\n"
" -D --directory=PATH Root directory for the container\n"
" --template=PATH Initialize root directory from template directory,\n"
@@ -693,6 +696,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_IMAGE_POLICY,
ARG_BACKGROUND,
ARG_CLEANUP,
ARG_NO_ASK_PASSWORD,
};
static const struct option options[] = {
@@ -769,6 +773,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "image-policy", required_argument, NULL, ARG_IMAGE_POLICY },
{ "background", required_argument, NULL, ARG_BACKGROUND },
{ "cleanup", no_argument, NULL, ARG_CLEANUP },
{ "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
{}
};
@@ -1556,6 +1561,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_cleanup = true;
break;
case ARG_NO_ASK_PASSWORD:
arg_ask_password = false;
break;
case '?':
return -EINVAL;
@@ -3828,7 +3837,7 @@ static DissectImageFlags determine_dissect_image_flags(void) {
DISSECT_IMAGE_PIN_PARTITION_DEVICES |
(arg_read_only ? DISSECT_IMAGE_READ_ONLY : DISSECT_IMAGE_FSCK|DISSECT_IMAGE_GROWFS) |
DISSECT_IMAGE_ALLOW_USERSPACE_VERITY |
(arg_console_mode == CONSOLE_INTERACTIVE ? DISSECT_IMAGE_ALLOW_INTERACTIVE_AUTH : 0) |
(arg_console_mode == CONSOLE_INTERACTIVE && arg_ask_password ? DISSECT_IMAGE_ALLOW_INTERACTIVE_AUTH : 0) |
((arg_userns_ownership == USER_NAMESPACE_OWNERSHIP_FOREIGN) ? DISSECT_IMAGE_FOREIGN_UID :
(arg_userns_ownership != USER_NAMESPACE_OWNERSHIP_AUTO) ? DISSECT_IMAGE_IDENTITY_UID : 0);
}
@@ -5410,6 +5419,8 @@ static int run_container(
r = sd_bus_set_close_on_exit(bus, false);
if (r < 0)
return log_error_errno(r, "Failed to disable close-on-exit behaviour: %m");
(void) sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
}
if (!arg_keep_unit) {
@@ -5537,6 +5548,11 @@ static int run_container(
log_warning_errno(r, "Failed to send readiness notification, ignoring: %m");
}
/* All operations that might need Polkit authorizations (i.e. userns registration, mounts, and
* machine registration are complete now, get rid of the agent again, so that we retain exclusive
* control of the TTY from now on. */
polkit_agent_close();
/* Note: we do not use SD_EVENT_SIGNAL_PROCMASK or sd_event_set_signal_exit(), since we want the
* signals to be block continuously, even if we destroy the event loop and allocate a new one on
* container reboot. */
@@ -5951,6 +5967,8 @@ static int run(int argc, char *argv[]) {
if (arg_console_mode == CONSOLE_PIPE) /* if we pass STDERR on to the container, don't add our own logs into it too */
arg_quiet = true;
polkit_agent_open();
if (arg_userns_mode == USER_NAMESPACE_MANAGED) {
/* Let's allocate a 64K userns first, if managed mode is chosen */
@@ -6353,6 +6371,7 @@ static int run(int argc, char *argv[]) {
}
expose_args.fw_ctx = fw_ctx;
}
for (;;) {
r = run_container(
rootdir,