From 1361f015773e3b4d74e382edf1565f3315a3396b Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Fri, 21 Jan 2022 13:08:19 +0100 Subject: [PATCH 1/2] core/namespace: allow using ProtectSubset=pid and ProtectHostname=true together If a service requests both ProtectSubset=pid and ProtectHostname=true then it will currently fail to start. The ProcSubset=pid option instructs systemd to mount procfs for the service with subset=pid which hides all entries other than /proc/. Consequently trying to interact with the two files /proc/sys/kernel/{hostname,domainname} covered by ProtectHostname=true will fail. Fix this by only performing this check when ProtectSubset=pid is not requested. Essentially ProtectSubset=pid implies/provides ProtectHostname=true. --- src/core/namespace.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/namespace.c b/src/core/namespace.c index ecbd23833c..e55e9df702 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -2157,14 +2157,19 @@ int setup_namespace( goto finish; } + /* Note, if proc is mounted with subset=pid then neither of the + * two paths will exist, i.e. they are implicitly protected by + * the mount option. */ if (ns_info->protect_hostname) { *(m++) = (MountEntry) { .path_const = "/proc/sys/kernel/hostname", .mode = READONLY, + .ignore = ignore_protect_proc, }; *(m++) = (MountEntry) { .path_const = "/proc/sys/kernel/domainname", .mode = READONLY, + .ignore = ignore_protect_proc, }; } From fbf90c0d5cadc5d1e95485f770f45a7d4cd39daa Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Mon, 24 Jan 2022 10:12:57 +0100 Subject: [PATCH 2/2] core/namespace: s/normalize_mounts()/drop_unused_mounts() Rename the normalize_mounts() helper to drop_unused_mounts. All the helpers called in there get rid of mounts that are unused for a variety of reasons. And whereas the helpers are aptly prefixed with "drop" the overall helper isn't and instead uses "normalize". Make it more obvious what the helper actually does by renaming it from normalize_mounts() to drop_unused_mounts(). Readers of code calling this helper will immediately see that it will get rid of unused mounts. Link: https://github.com/systemd/systemd/issues/22206 --- src/core/namespace.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/core/namespace.c b/src/core/namespace.c index e55e9df702..e2e88b0eb6 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -1578,7 +1578,14 @@ static size_t namespace_calculate_mounts( ns_info->private_ipc; /* /dev/mqueue */ } -static void normalize_mounts(const char *root_directory, MountEntry *mounts, size_t *n_mounts) { +/* Walk all mount entries and dropping any unused mounts. This affects all + * mounts: + * - that are implicitly protected by a path that has been rendered inaccessible + * - whose immediate parent requests the same protection mode as the mount itself + * - that are outside of the relevant root directory + * - which are duplicates + */ +static void drop_unused_mounts(const char *root_directory, MountEntry *mounts, size_t *n_mounts) { assert(root_directory); assert(n_mounts); assert(mounts || *n_mounts == 0); @@ -1684,7 +1691,7 @@ static int apply_mounts( if (!again) break; - normalize_mounts(root, mounts, n_mounts); + drop_unused_mounts(root, mounts, n_mounts); } /* Now that all filesystems have been set up, but before the @@ -2250,7 +2257,7 @@ int setup_namespace( if (r < 0) goto finish; - normalize_mounts(root, mounts, &n_mounts); + drop_unused_mounts(root, mounts, &n_mounts); } /* All above is just preparation, figuring out what to do. Let's now actually start doing something. */