void main(int argc, char **argv) { uid_t uid = getuid(); uid_t gid = getgid(); char *sandbox_root; char **cmd_args; if(argc < 3) { fprintf(stderr, "Usage: sandbox_root command...\n"); exit(-1); } new_root = argv[1]; cmd_args = argv+2; /* 1. Unshare. From here onwards, we have most root-equiv capabilities until we execve-ed, FIXME LWN article here. */ // FIXME try clone here, just to see if that works too. check("unshare", unshare(CLONE_NEWNS | CLONE_NEWUSER | CLONE_NEWPID | CLONE_NEWUTS)); /* 2. Fork once, so we become the parent of the new process id space and can mount proc */ fork_once(); /* 3. Set UID/GID maps, FIXME LWN article here */ write_file("/proc/self/setgroups", "deny"); write_file("/proc/self/uid_map", aasprintf("%d %d 1", uid, uid)); write_file("/proc/self/gid_map", aasprintf("%d %d 1", gid, gid)); /* 4. Mount minimal fstab */ mount_fstab(); /* 5. Pivot into the new root */ pivot(); /* 6. Exec */ check("execve", execv(cmd_args[0], cmd_args)); }
int mount_fstab_main(int argc, char *argv[]) { int opt; static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; int long_index = 0; while ((opt = getopt_long(argc, argv, "h", long_options, &long_index)) != -1) { switch (opt) { case 'h': mount_fstab_usage(0); return EXIT_SUCCESS; default: mount_fstab_usage(1); return EXIT_FAILURE; } } // We only expect one argument if (argc - optind != 1) { mount_fstab_usage(1); return EXIT_FAILURE; } // Use the kernel log since logcat hasn't run yet util::log_set_logger(std::make_shared<util::KmsgLogger>()); // Patch SELinux policy if (!patch_loaded_sepolicy()) { LOGE("Failed to patch loaded SELinux policy. Continuing anyway"); } else { LOGV("SELinux policy patching completed"); } #if FORCE_SELINUX_PERMISSIVE int fd = open("/sys/fs/selinux/enforce", O_RDWR); if (fd > 0) { write(fd, "0", 1); close(fd); } #endif if (!mount_fstab(argv[optind])) { LOGE("Failed to mount filesystems. Rebooting into recovery"); reboot_directly("recovery"); return EXIT_FAILURE; } return EXIT_SUCCESS; }
int init_main(int argc, char *argv[]) { for (int i = 1; i < argc; ++i) { if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { init_usage(true); return EXIT_SUCCESS; } } umask(0); 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, nullptr); mount("proc", "/proc", "proc", 0, nullptr); mount("sysfs", "/sys", "sysfs", 0, nullptr); open_devnull_stdio(); util::log_set_logger(std::make_shared<util::KmsgLogger>()); if (klogctl(KLOG_CONSOLE_LEVEL, nullptr, 8) < 0) { LOGE("Failed to set loglevel: %s", strerror(errno)); } LOGV("Booting up with version %s (%s)", get_mbtool_version(), get_git_version()); // Start probing for devices device_init(); std::string fstab = find_fstab(); if (fstab.empty()) { LOGE("Failed to find a suitable fstab file"); emergency_reboot(); return EXIT_FAILURE; } mkdir("/system", 0755); mkdir("/cache", 0770); mkdir("/data", 0771); util::chown("/cache", "system", "cache", 0); util::chown("/data", "system", "system", 0); fix_arter97(); // Mount fstab and write new redacted version if (!mount_fstab(fstab, true)) { LOGE("Failed to mount fstab"); emergency_reboot(); return EXIT_FAILURE; } LOGE("Successfully mounted fstab"); fix_file_contexts(); add_mbtool_services(); strip_manual_mounts(); struct stat sb; if (stat("/sepolicy", &sb) == 0) { if (!patch_sepolicy("/sepolicy", "/sepolicy")) { LOGW("Failed to patch /sepolicy"); emergency_reboot(); return EXIT_FAILURE; } } // Kill uevent thread and close uevent socket device_close(); // Unmount partitions umount("/dev/pts"); umount("/dev"); umount("/proc"); umount("/sys"); // Do not remove these as Android 6.0 init's stage 1 no longer creates these // (platform/system/core commit a1f6a4b13921f61799be14a2544bdbf95958eae7) //rmdir("/dev"); //rmdir("/proc"); //rmdir("/sys"); // Start real init unlink("/init"); rename("/init.orig", "/init"); LOGD("Launching real init ..."); execlp("/init", "/init", nullptr); LOGE("Failed to exec real init: %s", strerror(errno)); emergency_reboot(); return EXIT_FAILURE; }