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).
This commit is contained in:
Luca Boccassi 2022-03-10 01:30:08 +00:00 committed by Luca Boccassi
parent 270fd40da5
commit 24759d8f08
8 changed files with 38 additions and 7 deletions

View file

@ -479,7 +479,8 @@
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>

View 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,6 +3538,16 @@ 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,
@ -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);

View 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 |

View 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);

View file

@ -208,6 +208,7 @@ TEST(protect_kernel_logs) {
NULL,
NULL,
NULL,
NULL,
NULL);
assert_se(r == 0);

View 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");

View file

@ -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
)

View file

@ -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