]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: support ExtensionDirectories in user manager
authorLuca Boccassi <bluca@debian.org>
Thu, 10 Mar 2022 01:30:08 +0000 (01:30 +0000)
committerLuca Boccassi <luca.boccassi@gmail.com>
Thu, 10 Mar 2022 20:38:10 +0000 (20:38 +0000)
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).

man/systemd.exec.xml
src/core/execute.c
src/core/namespace.c
src/core/namespace.h
src/test/test-namespace.c
src/test/test-ns.c
test/TEST-43-PRIVATEUSER-UNPRIV/test.sh
test/units/testsuite-43.sh

index defca12d1ba4c2509c5d535463bc2c7eb183083c..f182919673df59c613ecbf155aa91c85096f80b7 100644 (file)
         or the host. See:
         <citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
 
-        <xi:include href="system-only.xml" xpointer="singular"/></listitem>
+        <para>Note that usage from user units requires overlayfs support in unprivileged user namespaces,
+        which was first introduced in kernel v5.11.</para></listitem>
       </varlistentry>
     </variablelist>
   </refsect1>
index 027e5473b608986e7725d6351d283724c584e681..94cd198b4ddd7e39e60dc5ccd5256ac5860f7052 100644 (file)
@@ -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);
 
index 77dd473a48d052aa52a6094ba2be0fcefdba67a5..e6293882fe2c9507b22540b166a087c612fc0c7e 100644 (file)
@@ -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 |
index ae84d2b03b101b71e8012e66ba607bdf7d9650ee..3ef41d2c62853d3c405d2fbf3a62b6be9326d853 100644 (file)
@@ -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);
 
index 8dea195745776f39d725f4274a35c5e47becb28c..37acc782eb862094db673c72952ade9c5ed76fc6 100644 (file)
@@ -208,6 +208,7 @@ TEST(protect_kernel_logs) {
                                     NULL,
                                     NULL,
                                     NULL,
+                                    NULL,
                                     NULL);
                 assert_se(r == 0);
 
index cd455a3a5b79a3de0dd298029e97bdd5c239198b..7eb29d109d11ee28dc37a25a13543fe2de53bf6f 100644 (file)
@@ -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");
index dafcdb58fc98e66d56a88e7a397055b5fed419b3..6e1a91a64965376b448c1a96886b06a8333d239a 100755 (executable)
@@ -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
     )
index cda1fe1fda4144131c493593c1c0fbf11b544822..8b755b1a0f10097df21696f2905370f9aa5927bf 100755 (executable)
@@ -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