diff options
-rw-r--r-- | pkg/rootless/rootless_linux.c | 16 | ||||
-rw-r--r-- | pkg/rootless/rootless_linux.go | 20 | ||||
-rw-r--r-- | pkg/rootless/rootless_unsupported.go | 5 |
3 files changed, 41 insertions, 0 deletions
diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c index a08cfd36a..098ca7830 100644 --- a/pkg/rootless/rootless_linux.c +++ b/pkg/rootless/rootless_linux.c @@ -40,6 +40,7 @@ static const char *_unprivileged_user_namespaces = "/proc/sys/kernel/unprivilege static int open_files_max_fd; fd_set open_files_set; static uid_t rootless_uid_init; +static gid_t rootless_gid_init; static int syscall_setresuid (uid_t ruid, uid_t euid, uid_t suid) @@ -59,6 +60,12 @@ rootless_uid () return rootless_uid_init; } +uid_t +rootless_gid () +{ + return rootless_gid_init; +} + static void do_pause () { @@ -224,6 +231,7 @@ static void __attribute__((constructor)) init() long pid; char buf[12]; uid_t uid; + gid_t gid; char path[PATH_MAX]; const char *const suffix = "/libpod/pause.pid"; char *cwd = getcwd (NULL, 0); @@ -263,6 +271,7 @@ static void __attribute__((constructor)) init() } uid = geteuid (); + gid = getegid (); sprintf (path, "/proc/%d/ns/user", pid); fd = open (path, O_RDONLY); @@ -310,6 +319,7 @@ static void __attribute__((constructor)) init() free (cwd); rootless_uid_init = uid; + rootless_gid_init = gid; } } @@ -440,6 +450,7 @@ reexec_userns_join (int userns, int mountns, char *pause_pid_file_path) { pid_t ppid = getpid (); char uid[16]; + char gid[16]; char **argv; int pid; char *cwd = getcwd (NULL, 0); @@ -451,6 +462,7 @@ reexec_userns_join (int userns, int mountns, char *pause_pid_file_path) } sprintf (uid, "%d", geteuid ()); + sprintf (gid, "%d", getegid ()); argv = get_cmd_line_args (ppid); if (argv == NULL) @@ -477,6 +489,7 @@ reexec_userns_join (int userns, int mountns, char *pause_pid_file_path) setenv ("_CONTAINERS_USERNS_CONFIGURED", "init", 1); setenv ("_CONTAINERS_ROOTLESS_UID", uid, 1); + setenv ("_CONTAINERS_ROOTLESS_GID", gid, 1); if (prctl (PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0) < 0) { @@ -556,6 +569,7 @@ reexec_in_user_namespace (int ready, char *pause_pid_file_path) pid_t ppid = getpid (); char **argv; char uid[16]; + char gid[16]; char *listen_fds = NULL; char *listen_pid = NULL; bool do_socket_activation = false; @@ -577,6 +591,7 @@ reexec_in_user_namespace (int ready, char *pause_pid_file_path) } sprintf (uid, "%d", geteuid ()); + sprintf (gid, "%d", getegid ()); pid = syscall_clone (CLONE_NEWUSER|CLONE_NEWNS|SIGCHLD, NULL); if (pid < 0) @@ -621,6 +636,7 @@ reexec_in_user_namespace (int ready, char *pause_pid_file_path) setenv ("_CONTAINERS_USERNS_CONFIGURED", "init", 1); setenv ("_CONTAINERS_ROOTLESS_UID", uid, 1); + setenv ("_CONTAINERS_ROOTLESS_GID", gid, 1); do ret = read (ready, &b, 1) < 0; diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go index ddf881368..9132c0fe5 100644 --- a/pkg/rootless/rootless_linux.go +++ b/pkg/rootless/rootless_linux.go @@ -25,6 +25,7 @@ import ( #cgo remoteclient CFLAGS: -DDISABLE_JOIN_SHORTCUT #include <stdlib.h> extern uid_t rootless_uid(); +extern uid_t rootless_gid(); extern int reexec_in_user_namespace(int ready, char *pause_pid_file_path); extern int reexec_in_user_namespace_wait(int pid); extern int reexec_userns_join(int userns, int mountns, char *pause_pid_file_path); @@ -49,10 +50,12 @@ var ( func IsRootless() bool { isRootlessOnce.Do(func() { rootlessUIDInit := int(C.rootless_uid()) + rootlessGIDInit := int(C.rootless_gid()) if rootlessUIDInit != 0 { // This happens if we joined the user+mount namespace as part of os.Setenv("_CONTAINERS_USERNS_CONFIGURED", "done") os.Setenv("_CONTAINERS_ROOTLESS_UID", fmt.Sprintf("%d", rootlessUIDInit)) + os.Setenv("_CONTAINERS_ROOTLESS_GID", fmt.Sprintf("%d", rootlessGIDInit)) } isRootless = os.Geteuid() != 0 || os.Getenv("_CONTAINERS_USERNS_CONFIGURED") != "" }) @@ -69,6 +72,23 @@ func GetRootlessUID() int { return os.Geteuid() } +// GetRootlessGID returns the GID of the user in the parent userNS +func GetRootlessGID() int { + gidEnv := os.Getenv("_CONTAINERS_ROOTLESS_GID") + if gidEnv != "" { + u, _ := strconv.Atoi(gidEnv) + return u + } + + /* If the _CONTAINERS_ROOTLESS_UID is set, assume the gid==uid. */ + uidEnv := os.Getenv("_CONTAINERS_ROOTLESS_UID") + if uidEnv != "" { + u, _ := strconv.Atoi(uidEnv) + return u + } + return os.Getegid() +} + func tryMappingTool(tool string, pid int, hostID int, mappings []idtools.IDMap) error { path, err := exec.LookPath(tool) if err != nil { diff --git a/pkg/rootless/rootless_unsupported.go b/pkg/rootless/rootless_unsupported.go index 42f8f3aec..221baff97 100644 --- a/pkg/rootless/rootless_unsupported.go +++ b/pkg/rootless/rootless_unsupported.go @@ -24,6 +24,11 @@ func GetRootlessUID() int { return -1 } +// GetRootlessGID returns the GID of the user in the parent userNS +func GetRootlessGID() int { + return -1 +} + // JoinUserAndMountNS re-exec podman in a new userNS and join the user and mount // namespace of the specified PID without looking up its parent. Useful to join directly // the conmon process. It is a convenience function for JoinUserAndMountNSWithOpts |