static int do_child(void *vargv) { char **argv = (char **)vargv; // Assume we want to become root if (setgid(0) < 0) { perror("setgid"); return -1; } if (setuid(0) < 0) { perror("setuid"); return -1; } if (setgroups(0, NULL) < 0) { perror("setgroups"); return -1; } if (unshare(CLONE_NEWNS) < 0) { perror("unshare CLONE_NEWNS"); return -1; } if (detect_shared_rootfs()) { if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) { printf("Failed to make / rslave"); return -1; } } execvp(argv[0], argv); perror("execvpe"); return -1; }
static int do_child(void *vargv) { int ret; char **argv = (char **)vargv; /* Assume we want to become root */ if (!lxc_switch_uid_gid(0, 0)) return -1; if (!lxc_setgroups(0, NULL)) return -1; ret = unshare(CLONE_NEWNS); if (ret < 0) { CMD_SYSERROR("Failed to unshare mount namespace"); return -1; } if (detect_shared_rootfs()) { ret = mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL); if (ret < 0) { CMD_SYSINFO("Failed to make \"/\" rslave"); return -1; } } execvp(argv[0], argv); CMD_SYSERROR("Failed to execute \"%s\"", argv[0]); return -1; }
static int lxc_attach_remount_sys_proc(void) { int ret; ret = unshare(CLONE_NEWNS); if (ret < 0) { SYSERROR("failed to unshare mount namespace"); return -1; } if (detect_shared_rootfs()) { if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) { SYSERROR("Failed to make / rslave"); ERROR("Continuing..."); } } /* assume /proc is always mounted, so remount it */ ret = umount2("/proc", MNT_DETACH); if (ret < 0) { SYSERROR("failed to unmount /proc"); return -1; } ret = mount("none", "/proc", "proc", 0, NULL); if (ret < 0) { SYSERROR("failed to remount /proc"); return -1; } /* try to umount /sys - if it's not a mount point, * we'll get EINVAL, then we ignore it because it * may not have been mounted in the first place */ ret = umount2("/sys", MNT_DETACH); if (ret < 0 && errno != EINVAL) { SYSERROR("failed to unmount /sys"); return -1; } else if (ret == 0) { /* remount it */ ret = mount("none", "/sys", "sysfs", 0, NULL); if (ret < 0) { SYSERROR("failed to remount /sys"); return -1; } } return 0; }
/* * Given a lxc_storage (presumably blockdev-based), detect the fstype * by trying mounting (in a private mntns) it. * @lxc_storage: bdev to investigate * @type: preallocated char* in which to write the fstype * @len: length of passed in char* * Returns length of fstype, of -1 on error */ int detect_fs(struct lxc_storage *bdev, char *type, int len) { int ret; int p[2]; size_t linelen; pid_t pid; FILE *f; char *sp1, *sp2, *sp3; const char *l, *srcdev; char devpath[PATH_MAX]; char *line = NULL; if (!bdev || !bdev->src || !bdev->dest) return -1; srcdev = lxc_storage_get_path(bdev->src, bdev->type); ret = pipe(p); if (ret < 0) { SYSERROR("Failed to create pipe"); return -1; } pid = fork(); if (pid < 0) { SYSERROR("Failed to fork process"); return -1; } if (pid > 0) { int status; close(p[1]); memset(type, 0, len); ret = read(p[0], type, len - 1); if (ret < 0) { SYSERROR("Failed to read FSType from pipe"); } else if (ret == 0) { ERROR("FSType not found - child exited early"); ret = -1; } close(p[0]); wait(&status); if (ret < 0) return ret; type[len - 1] = '\0'; INFO("Detected FSType \"%s\" for \"%s\"", type, srcdev); return ret; } if (unshare(CLONE_NEWNS) < 0) _exit(EXIT_FAILURE); if (detect_shared_rootfs()) if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL)) { SYSERROR("Failed to make / rslave"); ERROR("Continuing..."); } ret = mount_unknown_fs(srcdev, bdev->dest, bdev->mntopts); if (ret < 0) { ERROR("Failed to mount \"%s\" onto \"%s\" to detect FSType", srcdev, bdev->dest); _exit(EXIT_FAILURE); } l = linkderef(srcdev, devpath); if (!l) _exit(EXIT_FAILURE); f = fopen("/proc/self/mounts", "r"); if (!f) _exit(EXIT_FAILURE); while (getline(&line, &linelen, f) != -1) { sp1 = strchr(line, ' '); if (!sp1) _exit(EXIT_FAILURE); *sp1 = '\0'; if (strcmp(line, l)) continue; sp2 = strchr(sp1 + 1, ' '); if (!sp2) _exit(EXIT_FAILURE); *sp2 = '\0'; sp3 = strchr(sp2 + 1, ' '); if (!sp3) _exit(EXIT_FAILURE); *sp3 = '\0'; sp2++; if (write(p[1], sp2, strlen(sp2)) != strlen(sp2)) _exit(EXIT_FAILURE); _exit(EXIT_SUCCESS); } _exit(EXIT_FAILURE); }
/* * Given a lxc_storage (presumably blockdev-based), detect the fstype * by trying mounting (in a private mntns) it. * @lxc_storage: bdev to investigate * @type: preallocated char* in which to write the fstype * @len: length of passed in char* * Returns length of fstype, of -1 on error */ int detect_fs(struct lxc_storage *bdev, char *type, int len) { int ret; int p[2]; size_t linelen; pid_t pid; FILE *f; char *sp1, *sp2, *sp3; const char *l, *srcdev; char devpath[PATH_MAX]; char *line = NULL; if (!bdev || !bdev->src || !bdev->dest) return -1; srcdev = lxc_storage_get_path(bdev->src, bdev->type); ret = pipe(p); if (ret < 0) return -1; if ((pid = fork()) < 0) return -1; if (pid > 0) { int status; close(p[1]); memset(type, 0, len); ret = read(p[0], type, len - 1); close(p[0]); if (ret < 0) { SYSERROR("error reading from pipe"); wait(&status); return -1; } else if (ret == 0) { ERROR("child exited early - fstype not found"); wait(&status); return -1; } wait(&status); type[len - 1] = '\0'; INFO("detected fstype %s for %s", type, srcdev); return ret; } if (unshare(CLONE_NEWNS) < 0) exit(1); if (detect_shared_rootfs()) { if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL)) { SYSERROR("Failed to make / rslave"); ERROR("Continuing..."); } } ret = mount_unknown_fs(srcdev, bdev->dest, bdev->mntopts); if (ret < 0) { ERROR("failed mounting %s onto %s to detect fstype", srcdev, bdev->dest); exit(1); } l = linkderef(srcdev, devpath); if (!l) exit(1); f = fopen("/proc/self/mounts", "r"); if (!f) exit(1); while (getline(&line, &linelen, f) != -1) { sp1 = strchr(line, ' '); if (!sp1) exit(1); *sp1 = '\0'; if (strcmp(line, l)) continue; sp2 = strchr(sp1 + 1, ' '); if (!sp2) exit(1); *sp2 = '\0'; sp3 = strchr(sp2 + 1, ' '); if (!sp3) exit(1); *sp3 = '\0'; sp2++; if (write(p[1], sp2, strlen(sp2)) != strlen(sp2)) exit(1); exit(0); } exit(1); }