static int set_ct_root(struct container *ct) { char put_root[] = "libct-root.XXXXXX"; if (!(ct->nsmask & CLONE_NEWNS)) return set_current_root(ct->root_path); /* * We're in new mount namespace. No need in * just going into chroot, do pivot root, that * gives us the ability to umount old tree. */ if (mount(ct->root_path, ct->root_path, NULL, MS_BIND | MS_REC, NULL) == -1) return -1; if (chdir(ct->root_path)) return -1; if (mkdtemp(put_root) == NULL) return -1; if (pivot_root(".", put_root)) { rmdir(put_root); return -1; } if (umount2(put_root, MNT_DETACH)) return -1; rmdir(put_root); return 0; }
static int pivot_to_new_root(void) { if (chdir("/run/initramfs") < 0) { log_error("Failed to change directory to /run/initramfs: %m"); return -errno; } /* Work-around for a kernel bug: for some reason the kernel * refuses switching root if any file systems are mounted * MS_SHARED. Hence remount them MS_PRIVATE here as a * work-around. * * https://bugzilla.redhat.com/show_bug.cgi?id=847418 */ if (mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL) < 0) log_warning("Failed to make \"/\" private mount: %m"); if (pivot_root(".", "oldroot") < 0) { log_error("pivot failed: %m"); /* only chroot if pivot root succeeded */ return -errno; } chroot("."); setsid(); make_console_stdio(); log_info("Successfully changed into root pivot."); return 0; }
static int pivot_to_new_root(void) { if (chdir("/run/initramfs") < 0) { log_error("Failed to change directory to /run/initramfs: %m"); return -errno; } /* In case some evil process made "/" MS_SHARED It works for pivot_root, but the ref count for the root device is not decreasing :-/ */ if (mount(NULL, "/", NULL, MS_PRIVATE, NULL) < 0) { log_error("Failed to make \"/\" private mount %m"); return -errno; } if (pivot_root(".", "oldroot") < 0) { log_error("pivot failed: %m"); /* only chroot if pivot root succeeded */ return -errno; } chroot("."); setsid(); make_console_stdio(); log_info("Successfully changed into root pivot."); return 0; }
int main(int argc, char **argv) { int ch; static const struct option longopts[] = { {"version", no_argument, NULL, 'V'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0} }; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); while ((ch = getopt_long(argc, argv, "Vh", longopts, NULL)) != -1) switch (ch) { case 'V': printf(UTIL_LINUX_VERSION); return EXIT_SUCCESS; case 'h': usage(stdout); default: usage(stderr); } if (argc != 3) usage(stderr); if (pivot_root(argv[1], argv[2]) < 0) err(EXIT_FAILURE, _("failed to change root from `%s' to `%s'"), argv[1], argv[2]); return EXIT_SUCCESS; }
void pivot() { char *pivot = jail_dir(".pivot_root"); // Bind root to itself so it becomes a pivotable mount. mount(new_root, new_root, "bind", MS_BIND | MS_REC, NULL); mkdir(pivot, S_IRWXU); check("pivot_root", pivot_root(new_root, pivot)); check("chdir_root", chdir("/")); check("umount_pivot_root", umount2("/.pivot_root", MNT_DETACH)); check("rmdir_pivot_root", rmdir("/.pivot_root")); };
int pivot_root_main(int argc, char **argv) { if (argc != 3) bb_show_usage(); if (pivot_root(argv[1],argv[2]) < 0) bb_perror_msg_and_die("pivot_root"); return EXIT_SUCCESS; }
int main(int argc, const char **argv) { if (argc != 3) { fprintf(stderr, "usage: %s new_root put_old\n", argv[0]); return 1; } if (pivot_root(argv[1], argv[2]) < 0) { perror("pivot_root"); return 1; } return 0; }
void syscall_helper(int argc, char **argv) { (void) argc; if (strcmp(argv[2], "mount") == 0) { int rv = mount(NULL, NULL, NULL, 0, NULL); (void) rv; printf("\nUGLY: mount syscall permitted.\n"); } else if (strcmp(argv[2], "umount2") == 0) { umount2(NULL, 0); printf("\nUGLY: umount2 syscall permitted.\n"); } else if (strcmp(argv[2], "ptrace") == 0) { ptrace(0, 0, NULL, NULL); printf("\nUGLY: ptrace syscall permitted.\n"); } else if (strcmp(argv[2], "swapon") == 0) { swapon(NULL, 0); printf("\nUGLY: swapon syscall permitted.\n"); } else if (strcmp(argv[2], "swapoff") == 0) { swapoff(NULL); printf("\nUGLY: swapoff syscall permitted.\n"); } else if (strcmp(argv[2], "init_module") == 0) { init_module(NULL, 0, NULL); printf("\nUGLY: init_module syscall permitted.\n"); } else if (strcmp(argv[2], "delete_module") == 0) { delete_module(NULL, 0); printf("\nUGLY: delete_module syscall permitted.\n"); } else if (strcmp(argv[2], "chroot") == 0) { int rv = chroot("/blablabla-57281292"); (void) rv; printf("\nUGLY: chroot syscall permitted.\n"); } else if (strcmp(argv[2], "pivot_root") == 0) { pivot_root(NULL, NULL); printf("\nUGLY: pivot_root syscall permitted.\n"); } #if defined(__i386__) || defined(__x86_64__) else if (strcmp(argv[2], "iopl") == 0) { iopl(0L); printf("\nUGLY: iopl syscall permitted.\n"); } else if (strcmp(argv[2], "ioperm") == 0) { ioperm(0, 0, 0); printf("\nUGLY: ioperm syscall permitted.\n"); } #endif exit(0); }
void do_pivot(setup_vals *s) { char * oldroot = safemalloc(sizeof(char) * (strlen(s->newroot) + 1 + strlen("oldroot") + 1)); strcpy(oldroot, s->newroot); strcat(oldroot, "/"); strcat(oldroot, "oldroot"); if(!dir_exists(oldroot)) mkdir(oldroot, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); pivot_root(s->newroot, oldroot); chdir("/"); }
int child_run(void *data) { wshd_t *w = (wshd_t *)data; int rv; char pivoted_lib_path[PATH_MAX]; size_t pivoted_lib_path_len; /* Wait for parent */ rv = barrier_wait(&w->barrier_parent); assert(rv == 0); rv = run(w->lib_path, "hook-child-before-pivot.sh"); assert(rv == 0); /* Prepare lib path for pivot */ strcpy(pivoted_lib_path, "/mnt"); pivoted_lib_path_len = strlen(pivoted_lib_path); realpath(w->lib_path, pivoted_lib_path + pivoted_lib_path_len); rv = chdir(w->root_path); if (rv == -1) { perror("chdir"); abort(); } rv = mkdir("mnt", 0700); if (rv == -1 && errno != EEXIST) { perror("mkdir"); abort(); } rv = pivot_root(".", "mnt"); if (rv == -1) { perror("pivot_root"); abort(); } rv = chdir("/"); if (rv == -1) { perror("chdir"); abort(); } rv = run(pivoted_lib_path, "hook-child-after-pivot.sh"); assert(rv == 0); child_save_to_shm(w); execl("/sbin/wshd", "/sbin/wshd", "--continue", NULL); perror("exec"); abort(); }
static int pivot_to_new_root(void) { int fd; chdir("/run/initramfs"); /* In case some evil process made "/" MS_SHARED It works for pivot_root, but the ref count for the root device is not decreasing :-/ */ if (mount(NULL, "/", NULL, MS_PRIVATE, NULL) < 0) { log_error("Failed to make \"/\" private mount %m"); return -errno; } if (pivot_root(".", "oldroot") < 0) { log_error("pivot failed: %m"); /* only chroot if pivot root succeded */ return -errno; } chroot("."); log_info("Successfully changed into root pivot."); fd = open("/dev/console", O_RDWR); if (fd < 0) log_error("Failed to open /dev/console: %m"); else { make_stdio(fd); /* Initialize the controlling terminal */ setsid(); ioctl(STDIN_FILENO, TIOCSCTTY, NULL); } return 0; }
/** * li_run_env_enter: * * Enter (pivot_root) a previously prepared application environment. * * Returns: %TRUE on success. */ gboolean li_run_env_enter (const gchar *newroot) { /* now move into the application's private environment */ chdir (newroot); if (pivot_root (newroot, ".oldroot") != 0) { g_printerr ("pivot_root failed: %s\n", strerror(errno)); return FALSE; } chdir ("/"); /* The old root better be rprivate or we will send unmount events to the parent namespace */ if (mount (".oldroot", ".oldroot", NULL, MS_REC | MS_PRIVATE, NULL) != 0) { g_printerr ("Failed to make old root rprivate: %s\n", strerror (errno)); return FALSE; } if (umount2 (".oldroot", MNT_DETACH)) { g_printerr ("unmount oldroot failed: %s\n", strerror (errno)); return FALSE; } return TRUE; }
static int lxcContainerPivotRoot(virDomainFSDefPtr root) { int rc, ret; char *oldroot = NULL, *newroot = NULL; ret = -1; /* root->parent must be private, so make / private. */ if (mount("", "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0) { virReportSystemError(errno, "%s", _("Failed to make root private")); goto err; } if (virAsprintf(&oldroot, "%s/.oldroot", root->src) < 0) { virReportOOMError(); goto err; } if ((rc = virFileMakePath(oldroot)) != 0) { virReportSystemError(rc, _("Failed to create %s"), oldroot); goto err; } /* Create a tmpfs root since old and new roots must be * on separate filesystems */ if (mount("tmprootfs", oldroot, "tmpfs", 0, NULL) < 0) { virReportSystemError(errno, _("Failed to mount empty tmpfs at %s"), oldroot); goto err; } /* Create a directory called 'new' in tmpfs */ if (virAsprintf(&newroot, "%s/new", oldroot) < 0) { virReportOOMError(); goto err; } if ((rc = virFileMakePath(newroot)) != 0) { virReportSystemError(rc, _("Failed to create %s"), newroot); goto err; } /* ... and mount our root onto it */ if (mount(root->src, newroot, NULL, MS_BIND|MS_REC, NULL) < 0) { virReportSystemError(errno, _("Failed to bind new root %s into tmpfs"), root->src); goto err; } /* Now we chroot into the tmpfs, then pivot into the * root->src bind-mounted onto '/new' */ if (chdir(newroot) < 0) { virReportSystemError(errno, _("Failed to chroot into %s"), newroot); goto err; } /* The old root directory will live at /.oldroot after * this and will soon be unmounted completely */ if (pivot_root(".", ".oldroot") < 0) { virReportSystemError(errno, "%s", _("Failed to pivot root")); goto err; } /* CWD is undefined after pivot_root, so go to / */ if (chdir("/") < 0) goto err; ret = 0; err: VIR_FREE(oldroot); VIR_FREE(newroot); return ret; }
void pivot_host(const gchar *guest) { g_autofree gchar *point = g_build_filename(guest, "host", NULL); fail_if(g_mkdir(point, 0755)); fail_if(pivot_root(guest, point)); }
int main(int argc, char **argv) { int x = 0; char *args[10]; setuid(2); signal(SIGCHLD, sigchld); do_signals(); x += getpid(); x += getppid(); x += getuid(); x += getgid(); x += setsid(); x += seteuid(); x += setegid(); lseek(0, 0, -1); kill(0, 0); signal(99, 0); signal(SIGINT, int_handler); signal(SIGSEGV, segv_handler); // *(int *) 0 = 0; pipe(0); munmap(0, 0); mincore(0, 0); shmget(0); shmat(0); line = __LINE__; poll(-1, 0, 0); signal(SIGSEGV, SIG_IGN); // ppoll(-1, -1, -1, 0); signal(SIGSEGV, SIG_DFL); sched_yield(); readv(-1, 0, 0, 0); writev(-1, 0, 0, 0); msync(0, 0, 0); fsync(-1); fdatasync(-1); semget(0, 0, 0); semctl(0, 0, 0); uselib(NULL); pivot_root(0, 0); personality(-1); setfsuid(-1); flock(-1, 0); shmdt(0, 0, 0); times(0); mremap(0, 0, 0, 0, 0); madvise(0, 0, 0); fchown(-1, 0, 0); lchown(0, 0, 0); setreuid(); setregid(); link("/nonexistant", "/also-nonexistant"); do_slow(); symlink("/nothing", "/"); rename("/", "/"); mkdir("/junk/stuff////0", 0777); geteuid(); getsid(); getpgid(); getresuid(); getresgid(); getpgid(); ptrace(-1, 0, 0, 0); semop(0, 0, 0); capget(0, 0); line = __LINE__; gettimeofday(0, 0); settimeofday(0, 0); dup(-1); dup2(-1, -1); shmctl(0, 0, 0, 0); execve("/bin/nothing", "/bin/nothing", 0); alarm(9999); bind(0, 0, 0); socket(0, 0, 0); accept(0, 0, 0); listen(0); shutdown(0); getsockname(0, 0, 0); getpeername(0, 0, 0); truncate(0, 0); ftruncate(0, 0); line = __LINE__; if (vfork() == 0) exit(0); line = __LINE__; x = opendir("/", 0, 0); line = __LINE__; readdir(x, 0, 0); line = __LINE__; closedir(x); line = __LINE__; chroot("/"); line = __LINE__; sigaction(0, 0, 0); line = __LINE__; sigprocmask(0, 0, 0); x += open("/nothing", 0); x += chdir("/nothing"); x += mknod("/nothing/nothing", 0); x += ioctl(); execve("/nothing", NULL, NULL); line = __LINE__; x += close(-2); line = __LINE__; if (fork() == 0) exit(0); line = __LINE__; clone(clone_func, 0, 0, 0); line = __LINE__; brk(0); sbrk(0); line = __LINE__; mmap(0, 0, 0, 0, 0); line = __LINE__; uname(0); line = __LINE__; getcwd(0, 0); line = __LINE__; iopl(3); ioperm(0, 0, 0); mount(0, 0, 0, 0, 0); umount(0, 0); umount(0, 0, 0); swapon(0, 0); swapoff(0); sethostname(0); line = __LINE__; time(NULL); unlink("/nothing"); line = __LINE__; rmdir("/nothing"); chmod(0, 0); line = __LINE__; # if defined(__i386) || defined(__amd64) modify_ldt(0); # endif stat("/doing-nice", 0); nice(0); args[0] = "/bin/df"; args[1] = "-l"; args[2] = NULL; close(1); open("/dev/null", O_WRONLY); /***********************************************/ /* Some syscalls arent available direct */ /* from libc, so get them here. We mostly */ /* care about the ones which have caused */ /* implementation difficulty and kernel */ /* crashes - eventually we can be complete. */ /***********************************************/ line = __LINE__; open("/system-dependent-syscalls-follow", 0); line = __LINE__; if (fork() == 0) exit(0); {int status; while (wait(&status) >= 0) ; } sigaltstack(0, 0); /*vm86(0, 0);*/ /***********************************************/ /* Some syscalls arent directly accessible, */ /* e.g. legacy. */ /***********************************************/ #if defined(__x86_64__) trace(__LINE__, "x64 syscalls"); syscall(174, 0, 0, 0); // create_module syscall(176, 0, 0, 0); // delete_module syscall(178, 0, 0, 0); // query_module #else trace(__LINE__, "x32 syscalls"); syscall(0, 0, 0, 0); // restart_syscall syscall(34, 0, 0, 0); // nice syscall(59, 0, 0, 0); // oldolduname syscall(109, 0, 0, 0); // olduname if (fork() == 0) syscall(1, 0, 0, 0); // exit #endif line = __LINE__; execve("/bin/df", args, NULL); fprintf(stderr, "Error: should not get here -- %s\n", strerror(errno)); exit(1); }
static int prepare_mntns() { int dfd; char *root; root = getenv("ZDTM_ROOT"); if (!root) { fprintf(stderr, "ZDTM_ROOT isn't set\n"); return -1; } dfd = open(".", O_RDONLY); if (dfd == -1) { fprintf(stderr, "open(.) failed: %m\n"); return -1; } if (chdir(root)) { fprintf(stderr, "chdir(%s) failed: %m\n", root); return -1; } if (mkdir("old", 0777) && errno != EEXIST) { fprintf(stderr, "mkdir(old) failed: %m\n"); return -1; } if (mount("none", "/", "none", MS_REC|MS_PRIVATE, NULL)) { fprintf(stderr, "Can't remount root with MS_PRIVATE: %m\n"); return -1; } if (pivot_root(".", "./old")) { fprintf(stderr, "pivot_root(., ./old) failed: %m\n"); return -1; } if (umount2("./old", MNT_DETACH)) { fprintf(stderr, "umount(./old) failed: %m\n"); return -1; } if (mkdir("proc", 0777) && errno != EEXIST) { fprintf(stderr, "mkdir(proc) failed: %m\n"); return -1; } if (mount("proc", "/proc", "proc", MS_MGC_VAL, NULL)) { fprintf(stderr, "mount(/proc) failed: %m\n"); return -1; } if (mkdir("/dev", 0755) && errno != EEXIST) { fprintf(stderr, "mkdir(/dev) failed: %m\n"); return -1; } if (mkdir("/dev/pts", 0755) && errno != EEXIST) { fprintf(stderr, "mkdir(/dev/pts) failed: %m\n"); return -1; } if (symlink("/dev/pts/ptmx", "/dev/ptmx") && errno != EEXIST) { fprintf(stderr, "mknod(/dev/ptmx) failed: %m\n"); return -1; } chmod("/dev/ptmx", 0666); if (mount("pts", "/dev/pts", "devpts", MS_MGC_VAL, "mode=666,ptmxmode=666,newinstance")) { fprintf(stderr, "mount(/dev/pts) failed: %m\n"); return -1; } if (mount("/dev/pts/ptmx", "/dev/ptmx", NULL, MS_BIND, NULL)) { fprintf(stderr, "mount(/dev/pts) failed: %m\n"); return -1; } if (fchdir(dfd)) { fprintf(stderr, "fchdir() failed: %m\n"); return -1; } close(dfd); mkdir("/dev", 0777); mknod("/dev/null", 0777 | S_IFCHR, makedev(1, 3)); chmod("/dev/null", 0777); mkdir("/dev/net", 0777); mknod("/dev/net/tun", 0777 | S_IFCHR, makedev(10, 200)); chmod("/dev/net/tun", 0777); mknod("/dev/rtc", 0777 | S_IFCHR, makedev(254, 0)); chmod("/dev/rtc", 0777); return 0; }
void linux_namespace_jail() { char *ns_tmp_mountpoint = NULL, *ns_tmp_mountpoint2 = NULL; if (getpid() != 1) { uwsgi_log("your kernel does not support linux pid namespace\n"); exit(1); } char *ns_hostname = strchr(uwsgi.ns, ':'); if (ns_hostname) { ns_hostname[0] = 0; ns_hostname++; if (sethostname(ns_hostname, strlen(ns_hostname))) { uwsgi_error("sethostname()"); } } FILE *procmounts; char line[1024]; int unmounted = 1; char *delim0, *delim1; if (chdir(uwsgi.ns)) { uwsgi_error("chdir()"); exit(1); } if (strcmp(uwsgi.ns, "/")) { ns_tmp_mountpoint = uwsgi_concat2(uwsgi.ns, "/.uwsgi_ns_tmp_mountpoint"); mkdir(ns_tmp_mountpoint, S_IRWXU); ns_tmp_mountpoint2 = uwsgi_concat2(ns_tmp_mountpoint, "/.uwsgi_ns_tmp_mountpoint"); mkdir(ns_tmp_mountpoint2, S_IRWXU); if (mount(uwsgi.ns, ns_tmp_mountpoint, "none", MS_BIND, NULL)) { uwsgi_error("mount()"); } if (chdir(ns_tmp_mountpoint)) { uwsgi_error("chdir()"); } if (pivot_root(".", ns_tmp_mountpoint2)) { uwsgi_error("pivot_root()"); exit(1); } if (chdir("/")) { uwsgi_error("chdir()"); exit(1); } } uwsgi_log("remounting /proc\n"); if (mount("proc", "/proc", "proc", 0, NULL)) { uwsgi_error("mount()"); } struct uwsgi_string_list *usl = uwsgi.ns_keep_mount; while(usl) { // bind mounting keep-mount items char *keep_mountpoint = usl->value; char *destination = strchr(usl->value, ':'); if (destination) { keep_mountpoint = uwsgi_concat2n(usl->value, destination - usl->value, "", 0); } char *ks = uwsgi_concat2("/.uwsgi_ns_tmp_mountpoint", keep_mountpoint); if (!destination) { destination = usl->value; // skip first part of the name if under the jail if (!uwsgi_startswith(destination, uwsgi.ns, strlen(uwsgi.ns))) { if (uwsgi.ns[strlen(uwsgi.ns)-1] == '/') { destination += strlen(uwsgi.ns)-1; } else { destination += strlen(uwsgi.ns); } } } else { free(keep_mountpoint); destination++; } uwsgi_log("remounting %s to %s\n", ks+25, destination); if (mount(ks, destination, "none", MS_BIND, NULL)) { uwsgi_error("mount()"); } free(ks); usl = usl->next; } while (unmounted) { unmounted = 0; procmounts = fopen("/proc/self/mounts", "r"); while (fgets(line, 1024, procmounts) != NULL) { delim0 = strchr(line, ' '); delim0++; delim1 = strchr(delim0, ' '); *delim1 = 0; // and now check for keep-mounts if (uwsgi_is_a_keep_mount(delim0)) continue; if (!strcmp(delim0, "/") || !strcmp(delim0, "/proc")) continue; if (!umount(delim0)) { unmounted++; } } fclose(procmounts); } if (rmdir("/.uwsgi_ns_tmp_mountpoint/.uwsgi_ns_tmp_mountpoint")) { uwsgi_error("rmdir()"); } if (rmdir("/.uwsgi_ns_tmp_mountpoint")) { uwsgi_error("rmdir()"); } if (strcmp(uwsgi.ns, "/")) { free(ns_tmp_mountpoint2); free(ns_tmp_mountpoint); } }
int main (int argc, char **argv) { mode_t old_umask; cleanup_free char *base_path = NULL; int clone_flags; char *old_cwd = NULL; pid_t pid; int event_fd = -1; const char *new_cwd; uid_t ns_uid; gid_t ns_gid; /* Get the (optional) capabilities we need, drop root */ acquire_caps (); /* Never gain any more privs during exec */ if (prctl (PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) die_with_error ("prctl(PR_SET_NO_NEW_CAPS) failed"); /* The initial code is run with high permissions (i.e. CAP_SYS_ADMIN), so take lots of care. */ argv0 = argv[0]; if (isatty (1)) host_tty_dev = ttyname (1); argv++; argc--; if (argc == 0) usage (EXIT_FAILURE); parse_args (&argc, &argv); /* We have to do this if we weren't installed setuid, so let's just DWIM */ if (!is_privileged) opt_unshare_user = TRUE; if (argc == 0) usage (EXIT_FAILURE); __debug__(("Creating root mount point\n")); uid = getuid (); if (opt_sandbox_uid == -1) opt_sandbox_uid = uid; gid = getgid (); if (opt_sandbox_gid == -1) opt_sandbox_gid = gid; if (!opt_unshare_user && opt_sandbox_uid != uid) die ("Specifying --uid requires --unshare-user"); if (!opt_unshare_user && opt_sandbox_gid != gid) die ("Specifying --gid requires --unshare-user"); /* We need to read stuff from proc during the pivot_root dance, etc. Lets keep a fd to it open */ proc_fd = open ("/proc", O_RDONLY | O_PATH); if (proc_fd == -1) die_with_error ("Can't open /proc"); /* We need *some* mountpoint where we can mount the root tmpfs. We first try in /run, and if that fails, try in /tmp. */ base_path = xasprintf ("/run/user/%d/.bubblewrap", uid); if (mkdir (base_path, 0755) && errno != EEXIST) { free (base_path); base_path = xasprintf ("/tmp/.bubblewrap-%d", uid); if (mkdir (base_path, 0755) && errno != EEXIST) die_with_error ("Creating root mountpoint failed"); } __debug__(("creating new namespace\n")); if (opt_unshare_pid) { event_fd = eventfd (0, EFD_CLOEXEC | EFD_NONBLOCK); if (event_fd == -1) die_with_error ("eventfd()"); } /* We block sigchild here so that we can use signalfd in the monitor. */ block_sigchild (); clone_flags = SIGCHLD | CLONE_NEWNS; if (opt_unshare_user) clone_flags |= CLONE_NEWUSER; if (opt_unshare_pid) clone_flags |= CLONE_NEWPID; if (opt_unshare_net) clone_flags |= CLONE_NEWNET; if (opt_unshare_ipc) clone_flags |= CLONE_NEWIPC; if (opt_unshare_uts) clone_flags |= CLONE_NEWUTS; pid = raw_clone (clone_flags, NULL); if (pid == -1) { if (opt_unshare_user) { if (errno == EINVAL) die ("Creating new namespace failed, likely because the kernel does not support user namespaces. bwrap must be installed setuid on such systems."); else if (errno == EPERM && !is_privileged) die ("No permissions to creating new namespace, likely because the kernel does not allow non-privileged user namespaces. On e.g. debian this can be enabled with 'sysctl kernel.unprivileged_userns_clone=1'."); } die_with_error ("Creating new namespace failed"); } if (pid != 0) { /* Initial launched process, wait for exec:ed command to exit */ /* We don't need any caps in the launcher, drop them immediately. */ drop_caps (); monitor_child (event_fd); exit (0); /* Should not be reached, but better safe... */ } if (opt_unshare_net && loopback_setup () != 0) die ("Can't create loopback device"); ns_uid = opt_sandbox_uid; ns_gid = opt_sandbox_gid; if (opt_unshare_user) { if (opt_needs_devpts) { /* This is a bit hacky, but we need to first map the real uid/gid to 0, otherwise we can't mount the devpts filesystem because root is not mapped. Later we will create another child user namespace and map back to the real uid */ ns_uid = 0; ns_gid = 0; } write_uid_gid_map (ns_uid, uid, ns_gid, gid, TRUE); } old_umask = umask (0); /* Mark everything as slave, so that we still * receive mounts from the real root, but don't * propagate mounts to the real root. */ if (mount (NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) die_with_error ("Failed to make / slave"); /* Create a tmpfs which we will use as / in the namespace */ if (mount ("", base_path, "tmpfs", MS_NODEV|MS_NOSUID, NULL) != 0) die_with_error ("Failed to mount tmpfs"); old_cwd = get_current_dir_name (); /* Chdir to the new root tmpfs mount. This will be the CWD during the entire setup. Access old or new root via "oldroot" and "newroot". */ if (chdir (base_path) != 0) die_with_error ("chdir base_path"); /* We create a subdir "$base_path/newroot" for the new root, that * way we can pivot_root to base_path, and put the old root at * "$base_path/oldroot". This avoids problems accessing the oldroot * dir if the user requested to bind mount something over / */ if (mkdir ("newroot", 0755)) die_with_error ("Creating newroot failed"); if (mkdir ("oldroot", 0755)) die_with_error ("Creating oldroot failed"); if (pivot_root (base_path, "oldroot")) die_with_error ("pivot_root"); if (chdir ("/") != 0) die_with_error ("chdir / (base path)"); if (is_privileged) { pid_t child; int privsep_sockets[2]; if (socketpair (AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, privsep_sockets) != 0) die_with_error ("Can't create privsep socket"); child = fork (); if (child == -1) die_with_error ("Can't fork unprivileged helper"); if (child == 0) { /* Unprivileged setup process */ drop_caps (); close (privsep_sockets[0]); setup_newroot (opt_unshare_pid, privsep_sockets[1]); exit (0); } else { uint32_t buffer[2048]; /* 8k, but is int32 to guarantee nice alignment */ uint32_t op, flags; const char *arg1, *arg2; cleanup_fd int unpriv_socket = -1; unpriv_socket = privsep_sockets[0]; close (privsep_sockets[1]); do { op = read_priv_sec_op (unpriv_socket, buffer, sizeof (buffer), &flags, &arg1, &arg2); privileged_op (-1, op, flags, arg1, arg2); if (write (unpriv_socket, buffer, 1) != 1) die ("Can't write to op_socket"); } while (op != PRIV_SEP_OP_DONE); /* Continue post setup */ } } else setup_newroot (opt_unshare_pid, -1); /* The old root better be rprivate or we will send unmount events to the parent namespace */ if (mount ("oldroot", "oldroot", NULL, MS_REC|MS_PRIVATE, NULL) != 0) die_with_error ("Failed to make old root rprivate"); if (umount2 ("oldroot", MNT_DETACH)) die_with_error ("unmount old root"); if (opt_unshare_user && (ns_uid != opt_sandbox_uid || ns_gid != opt_sandbox_gid)) { /* Now that devpts is mounted and we've no need for mount permissions we can create a new userspace and map our uid 1:1 */ if (unshare (CLONE_NEWUSER)) die_with_error ("unshare user ns"); write_uid_gid_map (opt_sandbox_uid, ns_uid, opt_sandbox_gid, ns_gid, FALSE); } /* Now make /newroot the real root */ if (chdir ("/newroot") != 0) die_with_error ("chdir newroot"); if (chroot ("/newroot") != 0) die_with_error ("chroot /newroot"); if (chdir ("/") != 0) die_with_error ("chdir /"); /* Now we have everything we need CAP_SYS_ADMIN for, so drop it */ drop_caps (); if (opt_seccomp_fd != -1) { cleanup_free char *seccomp_data = NULL; size_t seccomp_len; struct sock_fprog prog; seccomp_data = load_file_data (opt_seccomp_fd, &seccomp_len); if (seccomp_data == NULL) die_with_error ("Can't read seccomp data"); if (seccomp_len % 8 != 0) die ("Invalide seccomp data, must be multiple of 8"); prog.len = seccomp_len / 8; prog.filter = (struct sock_filter *)seccomp_data; close (opt_seccomp_fd); if (prctl (PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) != 0) die_with_error ("prctl(PR_SET_SECCOMP)"); } umask (old_umask); new_cwd = "/"; if (opt_chdir_path) { if (chdir (opt_chdir_path)) die_with_error ("Can't chdir to %s", opt_chdir_path); new_cwd = opt_chdir_path; } else if (chdir (old_cwd) == 0) { /* If the old cwd is mapped in the sandbox, go there */ new_cwd = old_cwd; } else { /* If the old cwd is not mapped, go to home */ const char *home = getenv ("HOME"); if (home != NULL && chdir (home) == 0) new_cwd = home; } xsetenv ("PWD", new_cwd, 1); free (old_cwd); __debug__(("forking for child\n")); if (opt_unshare_pid || lock_files != NULL || opt_sync_fd != -1) { /* We have to have a pid 1 in the pid namespace, because * otherwise we'll get a bunch of zombies as nothing reaps * them. Alternatively if we're using sync_fd or lock_files we * need some process to own these. */ pid = fork (); if (pid == -1) die_with_error("Can't fork for pid 1"); if (pid != 0) { /* Close fds in pid 1, except stdio and optionally event_fd (for syncing pid 2 lifetime with monitor_child) and opt_sync_fd (for syncing sandbox lifetime with outside process). Any other fds will been passed on to the child though. */ { int dont_close[3]; int j = 0; if (event_fd != -1) dont_close[j++] = event_fd; if (opt_sync_fd != -1) dont_close[j++] = opt_sync_fd; dont_close[j++] = -1; fdwalk (proc_fd, close_extra_fds, dont_close); } return do_init (event_fd, pid); } } __debug__(("launch executable %s\n", argv[0])); if (proc_fd != -1) close (proc_fd); if (opt_sync_fd != -1) close (opt_sync_fd); /* We want sigchild in the child */ unblock_sigchild (); if (label_exec (opt_exec_label) == -1) die_with_error ("label_exec %s", argv[0]); if (execvp (argv[0], argv) == -1) die_with_error ("execvp %s", argv[0]); return 0; }
int bootup_main(int argc, char **argv) { FILE *fp; DIR *dp; struct dirent *dt; int t=0, rc; char cmd[1024], buf[1024], name[1024]; time_t curtime; struct tm *loctime; signal(SIGINT,SIG_IGN); putenv("PATH=/bin"); putenv("TERM=linux"); umask(0770); chdir("/"); putchar('\n'); print_banner(); putchar('\n'); xsystem("mount -t proc -o ro virtual /proc"); xsystem("mount -t sysfs -o ro virtual /sys"); // STAGE 1 calculate_mem(); fprintf_stdout("* Creating Mybox filesystem (%d kB) on shared memory...\n",RAMSIZE); xsystem("mount -t tmpfs -o \"rw,size=%dk\" virtual /ramd",RAMSIZE); chmod("/ramd",S_IREAD | S_IWRITE | S_IEXEC); chdir("/ramd"); if((dp=opendir("/")) == NULL) { perror("opendir"); exit(1); } while((dt=readdir(dp))!=NULL) { if(!strcmp(dt->d_name,".") || !strcmp(dt->d_name,"..") || !strcmp(dt->d_name,"lost+found") || !strcmp(dt->d_name,"ramd") || !strcmp(dt->d_name,"proc") || !strcmp(dt->d_name,"dev") || !strcmp(dt->d_name,"sys")) continue; xsystem("cp -dpR /%s /ramd/",dt->d_name); } closedir(dp); xmkdir("dev/pts"); xmkdir("initrd"); umount("/proc"); umount("/sys"); // STAGE 2 rc=pivot_root(".","initrd"); if(rc==-1) { fprintf_stdout("#### ERROR: Change root file system failed!\n"); exit(1); } chdir("/"); xmkdir("proc"); xmkdir("sys"); xsystem("mount -t proc -o rw virtual /proc"); xsystem("mount -t sysfs -o rw virtual /sys"); save_to_file("/proc/sys/kernel/printk","0 0 0 0\n"); if((dp=opendir("/tmp")) == NULL) { perror("opendir"); exit(1); } fprintf_stdout("-> Extracting base tools: "); while((dt=readdir(dp))!=NULL) { if(!strcmp(dt->d_name,".") || !strcmp(dt->d_name,"..")) continue; if(strstr(dt->d_name,".mpk")) { fprintf_stdout("#"); xsystem("tar -C / -axf /tmp/%s",dt->d_name); } } free(dt); closedir(dp); fprintf_stdout("\r* Extracting base tools. Done.%s\n",SPACE); save_to_file("/proc/sys/kernel/modprobe","/bin/modprobe\n"); xsystem("depmod -a"); // STAGE 3 chdir("/"); xsystem("mdev -s"); xsystem("mount -t devpts /dev/devpts /dev/pts -o \"rw,gid=0,mode=620\""); rename("/dev/random","/dev/random-block"); symlink("/dev/urandom","/dev/random"); xsystem("chmod 700 *"); if((fp=fopen("/etc/inittab","w"))!=NULL) { fprintf(fp,"::sysinit:/etc/init.boot/rc.init\n"); fprintf(fp,"tty1::respawn:/bin/getty -h -n -L tty1 115200 linux\n"); fprintf(fp,"ttyS0::respawn:/bin/getty -h -n -L ttyS0 115200 vt100\n"); fprintf(fp,"tty7::respawn:/bin/chkprog\n"); fprintf(fp,"tty8::respawn:/bin/trafficd\n"); fprintf(fp,"::restart:/bin/init\n"); fprintf(fp,"::ctrlaltdel:/bin/bootdown\n"); fprintf(fp,"::ctrlaltdel:/bin/reset\n"); fprintf(fp,"::ctrlaltdel:/bin/reboot\n"); fprintf(fp,"::shutdown:/bin/bootdown\n"); fclose(fp); } curtime=time(NULL); loctime=localtime(&curtime); strftime(cmd, sizeof(cmd), "[%d/%m/%Y %T] TYPE=INFO MSG=****** SYSTEM LOADING ******\n",loctime); append_to_file("/tmp/bootup",cmd); if(file_exists("/bin/getkey")) { if(system("getkey -c 3 -m \"-> Starting Init: %d\" R")==0) { fprintf_stdout("\r#### WARNING: LOGIN DISABLED\n"); xtouch("/etc/noconsole"); } else { fprintf_stdout("\r* Starting Init. Done.\n"); } } memset(buf,0x0,sizeof(buf)); snprintf(buf,sizeof(buf),"%s\n","/bin/mdev"); save_to_file("/proc/sys/kernel/hotplug",buf); do_chroot(); signal(SIGINT,SIG_DFL); fprintf_stdout("#### ERROR: Failed to boot file system!\n"); fprintf_stdout("#### ERROR: Press Ctrl+Alt+Del or switch off/on for reboot.\n"); while(1); exit(0); }
static int prepare_mntns() { int fd, ret; char *root; char path[PATH_MAX]; root = getenv("ZDTM_ROOT"); if (!root) { fprintf(stderr, "ZDTM_ROOT isn't set\n"); return -1; } if (mount("none", "/", "none", MS_REC|MS_PRIVATE, NULL)) { fprintf(stderr, "Can't remount root with MS_PRIVATE: %m\n"); return -1; } if (mount(root, root, NULL, MS_BIND | MS_REC, NULL)) { fprintf(stderr, "Can't bind-mount root: %m\n"); return -1; } printf("chdir(%s)\n", root); if (chdir(root)) { fprintf(stderr, "chdir(%s) failed: %m\n", root); return -1; } if (mkdir("old", 0777) && errno != EEXIST) { fprintf(stderr, "mkdir(old) failed: %m\n"); return -1; } printf("pivot_root(., ./old)\n"); if (pivot_root(".", "./old")) { fprintf(stderr, "pivot_root(., ./old) failed: %m\n"); return -1; } chdir("/"); if (mkdir("proc", 0777) && errno != EEXIST) { fprintf(stderr, "mkdir(proc) failed: %m\n"); return -1; } printf("Mount /proc\n"); if (mount("proc", "/proc", "proc", MS_MGC_VAL, NULL)) { fprintf(stderr, "mount(/proc) failed: %m\n"); return -1; } printf("Open the mount point, where is a target file\n"); fd = open("/old/tmp/xxx", O_DIRECTORY | O_RDONLY); if (fd < 0) { fprintf(stderr, "open(/old/mnt/xxx) failed: %m\n"); return -1; } printf("Detach mounts from the previous mount namespace\n"); if (umount2("./old", MNT_DETACH)) { fprintf(stderr, "umount(./old) failed: %m\n"); return -1; } printf("Try to read the target file\n"); snprintf(path, sizeof(path), "/proc/self/fd/%d/yyy/zzz", fd); fd = open(path, O_RDONLY); if (fd < 0) return 0; printf("We have done this\n"); ret = read(fd, path, sizeof(path) - 1); if (ret < 0) { fprintf(stderr, "read() failed: %m\n"); return -1; } path[ret] = 0; fprintf(stderr, "%s\n", path); return -1; }
void stage2(void) { DIR *dp; struct dirent *dt; FILE *fp; char **xargv; char buf[1024], name[150]; int rc; rc=pivot_root(".","initrd"); if(rc==-1) { perror("pivot_root"); exit(1); } chdir("/"); xmkdir("proc"); xmkdir("sys"); xmkdir("config"); xmkdir("config/download"); xmkdir("config/localsave"); xmkdir("config/logs"); xsystem("mount -t proc -o rw virtual /proc"); xsystem("mount -t sysfs -o rw virtual /sys"); save_to_file("/proc/sys/kernel/printk","0 0 0 0\n"); if((dp=opendir("/tmp")) == NULL) { perror("opendir"); exit(1); } fprintf_stdout("-> Extracting base tools."); while((dt=readdir(dp))!=NULL) { if(!strcmp(dt->d_name,".") || !strcmp(dt->d_name,"..")) continue; if(strstr(dt->d_name,".bz2")) { fprintf_stdout("."); xsystem("tar -C / -jxf /tmp/%s",dt->d_name); usleep(10000); } } free(dt); closedir(dp); fprintf_stdout("\r* Extracting base tools. Done.%s\n",SPACE); save_to_file("/proc/sys/kernel/modprobe","/bin/modprobe\n"); xsystem("depmod -a"); if(file_exists("/lib/modules/drivers.txt")) { memset(buf,0x0,sizeof(buf)); if((fp=fopen("/lib/modules/drivers.txt","r"))!=NULL) { while(fgets(buf,sizeof(buf),fp)!=NULL) { trim(buf); if(buf[0]=='\0') continue; xargv[0]=NULL;xargv[1]=NULL; memset(name,0x0,sizeof(name)); xargv[0]=buf; xargv[1]=".ko"; snprintf(name,sizeof(name),"%s",base_name(xargv)); fprintf_stdout("-> Scanning for %s..%s\r",name,SPACE); if(!strcmp(name,"ne")) { memset(name,0x0,sizeof(name)); strncpy(name,"ne io=0x300,0x340",sizeof(name)); } xsystem("modprobe -q -k %s",name); usleep(1000); } fclose(fp); fprintf_stdout("%s\r* Scanning. Done.\n",SPACE); } } }
void linux_namespace_jail() { char *ns_tmp_mountpoint = NULL, *ns_tmp_mountpoint2 = NULL; if (getpid() != 1) { uwsgi_log("your kernel does not support linux pid namespace\n"); exit(1); } char *ns_hostname = strchr(uwsgi.ns, ':'); if (ns_hostname) { ns_hostname[0] = 0; ns_hostname++; if (sethostname(ns_hostname, strlen(ns_hostname))) { uwsgi_error("sethostname()"); } } FILE *procmounts; char line[1024]; int unmounted = 1; char *delim0, *delim1; if (chdir(uwsgi.ns)) { uwsgi_error("chdir()"); exit(1); } if (strcmp(uwsgi.ns, "/")) { ns_tmp_mountpoint = uwsgi_concat2(uwsgi.ns, "/.uwsgi_ns_tmp_mountpoint"); mkdir(ns_tmp_mountpoint, S_IRWXU); ns_tmp_mountpoint2 = uwsgi_concat2(ns_tmp_mountpoint, "/.uwsgi_ns_tmp_mountpoint"); mkdir(ns_tmp_mountpoint2, S_IRWXU); if (mount(uwsgi.ns, ns_tmp_mountpoint, "none", MS_BIND, NULL)) { uwsgi_error("mount()"); } if (chdir(ns_tmp_mountpoint)) { uwsgi_error("chdir()"); } if (pivot_root(".", ns_tmp_mountpoint2)) { uwsgi_error("pivot_root()"); exit(1); } if (chdir("/")) { uwsgi_error("chdir()"); exit(1); } } uwsgi_log("remounting /proc\n"); if (mount("proc", "/proc", "proc", 0, NULL)) { uwsgi_error("mount()"); } while (unmounted) { unmounted = 0; procmounts = fopen("/proc/self/mounts", "r"); while (fgets(line, 1024, procmounts) != NULL) { delim0 = strchr(line, ' '); delim0++; delim1 = strchr(delim0, ' '); *delim1 = 0; if (!strcmp(delim0, "/") || !strcmp(delim0, "/proc")) continue; if (!umount(delim0)) { unmounted++; } } fclose(procmounts); } if (rmdir("/.uwsgi_ns_tmp_mountpoint/.uwsgi_ns_tmp_mountpoint")) { uwsgi_error("rmdir()"); } if (rmdir("/.uwsgi_ns_tmp_mountpoint")) { uwsgi_error("rmdir()"); } if (strcmp(uwsgi.ns, "/")) { free(ns_tmp_mountpoint2); free(ns_tmp_mountpoint); } }
static int child(void *arg) { errno = 0; pivot_root("/proc", proc_policy_dir); return errno; }
static int prepare_mntns(void) { int dfd, ret; char *root, *criu_path; char path[PATH_MAX]; root = getenv("ZDTM_ROOT"); if (!root) { fprintf(stderr, "ZDTM_ROOT isn't set\n"); return -1; } /* * In a new userns all mounts are locked to protect what is * under them. So we need to create another mount for the * new root. */ if (mount(root, root, NULL, MS_SLAVE , NULL)) { fprintf(stderr, "Can't bind-mount root: %m\n"); return -1; } if (mount(root, root, NULL, MS_BIND | MS_REC, NULL)) { fprintf(stderr, "Can't bind-mount root: %m\n"); return -1; } criu_path = getenv("ZDTM_CRIU"); if (criu_path) { snprintf(path, sizeof(path), "%s%s", root, criu_path); if (mount(criu_path, path, NULL, MS_BIND, NULL) || mount(NULL, path, NULL, MS_PRIVATE, NULL)) { pr_perror("Unable to mount %s", path); return -1; } } /* Move current working directory to the new root */ ret = readlink("/proc/self/cwd", path, sizeof(path) - 1); if (ret < 0) return -1; path[ret] = 0; dfd = open(path, O_RDONLY | O_DIRECTORY); if (dfd == -1) { fprintf(stderr, "open(.) failed: %m\n"); return -1; } if (chdir(root)) { fprintf(stderr, "chdir(%s) failed: %m\n", root); return -1; } if (mkdir("old", 0777) && errno != EEXIST) { fprintf(stderr, "mkdir(old) failed: %m\n"); return -1; } if (pivot_root(".", "./old")) { fprintf(stderr, "pivot_root(., ./old) failed: %m\n"); return -1; } if (mount("./old", "./old", NULL, MS_SLAVE | MS_REC , NULL)) { fprintf(stderr, "Can't bind-mount root: %m\n"); return -1; } /* * proc and sysfs can be mounted in an unprivileged namespace, * if they are already mounted when the user namespace is created. * So ./old must be umounted after mounting /proc and /sys. */ if (mount("proc", "/proc", "proc", MS_MGC_VAL | MS_NOSUID | MS_NOEXEC | MS_NODEV, NULL)) { fprintf(stderr, "mount(/proc) failed: %m\n"); return -1; } if (mount("zdtm_run", "/run", "tmpfs", 0, NULL)) { fprintf(stderr, "Unable to mount /run: %m\n"); return -1; } if (umount2("./old", MNT_DETACH)) { fprintf(stderr, "umount(./old) failed: %m\n"); return -1; } if (mount("pts", "/dev/pts", "devpts", MS_MGC_VAL, "mode=666,ptmxmode=666,newinstance")) { fprintf(stderr, "mount(/dev/pts) failed: %m\n"); return -1; } /* * If CONFIG_DEVPTS_MULTIPLE_INSTANCES=n, then /dev/pts/ptmx * does not exist. Fall back to creating the device with * mknod() in that case. */ if (access("/dev/pts/ptmx", F_OK) == 0) { if (symlink("pts/ptmx", "/dev/ptmx") && errno != EEXIST) { fprintf(stderr, "symlink(/dev/ptmx) failed: %m\n"); return -1; } } else { if (mknod("/dev/ptmx", 0666 | S_IFCHR, makedev(5, 2)) == 0) { chmod("/dev/ptmx", 0666); } else if (errno != EEXIST) { fprintf(stderr, "mknod(/dev/ptmx) failed: %m\n"); return -1; } } if (fchdir(dfd)) { fprintf(stderr, "fchdir() failed: %m\n"); return -1; } close(dfd); return 0; }
int ps_daemon_change_rootfs(char *newroot) { ps_log(0, LOG_INFO("change root dir to [%s]"), newroot); if (ps_daemon_rootfs_changed) { ps_log(0, LOG_ERROR("rootfs already changed!")); return EXIT_FAILURE; } if (chdir(newroot) == -1) { ps_log(0, LOG_ERROR("failed to change rootdir to [%s] - error [%s]"), newroot, strerror(errno)); return EXIT_FAILURE; } // create a directory where pivot_root can attach us_root if (mkdir("./us_rootfs", 0755) == -1) { if (errno != EEXIST) { ps_log(0, LOG_ERROR("failed to create directory /us_rootfs - error [%s]"), strerror(errno)); return EXIT_FAILURE; } } if (unshare(CLONE_NEWNS) == -1) { ps_log(0, LOG_ERROR("unable to unshare mount namespace - error [%s]"), strerror(errno)); return EXIT_FAILURE; } if (pivot_root(".", "./us_rootfs") == -1) { ps_log(0, LOG_ERROR("pivot_root failed - error [%s]"), strerror(errno)); return EXIT_FAILURE; } // unmount user space rootfs if (mount("", "/us_rootfs", "none", MS_REC | MS_PRIVATE, "") == -1) { ps_log(0, LOG_ERROR("failed to re-mount /us_rootfs as private - error [%s]"), strerror(errno)); return EXIT_FAILURE; } if (umount2("/us_rootfs", MNT_DETACH) == -1) { ps_log(0, LOG_ERROR("failed to unmount /us_rootfs - error [%s]"), strerror(errno)); return EXIT_FAILURE; } if (rmdir("/us_rootfs") == -1) ps_log(0, LOG_ERROR("failed to remove directory /us_rootfs - error [%s]"), strerror(errno)); if (chdir("/") == -1) { ps_log(0, LOG_ERROR("failed to change to / - error [%s]"), strerror(errno)); return EXIT_FAILURE; } if (mkdir("/proc", 0755) == -1); if (errno != EEXIST) { ps_log(0, LOG_ERROR("failed to create /proc directory - error [%s]"), strerror(errno)); return EXIT_FAILURE; } if (mount("", "/proc","proc", MS_NODEV | MS_NOEXEC | MS_NOSUID,"") == -1) { ps_log(0, LOG_ERROR("failed to re-mount /proc - error [%s]"), strerror(errno)); return EXIT_FAILURE; } if (mkdir("/dev", 0755) == -1); if (errno != EEXIST) { ps_log(0, LOG_ERROR("failed to create /dev directory - error [%s]"), strerror(errno)); return EXIT_FAILURE; } if (mkdir("/dev/pts", 0755) == -1); if (errno != EEXIST) { ps_log(0, LOG_ERROR("failed to create /dev/pts directory - error [%s]"), strerror(errno)); return EXIT_FAILURE; } if (mount("devpts", "/dev/pts", "devpts", MS_MGC_VAL , "newinstance,ptmxmode=0666") == -1) { ps_log(0, LOG_ERROR("unable to mount /dev/pts - error [%s]"), strerror(errno)); return EXIT_FAILURE; } if (access("/dev/ptmx", F_OK) == -1) { if (symlink("/dev/pts/ptmx", "/dev/ptmx") == -1) ps_log(0, LOG_ERROR("unable to create /dev/ptmx symlink - error [%s]"), strerror(errno)); } ps_daemon_rootfs_changed=1; return EXIT_SUCCESS; }