free(opts.uidmap);
free(opts.gidmap);
free(opts.annotations);
+ free(opts.extroot);
+ free(opts.overlaydir);
free_hooklist(opts.hooks.createRuntime);
free_hooklist(opts.hooks.createContainer);
free_hooklist(opts.hooks.startContainer);
ERROR("sysctl: can't open %s\n", fname);
return errno;
}
- write(f, (*cur)->value, strlen((*cur)->value));
+ if (write(f, (*cur)->value, strlen((*cur)->value)) < 0) {
+ ERROR("sysctl: write to %s\n", fname);
+ return errno;
+ }
free(fname);
close(f);
}
/* Dev symbolic links as defined in OCI spec */
- symlink("/dev/pts/ptmx", "/dev/ptmx");
- symlink("/proc/self/fd", "/dev/fd");
- symlink("/proc/self/fd/0", "/dev/stdin");
- symlink("/proc/self/fd/1", "/dev/stdout");
- symlink("/proc/self/fd/2", "/dev/stderr");
+ (void) symlink("/dev/pts/ptmx", "/dev/ptmx");
+ (void) symlink("/proc/self/fd", "/dev/fd");
+ (void) symlink("/proc/self/fd/0", "/dev/stdin");
+ (void) symlink("/proc/self/fd/1", "/dev/stdout");
+ (void) symlink("/proc/self/fd/2", "/dev/stderr");
return 0;
}
static int build_jail_fs(void)
{
char *overlaydir = NULL;
+ int ret;
old_umask = umask(0);
if (opts.overlaydir)
overlaydir = opts.overlaydir;
- if (overlaydir)
- mount_overlay(jail_root, overlaydir);
+ if (overlaydir) {
+ ret = mount_overlay(jail_root, overlaydir);
+ if (ret)
+ return ret;
+ }
if (chdir(jail_root)) {
ERROR("chdir(%s) (jail_root) failed: %m\n", jail_root);
create_dev_console(jail_root);
/* make sure /etc/resolv.conf exists if in new network namespace */
- if (opts.namespace & CLONE_NEWNET) {
+ if (!opts.extroot && opts.namespace & CLONE_NEWNET) {
char jailetc[PATH_MAX], jaillink[PATH_MAX];
snprintf(jailetc, PATH_MAX, "%s/etc", jail_root);
if (overlaydir)
unlink(jaillink);
- symlink("../dev/resolv.conf.d/resolv.conf.auto", jaillink);
+ (void) symlink("../dev/resolv.conf.d/resolv.conf.auto", jaillink);
}
run_hooks(opts.hooks.createContainer, enter_jail_fs);
return 0;
}
-#define MAX_ENVP 16
+#define MAX_ENVP 64
static char** build_envp(const char *seccomp, char **ocienvp)
{
static char *envp[MAX_ENVP];
static int parseOCIroot(const char *jsonfile, struct blob_attr *msg)
{
- static char extroot[PATH_MAX] = { 0 };
+ char extroot[PATH_MAX] = { 0 };
struct blob_attr *tb[__OCI_ROOT_MAX];
char *cur;
char *root_path;
strncat(extroot, root_path, PATH_MAX - (strlen(extroot) + 1));
- opts.extroot = extroot;
+ /* follow symbolic link(s) */
+ opts.extroot = realpath(extroot, NULL);
+ if (!opts.extroot)
+ return errno;
if (tb[OCI_ROOT_READONLY])
opts.ronly = blobmsg_get_bool(tb[OCI_ROOT_READONLY]);
return 0;
}
+static int checkpath(const char *path)
+{
+ int dirfd = open(path, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
+ if (dirfd == -1) {
+ ERROR("path %s open failed %m\n", path);
+ return -1;
+ }
+ close(dirfd);
+
+ return 0;
+}
+
static struct ubus_method container_methods[] = {
UBUS_METHOD_NOARG("start", handle_start),
UBUS_METHOD_NOARG("state", handle_state),
opts.namespace |= CLONE_NEWCGROUP;
break;
case 'R':
- opts.extroot = optarg;
+ opts.extroot = realpath(optarg, NULL);
break;
case 's':
opts.namespace |= CLONE_NEWNS;
opts.group = optarg;
break;
case 'O':
- opts.overlaydir = optarg;
+ opts.overlaydir = realpath(optarg, NULL);
break;
case 'T':
opts.tmpoverlaysize = optarg;
goto errout;
}
+ if (opts.extroot && checkpath(opts.extroot)) {
+ ERROR("invalid rootfs path '%s'", opts.extroot);
+ ret=-1;
+ goto errout;
+ }
+
+ if (opts.overlaydir && checkpath(opts.overlaydir)) {
+ ERROR("invalid rootfs overlay path '%s'", opts.overlaydir);
+ ret=-1;
+ goto errout;
+ }
+
/* no <binary> param found */
if (!opts.ocibundle && (argc - optind < 1)) {
usage();
ERROR("prctl(PR_SET_SECUREBITS) failed: %m\n");
free_and_exit(EXIT_FAILURE);
}
- seteuid(opts.root_map_uid);
+ if (seteuid(opts.root_map_uid)) {
+ ERROR("seteuid(%d) failed: %m\n", opts.root_map_uid);
+ free_and_exit(EXIT_FAILURE);
+ }
}
jail_process.pid = clone(exec_jail, child_stack + STACK_SIZE, SIGCHLD | (opts.namespace & (~CLONE_NEWCGROUP)), NULL);
uloop_process_add(&jail_process);
jail_running = 1;
- seteuid(0);
+ if (seteuid(0)) {
+ ERROR("seteuid(%d) failed: %m\n", opts.root_map_uid);
+ free_and_exit(EXIT_FAILURE);
+ }
+
prctl(PR_SET_SECUREBITS, 0);
if (pidns_fd != -1) {