static int container_setup_dns(struct hyper_container *container) { int fd; struct stat st; char *src = "/.oldroot/tmp/hyper/resolv.conf"; if (stat(src, &st) < 0) { if (errno == ENOENT) { fprintf(stdout, "no dns configured\n"); return 0; } perror("stat resolve.conf failed"); return -1; } hyper_mkdir("/etc"); fd = open("/etc/resolv.conf", O_CREAT| O_WRONLY, 0644); if (fd < 0) { perror("create /etc/resolv.conf failed"); return -1; } close(fd); if (mount(src, "/etc/resolv.conf", NULL, MS_BIND, NULL) < 0) { perror("bind to /etc/resolv.conf failed"); return -1; } return 0; }
static int container_setup_volume(struct hyper_container *container) { int i; char dev[512], path[512]; struct volume *vol; for (i = 0; i < container->vols_num; i++) { vol = &container->vols[i]; sprintf(dev, "/.oldroot/dev/%s", vol->device); sprintf(path, "/tmp/%s", vol->mountpoint); fprintf(stdout, "mount %s to %s, tmp path %s\n", dev, vol->mountpoint, path); if (hyper_mkdir(path) < 0 || hyper_mkdir(vol->mountpoint) < 0) { perror("create volume dir failed"); return -1; } if (mount(dev, path, vol->fstype, 0, NULL) < 0) { perror("mount volume device faled"); return -1; } if (mount(path, vol->mountpoint, NULL, MS_BIND, NULL) < 0) { perror("mount volume device faled"); return -1; } if (vol->readonly && mount(path, vol->mountpoint, NULL, MS_BIND | MS_REMOUNT | MS_RDONLY, NULL) < 0) { perror("mount fsmap faled"); return -1; } umount(path); } return 0; }
int hyper_mkdir(char *hyper_path, mode_t mode) { struct stat st; char *p, *path = strdup(hyper_path); if (path == NULL) { errno = ENOMEM; goto fail; } if (stat(path, &st) >= 0) { if (S_ISDIR(st.st_mode)) goto out; errno = ENOTDIR; goto fail; } if (errno != ENOENT) goto fail; p = strrchr(path, '/'); if (p == NULL) { errno = EINVAL; goto fail; } if (p != path) { *p = '\0'; if (hyper_mkdir(path, mode) < 0) goto fail; *p = '/'; } fprintf(stdout, "create directory %s\n", path); if (mkdir(path, mode) < 0 && errno != EEXIST) { perror("failed to create directory"); goto fail; } out: free(path); return 0; fail: free(path); return -1; }
static int hyper_create_parent_dir(const char *hyper_path) { char *p, *path = strdup(hyper_path); int ret = 0; if (path == NULL) return -1; p = strrchr(path, '/'); if (p != NULL && p != path) { *p = '\0'; ret = hyper_mkdir(path, 0777); } free(path); return ret; }
static int hyper_setup_pty(struct hyper_container *c) { char root[512]; sprintf(root, "/tmp/hyper/%s/devpts/", c->id); if (hyper_mkdir(root) < 0) { perror("make container pts directroy failed"); return -1; } if (mount("devpts", root, "devpts", MS_NOSUID, "newinstance,ptmxmode=0666,mode=0620") < 0) { perror("mount devpts failed"); return -1; } if (hyper_setup_exec_tty(&c->exec) < 0) { fprintf(stderr, "setup container pts failed\n"); return -1; } return 0; }
static int container_setup_mount(struct hyper_container *container) { int i, fd; char src[512]; struct fsmap *map; hyper_mkdir("/proc"); hyper_mkdir("/sys"); hyper_mkdir("/dev"); if (mount("proc", "/proc", "proc", MS_NOSUID| MS_NODEV| MS_NOEXEC, NULL) < 0 || mount("sysfs", "/sys", "sysfs", MS_NOSUID| MS_NODEV| MS_NOEXEC, NULL) < 0 || mount("devtmpfs", "/dev", "devtmpfs", MS_NOSUID, NULL) < 0) { perror("mount basic filesystem for container failed"); return -1; } if (hyper_mkdir("/dev/shm") < 0) { fprintf(stderr, "create /dev/shm failed\n"); return -1; } if (mount("tmpfs", "/dev/shm/", "tmpfs", MS_NOSUID| MS_NODEV, NULL) < 0) { perror("mount shm failed"); return -1; } if (hyper_mkdir("/dev/pts") < 0) { fprintf(stderr, "create /dev/pts failed\n"); return -1; } if (sprintf(src, "/.oldroot/tmp/hyper/%s/devpts", container->id) < 0) { fprintf(stderr, "get container devpts failed\n"); return -1; } if (mount(src, "/dev/pts/", NULL, MS_BIND, NULL) < 0) { perror("move pts to /dev/pts failed"); return -1; } if (unlink("/dev/ptmx") < 0) perror("remove /dev/ptmx failed"); if (symlink("/dev/pts/ptmx", "/dev/ptmx") < 0) perror("link /dev/pts/ptmx to /dev/ptmx failed"); for (i = 0; i < container->maps_num; i++) { struct stat st; map = &container->maps[i]; sprintf(src, "/.oldroot/tmp/hyper/shared/%s", map->source); fprintf(stdout, "mount %s to %s\n", src, map->path); stat(src, &st); if (st.st_mode & S_IFDIR) { if (hyper_mkdir(map->path) < 0) { perror("create map dir failed"); continue; } } else { fd = open(map->path, O_CREAT|O_WRONLY, 0755); if (fd < 0) { perror("create map file failed"); continue; } close(fd); } if (mount(src, map->path, NULL, MS_BIND, NULL) < 0) { perror("mount fsmap faled"); continue; } if (map->readonly == 0) continue; if (mount(src, map->path, NULL, MS_BIND | MS_REMOUNT | MS_RDONLY, NULL) < 0) perror("mount fsmap faled"); } return 0; }
static int hyper_container_init(void *data) { struct hyper_container_arg *arg = data; struct hyper_container *container = arg->c; char root[512], oldroot[512]; fprintf(stdout, "%s in\n", __func__); if (container->exec.argv == NULL) { fprintf(stdout, "no cmd!\n"); goto fail; } if (setns(arg->ipcns, CLONE_NEWIPC) < 0) { perror("setns to ipcns of pod init faild"); goto fail; } if (setns(arg->utsns, CLONE_NEWUTS) < 0) { perror("setns to ipcns of pod init faild"); goto fail; } if (hyper_rescan_scsi() < 0) { fprintf(stdout, "rescan scsi failed\n"); goto fail; } if (hyper_setup_env(container->envs, container->envs_num) < 0) { fprintf(stdout, "setup env failed\n"); goto fail; } if (mount("", "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) { perror("mount SLAVE failed"); goto fail; } if (mount("", "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0) { perror("mount PRIVATE failed"); goto fail; } sprintf(root, "/tmp/hyper/%s/root/", container->id); if (hyper_mkdir(root) < 0) { perror("make root directroy failed"); goto fail; } fprintf(stdout, "container root directory %s\n", root); if (container->fstype) { char dev[128]; sprintf(dev, "/dev/%s", container->image); fprintf(stdout, "device %s\n", dev); if (mount(dev, root, container->fstype, 0, NULL) < 0) { perror("mount device failed"); goto fail; } } else { char path[512]; sprintf(path, "/tmp/hyper/shared/%s/", container->image); fprintf(stdout, "src directory %s\n", path); if (mount(path, root, NULL, MS_BIND, NULL) < 0) { perror("mount src dir failed"); goto fail; } } fprintf(stdout, "root directory for container is %s/%s, init task %s\n", root, container->rootfs, container->exec.argv[0]); sprintf(oldroot, "%s/%s/.oldroot", root, container->rootfs); if (hyper_mkdir(oldroot) < 0) { perror("make oldroot directroy failed"); goto fail; } if (mount("/", oldroot, NULL, MS_BIND|MS_REC, NULL) < 0) { perror("bind oldroot failed"); goto fail; } /* reuse oldroot array */ sprintf(oldroot, "%s/%s/", root, container->rootfs); /* pivot_root won't work, see * Documention/filesystem/ramfs-rootfs-initramfs.txt */ chroot(oldroot); chdir("/"); if (container_setup_volume(container) < 0) { fprintf(stderr, "container sets up voulme failed\n"); goto fail; } if (container_setup_mount(container) < 0) { fprintf(stderr, "container sets up mount failed\n"); goto fail; } if (container_setup_sysctl(container) < 0) { fprintf(stderr, "container sets up sysctl failed\n"); goto fail; } if (container_setup_dns(container) < 0) { fprintf(stderr, "container sets up dns failed\n"); goto fail; } if (container_setup_workdir(container) < 0) { fprintf(stderr, "container sets up work directory failed\n"); goto fail; } container_unmount_oldroot("/.oldroot"); fflush(stdout); if (container_setup_tty(arg->pipe[1], container) < 0) { fprintf(stdout, "setup tty failed\n"); goto fail; } 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"); execvp(container->exec.argv[0], container->exec.argv); perror("exec container command failed"); _exit(-1); fail: hyper_send_type(arg->pipe[1], ERROR); _exit(-1); }
static int hyper_container_init(void *data) { struct hyper_container_arg *arg = data; struct hyper_container *container = arg->c; char root[512], oldroot[512]; fprintf(stdout, "%s in\n", __func__); if (container->exec.argv == NULL) { fprintf(stdout, "no cmd!\n"); goto fail; } if (hyper_rescan_scsi() < 0) { fprintf(stdout, "rescan scsi failed\n"); goto fail; } if (container_setup_env(container) < 0) { fprintf(stdout, "setup env failed\n"); goto fail; } if (mount("", "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) { perror("mount SLAVE failed"); goto fail; } if (mount("", "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0) { perror("mount PRIVATE failed"); goto fail; } sprintf(root, "/tmp/hyper/%s/root/", container->id); if (hyper_mkdir(root) < 0) { perror("make root directroy failed"); goto fail; } fprintf(stdout, "container root directory %s\n", root); if (container->fstype) { char dev[128]; sprintf(dev, "/dev/%s", container->image); fprintf(stdout, "device %s\n", dev); if (mount(dev, root, container->fstype, 0, NULL) < 0) { perror("mount device failed"); goto fail; } } else { char path[512]; sprintf(path, "/tmp/hyper/shared/%s/", container->image); fprintf(stdout, "src directory %s\n", path); if (mount(path, root, NULL, MS_BIND, NULL) < 0) { perror("mount src dir failed"); goto fail; } } fprintf(stdout, "root directory for container is %s/%s, init task %s\n", root, container->rootfs, container->exec.argv[0]); hyper_list_dir(root); sprintf(oldroot, "%s/%s/.oldroot", root, container->rootfs); if (hyper_mkdir(oldroot) < 0) { perror("make oldroot directroy failed"); goto fail; } if (mount("/", oldroot, NULL, MS_BIND|MS_REC, NULL) < 0) { perror("bind oldroot failed"); goto fail; } /* reuse oldroot array */ sprintf(oldroot, "%s/%s/", root, container->rootfs); /* pivot_root won't work, see * Documention/filesystem/ramfs-rootfs-initramfs.txt */ chroot(oldroot); chdir("/"); if (container_setup_volume(container) < 0) { fprintf(stderr, "container sets up voulme failed\n"); goto fail; } if (container_setup_mount(container) < 0) { fprintf(stderr, "container sets up mount ns failed\n"); goto fail; } if (container_setup_workdir(container) < 0) { fprintf(stderr, "container sets up work directory failed\n"); goto fail; } container_unmount_oldroot("/.oldroot"); fflush(stdout); if (container_setup_tty(arg->pipe[1], container) < 0) { fprintf(stdout, "setup tty failed\n"); goto fail; } close(arg->pipe[0]); close(arg->pipe[1]); execvp(container->exec.argv[0], container->exec.argv); _exit(-1); fail: container->exec.code = -1; hyper_send_type_block(arg->pipe[1], ERROR, 0); _exit(-1); }