diff options
Diffstat (limited to 'pkg/rootless')
-rw-r--r-- | pkg/rootless/rootless_linux.c | 71 | ||||
-rw-r--r-- | pkg/rootless/rootless_linux.go | 7 |
2 files changed, 50 insertions, 28 deletions
diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c index 041a161dc..6643bfbbf 100644 --- a/pkg/rootless/rootless_linux.c +++ b/pkg/rootless/rootless_linux.c @@ -58,7 +58,7 @@ static const char *_max_user_namespaces = "/proc/sys/user/max_user_namespaces"; static const char *_unprivileged_user_namespaces = "/proc/sys/kernel/unprivileged_userns_clone"; static int open_files_max_fd; -fd_set open_files_set; +static fd_set *open_files_set; static uid_t rootless_uid_init; static gid_t rootless_gid_init; @@ -108,10 +108,9 @@ do_pause () } static char ** -get_cmd_line_args (pid_t pid) +get_cmd_line_args () { int fd; - char path[PATH_MAX]; char *buffer; size_t allocated; size_t used = 0; @@ -119,11 +118,7 @@ get_cmd_line_args (pid_t pid) int i, argc = 0; char **argv; - if (pid) - sprintf (path, "/proc/%d/cmdline", pid); - else - strcpy (path, "/proc/self/cmdline"); - fd = open (path, O_RDONLY); + fd = open ("/proc/self/cmdline", O_RDONLY); if (fd < 0) return NULL; @@ -196,10 +191,13 @@ can_use_shortcut () return false; #endif - argv = get_cmd_line_args (0); + argv = get_cmd_line_args (); if (argv == NULL) return false; + if (strstr (argv[0], "podman") == NULL) + return false; + for (argc = 0; argv[argc]; argc++) { if (argc == 0 || argv[argc][0] == '-') @@ -237,17 +235,39 @@ static void __attribute__((constructor)) init() if (d) { struct dirent *ent; + size_t size = 0; - FD_ZERO (&open_files_set); for (ent = readdir (d); ent; ent = readdir (d)) { - int fd = atoi (ent->d_name); - if (fd != dirfd (d)) + int fd; + + if (ent->d_name[0] == '.') + continue; + + fd = atoi (ent->d_name); + if (fd == dirfd (d)) + continue; + + if (fd >= size * FD_SETSIZE) { - if (fd > open_files_max_fd) - open_files_max_fd = fd; - FD_SET (fd, &open_files_set); + int i; + size_t new_size; + + new_size = (fd / FD_SETSIZE) + 1; + open_files_set = realloc (open_files_set, new_size * sizeof (fd_set)); + if (open_files_set == NULL) + _exit (EXIT_FAILURE); + + for (i = size; i < new_size; i++) + FD_ZERO (&(open_files_set[i])); + + size = new_size; } + + if (fd > open_files_max_fd) + open_files_max_fd = fd; + + FD_SET (fd % FD_SETSIZE, &(open_files_set[fd / FD_SETSIZE])); } closedir (d); } @@ -517,7 +537,6 @@ create_pause_process (const char *pause_pid_file_path, char **argv) int reexec_userns_join (int userns, int mountns, char *pause_pid_file_path) { - pid_t ppid = getpid (); char uid[16]; char gid[16]; char **argv; @@ -534,7 +553,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); + argv = get_cmd_line_args (); if (argv == NULL) { fprintf (stderr, "cannot read argv: %s\n", strerror (errno)); @@ -550,10 +569,8 @@ reexec_userns_join (int userns, int mountns, char *pause_pid_file_path) /* We passed down these fds, close them. */ int f; for (f = 3; f < open_files_max_fd; f++) - { - if (FD_ISSET (f, &open_files_set)) - close (f); - } + if (open_files_set == NULL || FD_ISSET (f % FD_SETSIZE, &(open_files_set[f / FD_SETSIZE]))) + close (f); return pid; } @@ -701,7 +718,6 @@ reexec_in_user_namespace (int ready, char *pause_pid_file_path, char *file_to_re int ret; pid_t pid; char b; - pid_t ppid = getpid (); char **argv; char uid[16]; char gid[16]; @@ -744,10 +760,11 @@ reexec_in_user_namespace (int ready, char *pause_pid_file_path, char *file_to_re num_fds = strtol (listen_fds, NULL, 10); if (num_fds != LONG_MIN && num_fds != LONG_MAX) { - long i; - for (i = 3; i < num_fds + 3; i++) - if (FD_ISSET (i, &open_files_set)) - close (i); + int f; + + for (f = 3; f < num_fds + 3; f++) + if (open_files_set == NULL || FD_ISSET (f % FD_SETSIZE, &(open_files_set[f / FD_SETSIZE]))) + close (f); } unsetenv ("LISTEN_PID"); unsetenv ("LISTEN_FDS"); @@ -777,7 +794,7 @@ reexec_in_user_namespace (int ready, char *pause_pid_file_path, char *file_to_re _exit (EXIT_FAILURE); } - argv = get_cmd_line_args (ppid); + argv = get_cmd_line_args (); if (argv == NULL) { fprintf (stderr, "cannot read argv: %s\n", strerror (errno)); diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go index 182a39f6b..5ddfab7ad 100644 --- a/pkg/rootless/rootless_linux.go +++ b/pkg/rootless/rootless_linux.go @@ -452,6 +452,7 @@ func TryJoinFromFilePaths(pausePidPath string, needNewNamespace bool, paths []st var lastErr error var pausePid int + foundProcess := false for _, path := range paths { if !needNewNamespace { @@ -502,12 +503,16 @@ func TryJoinFromFilePaths(pausePidPath string, needNewNamespace bool, paths []st } pausePid, err = strconv.Atoi(string(b[:n])) - if err == nil { + if err == nil && unix.Kill(pausePid, 0) == nil { + foundProcess = true lastErr = nil break } } } + if !foundProcess && pausePidPath != "" { + return BecomeRootInUserNS(pausePidPath) + } if lastErr != nil { return false, 0, lastErr } |