]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
namespace-util: make "setgroups" users property writable via userns_acquire()
authorLennart Poettering <lennart@poettering.net>
Mon, 10 Mar 2025 10:24:59 +0000 (11:24 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 17 Mar 2025 15:03:18 +0000 (16:03 +0100)
Unprivileged namespaces are only allowed if the "setgroups" file is set
to "deny" for processes. And we need to write it before writing the
gidmap. Hence add a parameter for that.

Then, also patch all current users to actually enable this. The usecase
generally don't need it (because they don't care about unprivileged
userns), but it doesn't hurt to enable the concept anyway in all current
users (none of them actually runs complex userspace in them, but they
mostly use userns_acquire() for idmapped mounts and similar).

Let's anyway make this option explicit in the function call, to indicate
that the concept exists and is applied.

src/basic/namespace-util.c
src/basic/namespace-util.h
src/core/namespace.c
src/home/homework-mount.c
src/mountfsd/mountwork.c
src/nsresourced/test-userns-restrict.c
src/shared/mount-util.c
src/test/test-namespace.c

index 322cba4cf36f1bd51b2019fde645256989ba4a65..b24901c0820fc9c7af0a70e93268873272bd0d1b 100644 (file)
@@ -524,8 +524,8 @@ int userns_acquire_empty(void) {
         return pidref_namespace_open_by_type(&pid, NAMESPACE_USER);
 }
 
