diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/rootless/rootless_linux.c | 92 | ||||
-rw-r--r-- | pkg/spec/createconfig.go | 13 |
2 files changed, 92 insertions, 13 deletions
diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c index d78d95453..9eb16c1a5 100644 --- a/pkg/rootless/rootless_linux.c +++ b/pkg/rootless/rootless_linux.c @@ -11,6 +11,22 @@ #include <signal.h> #include <fcntl.h> #include <sys/wait.h> +#include <string.h> + +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 +syscall_setresuid (uid_t ruid, uid_t euid, uid_t suid) +{ + return (int) syscall (__NR_setresuid, ruid, euid, suid); +} + +static int +syscall_setresgid (gid_t rgid, gid_t egid, gid_t sgid) +{ + return (int) syscall (__NR_setresgid, rgid, egid, sgid); +} static int syscall_clone (unsigned long flags, void *child_stack) @@ -94,9 +110,14 @@ reexec_userns_join (int userns) argv = get_cmd_line_args (ppid); if (argv == NULL) - _exit (EXIT_FAILURE); + { + fprintf (stderr, "cannot read argv: %s\n", strerror (errno)); + _exit (EXIT_FAILURE); + } pid = fork (); + if (pid < 0) + fprintf (stderr, "cannot fork: %s\n", strerror (errno)); if (pid) return pid; @@ -104,18 +125,48 @@ reexec_userns_join (int userns) setenv ("_LIBPOD_ROOTLESS_UID", uid, 1); if (setns (userns, 0) < 0) - _exit (EXIT_FAILURE); + { + fprintf (stderr, "cannot setns: %s\n", strerror (errno)); + _exit (EXIT_FAILURE); + } close (userns); - if (setresgid (0, 0, 0) < 0 || - setresuid (0, 0, 0) < 0) - _exit (EXIT_FAILURE); + if (syscall_setresgid (0, 0, 0) < 0) + { + fprintf (stderr, "cannot setresgid: %s\n", strerror (errno)); + _exit (EXIT_FAILURE); + } + + if (syscall_setresuid (0, 0, 0) < 0) + { + fprintf (stderr, "cannot setresuid: %s\n", strerror (errno)); + _exit (EXIT_FAILURE); + } execvp (argv[0], argv); _exit (EXIT_FAILURE); } +static void +check_proc_sys_userns_file (const char *path) +{ + FILE *fp; + fp = fopen (path, "r"); + if (fp) + { + char buf[32]; + size_t n_read = fread (buf, 1, sizeof(buf) - 1, fp); + if (n_read > 0) + { + buf[n_read] = '\0'; + if (strtol (buf, NULL, 10) == 0) + fprintf (stderr, "user namespaces are not enabled in %s\n", path); + } + fclose (fp); + } +} + int reexec_in_user_namespace (int ready) { @@ -129,12 +180,22 @@ reexec_in_user_namespace (int ready) sprintf (uid, "%d", geteuid ()); pid = syscall_clone (CLONE_NEWUSER|CLONE_NEWNS|SIGCHLD, NULL); + if (pid < 0) + { + FILE *fp; + fprintf (stderr, "cannot clone: %s\n", strerror (errno)); + check_proc_sys_userns_file (_max_user_namespaces); + check_proc_sys_userns_file (_unprivileged_user_namespaces); + } if (pid) return pid; argv = get_cmd_line_args (ppid); if (argv == NULL) - _exit (EXIT_FAILURE); + { + fprintf (stderr, "cannot read argv: %s\n", strerror (errno)); + _exit (EXIT_FAILURE); + } setenv ("_LIBPOD_USERNS_CONFIGURED", "init", 1); setenv ("_LIBPOD_ROOTLESS_UID", uid, 1); @@ -143,12 +204,23 @@ reexec_in_user_namespace (int ready) ret = read (ready, &b, 1) < 0; while (ret < 0 && errno == EINTR); if (ret < 0) - _exit (EXIT_FAILURE); + { + fprintf (stderr, "cannot read from sync pipe: %s\n", strerror (errno)); + _exit (EXIT_FAILURE); + } close (ready); - if (setresgid (0, 0, 0) < 0 || - setresuid (0, 0, 0) < 0) - _exit (EXIT_FAILURE); + if (syscall_setresgid (0, 0, 0) < 0) + { + fprintf (stderr, "cannot setresgid: %s\n", strerror (errno)); + _exit (EXIT_FAILURE); + } + + if (syscall_setresuid (0, 0, 0) < 0) + { + fprintf (stderr, "cannot setresuid: %s\n", strerror (errno)); + _exit (EXIT_FAILURE); + } execvp (argv[0], argv); diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index 9e8f6253b..d34b21189 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -2,6 +2,7 @@ package createconfig import ( "encoding/json" + "net" "os" "strconv" "strings" @@ -315,9 +316,6 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime) ([]lib var pod *libpod.Pod var err error - // Uncomment after talking to mheon about unimplemented funcs - // options = append(options, libpod.WithLabels(c.labels)) - if c.Interactive { options = append(options, libpod.WithStdin()) } @@ -446,6 +444,15 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime) ([]lib if logPath != "" { options = append(options, libpod.WithLogPath(logPath)) } + if c.IPAddress != "" { + ip := net.ParseIP(c.IPAddress) + if ip == nil { + return nil, errors.Wrapf(libpod.ErrInvalidArg, "cannot parse %s as IP address", c.IPAddress) + } else if ip.To4() == nil { + return nil, errors.Wrapf(libpod.ErrInvalidArg, "%s is not an IPv4 address", c.IPAddress) + } + options = append(options, libpod.WithStaticIP(ip)) + } options = append(options, libpod.WithPrivileged(c.Privileged)) |