/* * mount a cgroup namespace * * returned values: * - XCGROUP_ERROR * - XCGROUP_SUCCESS * * If an error occurs, errno will be set. */ int xcgroup_ns_mount(xcgroup_ns_t* cgns) { int fstatus; char* options; char opt_combined[1024]; char* mnt_point; char* p; xcgroup_t cg; mode_t cmask; mode_t omask; cmask = S_IWGRP | S_IWOTH; omask = umask(cmask); fstatus = mkdir(cgns->mnt_point, 0755); if (fstatus && errno != EEXIST) { if (cgns->mnt_point[0] != '/') { debug("unable to create cgroup ns directory '%s'" " : do not start with '/'", cgns->mnt_point); umask(omask); return XCGROUP_ERROR; } mnt_point = xstrdup(cgns->mnt_point); p = mnt_point; while ((p = index(p+1, '/')) != NULL) { *p = '\0'; fstatus = mkdir(mnt_point, 0755); if (fstatus && errno != EEXIST) { debug("unable to create cgroup ns required " "directory '%s'", mnt_point); xfree(mnt_point); umask(omask); return XCGROUP_ERROR; } *p='/'; } xfree(mnt_point); fstatus = mkdir(cgns->mnt_point, 0755); } if (fstatus && errno != EEXIST) { debug("unable to create cgroup ns directory '%s'" " : %m", cgns->mnt_point); umask(omask); return XCGROUP_ERROR; } umask(omask); if (cgns->mnt_args == NULL || strlen(cgns->mnt_args) == 0) options = cgns->subsystems; else { if (snprintf(opt_combined, sizeof(opt_combined), "%s,%s", cgns->subsystems, cgns->mnt_args) >= sizeof(opt_combined)) { debug2("unable to build cgroup options string"); return XCGROUP_ERROR; } options = opt_combined; } #if defined(__FreeBSD__) if (mount("cgroup", cgns->mnt_point, MS_NOSUID|MS_NOEXEC|MS_NODEV, options)) #else if (mount("cgroup", cgns->mnt_point, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV, options)) #endif return XCGROUP_ERROR; else { /* FIXME: this only gets set when we aren't mounted at all. Since we never umount this may only be loaded at startup the first time. */ /* we then set the release_agent if necessary */ if (cgns->notify_prog) { if (xcgroup_create(cgns, &cg, "/", 0, 0) == XCGROUP_ERROR) return XCGROUP_SUCCESS; xcgroup_set_param(&cg, "release_agent", cgns->notify_prog); xcgroup_destroy(&cg); } return XCGROUP_SUCCESS; } }
static int do_mount(const char *mnt, char **typep, mode_t rootmode, int fd, const char *opts, const char *dev, char **sourcep, char **mnt_optsp) { int res; int flags = MS_NOSUID | MS_NODEV; char *optbuf; char *mnt_opts = NULL; const char *s; char *d; char *fsname = NULL; char *source = NULL; char *type = NULL; int blkdev = 0; optbuf = (char *) malloc(strlen(opts) + 128); if (!optbuf) { fprintf(stderr, "%s: failed to allocate memory\n", progname); return -1; } for (s = opts, d = optbuf; *s;) { unsigned len; const char *fsname_str = "fsname="; for (len = 0; s[len] && s[len] != ','; len++); if (begins_with(s, fsname_str)) { if (!get_string_opt(s, len, fsname_str, &fsname)) goto err; } else if (opt_eq(s, len, "blkdev")) { blkdev = 1; } else if (!begins_with(s, "fd=") && !begins_with(s, "rootmode=") && !begins_with(s, "user_id=") && !begins_with(s, "group_id=")) { int on; int flag; int skip_option = 0; if (opt_eq(s, len, "large_read")) { struct utsname utsname; unsigned kmaj, kmin; res = uname(&utsname); if (res == 0 && sscanf(utsname.release, "%u.%u", &kmaj, &kmin) == 2 && (kmaj > 2 || (kmaj == 2 && kmin > 4))) { fprintf(stderr, "%s: note: 'large_read' mount option is " "deprecated for %i.%i kernels\n", progname, kmaj, kmin); skip_option = 1; } } if (!skip_option) { if (find_mount_flag(s, len, &on, &flag)) { if (on) flags |= flag; else flags &= ~flag; } else { memcpy(d, s, len); d += len; *d++ = ','; } } } s += len; if (*s) s++; } *d = '\0'; res = get_mnt_opts(flags, optbuf, &mnt_opts); if (res == -1) goto err; sprintf(d, "fd=%i,rootmode=%o,user_id=%i,group_id=%i", fd, rootmode, getuid(), getgid()); source = malloc((fsname ? strlen(fsname) : 0) + strlen(dev) + 32); type = malloc(32); if (!type || !source) { fprintf(stderr, "%s: failed to allocate memory\n", progname); goto err; } strcpy(type, blkdev ? "fuseblk" : "fuse"); if (fsname) strcpy(source, fsname); else strcpy(source, dev); if (restore_privs()) goto err; res = mount(source, mnt, type, flags, optbuf); if (res == -1 && errno == EINVAL) { /* It could be an old version not supporting group_id */ sprintf(d, "fd=%i,rootmode=%o,user_id=%i", fd, rootmode, getuid()); res = mount(source, mnt, type, flags, optbuf); } if (drop_privs()) goto err; if (res == -1) { int errno_save = errno; if (blkdev && errno == ENODEV && !fuse_mnt_check_fuseblk()) fprintf(stderr, "%s: 'fuseblk' support missing\n", progname); else { fprintf(stderr, "%s: mount failed: %s\n", progname, strerror(errno_save)); if (errno_save == EPERM) fprintf(stderr, "User doesn't have privilege to mount. " "For more information\nplease see: " "http://ntfs-3g.org/support.html#unprivileged\n"); } goto err; } else { *sourcep = source; *typep = type; *mnt_optsp = mnt_opts; } out: free(fsname); free(optbuf); return res; err: free(source); free(type); free(mnt_opts); res = -1; goto out; }
int main(int argc, char **argv) { pid_t installpid, childpid; int waitStatus; int fd = -1; int doReboot = 0; int doShutdown =0; int isSerial = 0; char * console = NULL; int noKill = 0; char * argvc[15]; char ** argvp = argvc; char twelve = 12; struct serial_struct si; int i, disable_keys; if (!strncmp(basename(argv[0]), "poweroff", 8)) { printf("Running poweroff...\n"); fd = getInitPid(); if (fd > 0) kill(fd, SIGUSR2); exit(0); } else if (!strncmp(basename(argv[0]), "halt", 4)) { printf("Running halt...\n"); fd = getInitPid(); if (fd > 0) kill(fd, SIGUSR1); exit(0); } else if (!strncmp(basename(argv[0]), "reboot", 6)) { printf("Running reboot...\n"); fd = getInitPid(); if (fd > 0) kill(fd, SIGINT); exit(0); } #if !defined(__s390__) && !defined(__s390x__) testing = (getppid() != 0) && (getppid() != 1); #endif if (!testing) { /* turn off screen blanking */ printstr("\033[9;0]"); printstr("\033[8]"); } else { printstr("(running in test mode).\n"); sleep(2); } umask(022); printstr("\nGreetings.\n"); printf("Redoop installer init version %s starting\n", VERSION); printf("mounting /proc filesystem... "); if (!testing) { if (mount("/proc", "/proc", "proc", 0, NULL)) fatal_error(1); } printf("done\n"); printf("creating /dev filesystem... "); if (!testing) { if (mount("/dev", "/dev", "tmpfs", 0, NULL)) fatal_error(1); createDevices(); printf("done\n"); printf("starting udev..."); if (fork() == 0) { execl("/sbin/udevd", "/sbin/udevd","--daemon",NULL); exit(1); } } printf("done\n"); printf("populating /dev filesystem... "); if (fork() == 0) { execl("/sbin/udevadm", "/sbin/udevadm","trigger", "--action=add", NULL); exit(1); } printf("done\n"); printf("mounting /dev/pts (unix98 pty) filesystem... "); if (!testing) { if (mount("/dev/pts", "/dev/pts", "devpts", 0, NULL)) fatal_error(1); } printf("done\n"); printf("mounting /sys filesystem... "); if (!testing) { if (mount("/sys", "/sys", "sysfs", 0, NULL)) fatal_error(1); } printf("done\n"); /* these args are only for testing from commandline */ for (i = 1; i < argc; i++) { if (!strcmp (argv[i], "serial")) { isSerial = 1; break; } } noKill = getNoKill(); #if !defined(__s390__) && !defined(__s390x__) static struct termios orig_cmode; struct termios cmode, mode; int cfd; cfd = open("/dev/console", O_RDONLY); tcgetattr(cfd,&orig_cmode); close(cfd); cmode = orig_cmode; cmode.c_lflag &= (~ECHO); cfd = open("/dev/console", O_WRONLY); tcsetattr(cfd,TCSANOW,&cmode); close(cfd); /* handle weird consoles */ #if defined(__powerpc__) char * consoles[] = { "/dev/hvc0", /* hvc for JS20 */ "/dev/hvsi0", "/dev/hvsi1", "/dev/hvsi2", /* hvsi for POWER5 */ NULL }; #elif defined (__ia64__) char * consoles[] = { "/dev/ttySG0", "/dev/xvc0", "/dev/hvc0", NULL }; #elif defined (__i386__) || defined (__x86_64__) char * consoles[] = { "/dev/xvc0", "/dev/hvc0", NULL }; #else char * consoles[] = { NULL }; #endif for (i = 0; consoles[i] != NULL; i++) { if ((fd = open(consoles[i], O_RDWR)) >= 0 && !tcgetattr(fd, &mode) && !termcmp(&cmode, &mode)) { printf("Redoop installer init version %s using %s as console\n", VERSION, consoles[i]); isSerial = 3; console = strdup(consoles[i]); break; } close(fd); } cfd = open("/dev/console", O_WRONLY); tcsetattr(cfd,TCSANOW,&orig_cmode); close(cfd); if ((fd < 0) && (ioctl (0, TIOCLINUX, &twelve) < 0)) { isSerial = 2; if (ioctl(0, TIOCGSERIAL, &si) == -1) { isSerial = 0; } } if (isSerial && (isSerial != 3)) { char *device = "/dev/ttyS0"; printf("anaconda installer init version %s using a serial console\n", VERSION); if (isSerial == 2) device = "/dev/console"; fd = open(device, O_RDWR, 0); if (fd < 0) device = "/dev/tts/0"; if (fd < 0) { printf("failed to open %s\n", device); fatal_error(1); } setupTerminal(fd); } else if (isSerial == 3) { setupTerminal(fd); } else if (fd < 0) { fd = open("/dev/tty1", O_RDWR, 0); if (fd < 0) fd = open("/dev/vc/1", O_RDWR, 0); if (fd < 0) { printf("failed to open /dev/tty1 and /dev/vc/1"); fatal_error(1); } } if (testing) exit(0); setsid(); if (ioctl(0, TIOCSCTTY, NULL)) { printf("could not set new controlling tty\n"); } dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); if (fd > 2) close(fd); #else dup2(0, 1); dup2(0, 2); #endif /* disable Ctrl+Z, Ctrl+C, etc ... but not in rescue mode */ disable_keys = 1; if (argc > 1) if (strstr(argv[1], "rescue")) disable_keys = 0; if (disable_keys) { tcgetattr(0, &ts); ts.c_iflag &= ~BRKINT; ts.c_iflag |= IGNBRK; ts.c_iflag &= ~ISIG; tcsetattr(0, TCSANOW, &ts); } if (!testing) { int ret; ret = sethostname("localhost.localdomain", 21); /* the default domainname (as of 2.0.35) is "(none)", which confuses glibc */ ret = setdomainname("", 0); } printf("trying to remount root filesystem read write... "); if (mount("/", "/", "ext2", MS_REMOUNT | MS_MGC_VAL, NULL)) { fatal_error(1); } printf("done\n"); /* we want our /tmp to be ramfs, but we also want to let people hack * their initrds to add things like a ks.cfg, so this has to be a little * tricky */ if (!testing) { rename("/tmp", "/oldtmp"); mkdir("/tmp", 0755); printf("mounting /tmp as ramfs... "); if (mount("none", "/tmp", "ramfs", 0, NULL)) fatal_error(1); printf("done\n"); copyDirectory("/oldtmp", "/tmp", copyErrorFn, copyErrorFn); unlink("/oldtmp"); } /* Now we have some /tmp space set up, and /etc and /dev point to it. We should be in pretty good shape. */ if (!testing) doklog("/dev/tty4"); /* write out a pid file */ if ((fd = open("/var/run/init.pid", O_WRONLY|O_CREAT, 0644)) > 0) { char * buf = malloc(10); int ret; snprintf(buf, 9, "%d", getpid()); ret = write(fd, buf, strlen(buf)); close(fd); free(buf); } else { printf("unable to write init.pid (%d): %m\n", errno); sleep(2); } /* D-Bus */ if (!testing) { if (fork() == 0) { execl("/sbin/dbus-uuidgen", "/sbin/dbus-uuidgen", "--ensure", NULL); perror("launching /sbin/dbus-uuidgen"); exit(1); } if (fork() == 0) { execl("/sbin/dbus-daemon", "/sbin/dbus-daemon", "--system", NULL); perror("launching /sbin/dbus-daemon"); exit(1); } sleep(3); } /* Go into normal init mode - keep going, and then do a orderly shutdown when: 1) /bin/install exits 2) we receive a SIGHUP */ printf("running install...\n"); setsid(); if (!(installpid = fork())) { /* * comment out this lines for loader * debuging, and comment in the following * loader line. */ //printf("running bash for early testing\n"); //*argvp++ = "/bin/bash"; *argvp++ = "/sbin/loader"; if (isSerial == 3) { *argvp++ = "--virtpconsole"; *argvp++ = console; } *argvp++ = NULL; printf("running %s\n", argvc[0]); execve(argvc[0], argvc, env); shutDown(1, 0, 0); } /* signal handlers for halt/poweroff */ signal(SIGUSR1, sigUsr1Handler); signal(SIGUSR2, sigUsr2Handler); /* set up the ctrl+alt+delete handler to kill our pid, not pid 1 */ signal(SIGINT, sigintHandler); if ((fd = open("/proc/sys/kernel/cad_pid", O_WRONLY)) != -1) { char buf[7]; size_t count; sprintf(buf, "%d", getpid()); count = write(fd, buf, strlen(buf)); close(fd); /* if we succeeded in writing our pid, turn off the hard reboot ctrl-alt-del handler */ if (count == strlen(buf) && (fd = open("/proc/sys/kernel/ctrl-alt-del", O_WRONLY)) != -1) { int ret; ret = write(fd, "0", 1); close(fd); } } while (!doShutdown) { childpid = waitpid(-1, &waitStatus, 0); if (childpid == installpid) doShutdown = 1; } if (!WIFEXITED(waitStatus) || (WIFEXITED(waitStatus) && WEXITSTATUS(waitStatus))) { printf("install exited abnormally [%d/%d] ", WIFEXITED(waitStatus), WEXITSTATUS(waitStatus)); if (WIFSIGNALED(waitStatus)) { printf("-- received signal %d", WTERMSIG(waitStatus)); } printf("\n"); } else { doReboot = 1; } if (testing) exit(0); shutDown(noKill, doReboot, 0); return 0; }
int CHDDChkExec::exec(CMenuTarget* parent, const std::string& key) { char cmd[100]; CHintBox * hintbox; int res; char src[128], dst[128]; FILE * f; CProgressWindow * progress; int oldpass = 0, pass, step, total; int percent = 0, opercent = 0; sprintf(src, "/dev/%s1", key.c_str()); sprintf(dst, "/media/%s1", key.c_str()); printf("CHDDChkExec: key %s\n", key.c_str()); bool srun = system("killall -9 smbd"); //res = check_and_umount(dst); res = check_and_umount(src, dst); printf("CHDDChkExec: umount res %d\n", res); if(res) { hintbox = new CHintBox(LOCALE_HDD_CHECK, g_Locale->getText(LOCALE_HDD_UMOUNT_WARN)); hintbox->paint(); sleep(2); delete hintbox; return menu_return::RETURN_REPAINT; } switch(g_settings.hdd_fs) { case 0: sprintf(cmd, "/sbin/fsck.ext3 -C 1 -f -y %s", src); break; case 1: sprintf(cmd, "/sbin/fsck.ext2 -C 1 -f -y %s", src); break; case 2: sprintf(cmd, "/sbin/reiserfsck --fix-fixable %s", src); break; default: return 0; } printf("CHDDChkExec: Executing %s\n", cmd); f=popen(cmd, "r"); if(!f) { hintbox = new CHintBox(LOCALE_HDD_CHECK, g_Locale->getText(LOCALE_HDD_CHECK_FAILED)); hintbox->paint(); sleep(2); delete hintbox; goto ret1; } progress = new CProgressWindow(); progress->setTitle(LOCALE_HDD_CHECK); progress->exec(NULL,""); char buf[256]; while(fgets(buf, 255, f) != NULL) { if(isdigit(buf[0])) { sscanf(buf, "%d %d %d\n", &pass, &step, &total); if(total == 0) total = 1; if(oldpass != pass) { oldpass = pass; progress->showGlobalStatus(pass > 0 ? (pass-1)*20: 0); } percent = (step * 100) / total; if(opercent != percent) { opercent = percent; //printf("CHDDChkExec: pass %d : %d\n", pass, percent); progress->showLocalStatus(percent); } } else if(!strncmp(buf, "Pass", 4)) progress->showStatusMessageUTF(buf); } //printf("CHDDChkExec: %s\n", buf); pclose(f); progress->showGlobalStatus(100); progress->showStatusMessageUTF(buf); sleep(2); progress->hide(); delete progress; ret1: switch(g_settings.hdd_fs) { case 0: res = mount(src, dst, "ext3", 0, NULL); break; case 1: res = mount(src, dst, "ext2", 0, NULL); break; case 2: res = mount(src, dst, "reiserfs", 0, NULL); break; default: break; } printf("CHDDChkExec: mount res %d\n", res); if(!srun) system("smbd"); return menu_return::RETURN_REPAINT; }
static int do_umount(struct libmnt_context *cxt) { int rc = 0, flags = 0; const char *src, *target; char *tgtbuf = NULL; assert(cxt); assert(cxt->fs); assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); assert(cxt->syscall_status == 1); if (cxt->helper) return exec_helper(cxt); src = mnt_fs_get_srcpath(cxt->fs); target = mnt_fs_get_target(cxt->fs); if (!target) return -EINVAL; DBG(CXT, ul_debugobj(cxt, "do umount")); if (cxt->restricted && !mnt_context_is_fake(cxt)) { /* * extra paranoia for non-root users * -- chdir to the parent of the mountpoint and use NOFOLLOW * flag to avoid races and symlink attacks. */ if (umount_nofollow_support()) flags |= UMOUNT_NOFOLLOW; rc = mnt_chdir_to_parent(target, &tgtbuf); if (rc) return rc; target = tgtbuf; } if (mnt_context_is_lazy(cxt)) flags |= MNT_DETACH; else if (mnt_context_is_force(cxt)) flags |= MNT_FORCE; DBG(CXT, ul_debugobj(cxt, "umount(2) [target='%s', flags=0x%08x]%s", target, flags, mnt_context_is_fake(cxt) ? " (FAKE)" : "")); if (mnt_context_is_fake(cxt)) rc = 0; else { rc = flags ? umount2(target, flags) : umount(target); if (rc < 0) cxt->syscall_status = -errno; free(tgtbuf); } /* * try remount read-only */ if (rc < 0 && cxt->syscall_status == -EBUSY && mnt_context_is_rdonly_umount(cxt) && src) { mnt_context_set_mflags(cxt, (cxt->mountflags | MS_REMOUNT | MS_RDONLY)); mnt_context_enable_loopdel(cxt, FALSE); DBG(CXT, ul_debugobj(cxt, "umount(2) failed [errno=%d] -- trying to remount read-only", -cxt->syscall_status)); rc = mount(src, mnt_fs_get_target(cxt->fs), NULL, MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL); if (rc < 0) { cxt->syscall_status = -errno; DBG(CXT, ul_debugobj(cxt, "read-only re-mount(2) failed [errno=%d]", -cxt->syscall_status)); return -cxt->syscall_status; } cxt->syscall_status = 0; DBG(CXT, ul_debugobj(cxt, "read-only re-mount(2) success")); return 0; } if (rc < 0) { DBG(CXT, ul_debugobj(cxt, "umount(2) failed [errno=%d]", -cxt->syscall_status)); return -cxt->syscall_status; } cxt->syscall_status = 0; DBG(CXT, ul_debugobj(cxt, "umount(2) success")); return 0; }
/* Umount a single device. Return a status code, so don't exit on a non-fatal error. We lock/unlock around each umount. */ static int umount_one (const char *spec, const char *node, const char *type, const char *opts, struct mntentchn *mc) { int umnt_err = 0; int isroot; int res; int status; const char *loopdev; int myloop = 0; /* Special case for root. As of 0.99pl10 we can (almost) unmount root; the kernel will remount it readonly so that we can carry on running afterwards. The readonly remount is illegal if any files are opened for writing at the time, so we can't update mtab for an unmount of root. As it is only really a remount, this doesn't matter too much. [sct May 29, 1993] */ isroot = (streq (node, "/") || streq (node, "root") || streq (node, "rootfs")); if (isroot) nomtab++; /* * Call umount.TYPE for types that require a separate umount program. * All such special things must occur isolated in the types string. */ if (check_special_umountprog(spec, node, type, &status)) return status; /* * Ignore the option "-d" for non-loop devices and loop devices with * LO_FLAGS_AUTOCLEAR flag. */ if (delloop && is_loop_device(spec) && !is_loop_autoclear(spec)) myloop = 1; if (lazy) { res = umount2 (node, MNT_DETACH); if (res < 0) umnt_err = errno; goto writemtab; } if (force) { /* only supported for NFS */ res = umount2 (node, MNT_FORCE); if (res == -1) { int errsv = errno; perror("umount2"); errno = errsv; if (errno == ENOSYS) { if (verbose) printf(_("no umount2, trying umount...\n")); res = umount (node); } } } else res = umount (node); if (res < 0) umnt_err = errno; if (res < 0 && remount && umnt_err == EBUSY) { /* Umount failed - let us try a remount */ res = mount(spec, node, NULL, MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL); if (res == 0) { struct my_mntent remnt; fprintf(stderr, _("umount: %s busy - remounted read-only\n"), spec); remnt.mnt_type = remnt.mnt_fsname = NULL; remnt.mnt_dir = xstrdup(node); remnt.mnt_opts = xstrdup("ro"); if (!nomtab) update_mtab(node, &remnt); return 0; } else if (errno != EBUSY) { /* hmm ... */ perror("remount"); fprintf(stderr, _("umount: could not remount %s read-only\n"), spec); } } loopdev = 0; if (res >= 0) { /* Umount succeeded */ if (verbose) printf (_("%s umounted\n"), spec); /* Free any loop devices that we allocated ourselves */ if (mc) { char *optl; /* old style mtab line? */ if (streq(mc->m.mnt_type, "loop")) { loopdev = spec; goto gotloop; } /* new style mtab line? */ optl = mc->m.mnt_opts ? xstrdup(mc->m.mnt_opts) : ""; for (optl = strtok (optl, ","); optl; optl = strtok (NULL, ",")) { if (!strncmp(optl, "loop=", 5)) { loopdev = optl+5; goto gotloop; } } } else { /* * If option "-o loop=spec" occurs in mtab, * note the mount point, and delete mtab line. */ if ((mc = getmntoptfile (spec)) != NULL) node = mc->m.mnt_dir; } /* Also free loop devices when -d flag is given */ if (myloop) loopdev = spec; } gotloop: if (loopdev) del_loop(loopdev); writemtab: if (!nomtab && (umnt_err == 0 || umnt_err == EINVAL || umnt_err == ENOENT)) { update_mtab (node, NULL); } if (res >= 0) return 0; if (umnt_err) complain(umnt_err, node); return 1; }
int CHDDFmtExec::exec(CMenuTarget* parent, const std::string& key) { char cmd[100]; CHintBox * hintbox; int res; FILE * f; char src[128], dst[128]; CProgressWindow * progress; bool idone; sprintf(src, "/dev/%s1", key.c_str()); sprintf(dst, "/media/%s1", key.c_str()); printf("CHDDFmtExec: key %s\n", key.c_str()); res = ShowMsgUTF ( LOCALE_HDD_FORMAT, g_Locale->getText(LOCALE_HDD_FORMAT_WARN), CMessageBox::mbrNo, CMessageBox::mbYes | CMessageBox::mbNo ); if(res != CMessageBox::mbrYes) return 0; bool srun = system("killall -9 smbd"); //res = check_and_umount(dst); res = check_and_umount(src, dst); printf("CHDDFmtExec: umount res %d\n", res); if(res) { hintbox = new CHintBox(LOCALE_HDD_FORMAT, g_Locale->getText(LOCALE_HDD_UMOUNT_WARN)); hintbox->paint(); sleep(2); delete hintbox; goto _return; } f = fopen("/proc/sys/kernel/hotplug", "w"); if(f) { fprintf(f, "none\n"); fclose(f); } progress = new CProgressWindow(); progress->setTitle(LOCALE_HDD_FORMAT); progress->exec(NULL,""); progress->showStatusMessageUTF("Executing fdisk"); progress->showGlobalStatus(0); sprintf(cmd, "/sbin/sfdisk -f -uM /dev/%s", key.c_str()); printf("CHDDFmtExec: executing %s\n", cmd); f=popen(cmd, "w"); if (!f) { hintbox = new CHintBox(LOCALE_HDD_FORMAT, g_Locale->getText(LOCALE_HDD_FORMAT_FAILED)); hintbox->paint(); sleep(2); delete hintbox; goto _remount; } fprintf(f, "0,\n;\n;\n;\ny\n"); pclose(f); //sleep(1); switch(g_settings.hdd_fs) { case 0: sprintf(cmd, "/sbin/mkfs.ext3 -L RECORD -T largefile -j -m0 %s", src); break; case 1: sprintf(cmd, "/sbin/mkfs.ext2 -L RECORD -T largefile -m0 %s", src); break; case 2: sprintf(cmd, "/sbin/mkreiserfs -f -f %s", src); break; default: return 0; } printf("CHDDFmtExec: executing %s\n", cmd); f=popen(cmd, "r"); if (!f) { hintbox = new CHintBox(LOCALE_HDD_FORMAT, g_Locale->getText(LOCALE_HDD_FORMAT_FAILED)); hintbox->paint(); sleep(2); delete hintbox; goto _remount; } char buf[256]; idone = false; while(fgets(buf, 255, f) != NULL) { printf("%s", buf); if(!idone && strncmp(buf, "Writing inode", 13)) { idone = true; buf[21] = 0; progress->showGlobalStatus(20); progress->showStatusMessageUTF(buf); } else if(strncmp(buf, "Creating", 8)) { progress->showGlobalStatus(40); progress->showStatusMessageUTF(buf); } else if(strncmp(buf, "Writing superblocks", 19)) { progress->showGlobalStatus(60); progress->showStatusMessageUTF(buf); } } pclose(f); progress->showGlobalStatus(100); sleep(2); sprintf(cmd, "/sbin/tune2fs -r 0 -c 0 -i 0 %s", src); printf("CHDDFmtExec: executing %s\n", cmd); system(cmd); _remount: progress->hide(); delete progress; switch(g_settings.hdd_fs) { case 0: res = mount(src, dst, "ext3", 0, NULL); break; case 1: res = mount(src, dst, "ext2", 0, NULL); break; case 2: res = mount(src, dst, "reiserfs", 0, NULL); break; default: break; } f = fopen("/proc/sys/kernel/hotplug", "w"); if(f) { fprintf(f, "/sbin/hotplug\n"); fclose(f); } if(!res) { sprintf(cmd, "%s/movies", dst); safe_mkdir((char *) cmd); sprintf(cmd, "%s/pictures", dst); safe_mkdir((char *) cmd); sprintf(cmd, "%s/epg", dst); safe_mkdir((char *) cmd); sprintf(cmd, "%s/music", dst); safe_mkdir((char *) cmd); sync(); } _return: if(!srun) system("smbd"); return menu_return::RETURN_REPAINT; }
void __liblustre_setup_(void) { char *target = NULL; char *lustre_driver = "lustre"; unsigned mntflgs = 0; int err, count; lustre_path = getenv("LIBLUSTRE_MOUNT_POINT"); if (!lustre_path) { lustre_path = "/mnt/lustre"; } target = getenv("LIBLUSTRE_MOUNT_RETRY"); if (target) { mnt_retry = atoi(target); if (mnt_retry < 0) mnt_retry = 0; } /* mount target */ target = getenv("LIBLUSTRE_MOUNT_TARGET"); if (!target) { printf("LibLustre: no mount target specified\n"); exit(1); } CDEBUG(D_CONFIG, "LibLustre: mount point %s, target %s\n", lustre_path, target); #ifdef INIT_SYSIO /* initialize libsysio & mount rootfs */ if (_sysio_init()) { perror("init sysio"); exit(1); } _sysio_native_init(); err = _sysio_mount_root("/", "native", mntflgs, NULL); if (err) { fprintf(stderr, "sysio mount failed: %s\n", strerror(errno)); exit(1); } if (_sysio_lustre_init()) exit(1); #endif /* INIT_SYSIO */ count = mnt_retry; do { err = mount(target, lustre_path, lustre_driver, mntflgs, NULL); if (err && mnt_retry && (-- count)) { fprintf(stderr, "Lustre mount failed: %s. " "Will retry %d more times\n", strerror(errno), mnt_retry - count ); sleep(2); } } while (err && count > 0); if (err) { fprintf(stderr, "Lustre mount failed: %s\n", strerror(errno)); exit(1); } }
int ns_child(void *_arg) { struct ns_exec_args *args = _arg; int fd2; int id1, id2; struct stat st1, st2; char lpath[PATH_MAX], fpath[PATH_MAX]; snprintf(fpath, sizeof(fpath), "%s/1", dirname); if (umount(fpath)) { pr_perror("umount"); return 1; } snprintf(lpath, sizeof(lpath), "%s/0/2", dirname); snprintf(fpath, sizeof(fpath), "%s/2", dirname); if (mkdir(fpath, 0600) < 0) { fail("Can't make zdtm_sys"); return 1; } if (mount(lpath, fpath, NULL, MS_BIND, NULL)) { pr_perror("mount"); return 1; } snprintf(fpath, sizeof(fpath), "%s/0", dirname); if (umount(fpath)) { pr_perror("umount"); return 1; } snprintf(fpath, sizeof(fpath), "%s/2/%s", dirname, MPTS_FILE); fd2 = open(fpath, O_RDWR); if (fd2 < 0) { pr_perror("open"); return -1; } close(args->sync); test_waitsig(); id1 = get_mntid(args->fd); id2 = get_mntid(fd2); if (id1 <0 || id2 < 0) exit(1); if (fstat(args->fd, &st1) || fstat(fd2, &st2)) { pr_perror("stat"); exit(1); } test_msg("%d %d", id1, id2); #ifdef ZDTM_LINK_REMAP if (st1.st_nlink != 1) { #else if (st1.st_nlink != 0) { #endif pr_perror("Wrong number of links: %d", st1.st_nlink); exit(1); } if (id1 > 0 && id1 != id2 && st1.st_ino == st2.st_ino) exit(AWK_OK); else exit(AWK_FAIL); } int main(int argc, char **argv) { struct ns_exec_args args; pid_t pid = -1; char lpath[PATH_MAX], fpath[PATH_MAX]; char buf[256]; int p[2]; test_init(argc, argv); if (mkdir(dirname, 0600) < 0) { fail("Can't make zdtm_sys"); return 1; } if (mount("test", dirname, "tmpfs", 0, NULL)) { pr_perror("mount"); return 1; } snprintf(fpath, sizeof(fpath), "%s/0", dirname); if (mkdir(fpath, 0600) < 0) { fail("Can't make zdtm_sys"); return 1; } if (mount("test", fpath, "tmpfs", 0, NULL)) { pr_perror("mount"); return 1; } snprintf(lpath, sizeof(lpath), "%s/0/1", dirname); if (mkdir(lpath, 0600) < 0) { fail("Can't make zdtm_sys"); return 1; } snprintf(fpath, sizeof(fpath), "%s/1", dirname); if (mkdir(fpath, 0600) < 0) { fail("Can't make zdtm_sys"); return 1; } if (mount(lpath, fpath, NULL, MS_BIND, NULL)) { pr_perror("mount"); return 1; } snprintf(lpath, sizeof(lpath), "%s/0/2", dirname); if (mkdir(lpath, 0600) < 0) { fail("Can't make zdtm_sys"); return 1; } if (pipe(p) == -1) { pr_perror("pipe"); return 1; } if (getenv("ZDTM_NOSUBNS") == NULL) { snprintf(fpath, sizeof(fpath), "%s/1/%s", dirname, MPTS_FILE); args.fd = open(fpath, O_CREAT | O_RDWR, 0600); if (args.fd < 0) { fail("Can't open file"); return 1; } snprintf(fpath, sizeof(fpath), "%s/0/1/%s", dirname, MPTS_FILE); snprintf(lpath, sizeof(fpath), "%s/0/2/%s", dirname, MPTS_FILE); if (link(fpath, lpath) == -1) { pr_perror("link"); return -1; } #ifdef ZDTM_LINK_REMAP snprintf(lpath, sizeof(fpath), "%s/0/%s", dirname, MPTS_FILE); if (link(fpath, lpath) == -1) { pr_perror("link"); return -1; } #endif args.sync = p[1]; pid = clone(ns_child, args.stack_ptr, CLONE_NEWNS | SIGCHLD, &args); if (pid < 0) { pr_perror("Unable to fork child"); return 1; } close(args.fd); } close(p[1]); read(p[0], buf, sizeof(buf)); snprintf(fpath, sizeof(fpath), "%s/0/1/%s", dirname, MPTS_FILE); if (unlink(fpath)) return 1; snprintf(fpath, sizeof(fpath), "%s/0/2/%s", dirname, MPTS_FILE); if (unlink(fpath)) return 1; test_daemon(); test_waitsig(); if (pid > 0) { kill(pid, SIGTERM); int status = 1; wait(&status); if (WIFEXITED(status)) { if (WEXITSTATUS(status) == AWK_OK) pass(); else if (WEXITSTATUS(status) == AWK_FAIL) fail("Mount ID not restored"); else fail("Failed to check mount IDs (%d)", WEXITSTATUS(status)); } else fail("Test died"); } umount2(dirname, MNT_DETACH); rmdir(dirname); return 0; }
int main(int UNUSED(args), char *argv[]) { /* * Initial setup of signals, ignore all until we're up. */ sig_init(); /* * Mount base file system, kernel is assumed to run devtmpfs for /dev */ chdir("/"); umask(0); mount("none", "/proc", "proc", 0, NULL); mount("none", "/proc/bus/usb", "usbfs", 0, NULL); mount("none", "/sys", "sysfs", 0, NULL); mkdir("/dev/pts", 0755); mkdir("/dev/shm", 0755); mount("none", "/dev/pts", "devpts", 0, "gid=5,mode=620"); mount("none", "/dev/shm", "tmpfs", 0, NULL); umask(022); /* * Parse kernel parameters */ parse_kernel_cmdline(); cls(); echo("finit " VERSION " (built " __DATE__ " " __TIME__ " by " WHOAMI ")"); /* * Populate /dev and prepare for runtime events from kernel. */ #if defined(USE_UDEV) run_interactive("udevd --daemon", "Populating device tree"); #elif defined (MDEV) run_interactive(MDEV " -s", "Populating device tree"); #endif /* * Parse configuration file */ parse_finit_conf(FINIT_CONF); /* * Load plugins. Must run after finit.conf has registered * all services, or service plugins won't have anything to * hook on to. */ print_desc("", "Loading plugins"); print_result(plugin_load_all(PLUGIN_PATH)); /* * Mount filesystems */ _d("Mount filesystems in /etc/fstab ..."); #ifdef REMOUNT_ROOTFS_RW run("/bin/mount -n -o remount,rw /"); #endif #ifdef SYSROOT run(SYSROOT, "/", NULL, MS_MOVE, NULL); #endif _d("Root FS up, calling hooks ..."); plugin_run_hooks(HOOK_ROOTFS_UP); umask(0); run("/bin/mount -na"); run("/sbin/swapon -ea"); umask(0022); /* Cleanup stale files, if any still linger on. */ run_interactive("rm -rf /tmp/* /var/run/* /var/lock/*", "Cleanup temporary directories"); /* * Base FS up, enable standard SysV init signals */ sig_setup(); _d("Base FS up, calling hooks ..."); plugin_run_hooks(HOOK_BASEFS_UP); /* * Network stuff */ /* Setup kernel specific settings, e.g. allow broadcast ping, etc. */ run("/sbin/sysctl -e -p /etc/sysctl.conf >/dev/null"); /* Set initial hostname. */ set_hostname(hostname); ifconfig("lo", "127.0.0.1", "255.0.0.0", 1); if (network) run_interactive(network, "Starting networking: %s", network); umask(022); /* * Hooks that rely on loopback, or basic networking being up. */ plugin_run_hooks(HOOK_NETWORK_UP); /* * Start service monitor framework */ _d("Starting all static services from %s", FINIT_CONF); svc_start_all(); /* * Run startup scripts in /etc/finit.d/, if any. */ if (rcsd && fisdir(rcsd)) { _d("Running startup scripts in %s ...", rcsd); run_parts(rcsd, NULL); } /* * Hooks that should run at the very end */ plugin_run_hooks(HOOK_SYSTEM_UP); /* Start GETTY on console */ _d("Starting getty on console ..."); run_getty(GETTY, argv); /* * Enter main loop to monior /dev/initctl and services */ _d("Entering main loop ..."); return run_loop(); }
int board_app_initialize(uintptr_t arg) { #ifdef HAVE_RTC_DRIVER FAR struct rtc_lowerhalf_s *rtclower; #endif #if defined(HAVE_N25QXXX) FAR struct mtd_dev_s *mtd_temp; #endif #if defined(HAVE_N25QXXX_CHARDEV) char blockdev[18]; char chardev[12]; #endif int ret; (void)ret; #ifdef HAVE_PROC /* mount the proc filesystem */ syslog(LOG_INFO, "Mounting procfs to /proc\n"); ret = mount(NULL, CONFIG_NSH_PROC_MOUNTPOINT, "procfs", 0, NULL); if (ret < 0) { syslog(LOG_ERR, "ERROR: Failed to mount the PROC filesystem: %d (%d)\n", ret, errno); return ret; } #endif #ifdef HAVE_RTC_DRIVER /* Instantiate the STM32 lower-half RTC driver */ rtclower = stm32l4_rtc_lowerhalf(); if (!rtclower) { serr("ERROR: Failed to instantiate the RTC lower-half driver\n"); return -ENOMEM; } else { /* Bind the lower half driver and register the combined RTC driver * as /dev/rtc0 */ ret = rtc_initialize(0, rtclower); if (ret < 0) { serr("ERROR: Failed to bind/register the RTC driver: %d\n", ret); return ret; } } #endif #ifdef HAVE_N25QXXX /* Create an instance of the STM32L4 QSPI device driver */ g_qspi = stm32l4_qspi_initialize(0); if (!g_qspi) { _err("ERROR: stm32l4_qspi_initialize failed\n"); return ret; } else { /* Use the QSPI device instance to initialize the * N25QXXX device. */ mtd_temp = n25qxxx_initialize(g_qspi, true); if (!mtd_temp) { _err("ERROR: n25qxxx_initialize failed\n"); return ret; } g_mtd_fs = mtd_temp; #ifdef CONFIG_MTD_PARTITION { FAR struct mtd_geometry_s geo; off_t nblocks; /* Setup a partition of 256KiB for our file system. */ ret = MTD_IOCTL(g_mtd_fs, MTDIOC_GEOMETRY, (unsigned long)(uintptr_t)&geo); if (ret < 0) { _err("ERROR: MTDIOC_GEOMETRY failed\n"); return ret; } nblocks = (256*1024) / geo.blocksize; mtd_temp = mtd_partition(g_mtd_fs, 0, nblocks); if (!mtd_temp) { _err("ERROR: mtd_partition failed\n"); return ret; } g_mtd_fs = mtd_temp; } #endif #ifdef HAVE_N25QXXX_SMARTFS /* Configure the device with no partition support */ ret = smart_initialize(N25QXXX_SMART_MINOR, g_mtd_fs, NULL); if (ret != OK) { _err("ERROR: Failed to initialize SmartFS: %d\n", ret); } #elif defined(HAVE_N25QXXX_NXFFS) /* Initialize to provide NXFFS on the N25QXXX MTD interface */ ret = nxffs_initialize(g_mtd_fs); if (ret < 0) { _err("ERROR: NXFFS initialization failed: %d\n", ret); } /* Mount the file system at /mnt/nxffs */ ret = mount(NULL, "/mnt/nxffs", "nxffs", 0, NULL); if (ret < 0) { _err("ERROR: Failed to mount the NXFFS volume: %d\n", errno); return ret; } #else /* if defined(HAVE_N25QXXX_CHARDEV) */ /* Use the FTL layer to wrap the MTD driver as a block driver */ ret = ftl_initialize(N25QXXX_MTD_MINOR, g_mtd_fs); if (ret < 0) { _err("ERROR: Failed to initialize the FTL layer: %d\n", ret); return ret; } /* Use the minor number to create device paths */ snprintf(blockdev, 18, "/dev/mtdblock%d", N25QXXX_MTD_MINOR); snprintf(chardev, 12, "/dev/mtd%d", N25QXXX_MTD_MINOR); /* Now create a character device on the block device */ /* NOTE: for this to work, you will need to make sure that * CONFIG_FS_WRITABLE is set in the config. It's not a user- * visible setting, but you can make it set by selecting an * arbitrary writable file system (you don't have to actually * use it, just select it so that the block device created via * ftl_initialize() will be writable). */ ret = bchdev_register(blockdev, chardev, false); if (ret < 0) { _err("ERROR: bchdev_register %s failed: %d\n", chardev, ret); return ret; } #endif } #endif #ifdef HAVE_USBHOST /* Initialize USB host operation. stm32l4_usbhost_initialize() starts a thread * will monitor for USB connection and disconnection events. */ ret = stm32l4_usbhost_initialize(); if (ret != OK) { udbg("ERROR: Failed to initialize USB host: %d\n", ret); return ret; } #endif #ifdef HAVE_USBMONITOR /* Start the USB Monitor */ ret = usbmonitor_start(0, NULL); if (ret != OK) { udbg("ERROR: Failed to start USB monitor: %d\n", ret); return ret; } #endif return OK; }
static int create_ns(const char *statedir, const char *name) { char str[64]; uid_t uid = getuid(); gid_t gid = getgid(); if (unshare(CLONE_NEWNS | CLONE_NEWNET | CLONE_NEWUTS | CLONE_NEWUSER) < 0) pdie("can't unshare namespaces"); if (access("/proc/self/setgroups", O_RDONLY) == 0) write_file("/proc/self/setgroups", "deny"); snprintf(str, sizeof(str), "0 %d 1", uid); write_file("/proc/self/uid_map", str); snprintf(str, sizeof(str), "0 %d 1", gid); write_file("/proc/self/gid_map", str); if (sethostname(name, strlen(name)) < 0) pdie("can't set hostname"); setup_ipv4("lo", "127.0.0.1", "255.0.0.0", false, 0); mkdir(statedir, 0755); char *local_etc = populate_statedir(statedir, "etc", true); char *workdir = populate_statedir(statedir, "workdir", true); char *resolv = populate_statedir(statedir, "etc/resolv.conf", false); char *mount_opts; if (asprintf(&mount_opts, "lowerdir=/etc,upperdir=%s,workdir=%s", local_etc, workdir) < 0) { die("can't allocate memory\n"); } /* * overlayfs is only usable on patched kernels (e.g. Ubuntu) due to * permission checks, but it is the cleanest solution because it * overrides symlinks. If we have to use bind mounts instead, * tell the watcher process to re-create the bind mount if * resolv.conf gets deleted. */ int inotify_fd = -1, inotify_wd = -1; if (mount("overlay", "/etc", "overlay", 0, mount_opts) == 0) { /* pass through */ } else { inotify_fd = inotify_init(); if (inotify_fd < 0) pdie("can't create inotify socket"); inotify_wd = watch_and_bind_mount(inotify_fd, resolv); if (inotify_wd < 0) die("can't watch resolv.conf\n"); } /* * Create the initial watcher connection here so that the parent * process doesn't need to wait for the child process to start up. */ int initial_conn_fd[2]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, initial_conn_fd) < 0) pdie("socketpair failed"); write_pid(statedir, create_watcher(statedir, initial_conn_fd[1], resolv, inotify_fd, inotify_wd)); close(initial_conn_fd[1]); close(inotify_fd); free(mount_opts); free(resolv); free(workdir); free(local_etc); return initial_conn_fd[0]; }
int cli_main(int argc, char* argv[]) { umount("/"); mount("", "/", "memfs", 0, NULL); // Setup common environment variables, but don't override those // set already by ppapi_simple. setenv("HOME", "/home/user", 0); setenv("PATH", "/bin", 0); setenv("USER", "user", 0); setenv("LOGNAME", "user", 0); const char* home = getenv("HOME"); mkdir("/home", 0777); mkdir(home, 0777); mkdir("/tmp", 0777); mkdir("/bin", 0777); mkdir("/etc", 0777); mkdir("/mnt", 0777); mkdir("/mnt/http", 0777); mkdir("/mnt/html5", 0777); const char* data_url = getenv("NACL_DATA_URL"); if (!data_url) data_url = "./"; if (mount(data_url, "/mnt/http", "httpfs", 0, "") != 0) { perror("mounting http filesystem at /mnt/http failed"); } if (mount("/", "/mnt/html5", "html5fs", 0, "type=PERSISTENT") != 0) { perror("Mounting HTML5 filesystem in /mnt/html5 failed."); } else { mkdir("/mnt/html5/home", 0777); struct stat st; if (stat("/mnt/html5/home", &st) < 0 || !S_ISDIR(st.st_mode)) { perror("Unable to create home directory in persistent storage."); } else { if (mount("/home", home, "html5fs", 0, "type=PERSISTENT") != 0) { fprintf(stderr, "Mounting HTML5 filesystem in %s failed.\n", home); } } } if (mount("/", "/tmp", "html5fs", 0, "type=TEMPORARY") != 0) { perror("Mounting HTML5 filesystem in /tmp failed."); } /* naclprocess.js sends the current working directory using this * environment variable. */ if (getenv("PWD")) chdir(getenv("PWD")); // Tell the NaCl architecture to /etc/bashrc of mingn. #if defined(__x86_64__) static const char kNaClArch[] = "x86_64"; #elif defined(__i686__) static const char kNaClArch[] = "i686"; #elif defined(__arm__) static const char kNaClArch[] = "arm"; #elif defined(__pnacl__) static const char kNaClArch[] = "pnacl"; #else # error "Unknown architecture" #endif // Set NACL_ARCH with a guess if not set (0 == set if not already). setenv("NACL_ARCH", kNaClArch, 0); // Set NACL_BOOT_ARCH if not inherited from a parent (0 == set if not already // set). This will let us prefer PNaCl if we started with PNaCl (for tests // mainly). setenv("NACL_BOOT_ARCH", kNaClArch, 0); setlocale(LC_CTYPE, ""); nacl_spawn_pid = getenv_as_int("NACL_PID"); nacl_spawn_ppid = getenv_as_int("NACL_PPID"); return nacl_main(argc, argv); }
static void test_get_process_cmdline_harder(void) { char path[] = "/tmp/test-cmdlineXXXXXX"; _cleanup_close_ int fd = -1; _cleanup_free_ char *line = NULL; pid_t pid; if (geteuid() != 0) return; #if HAVE_VALGRIND_VALGRIND_H /* valgrind patches open(/proc//cmdline) * so, test_get_process_cmdline_harder fails always * See https://github.com/systemd/systemd/pull/3555#issuecomment-226564908 */ if (RUNNING_ON_VALGRIND) return; #endif pid = fork(); if (pid > 0) { siginfo_t si; (void) wait_for_terminate(pid, &si); assert_se(si.si_code == CLD_EXITED); assert_se(si.si_status == 0); return; } assert_se(pid == 0); assert_se(unshare(CLONE_NEWNS) >= 0); assert_se(mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) >= 0); fd = mkostemp(path, O_CLOEXEC); assert_se(fd >= 0); if (mount(path, "/proc/self/cmdline", "bind", MS_BIND, NULL) < 0) { /* This happens under selinux… Abort the test in this case. */ log_warning_errno(errno, "mount(..., \"/proc/self/cmdline\", \"bind\", ...) failed: %m"); assert(errno == EACCES); return; } assert_se(unlink(path) >= 0); assert_se(prctl(PR_SET_NAME, "testa") >= 0); assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) == -ENOENT); assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0); assert_se(streq(line, "[testa]")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 1, true, &line) >= 0); assert_se(streq(line, "")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 2, true, &line) >= 0); assert_se(streq(line, "[")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 3, true, &line) >= 0); assert_se(streq(line, "[.")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 4, true, &line) >= 0); assert_se(streq(line, "[..")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 5, true, &line) >= 0); assert_se(streq(line, "[...")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 6, true, &line) >= 0); assert_se(streq(line, "[...]")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 7, true, &line) >= 0); assert_se(streq(line, "[t...]")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 8, true, &line) >= 0); assert_se(streq(line, "[testa]")); line = mfree(line); assert_se(write(fd, "\0\0\0\0\0\0\0\0\0", 10) == 10); assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) == -ENOENT); assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0); assert_se(streq(line, "[testa]")); line = mfree(line); assert_se(write(fd, "foo\0bar\0\0\0\0\0", 10) == 10); assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) >= 0); assert_se(streq(line, "foo bar")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0); assert_se(streq(line, "foo bar")); line = mfree(line); assert_se(write(fd, "quux", 4) == 4); assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) >= 0); assert_se(streq(line, "foo bar quux")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0); assert_se(streq(line, "foo bar quux")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 1, true, &line) >= 0); assert_se(streq(line, "")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 2, true, &line) >= 0); assert_se(streq(line, ".")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 3, true, &line) >= 0); assert_se(streq(line, "..")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 4, true, &line) >= 0); assert_se(streq(line, "...")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 5, true, &line) >= 0); assert_se(streq(line, "f...")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 6, true, &line) >= 0); assert_se(streq(line, "fo...")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 7, true, &line) >= 0); assert_se(streq(line, "foo...")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 8, true, &line) >= 0); assert_se(streq(line, "foo...")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 9, true, &line) >= 0); assert_se(streq(line, "foo b...")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 10, true, &line) >= 0); assert_se(streq(line, "foo ba...")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 11, true, &line) >= 0); assert_se(streq(line, "foo bar...")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 12, true, &line) >= 0); assert_se(streq(line, "foo bar...")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 13, true, &line) >= 0); assert_se(streq(line, "foo bar quux")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 14, true, &line) >= 0); assert_se(streq(line, "foo bar quux")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 1000, true, &line) >= 0); assert_se(streq(line, "foo bar quux")); line = mfree(line); assert_se(ftruncate(fd, 0) >= 0); assert_se(prctl(PR_SET_NAME, "aaaa bbbb cccc") >= 0); assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) == -ENOENT); assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0); assert_se(streq(line, "[aaaa bbbb cccc]")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 10, true, &line) >= 0); assert_se(streq(line, "[aaaa...]")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 11, true, &line) >= 0); assert_se(streq(line, "[aaaa...]")); line = mfree(line); assert_se(get_process_cmdline(getpid_cached(), 12, true, &line) >= 0); assert_se(streq(line, "[aaaa b...]")); line = mfree(line); safe_close(fd); _exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { struct stat stbuf; struct statfs statfsbuf, totalbuf; struct maxwidths maxwidths; struct statfs *mntbuf; const char *fstype; char *mntpath, *mntpt; const char **vfslist; int i, mntsize; int ch, rv; fstype = "ufs"; (void)setlocale(LC_ALL, ""); memset(&maxwidths, 0, sizeof(maxwidths)); memset(&totalbuf, 0, sizeof(totalbuf)); totalbuf.f_bsize = DEV_BSIZE; strlcpy(totalbuf.f_mntfromname, "total", MNAMELEN); vfslist = NULL; while ((ch = getopt(argc, argv, "abcgHhiklmnPt:T,")) != -1) switch (ch) { case 'a': aflag = 1; break; case 'b': /* FALLTHROUGH */ case 'P': /* * POSIX specifically discusses the behavior of * both -k and -P. It states that the blocksize should * be set to 1024. Thus, if this occurs, simply break * rather than clobbering the old blocksize. */ if (kflag) break; setenv("BLOCKSIZE", "512", 1); hflag = 0; break; case 'c': cflag = 1; break; case 'g': setenv("BLOCKSIZE", "1g", 1); hflag = 0; break; case 'H': hflag = UNITS_SI; break; case 'h': hflag = UNITS_2; break; case 'i': iflag = 1; break; case 'k': kflag++; setenv("BLOCKSIZE", "1024", 1); hflag = 0; break; case 'l': if (vfslist != NULL) errx(1, "-l and -t are mutually exclusive."); vfslist = makevfslist(makenetvfslist()); lflag = 1; break; case 'm': setenv("BLOCKSIZE", "1m", 1); hflag = 0; break; case 'n': nflag = 1; break; case 't': if (lflag) errx(1, "-l and -t are mutually exclusive."); if (vfslist != NULL) errx(1, "only one -t option may be specified"); fstype = optarg; vfslist = makevfslist(optarg); break; case 'T': Tflag = 1; break; case ',': thousands = 1; break; case '?': default: usage(); } argc -= optind; argv += optind; rv = 0; if (!*argv) { /* everything (modulo -t) */ mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); mntsize = regetmntinfo(&mntbuf, mntsize, vfslist); } else { /* just the filesystems specified on the command line */ mntbuf = malloc(argc * sizeof(*mntbuf)); if (mntbuf == NULL) err(1, "malloc()"); mntsize = 0; /* continued in for loop below */ } /* iterate through specified filesystems */ for (; *argv; argv++) { if (stat(*argv, &stbuf) < 0) { if ((mntpt = getmntpt(*argv)) == NULL) { warn("%s", *argv); rv = 1; continue; } } else if (S_ISCHR(stbuf.st_mode)) { if ((mntpt = getmntpt(*argv)) == NULL) { mdev.fspec = *argv; mntpath = strdup("/tmp/df.XXXXXX"); if (mntpath == NULL) { warn("strdup failed"); rv = 1; continue; } mntpt = mkdtemp(mntpath); if (mntpt == NULL) { warn("mkdtemp(\"%s\") failed", mntpath); rv = 1; free(mntpath); continue; } if (mount(fstype, mntpt, MNT_RDONLY, &mdev) != 0) { warn("%s", *argv); rv = 1; (void)rmdir(mntpt); free(mntpath); continue; } else if (statfs(mntpt, &statfsbuf) == 0) { statfsbuf.f_mntonname[0] = '\0'; prtstat(&statfsbuf, &maxwidths); if (cflag) addstat(&totalbuf, &statfsbuf); } else { warn("%s", *argv); rv = 1; } (void)unmount(mntpt, 0); (void)rmdir(mntpt); free(mntpath); continue; } } else mntpt = *argv; /* * Statfs does not take a `wait' flag, so we cannot * implement nflag here. */ if (statfs(mntpt, &statfsbuf) < 0) { warn("%s", mntpt); rv = 1; continue; } /* * Check to make sure the arguments we've been given are * satisfied. Return an error if we have been asked to * list a mount point that does not match the other args * we've been given (-l, -t, etc.). */ if (checkvfsname(statfsbuf.f_fstypename, vfslist)) { rv = 1; continue; } /* the user asked for it, so ignore the ignore flag */ statfsbuf.f_flags &= ~MNT_IGNORE; /* add to list */ mntbuf[mntsize++] = statfsbuf; } memset(&maxwidths, 0, sizeof(maxwidths)); for (i = 0; i < mntsize; i++) { if (aflag || (mntbuf[i].f_flags & MNT_IGNORE) == 0) { update_maxwidths(&maxwidths, &mntbuf[i]); if (cflag) addstat(&totalbuf, &mntbuf[i]); } } for (i = 0; i < mntsize; i++) if (aflag || (mntbuf[i].f_flags & MNT_IGNORE) == 0) prtstat(&mntbuf[i], &maxwidths); if (cflag) prtstat(&totalbuf, &maxwidths); return (rv); }
int main(int argc, char **argv) { char path[PATH_MAX], bpath[PATH_MAX], spath[PATH_MAX], bspath[PATH_MAX]; pid_t pid; int status; task_waiter_t t; test_init(argc, argv); task_waiter_init(&t); mount(NULL, "/", NULL, MS_SHARED, NULL); snprintf(path, sizeof(path), "%s/test", dirname); snprintf(bpath, sizeof(bpath), "%s/test.bind", dirname); snprintf(spath, sizeof(spath), "%s/test/sub", dirname); snprintf(bspath, sizeof(bspath), "%s/test.bind/sub", dirname); if (mkdir(dirname, 0700) || mkdir(path, 0700) || mkdir(spath, 0700) || mkdir(bpath, 0700)) { err("mkdir"); return 1; } pid = fork(); if (pid < 0) { err("fork"); return 1; } if (pid == 0) { unshare(CLONE_NEWNS); if (mount(path, bpath, NULL, MS_BIND, NULL)) { err("mount"); return 1; } task_waiter_complete(&t, 1); task_waiter_wait4(&t, 2); if (access(bspath, F_OK)) { fail("%s isn't accessiable", bspath); return 1; } if (umount2(bpath, MNT_DETACH)) { fail("umount"); return 1; } return 0; } task_waiter_wait4(&t, 1); if (mount("test", spath, "tmpfs", 0, NULL)) { err("mount"); return 1; } test_daemon(); test_waitsig(); task_waiter_complete(&t, 2); if (waitpid(pid, &status, 0) != pid) { err("waitpid %d", pid); return 1; } if (status) { err("%d/%d/%d/%d", WIFEXITED(status), WEXITSTATUS(status), WIFSIGNALED(status), WTERMSIG(status)); return 1; } pass(); return 0; }
void main(int argc, char *argv[]) { int i = 0, cmd = -1, fd = 0; char line[128], cname[64], temp_pathname[124], pathname[124] = "NULL", basename[124] = "NULL", dirname[124] = "NULL", parameter[124] = "NULL", *device; //GETS DISK NAME TO MOUNT /* printf("Enter the name of your disk image\n"); fgets(device, 128, stdin); device[strlen(device)-1] = 0; // kill the \n char at end */ device = "mydisk"; mount_root(device, &fd); while(1) { //printf("P%d running: ", running.uid); printf("nick's@linux:"); pwd(P0.cwd); printf("$ "); fgets(line, 128, stdin); line[strlen(line)-1] = 0; // kill the \n char at end if (line[0]==0) continue; sscanf(line, "%s %s %s", cname, pathname, parameter); if(strcmp(pathname,"NULL") != 0) strcpy(PATHNAME, pathname); if(strcmp(parameter,"NULL") != 0) strcpy(PARAMETER, parameter); cmd = findCmd(cname); // map cname to an index switch(cmd) { case 0 : menu(); break; case 1 : pwd(P0.cwd);printf("\n"); break; case 2 : ls(); break; case 3 : cd(); break; case 4 : make_dir(); break; case 5 : rmdir(); break; case 6 : creat_file(); break; case 7 : link(); break; case 8 : unlink(); break; case 9 : symlink(); break; case 10: rm_file(); break; case 11: chmod_file(); break; case 12: chown_file(); break; case 13: stat_file(); break; case 14: touch_file(); break; case 20: open_file(); break; //LEVEL 2 case 21: close_file((int)PATHNAME); break; case 22: pfd(); break; case 23: lseek_file(); break; case 24: //access_file(); break; break; case 25: //read_file(); break; case 26: write_file(); break; case 27: cat_file(); break; case 28: cp_file(); break; case 29: mv_file(); break; case 30: mount(); break; //LEVLEL 3 case 31: //umount(); break; case 32: //cs(); break; case 33: //do_fork(); break; case 34: //do_ps(); break; case 40: //sync(); break; case 41: quit(); break; case 42 : system("clear"); break; default: printf("invalid command\n"); break; } //RESET NAMES strcpy(parameter, "NULL"); strcpy(pathname, "NULL"); strcpy(PATHNAME, "NULL"); } }
/* Invoked with stdin, stdout and stderr connected to the network connection */ void remoteside(int old) { char user[MaxStr], home[MaxStr], buf[MaxStr], xdir[MaxStr], cmd[MaxStr]; int i, n, fd, badchdir, gotcmd; rfork(RFENVG); putenv("service", "cpu"); fd = 0; /* negotiate authentication mechanism */ n = readstr(fd, cmd, sizeof(cmd)); if(n < 0) fatal(1, "authenticating"); if(setamalg(cmd) < 0 || (strcmp(am->name, "none") == 0 && !Nflag)){ writestr(fd, "unsupported auth method", nil, 0); fatal(1, "bad auth method %s", cmd); } else writestr(fd, "", "", 1); fd = (*am->sf)(fd, user); if(fd < 0) fatal(1, "srvauth"); /* Set environment values for the user */ putenv("user", user); sprint(home, "/usr/%s", user); putenv("home", home); /* Now collect invoking cpu's current directory or possibly a command */ gotcmd = 0; if(readstr(fd, xdir, sizeof(xdir)) < 0) fatal(1, "dir/cmd"); if(xdir[0] == '!') { strcpy(cmd, &xdir[1]); gotcmd = 1; if(readstr(fd, xdir, sizeof(xdir)) < 0) fatal(1, "dir"); } /* Establish the new process at the current working directory of the * gnot */ badchdir = 0; if(strcmp(xdir, "NO") == 0) chdir(home); else if(chdir(xdir) < 0) { badchdir = 1; chdir(home); } /* Start the gnot serving its namespace */ writestr(fd, "FS", "FS", 0); writestr(fd, "/", "exportfs dir", 0); n = read(fd, buf, sizeof(buf)); if(n != 2 || buf[0] != 'O' || buf[1] != 'K') exits("remote tree"); if(old) fd = old9p(fd); /* make sure buffers are big by doing fversion explicitly; pick a huge number; other side will trim */ strcpy(buf, VERSION9P); if(fversion(fd, 64*1024, buf, sizeof buf) < 0) exits("fversion failed"); if(mount(fd, -1, "/mnt/term", MCREATE|MREPL, "", 'M') < 0) exits("mount failed"); close(fd); /* the remote noteproc uses the mount so it must follow it */ rmtnoteproc(); for(i = 0; i < 3; i++) close(i); if(open("/mnt/term/dev/cons", OREAD) != 0) exits("open stdin"); if(open("/mnt/term/dev/cons", OWRITE) != 1) exits("open stdout"); dup(1, 2); if(badchdir) print("cpu: failed to chdir to '%s'\n", xdir); if(gotcmd) execl("/bin/rc", "rc", "-lc", cmd, nil); else execl("/bin/rc", "rc", "-li", nil); fatal(1, "exec shell"); }
/* * test_rwflag(int i, int cnt) * Validate the mount system call for rwflags. */ int test_rwflag(int i, int cnt) { int ret, fd, pid, status; char nobody_uid[] = "nobody"; time_t atime; struct passwd *ltpuser; struct stat file_stat; switch (i) { case 0: /* Validate MS_RDONLY flag of mount call */ snprintf(file, PATH_MAX, "%stmp", path_name); fd = open(file, O_CREAT | O_RDWR, S_IRWXU); if (fd == -1) { if (errno == EROFS) { return 0; } else { tst_resm(TWARN | TERRNO, "open didn't fail with EROFS"); return 1; } } close(fd); return 1; case 1: /* Validate MS_NODEV flag of mount call */ snprintf(file, PATH_MAX, "%smynod_%d_%d", path_name, getpid(), cnt); if (mknod(file, S_IFBLK | 0777, 0) == 0) { fd = open(file, O_RDWR, S_IRWXU); if (fd == -1) { if (errno == EACCES) { return 0; } else { tst_resm(TWARN | TERRNO, "open didn't fail with EACCES"); return 1; } } close(fd); } else { tst_resm(TWARN | TERRNO, "mknod(2) failed to create %s", file); return 1; } return 1; case 2: /* Validate MS_NOEXEC flag of mount call */ snprintf(file, PATH_MAX, "%stmp1", path_name); fd = open(file, O_CREAT | O_RDWR, S_IRWXU); if (fd == -1) { tst_resm(TWARN | TERRNO, "opening %s failed", file); } else { close(fd); ret = execlp(file, basename(file), NULL); if ((ret == -1) && (errno == EACCES)) return 0; } return 1; case 3: /* * Validate MS_SYNCHRONOUS flag of mount call. * Copy some data into data buffer. */ strcpy(write_buffer, "abcdefghijklmnopqrstuvwxyz"); /* Creat a temporary file under above directory */ snprintf(file, PATH_MAX, "%s%s", path_name, TEMP_FILE); fildes = open(file, O_RDWR | O_CREAT, FILE_MODE); if (fildes == -1) { tst_resm(TWARN | TERRNO, "open(%s, O_RDWR|O_CREAT, %#o) failed", file, FILE_MODE); return 1; } /* Write the buffer data into file */ if (write(fildes, write_buffer, strlen(write_buffer)) != strlen(write_buffer)) { tst_resm(TWARN | TERRNO, "writing to %s failed", file); close(fildes); return 1; } /* Set the file ptr to b'nning of file */ if (lseek(fildes, 0, SEEK_SET) < 0) { tst_resm(TWARN, "lseek() failed on %s, error=" " %d", file, errno); close(fildes); return 1; } /* Read the contents of file */ if (read(fildes, read_buffer, sizeof(read_buffer)) > 0) { if (strcmp(read_buffer, write_buffer)) { tst_resm(TWARN, "Data read from %s and written " "mismatch", file); close(fildes); return 1; } else { close(fildes); return 0; } } else { tst_resm(TWARN | TERRNO, "read() Fails on %s", file); close(fildes); return 1; } case 4: /* Validate MS_REMOUNT flag of mount call */ TEST(mount(device, mntpoint, fstype, MS_REMOUNT, NULL)); if (TEST_RETURN != 0) { tst_resm(TWARN | TTERRNO, "mount(2) failed to remount"); return 1; } else { snprintf(file, PATH_MAX, "%stmp2", path_name); fd = open(file, O_CREAT | O_RDWR, S_IRWXU); if (fd == -1) { tst_resm(TWARN, "open(%s) on readonly " "filesystem passed", file); return 1; } else { close(fd); return 0; } } case 5: /* Validate MS_NOSUID flag of mount call */ snprintf(file, PATH_MAX, "%ssetuid_test", path_name); SAFE_FILE_PRINTF(cleanup, file, "TEST FILE"); if (stat(file, &file_stat) < 0) tst_brkm(TBROK, cleanup, "stat for setuid_test failed"); if (file_stat.st_mode != SUID_MODE && chmod(file, SUID_MODE) < 0) tst_brkm(TBROK, cleanup, "setuid for setuid_test failed"); pid = fork(); switch (pid) { case -1: tst_resm(TBROK | TERRNO, "fork failed"); return 1; case 0: ltpuser = getpwnam(nobody_uid); if (setreuid(ltpuser->pw_uid, ltpuser->pw_uid) == -1) tst_resm(TWARN | TERRNO, "seteuid() failed to change euid to %d", ltpuser->pw_uid); execlp(file, basename(file), NULL); exit(1); default: waitpid(pid, &status, 0); if (WIFEXITED(status)) { /* reset the setup_uid */ if (status) return 0; else return 1; } } case 6: /* Validate MS_NOATIME flag of mount call */ snprintf(file, PATH_MAX, "%satime", path_name); fd = open(file, O_CREAT | O_RDWR, S_IRWXU); if (fd == -1) { tst_resm(TWARN | TERRNO, "opening %s failed", file); return 1; } if (write(fd, "TEST_MS_NOATIME", 15) != 15) { tst_resm(TWARN | TERRNO, "write %s failed", file); return 1; } if (fstat(fd, &file_stat) == -1) { tst_resm(TWARN | TERRNO, "stat %s failed #1", file); return 1; } atime = file_stat.st_atime; sleep(1); if (read(fd, NULL, 20) == -1) { tst_resm(TWARN | TERRNO, "read %s failed", file); return 1; } if (fstat(fd, &file_stat) == -1) { tst_resm(TWARN | TERRNO, "stat %s failed #2", file); return 1; } close(fd); if (file_stat.st_atime != atime) { tst_resm(TWARN, "access time is updated"); return 1; } return 0; } return 0; }
int main(int argc, char **argv) { int cgfd, l, ret = 1, i; char aux[1024], paux[1024]; FILE *cgf; struct stat st; test_init(argc, argv); if (mkdir(dirname, 0700) < 0) { pr_perror("Can't make dir"); goto out; } sprintf(aux, "none,name=%s", cgname); if (mount("none", dirname, "cgroup", 0, aux)) { pr_perror("Can't mount cgroups"); goto out_rd; } sprintf(paux, "%s/%s", dirname, subname); mkdir(paux, 0600); l = sprintf(aux, "%d", getpid()); sprintf(paux, "%s/%s/tasks", dirname, subname); cgfd = open(paux, O_WRONLY); if (cgfd < 0) { pr_perror("Can't open tasks"); goto out_rs; } l = write(cgfd, aux, l); close(cgfd); if (l < 0) { pr_perror("Can't move self to subcg"); goto out_rs; } for (i = 0; i < 2; i++) { sprintf(paux, "%s/%s/%s.%d", dirname, subname, empty, i); if (mkdir(paux, 0600)) { pr_perror("mkdir %s", paux); goto out_rs; } } test_daemon(); test_waitsig(); cgf = fopen("/proc/self/mountinfo", "r"); if (cgf == NULL) { fail("No mountinfo file"); goto out_rs; } while (fgets(paux, sizeof(paux), cgf)) { char *s; s = strstr(paux, cgname); if (!s) continue; sscanf(paux, "%*d %*d %*d:%*d %*s %s", aux); test_msg("found cgroup at %s\n", aux); for (i = 0; i < 2; i++) { ssprintf(paux, "%s/%s/%s.%d", aux, subname, empty, i); if (stat(paux, &st)) { fail("couldn't stat %s\n", paux); ret = -1; goto out_close; } if (!S_ISDIR(st.st_mode)) { fail("%s is not a directory\n", paux); ret = -1; goto out_close; } } pass(); ret = 0; goto out_close; } fail("empty cgroup not found!\n"); out_close: fclose(cgf); out_rs: umount(dirname); out_rd: rmdir(dirname); out: return ret; }
/* * mount in /dev a note file for the remote side to read. */ void lclnoteproc(int netfd) { Waitmsg *w; Note *np; int pfd[2]; int pid; if(pipe(pfd) < 0){ fprint(2, "cpu: can't start note proc: pipe: %r\n"); return; } /* new proc mounts and returns to start exportfs */ switch(pid = rfork(RFPROC|RFNAMEG|RFFDG|RFMEM)){ default: exportpid = pid; break; case -1: fprint(2, "cpu: can't start note proc: rfork: %r\n"); return; case 0: close(pfd[0]); if(mount(pfd[1], -1, "/dev", MBEFORE, "", 'M') < 0) fprint(2, "cpu: can't mount note proc: %r\n"); close(pfd[1]); return; } close(netfd); close(pfd[1]); /* new proc listens for note file system rpc's */ switch(rfork(RFPROC|RFNAMEG|RFMEM)){ case -1: fprint(2, "cpu: can't start note proc: rfork1: %r\n"); _exits(0); case 0: notefs(pfd[0]); _exits(0); } /* original proc waits for notes */ notify(catcher); w = nil; for(;;) { *notebuf = 0; free(w); w = wait(); if(w == nil) { if(*notebuf == 0) break; np = mallocz(sizeof(Note), 1); if(np != nil){ strcpy(np->msg, notebuf); lock(&nfs); if(nfs.nfirst == nil) nfs.nfirst = np; else nfs.nlast->next = np; nfs.nlast = np; unlock(&nfs); kick(pfd[0]); } unlock(&nfs); } else if(w->pid == exportpid) break; } if(w == nil) exits(nil); exits(0); /* exits(w->msg); */ }
static void stage_capability_test(void) { char tmp1[128]; char tmp2[128]; memset(tmp1, 0, sizeof(tmp1)); memset(tmp2, 0, sizeof(tmp2)); capability = "inet_tcp_create"; set_capability(); if (write_policy()) { int fd = socket(AF_INET, SOCK_STREAM, 0); show_result(fd, 1); if (fd != EOF) close(fd); delete_policy(); fd = socket(AF_INET, SOCK_STREAM, 0); show_result(fd, 0); if (fd != EOF) close(fd); } unset_capability(); { int fd1 = socket(AF_INET, SOCK_STREAM, 0); int fd2 = socket(AF_INET, SOCK_STREAM, 0); int fd3 = socket(AF_INET, SOCK_STREAM, 0); int fd4 = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in addr; socklen_t size = sizeof(addr); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); addr.sin_port = htons(0); bind(fd1, (struct sockaddr *) &addr, sizeof(addr)); bind(fd2, (struct sockaddr *) &addr, sizeof(addr)); bind(fd3, (struct sockaddr *) &addr, sizeof(addr)); bind(fd4, (struct sockaddr *) &addr, sizeof(addr)); getsockname(fd1, (struct sockaddr *) &addr, &size); capability = "inet_tcp_listen"; set_capability(); if (write_policy()) { show_result(listen(fd1, 5), 1); delete_policy(); show_result(listen(fd2, 5), 0); } unset_capability(); capability = "inet_tcp_connect"; set_capability(); if (write_policy()) { show_result(connect(fd3, (struct sockaddr *) &addr, sizeof(addr)), 1); delete_policy(); show_result(connect(fd4, (struct sockaddr *) &addr, sizeof(addr)), 0); } unset_capability(); if (fd1 != EOF) close(fd1); if (fd2 != EOF) close(fd2); if (fd3 != EOF) close(fd3); if (fd4 != EOF) close(fd4); } capability = "use_inet_udp"; set_capability(); if (write_policy()) { int fd = socket(AF_INET, SOCK_DGRAM, 0); show_result(fd, 1); if (fd != EOF) close(fd); delete_policy(); fd = socket(AF_INET, SOCK_DGRAM, 0); show_result(fd, 0); if (fd != EOF) close(fd); } unset_capability(); capability = "use_inet_ip"; set_capability(); if (write_policy()) { int fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); show_result(fd, 1); if (fd != EOF) close(fd); delete_policy(); fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); show_result(fd, 0); if (fd != EOF) close(fd); } unset_capability(); capability = "use_route"; set_capability(); if (write_policy()) { int fd = socket(AF_ROUTE, SOCK_RAW, 0); show_result(fd, 1); if (fd != EOF) close(fd); delete_policy(); fd = socket(AF_ROUTE, SOCK_RAW, 0); show_result(fd, 0); if (fd != EOF) close(fd); } unset_capability(); capability = "use_packet"; set_capability(); if (write_policy()) { int fd = socket(AF_PACKET, SOCK_RAW, 0); show_result(fd, 1); if (fd != EOF) close(fd); delete_policy(); fd = socket(AF_PACKET, SOCK_RAW, 0); show_result(fd, 0); if (fd != EOF) close(fd); } unset_capability(); capability = "use_kernel_module"; set_capability(); if (write_policy()) { if (!is_kernel26) show_result((int) create_module("", 0), 1); show_result(init_module("", NULL), 1); show_result(delete_module(""), 1); delete_policy(); if (!is_kernel26) show_result((int) create_module("", 0), 0); show_result(init_module("", NULL), 0); show_result(delete_module(""), 0); } unset_capability(); capability = "create_fifo"; set_capability(); if (write_policy()) { strcpy(tmp1, "/tmp/XXXXXX"); close(mkstemp(tmp1)); unlink(tmp1); show_result(mknod(tmp1, S_IFIFO, 0), 1); unlink(tmp1); delete_policy(); show_result(mknod(tmp1, S_IFIFO, 0), 0); unlink(tmp1); } unset_capability(); capability = "create_block_dev"; set_capability(); if (write_policy()) { strcpy(tmp1, "/tmp/XXXXXX"); close(mkstemp(tmp1)); unlink(tmp1); show_result(mknod(tmp1, S_IFBLK, MKDEV(1, 0)), 1); unlink(tmp1); delete_policy(); show_result(mknod(tmp1, S_IFBLK, MKDEV(1, 0)), 0); unlink(tmp1); } unset_capability(); capability = "create_char_dev"; set_capability(); if (write_policy()) { strcpy(tmp1, "/tmp/XXXXXX"); close(mkstemp(tmp1)); unlink(tmp1); show_result(mknod(tmp1, S_IFCHR, MKDEV(1, 3)), 1); unlink(tmp1); delete_policy(); show_result(mknod(tmp1, S_IFCHR, MKDEV(1, 3)), 0); unlink(tmp1); } unset_capability(); capability = "create_unix_socket"; set_capability(); if (write_policy()) { strcpy(tmp1, "/tmp/XXXXXX"); close(mkstemp(tmp1)); unlink(tmp1); show_result(mknod(tmp1, S_IFSOCK, 0), 1); unlink(tmp1); delete_policy(); show_result(mknod(tmp1, S_IFSOCK, 0), 0); unlink(tmp1); } if (write_policy()) { struct sockaddr_un addr; int fd1 = socket(AF_UNIX, SOCK_STREAM, 0); int fd2 = socket(AF_UNIX, SOCK_STREAM, 0); memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strcpy(tmp1, "/tmp/XXXXXX"); strncpy(addr.sun_path, tmp1, sizeof(addr.sun_path) - 1); show_result(bind(fd1, (struct sockaddr *) &addr, sizeof(addr)), 1); unlink(tmp1); delete_policy(); show_result(bind(fd2, (struct sockaddr *) &addr, sizeof(addr)), 0); unlink(tmp1); if (fd1 != EOF) close(fd1); if (fd2 != EOF) close(fd2); } unset_capability(); capability = "SYS_MOUNT"; set_capability(); if (write_policy()) { show_result(mount("/", "/", "tmpfs", 0, NULL), 1); delete_policy(); show_result(mount("/", "/", "tmpfs", 0, NULL), 0); } unset_capability(); capability = "SYS_UMOUNT"; set_capability(); if (write_policy()) { mount("/tmp", "/tmp", "tmpfs", 0, NULL); show_result(umount("/tmp"), 1); delete_policy(); mount("/tmp", "/tmp", "tmpfs", 0, NULL); show_result(umount("/"), 0); } unset_capability(); capability = "SYS_REBOOT"; set_capability(); if (write_policy()) { FILE *fp = fopen("/proc/sys/kernel/ctrl-alt-del", "a+"); unsigned int c; if (fp && fscanf(fp, "%u", &c) == 1) { show_result(reboot(LINUX_REBOOT_CMD_CAD_ON), 1); delete_policy(); show_result(reboot(LINUX_REBOOT_CMD_CAD_ON), 0); fprintf(fp, "%u\n", c); } else { /* Use invalid value */ show_result(reboot(0x0000C0DE), 1); delete_policy(); show_result(reboot(0x0000C0DE), 0); } if (fp) fclose(fp); } unset_capability(); capability = "SYS_CHROOT"; set_capability(); if (write_policy()) { show_result(chroot("/"), 1); delete_policy(); show_result(chroot("/"), 0); } unset_capability(); capability = "SYS_PIVOT_ROOT"; set_capability(); if (write_policy()) { int error; char *stack = malloc(8192); pid_t pid = clone(child, stack + (8192 / 2), CLONE_NEWNS, NULL); while (waitpid(pid, &error, __WALL) == EOF && errno == EINTR) error += 0; /* Dummy. */ errno = WIFEXITED(error) ? WEXITSTATUS(error) : -1; show_result(errno ? EOF : 0, 1); delete_policy(); pid = clone(child, stack + (8192 / 2), CLONE_NEWNS, NULL); while (waitpid(pid, &error, __WALL) == EOF && errno == EINTR) error += 0; /* Dummy. */ errno = WIFEXITED(error) ? WEXITSTATUS(error) : -1; show_result(errno ? EOF : 0, 0); free(stack); } unset_capability(); signal(SIGINT, SIG_IGN); capability = "SYS_KILL"; set_capability(); if (write_policy()) { show_result(kill(pid, SIGINT), 1); show_result(tkill(gettid(), SIGINT), 1); #ifdef __NR_tgkill if (is_kernel26) show_result(tgkill(pid, gettid(), SIGINT), 1); #endif delete_policy(); show_result(kill(pid, SIGINT), 0); show_result(tkill(gettid(), SIGINT), 0); #ifdef __NR_tgkill if (is_kernel26) show_result(tgkill(pid, gettid(), SIGINT), 0); #endif } unset_capability(); signal(SIGINT, SIG_DFL); capability = "SYS_KEXEC_LOAD"; set_capability(); if (write_policy()) { #ifdef __NR_sys_kexec_load if (is_kernel26) show_result(sys_kexec_load(0, 0, NULL, 0), 1); #endif delete_policy(); #ifdef __NR_sys_kexec_load if (is_kernel26) show_result(sys_kexec_load(0, 0, NULL, 0), 0); #endif } unset_capability(); capability = "SYS_VHANGUP"; set_capability(); if (write_policy()) { int pty_fd = EOF, status = 0; int pipe_fd[2] = { EOF, EOF }; pipe(pipe_fd); switch (forkpty(&pty_fd, NULL, NULL, NULL)) { case 0: errno = 0; vhangup(); /* Unreachable if vhangup() succeeded. */ status = errno; write(pipe_fd[1], &status, sizeof(status)); _exit(0); case -1: fprintf(stderr, "forkpty() failed.\n"); break; default: close(pipe_fd[1]); read(pipe_fd[0], &status, sizeof(status)); wait(NULL); close(pipe_fd[0]); close(pty_fd); errno = status; show_result(status ? EOF : 0, 1); } delete_policy(); status = 0; pipe(pipe_fd); switch (forkpty(&pty_fd, NULL, NULL, NULL)) { case 0: errno = 0; vhangup(); /* Unreachable if vhangup() succeeded. */ status = errno; write(pipe_fd[1], &status, sizeof(status)); _exit(0); case -1: fprintf(stderr, "forkpty() failed.\n"); break; default: close(pipe_fd[1]); read(pipe_fd[0], &status, sizeof(status)); wait(NULL); close(pipe_fd[0]); close(pty_fd); errno = status; show_result(status ? EOF : 0, 0); } } unset_capability(); capability = "SYS_TIME"; set_capability(); if (write_policy()) { struct timeval tv; struct timezone tz; struct timex buf; time_t now = time(NULL); show_result(stime(&now), 1); gettimeofday(&tv, &tz); show_result(settimeofday(&tv, &tz), 1); memset(&buf, 0, sizeof(buf)); buf.modes = 0x100; /* Use invalid value so that the clock won't change. */ show_result(adjtimex(&buf), 1); delete_policy(); now = time(NULL); show_result(stime(&now), 0); gettimeofday(&tv, &tz); show_result(settimeofday(&tv, &tz), 0); memset(&buf, 0, sizeof(buf)); buf.modes = 0x100; /* Use invalid value so that the clock won't change. */ show_result(adjtimex(&buf), 0); } unset_capability(); capability = "SYS_NICE"; set_capability(); if (write_policy()) { show_result(nice(0), 1); show_result(setpriority(PRIO_PROCESS, pid, getpriority(PRIO_PROCESS, pid)), 1); delete_policy(); show_result(nice(0), 0); show_result(setpriority(PRIO_PROCESS, pid, getpriority(PRIO_PROCESS, pid)), 0); } unset_capability(); capability = "SYS_SETHOSTNAME"; set_capability(); if (write_policy()) { char buffer[4096]; memset(buffer, 0, sizeof(buffer)); gethostname(buffer, sizeof(buffer) - 1); show_result(sethostname(buffer, strlen(buffer)), 1); getdomainname(buffer, sizeof(buffer) - 1); show_result(setdomainname(buffer, strlen(buffer)), 1); delete_policy(); gethostname(buffer, sizeof(buffer) - 1); show_result(sethostname(buffer, strlen(buffer)), 0); getdomainname(buffer, sizeof(buffer) - 1); show_result(setdomainname(buffer, strlen(buffer)), 0); } unset_capability(); capability = "SYS_LINK"; set_capability(); if (write_policy()) { strcpy(tmp1, "/tmp/link_source_XXXXXX"); close(mkstemp(tmp1)); strcpy(tmp2, "/tmp/link_target_XXXXXX"); show_result(link(tmp1, tmp2), 1); unlink(tmp2); unlink(tmp1); delete_policy(); strcpy(tmp1, "/tmp/link_source_XXXXXX"); close(mkstemp(tmp1)); strcpy(tmp2, "/tmp/link_target_XXXXXX"); show_result(link(tmp1, tmp2), 0); unlink(tmp2); unlink(tmp1); } unset_capability(); capability = "SYS_SYMLINK"; set_capability(); if (write_policy()) { strcpy(tmp1, "/tmp/symlink_target_XXXXXX"); close(mkstemp(tmp1)); strcpy(tmp2, "/tmp/symlink_source_XXXXXX"); show_result(symlink(tmp1, tmp2), 1); unlink(tmp2); unlink(tmp1); delete_policy(); strcpy(tmp1, "/tmp/symlink_target_XXXXXX"); close(mkstemp(tmp1)); strcpy(tmp2, "/tmp/symlink_source_XXXXXX"); show_result(symlink(tmp1, tmp2), 0); unlink(tmp2); unlink(tmp1); } unset_capability(); capability = "SYS_RENAME"; set_capability(); if (write_policy()) { strcpy(tmp1, "/tmp/rename_old_XXXXXX"); close(mkstemp(tmp1)); strcpy(tmp2, "/tmp/rename_new_XXXXXX"); show_result(rename(tmp1, tmp2), 1); unlink(tmp2); unlink(tmp1); delete_policy(); strcpy(tmp1, "/tmp/rename_old_XXXXXX"); close(mkstemp(tmp1)); strcpy(tmp2, "/tmp/rename_new_XXXXXX"); show_result(rename(tmp1, tmp2), 0); unlink(tmp2); unlink(tmp1); } unset_capability(); capability = "SYS_UNLINK"; set_capability(); if (write_policy()) { strcpy(tmp1, "/tmp/unlinkXXXXXX"); close(mkstemp(tmp1)); show_result(unlink(tmp1), 1); delete_policy(); strcpy(tmp1, "/tmp/unlinkXXXXXX"); close(mkstemp(tmp1)); show_result(unlink(tmp1), 0); } unset_capability(); unlink(tmp1); capability = "SYS_CHMOD"; set_capability(); if (write_policy()) { show_result(chmod("/dev/null", 0222), 1); delete_policy(); show_result(chmod("/dev/null", 0444), 0); } unset_capability(); chmod("/dev/null", 0666); capability = "SYS_CHOWN"; set_capability(); if (write_policy()) { show_result(chown("/dev/null", 1, 1), 1); delete_policy(); show_result(chown("/dev/null", 2, 2), 0); } unset_capability(); chown("/dev/null", 0, 0); capability = "SYS_IOCTL"; set_capability(); if (0 && write_policy()) { int fd = open("/dev/null", O_RDONLY); show_result(ioctl(fd, 0 /* Use invalid value so that nothing happen. */), 1); delete_policy(); show_result(ioctl(fd, 0 /* Use invalid value so that nothing happen. */), 0); close(fd); } if (write_policy()) { struct ifreq ifreq; int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); memset(&ifreq, 0, sizeof(ifreq)); snprintf(ifreq.ifr_name, sizeof(ifreq.ifr_name) - 1, "lo"); show_result(ioctl(fd, 35123, &ifreq), 1); delete_policy(); show_result(ioctl(fd, 35123, &ifreq), 0); close(fd); } unset_capability(); capability = "SYS_PTRACE"; set_capability(); if (write_policy()) { int status = 0; int pipe_fd[2] = { EOF, EOF }; pipe(pipe_fd); switch (fork()) { case 0: errno = 0; ptrace(PTRACE_TRACEME, 0, NULL, NULL); status = errno; write(pipe_fd[1], &status, sizeof(status)); _exit(0); case -1: fprintf(stderr, "fork() failed.\n"); break; default: close(pipe_fd[1]); read(pipe_fd[0], &status, sizeof(status)); wait(NULL); close(pipe_fd[0]); errno = status; show_result(status ? EOF : 0, 1); } delete_policy(); status = 0; pipe(pipe_fd); switch (fork()) { case 0: errno = 0; ptrace(PTRACE_TRACEME, 0, NULL, NULL); status = errno; write(pipe_fd[1], &status, sizeof(status)); _exit(0); case -1: fprintf(stderr, "fork() failed.\n"); break; default: close(pipe_fd[1]); read(pipe_fd[0], &status, sizeof(status)); wait(NULL); close(pipe_fd[0]); errno = status; show_result(status ? EOF : 0, 0); } } unset_capability(); }
static int test_fn(int argc, char **argv) { FILE *f; int fd, tmpfs_fd; unsigned fs_cnt, fs_cnt_last = 0; again: fs_cnt = 0; f = fopen("/proc/self/mountinfo", "r"); if (!f) { fail("Can't open mountinfo"); return -1; } while (fgets(buf, sizeof(buf), f) != NULL) { char *mp = buf, *end; mp = strchr(mp, ' ') + 1; mp = strchr(mp, ' ') + 1; mp = strchr(mp, ' ') + 1; mp = strchr(mp, ' ') + 1; end = strchr(mp, ' '); *end = '\0'; if (!strcmp(mp, "/")) continue; if (!strcmp(mp, "/proc")) continue; umount(mp); fs_cnt++; } fclose(f); if (fs_cnt == 0) goto done; if (fs_cnt != fs_cnt_last) { fs_cnt_last = fs_cnt; goto again; } fail("Can't umount all the filesystems"); return -1; done: rmdir(MPTS_ROOT); if (mkdir(MPTS_ROOT, 0600) < 0) { fail("Can't make zdtm_sys"); return 1; } if (mount("none", MPTS_ROOT, "sysfs", 0, "") < 0) { fail("Can't mount sysfs"); return 1; } if (mount("none", MPTS_ROOT"/dev", "tmpfs", 0, "") < 0) { fail("Can't mount tmpfs"); return 1; } tmpfs_fd = open(MPTS_ROOT"/dev/test", O_WRONLY | O_CREAT); if (write(tmpfs_fd, "hello", 5) <= 0) { err("write() failed"); return 1; } if (mount("none", MPTS_ROOT"/kernel", "proc", 0, "") < 0) { fail("Can't mount proc"); return 1; } if (mount("none", MPTS_ROOT"/kernel/sys/fs/binfmt_misc", "binfmt_misc", 0, "") < 0) { fail("Can't mount proc"); return 1; } mknod("/dev/null", 0777 | S_IFCHR, makedev(1, 3)); setup_outfile(); fd = open(MPTS_ROOT"/kernel/meminfo", O_RDONLY); if (fd == -1) return 1; test_daemon(); test_waitsig(); /* this checks both -- sys and proc presence */ if (access(MPTS_ROOT"/kernel/meminfo", F_OK)) { fail("No proc after restore"); return 1; } pass(); return 0; }
int main(int argc, char **argv) { int fd_count = 0; struct pollfd ufds[4]; char *tmpdev; char* debuggable; char tmp[32]; int property_set_fd_init = 0; int signal_fd_init = 0; int keychord_fd_init = 0; bool is_charger = false; // 判断是否是在充电 char* args_swapon[2]; args_swapon[0] = "swapon_all";; args_swapon[1] = "/fstab.sun8i";; char* args_write[3]; args_write[0] = "write"; args_write[1] = "/proc/sys/vm/page-cluster"; args_write[2] = "0"; if (!strcmp(basename(argv[0]), "ueventd")) return ueventd_main(argc, argv); if (!strcmp(basename(argv[0]), "watchdogd")) return watchdogd_main(argc, argv); /* clear the umask */ umask(0); /* Get the basic filesystem setup we need put * together in the initramdisk on / and then we'll * let the rc file figure out the rest. */ // 创建设备节点 mkdir("/dev", 0755); mkdir("/proc", 0755); mkdir("/sys", 0755); mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); mkdir("/dev/pts", 0755); mkdir("/dev/socket", 0755); mount("devpts", "/dev/pts", "devpts", 0, NULL); mount("proc", "/proc", "proc", 0, NULL); mount("sysfs", "/sys", "sysfs", 0, NULL); /* indicate that booting is in progress to background fw loaders, etc */ close(open("/dev/.booting", O_WRONLY | O_CREAT, 0000)); /* We must have some place other than / to create the * device nodes for kmsg and null, otherwise we won't * be able to remount / read-only later on. * Now that tmpfs is mounted on /dev, we can actually * talk to the outside world. */ open_devnull_stdio(); // stdio/stdout/stderr都指向__null__设备 klog_init(); // 从这里创建__kmsg__设备 property_init(); // 1. 完成property的环境变量初始化等动作 get_hardware_name(hardware, &revision); process_kernel_cmdline(); // 属性初始设置 union selinux_callback cb; cb.func_log = klog_write; selinux_set_callback(SELINUX_CB_LOG, cb); cb.func_audit = audit_callback; selinux_set_callback(SELINUX_CB_AUDIT, cb); selinux_initialize(); /* These directories were necessarily created before initial policy load * and therefore need their security context restored to the proper value. * This must happen before /dev is populated by ueventd. */ restorecon("/dev"); restorecon("/dev/socket"); restorecon("/dev/__properties__"); restorecon_recursive("/sys"); is_charger = !strcmp(bootmode, "charger"); // 从bootloader中获取是否在充电的信息 usb_charge_flag = is_charger; INFO("property init\n"); if (!is_charger) property_load_boot_defaults(); get_kernel_cmdline_partitions(); get_kernel_cmdline_signature(); INFO("reading config file\n"); init_parse_config_file("/init.rc"); action_for_each_trigger("early-init", action_add_queue_tail); queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done"); queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng"); queue_builtin_action(keychord_init_action, "keychord_init"); /* execute all the boot actions to get us started */ action_for_each_trigger("init", action_add_queue_tail); action_for_each_trigger("early-fs", action_add_queue_tail); /* skip mounting filesystems in charger mode */ if (!is_charger) { // 显示initlog.rle,也就是android第二张图片 queue_builtin_action(console_init_action, "console_init"); action_for_each_trigger("fs", action_add_queue_tail); action_for_each_trigger("post-fs", action_add_queue_tail); action_for_each_trigger("post-fs-data", action_add_queue_tail); //SWAP TO ZRAM if low mem devices if (!(get_dram_size() > 512)) { char trigger[] = {"early-fs"}; ERROR("***************************LOW MEM DEVICE DETECT"); add_command(trigger, 2, args_swapon); char trigger2[] = {"post-fs-data"}; add_command(trigger2, 3, args_write); } } /* Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random * wasn't ready immediately after wait_for_coldboot_done */ queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng"); queue_builtin_action(property_service_init_action, "property_service_init"); queue_builtin_action(signal_init_action, "signal_init"); queue_builtin_action(check_startup_action, "check_startup"); if (is_charger) { // 如果是charger模式,则调用charger.c queue_builtin_action(console_init_action, "console_init"); action_for_each_trigger("charger", action_add_queue_tail); } else { action_for_each_trigger("early-boot", action_add_queue_tail); action_for_each_trigger("boot", action_add_queue_tail); } /* run all property triggers based on current state of the properties */ queue_builtin_action(queue_property_triggers_action, "queue_property_triggers"); #if BOOTCHART queue_builtin_action(bootchart_init_action, "bootchart_init"); #endif for(;;) { // 监视事件 事件处理循环 int nr, i, timeout = -1; execute_one_command(); restart_processes(); if (!property_set_fd_init && get_property_set_fd() > 0) { // 通过套接字传递信息 ufds[fd_count].fd = get_property_set_fd(); ufds[fd_count].events = POLLIN; ufds[fd_count].revents = 0; fd_count++; property_set_fd_init = 1; } if (!signal_fd_init && get_signal_fd() > 0) { ufds[fd_count].fd = get_signal_fd(); ufds[fd_count].events = POLLIN; ufds[fd_count].revents = 0; fd_count++; signal_fd_init = 1; } if (!keychord_fd_init && get_keychord_fd() > 0) { ufds[fd_count].fd = get_keychord_fd(); ufds[fd_count].events = POLLIN; ufds[fd_count].revents = 0; fd_count++; keychord_fd_init = 1; } if (process_needs_restart) { timeout = (process_needs_restart - gettime()) * 1000; if (timeout < 0) timeout = 0; } if (!action_queue_empty() || cur_action) timeout = 0; #if BOOTCHART if (bootchart_count > 0) { if (timeout < 0 || timeout > BOOTCHART_POLLING_MS) timeout = BOOTCHART_POLLING_MS; if (bootchart_step() < 0 || --bootchart_count == 0) { bootchart_finish(); bootchart_count = 0; } } #endif nr = poll(ufds, fd_count, timeout); // 获取事件(热插拔检测) if (nr <= 0) continue; for (i = 0; i < fd_count; i++) { // 处理套接字传回的信息 if (ufds[i].revents & POLLIN) { if (ufds[i].fd == get_property_set_fd()) // 处理属性变更 handle_property_set_fd(); else if (ufds[i].fd == get_keychord_fd()) handle_keychord(); else if (ufds[i].fd == get_signal_fd()) // 处理子进程传回的信息 handle_signal(); } } } return 0; }
int ensure_path_mounted(const char* path) { if ((DataManager_GetIntValue(TW_HAS_DATA_MEDIA) == 1 || DataManager_GetIntValue(TW_HAS_DUAL_STORAGE) == 0) && strncmp(path, "/sdcard", 7) == 0) return 0; // sdcard is just a symlink Volume* v = volume_for_path(path); if (v == NULL) { LOGE("unknown volume for path [%s]\n", path); return -1; } if (strcmp(v->fs_type, "ramdisk") == 0) { // the ramdisk is always mounted. return 0; } int result; result = scan_mounted_volumes(); if (result < 0) { LOGE("failed to scan mounted volumes\n"); return -1; } const MountedVolume* mv = find_mounted_volume_by_mount_point(v->mount_point); if (mv) { // volume is already mounted return 0; } mkdir(v->mount_point, 0755); // in case it doesn't already exist if (strcmp(v->fs_type, "yaffs2") == 0) { // mount an MTD partition as a YAFFS2 filesystem. mtd_scan_partitions(); const MtdPartition* partition; partition = mtd_find_partition_by_name(v->device); if (partition == NULL) { LOGE("failed to find \"%s\" partition to mount at \"%s\"\n", v->device, v->mount_point); return -1; } return mtd_mount_partition(partition, v->mount_point, v->fs_type, 0); } else if (strcmp(v->fs_type, "ext4") == 0 || strcmp(v->fs_type, "ext3") == 0 || strcmp(v->fs_type, "ext2") == 0 || strcmp(v->fs_type, "vfat") == 0) { result = mount(v->device, v->mount_point, v->fs_type, MS_NOATIME | MS_NODEV | MS_NODIRATIME, ""); if (result == 0) return 0; if (v->device2) { LOGW("failed to mount %s (%s); trying %s\n", v->device, strerror(errno), v->device2); result = mount(v->device2, v->mount_point, v->fs_type, MS_NOATIME | MS_NODEV | MS_NODIRATIME, ""); if (result == 0) return 0; } LOGE("failed to mount %s (%s)\n", v->mount_point, strerror(errno)); return -1; } LOGE("unknown fs_type \"%s\" for %s\n", v->fs_type, v->mount_point); return -1; }
void afsd_mount_afs(const char *rn, const char *cacheMountDir) { int mountFlags; /*Flags passed to mount() */ char *mountDir; /* For HandleMTab() */ mountFlags = 0; /* Read/write file system, can do setuid() */ #if defined(AFS_SUN_ENV) || defined(AFS_SUN5_ENV) #ifdef AFS_SUN5_ENV mountFlags |= MS_DATA; #else mountFlags |= M_NEWTYPE; /* This searches by name in vfs_conf.c so don't need to recompile vfs.c because MOUNT_MAXTYPE has changed; it seems that Sun fixed this at last... */ #endif #endif #if defined(AFS_HPUX100_ENV) mountFlags |= MS_DATA; #endif if (afsd_verbose) printf("%s: Mounting the AFS root on '%s', flags: %d.\n", rn, cacheMountDir, mountFlags); #if defined(AFS_FBSD60_ENV) /* data must be non-NULL but is otherwise ignored */ if ((mount(MOUNT_AFS, cacheMountDir, mountFlags, rn)) < 0) { #elif defined(AFS_FBSD_ENV) if ((mount("AFS", cacheMountDir, mountFlags, (caddr_t) 0)) < 0) { #elif defined(AFS_AIX_ENV) if (aix_vmount(cacheMountDir)) { #elif defined(AFS_HPUX100_ENV) if ((mount("", cacheMountDir, mountFlags, "afs", NULL, 0)) < 0) { #elif defined(AFS_SUN5_ENV) if ((mount("AFS", cacheMountDir, mountFlags, "afs", NULL, 0)) < 0) { #elif defined(AFS_SGI_ENV) mountFlags = MS_FSS; if ((mount(MOUNT_AFS, cacheMountDir, mountFlags, (caddr_t) MOUNT_AFS)) < 0) { #elif defined(AFS_LINUX20_ENV) if ((mount("AFS", cacheMountDir, MOUNT_AFS, 0, NULL)) < 0) { #elif defined(AFS_NBSD50_ENV) if ((mount(MOUNT_AFS, cacheMountDir, mountFlags, NULL, 0)) < 0) { #else /* This is the standard mount used by the suns and rts */ if ((mount(MOUNT_AFS, cacheMountDir, mountFlags, (caddr_t) 0)) < 0) { #endif printf("%s: Can't mount AFS on %s(%d)\n", rn, cacheMountDir, errno); exit(1); } mountDir = strdup(cacheMountDir); HandleMTab(mountDir); free(mountDir); } int afsd_fork(int wait, afsd_callback_func cb, void *rock) { int code; code = fork(); if (code == 0) { (*cb) (rock); exit(1); } else { assert(code > 0); if (wait) { opr_Verify(waitpid(code, NULL, 0) != -1); } } return 0; } int afsd_daemon(int nochdir, int noclose) { return daemon(nochdir, noclose); } int afsd_check_mount(const char *rn, const char *mountdir) { struct stat statbuf; if (stat(mountdir, &statbuf)) { printf("%s: Mountpoint %s missing.\n", rn, mountdir); return -1; } else if (!S_ISDIR(statbuf.st_mode)) { printf("%s: Mountpoint %s is not a directory.\n", rn, mountdir); return -1; } return 0; } int main(int argc, char **argv) { int code; afsd_init(); code = afsd_parse(argc, argv); if (code) { return -1; } return afsd_run(); }
int singularity_mount_tmp(void) { char *container_dir = singularity_rootfs_dir(); char *tmp_source; char *vartmp_source; char *tmpdirpath; singularity_config_rewind(); if ( singularity_config_get_bool("mount tmp", 1) <= 0 ) { singularity_message(VERBOSE, "Skipping tmp dir mounting (per config)\n"); return(0); } if ( ( tmpdirpath = getenv("SINGULARITY_WORKDIR") ) != NULL ) { // Flawfinder: ignore singularity_config_rewind(); if ( singularity_config_get_bool("user bind control", 1) <= 0 ) { singularity_message(ERROR, "User bind control is disabled by system administrator\n"); ABORT(5); } tmp_source = joinpath(tmpdirpath, "/tmp"); vartmp_source = joinpath(tmpdirpath, "/var_tmp"); } else if ( getenv("SINGULARITY_CONTAIN") != NULL ) { // Flawfinder: ignore char *sessiondir = singularity_sessiondir_get(); tmp_source = joinpath(sessiondir, "/tmp"); vartmp_source = joinpath(sessiondir, "/var_tmp"); } else { tmp_source = strdup("/tmp"); vartmp_source = strdup("/var/tmp"); } if ( s_mkpath(tmp_source, 0755) < 0 ) { singularity_message(ERROR, "Could not create tmp directory %s: %s\n", tmp_source, strerror(errno)); ABORT(255); } if ( s_mkpath(vartmp_source, 0755) < 0 ) { singularity_message(ERROR, "Could not create vartmp directory %s: %s\n", vartmp_source, strerror(errno)); ABORT(255); } if ( is_dir(tmp_source) == 0 ) { if ( is_dir(joinpath(container_dir, "/tmp")) == 0 ) { singularity_priv_escalate(); singularity_message(VERBOSE, "Mounting directory: /tmp\n"); if ( mount(tmp_source, joinpath(container_dir, "/tmp"), NULL, MS_BIND|MS_NOSUID|MS_REC, NULL) < 0 ) { singularity_message(ERROR, "Failed to mount %s -> /tmp: %s\n", tmp_source, strerror(errno)); ABORT(255); } singularity_priv_drop(); } else { singularity_message(VERBOSE, "Could not mount container's /tmp directory: does not exist\n"); } } else { singularity_message(VERBOSE, "Could not mount host's /tmp directory (%s): does not exist\n", tmp_source); } if ( is_dir(vartmp_source) == 0 ) { if ( is_dir(joinpath(container_dir, "/var/tmp")) == 0 ) { singularity_priv_escalate(); singularity_message(VERBOSE, "Mounting directory: /var/tmp\n"); if ( mount(vartmp_source, joinpath(container_dir, "/var/tmp"), NULL, MS_BIND|MS_NOSUID|MS_REC, NULL) < 0 ) { singularity_message(ERROR, "Failed to mount %s -> /var/tmp: %s\n", vartmp_source, strerror(errno)); ABORT(255); } singularity_priv_drop(); } else { singularity_message(VERBOSE, "Could not mount container's /var/tmp directory: does not exist\n"); } } else { singularity_message(VERBOSE, "Could not mount host's /var/tmp directory (%s): does not exist\n", vartmp_source); } free(tmp_source); free(vartmp_source); return(0); }
// TODO: simplify this, after all it is just a tmpfs // TODO: fold this into bootstrap static void setup_private_mount(const char *security_tag) { uid_t uid = getuid(); gid_t gid = getgid(); char tmpdir[MAX_BUF] = { 0 }; // Create a 0700 base directory, this is the base dir that is // protected from other users. // // Under that basedir, we put a 1777 /tmp dir that is then bind // mounted for the applications to use must_snprintf(tmpdir, sizeof(tmpdir), "/tmp/snap.%d_%s_XXXXXX", uid, security_tag); if (mkdtemp(tmpdir) == NULL) { die("cannot create temporary directory essential for private /tmp"); } // now we create a 1777 /tmp inside our private dir mode_t old_mask = umask(0); char *d = strdup(tmpdir); if (!d) { die("cannot allocate memory for string copy"); } must_snprintf(tmpdir, sizeof(tmpdir), "%s/tmp", d); free(d); if (mkdir(tmpdir, 01777) != 0) { die("cannot create temporary directory for private /tmp"); } umask(old_mask); // chdir to '/' since the mount won't apply to the current directory char *pwd = get_current_dir_name(); if (pwd == NULL) die("cannot get current working directory"); if (chdir("/") != 0) die("cannot change directory to '/'"); // MS_BIND is there from linux 2.4 if (mount(tmpdir, "/tmp", NULL, MS_BIND, NULL) != 0) { die("cannot bind mount private /tmp"); } // MS_PRIVATE needs linux > 2.6.11 if (mount("none", "/tmp", NULL, MS_PRIVATE, NULL) != 0) { die("cannot change sharing on /tmp to make it private"); } // do the chown after the bind mount to avoid potential shenanigans if (chown("/tmp/", uid, gid) < 0) { die("cannot change ownership of /tmp"); } // chdir to original directory if (chdir(pwd) != 0) die("cannot change current working directory to the original directory"); free(pwd); // ensure we set the various TMPDIRs to our newly created tmpdir const char *tmpd[] = { "TMPDIR", "TEMPDIR", NULL }; int i; for (i = 0; tmpd[i] != NULL; i++) { if (setenv(tmpd[i], "/tmp", 1) != 0) { die("cannot set environment variable '%s'", tmpd[i]); } } }
/** * Bootstrap mount namespace. * * This is a chunk of tricky code that lets us have full control over the * layout and direction of propagation of mount events. The documentation below * assumes knowledge of the 'sharedsubtree.txt' document from the kernel source * tree. * * As a reminder two definitions are quoted below: * * A 'propagation event' is defined as event generated on a vfsmount * that leads to mount or unmount actions in other vfsmounts. * * A 'peer group' is defined as a group of vfsmounts that propagate * events to each other. * * (end of quote). * * The main idea is to setup a mount namespace that has a root filesystem with * vfsmounts and peer groups that, depending on the location, either isolate * or share with the rest of the system. * * The vast majority of the filesystem is shared in one direction. Events from * the outside (from the main mount namespace) propagate inside (to namespaces * of particular snaps) so things like new snap revisions, mounted drives, etc, * just show up as expected but even if a snap is exploited or malicious in * nature it cannot affect anything in another namespace where it might cause * security or stability issues. * * Selected directories (today just /media) can be shared in both directions. * This allows snaps with sufficient privileges to either create, through the * mount system call, additional mount points that are visible by the rest of * the system (both the main mount namespace and namespaces of individual * snaps) or remove them, through the unmount system call. **/ static void sc_bootstrap_mount_namespace(const struct sc_mount_config *config) { char scratch_dir[] = "/tmp/snap.rootfs_XXXXXX"; char src[PATH_MAX]; char dst[PATH_MAX]; if (mkdtemp(scratch_dir) == NULL) { die("cannot create temporary directory for the root file system"); } // NOTE: at this stage we just called unshare(CLONE_NEWNS). We are in a new // mount namespace and have a private list of mounts. debug("scratch directory for constructing namespace: %s", scratch_dir); // Make the root filesystem recursively shared. This way propagation events // will be shared with main mount namespace. debug("performing operation: mount --make-rshared /"); if (mount("none", "/", NULL, MS_REC | MS_SHARED, NULL) < 0) { die("cannot perform operation: mount --make-rshared /"); } // Bind mount the temporary scratch directory for root filesystem over // itself so that it is a mount point. This is done so that it can become // unbindable as explained below. debug("performing operation: mount --bind %s %s", scratch_dir, scratch_dir); if (mount(scratch_dir, scratch_dir, NULL, MS_BIND, NULL) < 0) { die("cannot perform operation: mount --bind %s %s", scratch_dir, scratch_dir); } // Make the scratch directory unbindable. // // This is necessary as otherwise a mount loop can occur and the kernel // would crash. The term unbindable simply states that it cannot be bind // mounted anywhere. When we construct recursive bind mounts below this // guarantees that this directory will not be replicated anywhere. debug("performing operation: mount --make-unbindable %s", scratch_dir); if (mount("none", scratch_dir, NULL, MS_UNBINDABLE, NULL) < 0) { die("cannot perform operation: mount --make-unbindable %s", scratch_dir); } // Recursively bind mount desired root filesystem directory over the // scratch directory. This puts the initial content into the scratch space // and serves as a foundation for all subsequent operations below. // // The mount is recursive because it can either be applied to the root // filesystem of a core system (aka all-snap) or the core snap on a classic // system. In the former case we need recursive bind mounts to accurately // replicate the state of the root filesystem into the scratch directory. debug("performing operation: mount --rbind %s %s", config->rootfs_dir, scratch_dir); if (mount(config->rootfs_dir, scratch_dir, NULL, MS_REC | MS_BIND, NULL) < 0) { die("cannot perform operation: mount --rbind %s %s", config->rootfs_dir, scratch_dir); } // Make the scratch directory recursively private. Nothing done there will // be shared with any peer group, This effectively detaches us from the // original namespace and coupled with pivot_root below serves as the // foundation of the mount sandbox. debug("performing operation: mount --make-rslave %s", scratch_dir); if (mount("none", scratch_dir, NULL, MS_REC | MS_SLAVE, NULL) < 0) { die("cannot perform operation: mount --make-rslave %s", scratch_dir); } // Bind mount certain directories from the host filesystem to the scratch // directory. By default mount events will propagate in both into and out // of the peer group. This way the running application can alter any global // state visible on the host and in other snaps. This can be restricted by // disabling the "is_bidirectional" flag as can be seen below. for (const struct sc_mount * mnt = config->mounts; mnt->path != NULL; mnt++) { if (mnt->is_bidirectional && mkdir(mnt->path, 0755) < 0 && errno != EEXIST) { die("cannot create %s", mnt->path); } must_snprintf(dst, sizeof dst, "%s/%s", scratch_dir, mnt->path); debug("performing operation: mount --rbind %s %s", mnt->path, dst); if (mount(mnt->path, dst, NULL, MS_REC | MS_BIND, NULL) < 0) { die("cannot perform operation: mount --rbind %s %s", mnt->path, dst); } if (!mnt->is_bidirectional) { // Mount events will only propagate inwards to the namespace. This // way the running application cannot alter any global state apart // from that of its own snap. debug("performing operation: mount --make-rslave %s", dst); if (mount("none", dst, NULL, MS_REC | MS_SLAVE, NULL) != 0) { die("cannot perform operation: mount --make-rslave %s", dst); } } } // Since we mounted /etc from the host filesystem to the scratch directory, // we may need to put /etc/alternatives from the desired root filesystem // (e.g. the core snap) back. This way the behavior of running snaps is not // affected by the alternatives directory from the host, if one exists. // // https://bugs.launchpad.net/snap-confine/+bug/1580018 const char *etc_alternatives = "/etc/alternatives"; if (access(etc_alternatives, F_OK) == 0) { must_snprintf(src, sizeof src, "%s%s", config->rootfs_dir, etc_alternatives); must_snprintf(dst, sizeof dst, "%s%s", scratch_dir, etc_alternatives); debug("performing operation: mount --bind %s %s", src, dst); if (mount(src, dst, NULL, MS_BIND, NULL) != 0) { die("cannot perform operation: mount --bind %s %s", src, dst); } debug("performing operation: mount --make-slave %s", dst); if (mount("none", dst, NULL, MS_SLAVE, NULL) != 0) { die("cannot perform operation: mount --make-slave %s", dst); } } // Bind mount the directory where all snaps are mounted. The location of // the this directory on the host filesystem may not match the location in // the desired root filesystem. In the "core" and "ubuntu-core" snaps the // directory is always /snap. On the host it is a build-time configuration // option stored in SNAP_MOUNT_DIR. must_snprintf(dst, sizeof dst, "%s/snap", scratch_dir); debug("performing operation: mount --rbind %s %s", SNAP_MOUNT_DIR, dst); if (mount(SNAP_MOUNT_DIR, dst, NULL, MS_BIND | MS_REC | MS_SLAVE, NULL) < 0) { die("cannot perform operation: mount --rbind -o slave %s %s", SNAP_MOUNT_DIR, dst); } debug("performing operation: mount --make-rslave %s", dst); if (mount("none", dst, NULL, MS_REC | MS_SLAVE, NULL) < 0) { die("cannot perform operation: mount --make-rslave %s", dst); } // Create the hostfs directory if one is missing. This directory is a part // of packaging now so perhaps this code can be removed later. if (access(SC_HOSTFS_DIR, F_OK) != 0) { debug("creating missing hostfs directory"); if (mkdir(SC_HOSTFS_DIR, 0755) != 0) { die("cannot perform operation: mkdir %s", SC_HOSTFS_DIR); } } // Make the upcoming "put_old" directory for pivot_root private so that // mount events don't propagate to any peer group. In practice pivot root // has a number of undocumented requirements and one of them is that the // "put_old" directory (the second argument) cannot be shared in any way. must_snprintf(dst, sizeof dst, "%s/%s", scratch_dir, SC_HOSTFS_DIR); debug("performing operation: mount --bind %s %s", dst, dst); if (mount(dst, dst, NULL, MS_BIND, NULL) < 0) { die("cannot perform operation: mount --bind %s %s", dst, dst); } debug("performing operation: mount --make-private %s", dst); if (mount("none", dst, NULL, MS_PRIVATE, NULL) < 0) { die("cannot perform operation: mount --make-private %s", dst); } // On classic mount the nvidia driver. Ideally this would be done in an // uniform way after pivot_root but this is good enough and requires less // code changes the nvidia code assumes it has access to the existing // pre-pivot filesystem. if (config->on_classic) { sc_mount_nvidia_driver(scratch_dir); } // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // pivot_root // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // Use pivot_root to "chroot" into the scratch directory. // // Q: Why are we using something as esoteric as pivot_root(2)? // A: Because this makes apparmor handling easy. Using a normal chroot // makes all apparmor rules conditional. We are either running on an // all-snap system where this would-be chroot didn't happen and all the // rules see / as the root file system _OR_ we are running on top of a // classic distribution and this chroot has now moved all paths to // /tmp/snap.rootfs_*. // // Because we are using unshare(2) with CLONE_NEWNS we can essentially use // pivot_root just like chroot but this makes apparmor unaware of the old // root so everything works okay. // // HINT: If you are debugging this and are trying to see why pivot_root // happens to return EINVAL with any changes you may be making, please // consider applying // misc/0001-Add-printk-based-debugging-to-pivot_root.patch to your tree // kernel. debug("performing operation: pivot_root %s %s", scratch_dir, dst); if (syscall(SYS_pivot_root, scratch_dir, dst) < 0) { die("cannot perform operation: pivot_root %s %s", scratch_dir, dst); } // Unmount the self-bind mount over the scratch directory created earlier // in the original root filesystem (which is now mounted on SC_HOSTFS_DIR). // This way we can remove the temporary directory we created and "clean up" // after ourselves nicely. must_snprintf(dst, sizeof dst, "%s/%s", SC_HOSTFS_DIR, scratch_dir); debug("performing operation: umount %s", dst); if (umount2(dst, 0) < 0) { die("cannot perform operation: umount %s", dst); } // Remove the scratch directory. Note that we are using the path that is // based on the old root filesystem as after pivot_root we cannot guarantee // what is present at the same location normally. (It is probably an empty // /tmp directory that is populated in another place). debug("performing operation: rmdir %s", dst); if (rmdir(scratch_dir) < 0) { die("cannot perform operation: rmdir %s", dst); }; // Make the old root filesystem recursively slave. This way operations // performed in this mount namespace will not propagate to the peer group. // This is another essential part of the confinement system. debug("performing operation: mount --make-rslave %s", SC_HOSTFS_DIR); if (mount("none", SC_HOSTFS_DIR, NULL, MS_REC | MS_SLAVE, NULL) < 0) { die("cannot perform operation: mount --make-rslave %s", SC_HOSTFS_DIR); } // Detach the redundant hostfs version of sysfs since it shows up in the // mount table and software inspecting the mount table may become confused // (eg, docker and LP:# 162601). must_snprintf(src, sizeof src, "%s/sys", SC_HOSTFS_DIR); debug("performing operation: umount --lazy %s", src); if (umount2(src, UMOUNT_NOFOLLOW | MNT_DETACH) < 0) { die("cannot perform operation: umount --lazy %s", src); } // Detach the redundant hostfs version of /dev since it shows up in the // mount table and software inspecting the mount table may become confused. must_snprintf(src, sizeof src, "%s/dev", SC_HOSTFS_DIR); debug("performing operation: umount --lazy %s", src); if (umount2(src, UMOUNT_NOFOLLOW | MNT_DETACH) < 0) { die("cannot perform operation: umount --lazy %s", src); } // Detach the redundant hostfs version of /proc since it shows up in the // mount table and software inspecting the mount table may become confused. must_snprintf(src, sizeof src, "%s/proc", SC_HOSTFS_DIR); debug("performing operation: umount --lazy %s", src); if (umount2(src, UMOUNT_NOFOLLOW | MNT_DETACH) < 0) { die("cannot perform operation: umount --lazy %s", src); } }
int main (int argc, char **argv) { char tempdir[] = "/tmp/approot_XXXXXX"; char *base_os; char **images; char *root; int n_images; pid_t child; int child_status = 0; char *app_root; char **mountpoints; int n_mountpoints; int i; uid_t ruid, euid, suid; gid_t rgid, egid, sgid; char cwd_buf[PATH_MAX]; char *cwd; if (argc < 2) fatal ("Too few arguments, need base and at least one image"); base_os = argv[1]; images = &argv[2]; n_images = argc - 2; root = mkdtemp (tempdir); if (root == NULL) fatal ("Can't create root"); if (getresgid (&rgid, &egid, &sgid) < 0) fatal_errno ("getresgid"); if (getresuid (&ruid, &euid, &suid) < 0) fatal_errno ("getresuid"); if ((child = syscall (__NR_clone, SIGCHLD | CLONE_NEWNS, NULL)) < 0) fatal_errno ("clone"); if (child == 0) { /* Child */ /* Disable setuid, new caps etc for children */ if (prctl (PR_SET_NO_NEW_PRIVS, 1) < 0 && errno != EINVAL) fatal_errno ("prctl (PR_SET_NO_NEW_PRIVS)"); else if (prctl (PR_SET_SECUREBITS, SECBIT_NOROOT | SECBIT_NOROOT_LOCKED) < 0) fatal_errno ("prctl (SECBIT_NOROOT)"); /* Don't leak our mounts to the parent namespace */ if (mount (NULL, "/", "none", MS_SLAVE | MS_REC, NULL) < 0) fatal_errno ("mount(/, MS_SLAVE | MS_REC)"); /* Check we're allowed to chdir into base os */ cwd = getcwd (cwd_buf, sizeof (cwd_buf)); if (fsuid_chdir (ruid, base_os) < 0) fatal_errno ("chdir"); if (chdir (cwd) < 0) fatal_errno ("chdir"); if (mount ("tmpfs", root, "tmpfs", MS_MGC_VAL | MS_PRIVATE, NULL) != 0) fatal_errno ("execv"); n_mountpoints = n_images + 1; mountpoints = calloc (n_mountpoints, sizeof (char *)); if (mountpoints == NULL) fatal ("oom"); mountpoints[0] = base_os; for (i = 0; i < n_images; i++) { if (fsuid_access (ruid, images[i], R_OK) < 0) fatal_errno ("access"); mountpoints[i+1] = mount_image (root, images[i]); if (mountpoints[i+1] == NULL) fatal ("mount image %s\n", images[i]); } app_root = make_fs_dir (root, "/root", 0555); if (app_root == NULL) fatal ("make_fs_dir root"); setup_base (app_root); merge_dirs (app_root, mountpoints, n_mountpoints); if (chdir (app_root) < 0) fatal_errno ("chdir"); if (chroot (".") < 0) fatal_errno ("chroot"); /* Switch back to the uid of our invoking process. These calls are * irrevocable - see setuid(2) */ if (setgid (rgid) < 0) fatal_errno ("setgid"); if (setuid (ruid) < 0) fatal_errno ("setuid"); if (execl ("/bin/sh", "/bin/sh", NULL) < 0) fatal_errno ("execl"); } /* Parent */ /* Let's also setuid back in the parent - there's no reason to stay uid 0, and * it's just better to drop privileges. */ if (setgid (rgid) < 0) fatal_errno ("setgid"); if (setuid (ruid) < 0) fatal_errno ("setuid"); if (child == -1) fatal_errno ("clone"); /* Ignore Ctrl-C in parent while waiting */ signal (SIGINT, SIG_IGN); if (waitpid (child, &child_status, 0) < 0) fatal_errno ("waitpid"); rmdir (root); if (WIFEXITED (child_status)) return WEXITSTATUS (child_status); else return 1; }