1 // SPDX-License-Identifier: GPL-2.0
6 #include <linux/limits.h>
10 #include <sys/mount.h>
12 #include <sys/types.h>
17 ssize_t read_nointr(int fd, void *buf, size_t count)
22 ret = read(fd, buf, count);
23 } while (ret < 0 && errno == EINTR);
28 ssize_t write_nointr(int fd, const void *buf, size_t count)
33 ret = write(fd, buf, count);
34 } while (ret < 0 && errno == EINTR);
39 static int write_file(const char *path, const void *buf, size_t count)
44 fd = open(path, O_WRONLY | O_CLOEXEC | O_NOCTTY | O_NOFOLLOW);
48 ret = write_nointr(fd, buf, count);
50 if (ret < 0 || (size_t)ret != count)
56 static int map_ids(pid_t pid, unsigned long nsid, unsigned long hostid,
59 char map[100], procfile[256];
61 snprintf(procfile, sizeof(procfile), "/proc/%d/uid_map", pid);
62 snprintf(map, sizeof(map), "%lu %lu %lu", nsid, hostid, range);
63 if (write_file(procfile, map, strlen(map)))
67 snprintf(procfile, sizeof(procfile), "/proc/%d/gid_map", pid);
68 snprintf(map, sizeof(map), "%lu %lu %lu", nsid, hostid, range);
69 if (write_file(procfile, map, strlen(map)))
75 #define __STACK_SIZE (8 * 1024 * 1024)
76 pid_t do_clone(int (*fn)(void *), void *arg, int flags)
80 stack = malloc(__STACK_SIZE);
85 return __clone2(fn, stack, __STACK_SIZE, flags | SIGCHLD, arg, NULL);
87 return clone(fn, stack + __STACK_SIZE, flags | SIGCHLD, arg, NULL);
91 static int get_userns_fd_cb(void *data)
93 return kill(getpid(), SIGSTOP);
96 int get_userns_fd(unsigned long nsid, unsigned long hostid, unsigned long range)
102 pid = do_clone(get_userns_fd_cb, NULL, CLONE_NEWUSER);
106 ret = map_ids(pid, nsid, hostid, range);
110 snprintf(path, sizeof(path), "/proc/%d/ns/user", pid);
111 ret = open(path, O_RDONLY | O_CLOEXEC);
117 int wait_for_pid(pid_t pid)
122 ret = waitpid(pid, &status, 0);
130 if (!WIFEXITED(status))
133 return WEXITSTATUS(status);