From: Luca Boccassi Date: Thu, 10 Mar 2022 01:30:08 +0000 (+0000) Subject: core: support ExtensionDirectories in user manager X-Git-Tag: v251-rc1~173 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=24759d8f089f7d8ecee460d92278af348af21dd1;p=thirdparty%2Fsystemd.git core: support ExtensionDirectories in user manager Unprivileged overlayfs is supported since Linux 5.11. The only change needed to get ExtensionDirectories to work is to avoid hard-coding the staging directory to the system manager runtime directory, everything else just works (TM). --- diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index defca12d1ba..f182919673d 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -479,7 +479,8 @@ or the host. See: os-release5. - + Note that usage from user units requires overlayfs support in unprivileged user namespaces, + which was first introduced in kernel v5.11. diff --git a/src/core/execute.c b/src/core/execute.c index 027e5473b60..94cd198b4dd 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -3438,7 +3438,8 @@ static int apply_mount_namespace( _cleanup_strv_free_ char **empty_directories = NULL, **symlinks = NULL; const char *tmp_dir = NULL, *var_tmp_dir = NULL; const char *root_dir = NULL, *root_image = NULL; - _cleanup_free_ char *creds_path = NULL, *incoming_dir = NULL, *propagate_dir = NULL; + _cleanup_free_ char *creds_path = NULL, *incoming_dir = NULL, *propagate_dir = NULL, + *extension_dir = NULL; NamespaceInfo ns_info; bool needs_sandboxing; BindMount *bind_mounts = NULL; @@ -3537,7 +3538,17 @@ static int apply_mount_namespace( r = -ENOMEM; goto finalize; } - } + + extension_dir = strdup("/run/systemd/unit-extensions"); + if (!extension_dir) { + r = -ENOMEM; + goto finalize; + } + } else + if (asprintf(&extension_dir, "/run/user/" UID_FMT "/systemd/unit-extensions", geteuid()) < 0) { + r = -ENOMEM; + goto finalize; + } r = setup_namespace(root_dir, root_image, context->root_image_options, &ns_info, context->read_write_paths, @@ -3566,6 +3577,7 @@ static int apply_mount_namespace( context->extension_directories, propagate_dir, incoming_dir, + extension_dir, root_dir || root_image ? params->notify_socket : NULL, error_path); diff --git a/src/core/namespace.c b/src/core/namespace.c index 77dd473a48d..e6293882fe2 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -422,12 +422,12 @@ static int append_extensions( char **hierarchy, **extension_directory; int r; - assert(p); - assert(extension_dir); - if (n == 0 && strv_isempty(extension_directories)) return 0; + assert(p); + assert(extension_dir); + /* Prepare a list of overlays, that will have as each element a string suitable for being * passed as a lowerdir= parameter, so start with the hierarchy on the root. * The overlays vector will have the same number of elements and will correspond to the @@ -1999,6 +1999,7 @@ int setup_namespace( char **extension_directories, const char *propagate_dir, const char *incoming_dir, + const char *extension_dir, const char *notify_socket, char **error_path) { @@ -2009,7 +2010,7 @@ int setup_namespace( _cleanup_strv_free_ char **hierarchies = NULL; MountEntry *m = NULL, *mounts = NULL; bool require_prefix = false, setup_propagate = false; - const char *root, *extension_dir = "/run/systemd/unit-extensions"; + const char *root; DissectImageFlags dissect_image_flags = DISSECT_IMAGE_GENERIC_ROOT | DISSECT_IMAGE_REQUIRE_ROOT | diff --git a/src/core/namespace.h b/src/core/namespace.h index ae84d2b03b1..3ef41d2c628 100644 --- a/src/core/namespace.h +++ b/src/core/namespace.h @@ -145,6 +145,7 @@ int setup_namespace( char **extension_directories, const char *propagate_dir, const char *incoming_dir, + const char *extension_dir, const char *notify_socket, char **error_path); diff --git a/src/test/test-namespace.c b/src/test/test-namespace.c index 8dea1957457..37acc782eb8 100644 --- a/src/test/test-namespace.c +++ b/src/test/test-namespace.c @@ -208,6 +208,7 @@ TEST(protect_kernel_logs) { NULL, NULL, NULL, + NULL, NULL); assert_se(r == 0); diff --git a/src/test/test-ns.c b/src/test/test-ns.c index cd455a3a5b7..7eb29d109d1 100644 --- a/src/test/test-ns.c +++ b/src/test/test-ns.c @@ -109,6 +109,7 @@ int main(int argc, char *argv[]) { NULL, NULL, NULL, + NULL, NULL); if (r < 0) { log_error_errno(r, "Failed to set up namespace: %m"); diff --git a/test/TEST-43-PRIVATEUSER-UNPRIV/test.sh b/test/TEST-43-PRIVATEUSER-UNPRIV/test.sh index dafcdb58fc9..6e1a91a6496 100755 --- a/test/TEST-43-PRIVATEUSER-UNPRIV/test.sh +++ b/test/TEST-43-PRIVATEUSER-UNPRIV/test.sh @@ -13,6 +13,8 @@ command -v mksquashfs >/dev/null 2>&1 || exit 0 test_append_files() { ( + instmods overlay =overlayfs + generate_module_dependencies inst_binary unsquashfs install_verity_minimal ) diff --git a/test/units/testsuite-43.sh b/test/units/testsuite-43.sh index cda1fe1fda4..8b755b1a0f1 100755 --- a/test/units/testsuite-43.sh +++ b/test/units/testsuite-43.sh @@ -84,6 +84,18 @@ mount --bind /tmp/img /tmp/img_bind runas testuser systemd-run --wait --user --unit=test-root-dir-bind \ -p PrivateUsers=yes -p RootDirectory=/tmp/img_bind \ grep MARKER=1 /etc/os-release + +# Unprivileged overlayfs was added to Linux 5.11, so try to detect it first +mkdir -p /tmp/a /tmp/b /tmp/c +if unshare --mount --user --map-root-user mount -t overlay overlay /tmp/c -o lowerdir=/tmp/a:/tmp/b; then + unsquashfs -no-xattrs -d /tmp/app2 /usr/share/app1.raw + runas testuser systemd-run --wait --user --unit=test-extension-dir \ + -p PrivateUsers=yes -p ExtensionDirectories=/tmp/app2 \ + -p TemporaryFileSystem=/run -p RootDirectory=/tmp/img \ + -p MountAPIVFS=yes \ + grep PORTABLE_PREFIXES=app1 /usr/lib/extension-release.d/extension-release.app2 +fi + umount /tmp/img_bind systemd-analyze log-level info