int su_main(int argc, char *argv[]) { int ppid = getppid(); if ((geteuid() != AID_ROOT && getuid() != AID_ROOT) || (get_api_version() >= 18 && getuid() == AID_SHELL) || get_api_version() >= 19) { // attempt to connect to daemon... LOGD("starting daemon client %d %d", getuid(), geteuid()); return connect_daemon(argc, argv, ppid); } else { return su_main_nodaemon(argc, argv); } }
static int l_get_compile_options(lua_State *L) { lua_settop(L, 0); lua_newtable(L); #ifdef CORSIX_TH_64BIT lua_pushboolean(L, 1); #else lua_pushboolean(L, 0); #endif lua_setfield(L, -2, "arch_64"); #if defined(CORSIX_TH_USE_OGL_RENDERER) lua_pushliteral(L, "OpenGL"); #elif defined(CORSIX_TH_USE_DX9_RENDERER) lua_pushliteral(L, "DirectX 9"); #elif defined(CORSIX_TH_USE_SDL_RENDERER) lua_pushliteral(L, "SDL"); #else lua_pushliteral(L, "Unknown"); #endif lua_setfield(L, -2, "renderer"); #ifdef CORSIX_TH_USE_SDL_MIXER lua_pushboolean(L, 1); #else lua_pushboolean(L, 0); #endif lua_setfield(L, -2, "audio"); lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); lua_getfield(L, -1, "jit"); if(lua_type(L, -1) == LUA_TNIL) { lua_replace(L, -2); } else { lua_getfield(L, -1, "version"); lua_replace(L, -3); lua_pop(L, 1); } lua_setfield(L, -2, "jit"); lua_pushinteger(L, get_api_version()); lua_setfield(L, -2, "api_version"); return 1; }
bool mount_fstab(const std::string &fstab_path) { bool ret = true; std::vector<util::fstab_rec> fstab; std::vector<util::fstab_rec *> recs_system; std::vector<util::fstab_rec *> recs_cache; std::vector<util::fstab_rec *> recs_data; std::vector<util::fstab_rec *> flags_system; std::vector<util::fstab_rec *> flags_cache; std::vector<util::fstab_rec *> flags_data; std::string target_system; std::string target_cache; std::string target_data; std::string path_fstab_gen; std::string path_completed; std::string path_failed; std::string base_name; std::string dir_name; struct stat st; std::shared_ptr<Rom> rom; std::string rom_id; Roms roms; roms.add_builtin(); base_name = util::base_name(fstab_path); dir_name = util::dir_name(fstab_path); path_fstab_gen += dir_name; path_fstab_gen += "/."; path_fstab_gen += base_name; path_fstab_gen += ".gen"; path_completed += dir_name; path_completed += "/."; path_completed += base_name; path_completed += ".completed"; path_failed += dir_name; path_failed += "/."; path_failed += base_name; path_failed += ".failed"; auto on_finish = util::finally([&] { if (ret) { util::create_empty_file(path_completed); LOGI("Successfully mounted partitions"); } else { util::create_empty_file(path_failed); } }); // This is a oneshot operation if (stat(path_completed.c_str(), &st) == 0) { LOGV("Filesystems already successfully mounted"); return true; } if (stat(path_failed.c_str(), &st) == 0) { LOGE("Failed to mount partitions ealier. No further attempts will be made"); return false; } // Remount rootfs as read-write so a new fstab file can be written if (mount("", "/", "", MS_REMOUNT, "") < 0) { LOGE("Failed to remount rootfs as rw: {}", strerror(errno)); } // Read original fstab fstab = util::read_fstab(fstab_path); if (fstab.empty()) { LOGE("Failed to read {}", fstab_path); return false; } // Generate new fstab without /system, /cache, or /data entries file_ptr out(std::fopen(path_fstab_gen.c_str(), "wb"), std::fclose); if (!out) { LOGE("Failed to open {} for writing: {}", path_fstab_gen, strerror(errno)); return false; } for (util::fstab_rec &rec : fstab) { if (rec.mount_point == "/system") { recs_system.push_back(&rec); } else if (rec.mount_point == "/cache") { recs_cache.push_back(&rec); } else if (rec.mount_point == "/data") { recs_data.push_back(&rec); } else { std::fprintf(out.get(), "%s\n", rec.orig_line.c_str()); } } out.reset(); // /system and /data are always in the fstab. The patcher should create // an entry for /cache for the ROMs that mount it manually in one of the // init scripts if (recs_system.empty() || recs_cache.empty() || recs_data.empty()) { LOGE("fstab does not contain all of /system, /cache, and /data!"); return false; } // Mount raw partitions to /raw/* if (!util::kernel_cmdline_get_option("romid", &rom_id) && !util::file_first_line("/romid", &rom_id)) { LOGE("Failed to determine ROM ID"); return false; } if (Roms::is_named_rom(rom_id)) { rom = Roms::create_named_rom(rom_id); } else { rom = roms.find_by_id(rom_id); if (!rom) { LOGE("Unknown ROM ID: {}", rom_id); return false; } } LOGD("ROM ID is: {}", rom_id); // Set property for the Android app to use if (!util::set_property("ro.multiboot.romid", rom_id)) { LOGE("Failed to set 'ro.multiboot.romid' to '{}'", rom_id); } // Because of how Android deals with partitions, if, say, the source path // for the /system bind mount resides on /cache, then the cache partition // must be mounted with the system partition's flags. In this future, this // may be avoided by mounting every partition with some more liberal flags, // since the current setup does not allow two bind mounted locations to // reside on the same partition. if (util::starts_with(rom->system_path, "/cache")) { flags_system = recs_cache; } else { flags_system = recs_system; } if (util::starts_with(rom->cache_path, "/system")) { flags_cache = recs_system; } else { flags_cache = recs_cache; } flags_data = recs_data; if (mkdir("/raw", 0755) < 0) { LOGE("Failed to create /raw"); return false; } if (!create_dir_and_mount(recs_system, flags_system, "/raw/system")) { LOGE("Failed to mount /raw/system"); return false; } if (!create_dir_and_mount(recs_cache, flags_cache, "/raw/cache")) { LOGE("Failed to mount /raw/cache"); return false; } if (!create_dir_and_mount(recs_data, flags_data, "/raw/data")) { LOGE("Failed to mount /raw/data"); return false; } // Make paths use /raw/... if (rom->system_path.empty() || rom->cache_path.empty() || rom->data_path.empty()) { LOGE("Invalid or empty paths"); return false; } target_system += "/raw"; target_system += rom->system_path; target_cache += "/raw"; target_cache += rom->cache_path; target_data += "/raw"; target_data += rom->data_path; if (!util::bind_mount(target_system, 0771, "/system", 0771)) { return false; } if (!util::bind_mount(target_cache, 0771, "/cache", 0771)) { return false; } if (!util::bind_mount(target_data, 0771, "/data", 0771)) { return false; } // Bind mount internal SD directory if (!util::bind_mount("/raw/data/media", 0771, "/data/media", 0771)) { return false; } // Prevent installd from dying because it can't unmount /data/media for // multi-user migration. Since <= 4.2 devices aren't supported anyway, // we'll bypass this. file_ptr fp(std::fopen("/data/.layout_version", "wb"), std::fclose); if (fp) { const char *layout_version; if (get_api_version() >= 21) { layout_version = "3"; } else { layout_version = "2"; } fwrite(layout_version, 1, strlen(layout_version), fp.get()); fp.reset(); } else { LOGE("Failed to open /data/.layout_version to disable migration"); } static std::string context("u:object_r:install_data_file:s0"); if (lsetxattr("/data/.layout_version", "security.selinux", context.c_str(), context.size() + 1, 0) < 0) { LOGE("{}: Failed to set SELinux context: {}", "/data/.layout_version", strerror(errno)); } // Global app sharing std::string config_path("/data/media/0/MultiBoot/"); config_path += rom->id; config_path += "/config.json"; RomConfig config; if (config.load_file(config_path)) { if (config.indiv_app_sharing && (config.global_app_sharing || config.global_paid_app_sharing)) { LOGW("Both individual and global sharing are enabled"); LOGW("Global sharing settings will be ignored"); } else { if (config.global_app_sharing || config.global_paid_app_sharing) { if (!util::bind_mount("/raw/data/app-lib", 0771, "/data/app-lib", 0771)) { return false; } } if (config.global_app_sharing) { if (!util::bind_mount("/raw/data/app", 0771, "/data/app", 0771)) { return false; } } if (config.global_paid_app_sharing) { if (!util::bind_mount("/raw/data/app-asec", 0771, "/data/app-asec", 0771)) { return false; } } } } return true; }