-int userns_acquire(const char *uid_map, const char *gid_map) {
-        char path[STRLEN("/proc//uid_map") + DECIMAL_STR_MAX(pid_t) + 1];
+int userns_acquire(const char *uid_map, const char *gid_map, bool setgroups_deny) {
+        char path[STRLEN("/proc//setgroups") + DECIMAL_STR_MAX(pid_t) + 1];
         _cleanup_(pidref_done_sigkill_wait) PidRef pid = PIDREF_NULL;
         int r;
 
@@ -546,6 +546,13 @@ int userns_acquire(const char *uid_map, const char *gid_map) {
         if (r < 0)
                 return log_debug_errno(r, "Failed to write UID map: %m");
 
+        if (setgroups_deny) {
+                xsprintf(path, "/proc/" PID_FMT "/setgroups", pid.pid);
+                r = write_string_file(path, "deny", WRITE_STRING_FILE_DISABLE_BUFFER);
+                if (r < 0)
+                        return log_debug_errno(r, "Failed to write setgroups file: %m");
+        }
+
         xsprintf(path, "/proc/" PID_FMT "/gid_map", pid.pid);
         r = write_string_file(path, gid_map, WRITE_STRING_FILE_DISABLE_BUFFER);
         if (r < 0)
@@ -713,7 +720,7 @@ int is_idmapping_supported(const char *path) {
         if (r < 0)
                 return r;
 
-        userns_fd = r = userns_acquire(uid_map, gid_map);
+        userns_fd = r = userns_acquire(uid_map, gid_map, /* setgroups_deny= */ true);
         if (ERRNO_IS_NEG_NOT_SUPPORTED(r) || ERRNO_IS_NEG_PRIVILEGE(r) || r == -EINVAL)
                 return false;
         if (r == -ENOSPC) {
index 3d40a515e79984b933d61a2e13e54b1458172f3a..74fd8a96d4889381bb7019006295a86db85a7f90 100644 (file)
@@ -86,7 +86,7 @@ static inline bool userns_shift_range_valid(uid_t shift, uid_t range) {
 int parse_userns_uid_range(const char *s, uid_t *ret_uid_shift, uid_t *ret_uid_range);
 
 int userns_acquire_empty(void);
-int userns_acquire(const char *uid_map, const char *gid_map);
+int userns_acquire(const char *uid_map, const char *gid_map, bool setgroups_deny);
 int userns_enter_and_pin(int userns_fd, pid_t *ret_pid);
 
 int userns_get_base_uid(int userns_fd, uid_t *ret_uid, gid_t *ret_gid);
index e801b6ea60c5cf64c5bb304346938ef2551e55cf..0943e0818fae497285bb67aee3f9f84b4f768ddd 100644 (file)
@@ -1917,7 +1917,7 @@ static int apply_one_mount(
                                 return log_oom();
                 }
 
-                userns_fd = userns_acquire(uid_map, gid_map);
+                userns_fd = userns_acquire(uid_map, gid_map, /* setgroups_deny= */ true);
                 if (userns_fd < 0)
                         return log_error_errno(userns_fd, "Failed to allocate user namespace: %m");
 
index 085ba09e81e12015b71f78c40413942166dbf8f3..52115d86be7a2c08350f9e426cc2d6c31b93e85a 100644 (file)
@@ -232,7 +232,7 @@ static int make_home_userns(uid_t stored_uid, uid_t exposed_uid) {
 
         log_debug("Creating userns with mapping:\n%s", text);
 
-        userns_fd = userns_acquire(text, text); /* same uid + gid mapping */
+        userns_fd = userns_acquire(text, text, /* setgroups_deny= */ true); /* same uid + gid mapping */
         if (userns_fd < 0)
                 return log_error_errno(userns_fd, "Failed to allocate user namespace: %m");
 
index eaf72893aab432a6229dfbc96b50fd464053691c..41c1d65391b5018086a10d3ee7cfe17760c9cc79 100644 (file)
@@ -860,7 +860,7 @@ static int vl_method_mount_directory(
                 if (r < 0)
                         return r;
 
-                _cleanup_close_ int idmap_userns_fd = userns_acquire(new_uid_map, new_uid_map);
+                _cleanup_close_ int idmap_userns_fd = userns_acquire(new_uid_map, new_uid_map, /* setgroups_deny= */ true);
                 if (idmap_userns_fd < 0)
                         return log_debug_errno(idmap_userns_fd, "Failed to acquire user namespace for id mapping: %m");
 
index d6df02428e5ab3dc6d2da46263cfa2a4a6ad3126..59ca1cabbb001b097e57b16760c47cf6eff7ea5a 100644 (file)
@@ -78,7 +78,7 @@ static int run(int argc, char *argv[]) {
         host_tmpfs = make_tmpfs_fsmount();
         assert_se(host_tmpfs >= 0);
 
-        userns_fd = userns_acquire("0 0 1", "0 0 1");
+        userns_fd = userns_acquire("0 0 1", "0 0 1", /* setgroups_deny= */ true);
         if (userns_fd < 0)
                 return log_error_errno(userns_fd, "Failed to make user namespace: %m");
 
index 97ff6d0764d4c901ecde006da726a2c1d2bc124d..d7471bc78d2127595fd9866896c2c20174751113 100644 (file)
@@ -1442,7 +1442,7 @@ int make_userns(uid_t uid_shift,
         }
 
         /* We always assign the same UID and GID ranges */
-        userns_fd = userns_acquire(line, line);
+        userns_fd = userns_acquire(line, line, /* setgroups_deny= */ true);
         if (userns_fd < 0)
                 return log_debug_errno(userns_fd, "Failed to acquire new userns: %m");
 
index cae65a14b107c7319c72c2084d3902a081a11999..52049efdb88f375f84b14a10eb721f826be3dc04 100644 (file)
@@ -258,7 +258,7 @@ TEST(namespace_is_init) {
 TEST(userns_get_base_uid) {
         _cleanup_close_ int fd = -EBADF;
 
-        fd = userns_acquire("0 1 1", "0 2 1");
+        fd = userns_acquire("0 1 1", "0 2 1", /* setgroups_deny= */ true);
         if (ERRNO_IS_NEG_NOT_SUPPORTED(fd))
                 return (void) log_tests_skipped("userns is not supported");
         if (ERRNO_IS_NEG_PRIVILEGE(fd))