Example #1
0
int uevent_dump_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':
            uevent_dump_usage(false);
            return EXIT_SUCCESS;
        default:
            uevent_dump_usage(true);
            return EXIT_FAILURE;
        }
    }

    // There should be no other arguments
    if (argc - optind != 0) {
        uevent_dump_usage(true);
        return EXIT_FAILURE;
    }

    LOGV("mbtool version %s (%s)", get_mbtool_version(), get_git_version());

    // Start probing for devices
    device_init(true);
    // Kill uevent thread and close uevent socket
    device_close();

    return EXIT_SUCCESS;
}
Example #2
0
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;
}
Example #3
0
static bool initialize_adb()
{
    bool ret = true;

    const char *version = get_mbtool_version();
    ret = write_file("/sys/class/android_usb/android0/enable", "0", 1) && ret;
    ret = write_file("/sys/class/android_usb/android0/idVendor", "18D1", 4) && ret;
    ret = write_file("/sys/class/android_usb/android0/idProduct", "4EE7", 4) && ret;
    ret = write_file("/sys/class/android_usb/android0/f_ffs/aliases", "adb", 3) && ret;
    ret = write_file("/sys/class/android_usb/android0/functions", "adb", 3) && ret;
    ret = write_file("/sys/class/android_usb/android0/iManufacturer", "mbtool", 6) && ret;
    ret = write_file("/sys/class/android_usb/android0/iProduct", "miniadbd", 8) && ret;
    ret = write_file("/sys/class/android_usb/android0/iSerial", version, strlen(version)) && ret;
    ret = write_file("/sys/class/android_usb/android0/enable", "1", 1) && ret;

    // Create functionfs paths
    if (!util::mkdir_recursive(USB_FFS_ADB_PATH, 0770)) {
        LOGW("%s: Failed to create directory: %s",
             USB_FFS_ADB_PATH, strerror(errno));
        ret = false;
    }
    if (!util::mount("adb", USB_FFS_ADB_PATH, "functionfs", 0, "")) {
        LOGW("%s: Failed to mount functionfs: %s",
             USB_FFS_ADB_PATH, strerror(errno));
        ret = false;
    }

    // Set environment variables
    ret = setenv("PATH", "/system/bin", 1) == 0 && ret;
    ret = setenv("LD_LIBRARY_PATH", "/system/lib", 1) == 0 && ret;
    ret = setenv("ANDROID_DATA", "/data", 1) == 0 && ret;
    ret = setenv("ANDROID_ROOT", "/system", 1) == 0 && ret;

    // Use TWRP's legacy property workspace hack. TouchWiz's sh binary segfaults
    // if there's no property service (i.e. no /dev/__properties__ and no valid
    // ANDROID_PROPERTY_WORKSPACE environment variable). This doesn't actually
    // start a "real" properties service (getprop and setprop will never work),
    // but it's enough to prevent the segfaults.
    char tmp[32];
    int propfd, propsz;
    legacy_properties_init();

    // Load /default.prop
    std::unordered_map<std::string, std::string> props;
    util::file_get_all_properties("/default.prop", &props);
    for (auto const &pair : props) {
        legacy_property_set(pair.first.c_str(), pair.second.c_str());
    }
    // Load /system/build.prop
    props.clear();
    util::file_get_all_properties("/system/build.prop", &props);
    for (auto const &pair : props) {
        legacy_property_set(pair.first.c_str(), pair.second.c_str());
    }

    legacy_get_property_workspace(&propfd, &propsz);
    snprintf(tmp, sizeof(tmp), "%d,%d", dup(propfd), propsz);

    char *orig_prop_env = getenv("ANDROID_PROPERTY_WORKSPACE");
    LOGD("Original properties environment: %s",
         orig_prop_env ? orig_prop_env : "null");

    setenv("ANDROID_PROPERTY_WORKSPACE", tmp, 1);

    LOGD("Switched to legacy properties environment: %s", tmp);

    return ret;
}
Example #4
0
int daemon_main(int argc, char *argv[])
{
    int opt;
    bool fork_flag = false;
    bool replace_flag = false;

    static struct option long_options[] = {
        {"daemonize", no_argument, 0, 'd'},
        {"replace",   no_argument, 0, 'r'},
        {"help",      no_argument, 0, 'h'},
        {0, 0, 0, 0}
    };

    int long_index = 0;

    while ((opt = getopt_long(argc, argv, "drh", long_options, &long_index)) != -1) {
        switch (opt) {
        case 'd':
            fork_flag = true;
            break;

        case 'r':
            replace_flag = true;
            break;

        case 'h':
            daemon_usage(0);
            return EXIT_SUCCESS;

        default:
            daemon_usage(1);
            return EXIT_FAILURE;
        }
    }

    // There should be no other arguments
    if (argc - optind != 0) {
        daemon_usage(1);
        return EXIT_FAILURE;
    }

    // Patch SELinux policy to make init permissive
    patch_loaded_sepolicy();

    // Allow untrusted_app to connect to our daemon
    patch_sepolicy_daemon();

    // Set version property if we're the system mbtool (i.e. launched by init)
    // Possible to override this with another program by double forking, letting
    // 2nd child reparent to init, and then calling execve("/mbtool", ...), but
    // meh ...
    if (getppid() == 1) {
        if (!util::set_property("ro.multiboot.version", get_mbtool_version())) {
            std::printf("Failed to set 'ro.multiboot.version' to '%s'\n",
                        get_mbtool_version());
        }
    }

    if (replace_flag) {
        PROCTAB *proc = openproc(PROC_FILLCOM | PROC_FILLSTAT);
        if (proc) {
            pid_t curpid = getpid();

            while (proc_t *info = readproc(proc, nullptr)) {
                if (strcmp(info->cmd, "mbtool") == 0          // This is mbtool
                        && info->cmdline                      // And we can see the command line
                        && info->cmdline[1]                   // And argc > 1
                        && strstr(info->cmdline[1], "daemon") // And it's a daemon process
                        && info->tid != curpid) {             // And we're not killing ourself
                    // Kill the daemon process
                    std::printf("Killing PID %d\n", info->tid);
                    kill(info->tid, SIGTERM);
                }

                freeproc(info);
            }

            closeproc(proc);
        }

        // Give processes a chance to exit
        usleep(500000);
    }

    // Set up logging
    if (!util::mkdir_parent(MULTIBOOT_LOG_DAEMON, 0775) && errno != EEXIST) {
        fprintf(stderr, "Failed to create parent directory of %s: %s\n",
                MULTIBOOT_LOG_DAEMON, strerror(errno));
        return EXIT_FAILURE;
    }

    autoclose::file fp(autoclose::fopen(MULTIBOOT_LOG_DAEMON, "w"));
    if (!fp) {
        fprintf(stderr, "Failed to open log file %s: %s\n",
                MULTIBOOT_LOG_DAEMON, strerror(errno));
        return EXIT_FAILURE;
    }

    fix_multiboot_permissions();

    // mbtool logging
    log::log_set_logger(std::make_shared<log::StdioLogger>(fp.get(), true));

    if (fork_flag) {
        run_daemon_fork();
    } else {
        return run_daemon() ? EXIT_SUCCESS : EXIT_FAILURE;
    }
}