Loading cmds/atrace/atrace.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -102,6 +102,7 @@ static const TracingCategory k_categories[] = { { "pm", "Package Manager", ATRACE_TAG_PACKAGE_MANAGER, { } }, { "ss", "System Server", ATRACE_TAG_SYSTEM_SERVER, { } }, { "database", "Database", ATRACE_TAG_DATABASE, { } }, { "network", "Network", ATRACE_TAG_NETWORK, { } }, { k_coreServiceCategory, "Core services", 0, { } }, { "sched", "CPU Scheduling", 0, { { REQ, "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" }, Loading cmds/atrace/atrace.rc +1 −1 Original line number Diff line number Diff line ## Permissions to allow system-wide tracing to the kernel trace buffer. ## on boot on fs # Allow writing to the kernel trace log. chmod 0222 /sys/kernel/debug/tracing/trace_marker Loading cmds/dumpstate/dumpstate.cpp +25 −13 Original line number Diff line number Diff line Loading @@ -149,7 +149,7 @@ void do_mountinfo(int pid, const char *name) { } void add_mountinfo() { if (!zip_writer) return; if (!is_zipping()) return; const char *title = "MOUNT INFO"; mount_points.clear(); DurationReporter duration_reporter(title, NULL); Loading Loading @@ -180,8 +180,8 @@ static void dump_dev_files(const char *title, const char *driverpath, const char } static void dump_systrace() { if (!zip_writer) { MYLOGD("Not dumping systrace because zip_writer is not set\n"); if (!is_zipping()) { MYLOGD("Not dumping systrace because dumpstate is not zipping\n"); return; } std::string systrace_path = bugreport_dir + "/systrace-" + suffix + ".txt"; Loading Loading @@ -237,7 +237,7 @@ static void dump_raft() { return; } if (!zip_writer) { if (!is_zipping()) { // Write compressed and encoded raft logs to stdout if not zip_writer. run_command("RAFT LOGS", 600, "logcompressor", "-r", RAFT_DIR, NULL); return; Loading Loading @@ -578,8 +578,8 @@ static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = { }; bool add_zip_entry_from_fd(const std::string& entry_name, int fd) { if (!zip_writer) { MYLOGD("Not adding zip entry %s from fd because zip_writer is not set\n", if (!is_zipping()) { MYLOGD("Not adding entry %s from fd because dumpstate is not zipping\n", entry_name.c_str()); return false; } Loading Loading @@ -648,8 +648,8 @@ static int _add_file_from_fd(const char *title, const char *path, int fd) { // TODO: move to util.cpp void add_dir(const char *dir, bool recursive) { if (!zip_writer) { MYLOGD("Not adding dir %s because zip_writer is not set\n", dir); if (!is_zipping()) { MYLOGD("Not adding dir %s because dumpstate is not zipping\n", dir); return; } MYLOGD("Adding dir %s (recursive: %d)\n", dir, recursive); Loading @@ -657,10 +657,14 @@ void add_dir(const char *dir, bool recursive) { dump_files(NULL, dir, recursive ? skip_none : is_dir, _add_file_from_fd); } bool is_zipping() { return zip_writer != nullptr; } /* adds a text entry entry to the existing zip file. */ static bool add_text_zip_entry(const std::string& entry_name, const std::string& content) { if (!zip_writer) { MYLOGD("Not adding text zip entry %s because zip_writer is not set\n", entry_name.c_str()); if (!is_zipping()) { MYLOGD("Not adding text entry %s because dumpstate is not zipping\n", entry_name.c_str()); return false; } MYLOGD("Adding zip text entry %s\n", entry_name.c_str()); Loading Loading @@ -690,10 +694,12 @@ static bool add_text_zip_entry(const std::string& entry_name, const std::string& static void dump_iptables() { run_command("IPTABLES", 10, "iptables", "-L", "-nvx", NULL); run_command("IP6TABLES", 10, "ip6tables", "-L", "-nvx", NULL); run_command("IPTABLE NAT", 10, "iptables", "-t", "nat", "-L", "-nvx", NULL); run_command("IPTABLES NAT", 10, "iptables", "-t", "nat", "-L", "-nvx", NULL); /* no ip6 nat */ run_command("IPTABLE RAW", 10, "iptables", "-t", "raw", "-L", "-nvx", NULL); run_command("IP6TABLE RAW", 10, "ip6tables", "-t", "raw", "-L", "-nvx", NULL); run_command("IPTABLES MANGLE", 10, "iptables", "-t", "mangle", "-L", "-nvx", NULL); run_command("IP6TABLES MANGLE", 10, "ip6tables", "-t", "mangle", "-L", "-nvx", NULL); run_command("IPTABLES RAW", 10, "iptables", "-t", "raw", "-L", "-nvx", NULL); run_command("IP6TABLES RAW", 10, "ip6tables", "-t", "raw", "-L", "-nvx", NULL); } static void dumpstate(const std::string& screenshot_path, const std::string& version) { Loading Loading @@ -1374,6 +1380,12 @@ int main(int argc, char *argv[]) { add_mountinfo(); dump_iptables(); // Capture any IPSec policies in play. No keys are exposed here. run_command("IP XFRM POLICY", 10, "ip", "xfrm", "policy", nullptr); // Run ss as root so we can see socket marks. run_command("DETAILED SOCKET STATE", 10, "ss", "-eionptu", NULL); if (!drop_root_user()) { return -1; } Loading cmds/dumpstate/dumpstate.h +3 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,9 @@ extern std::string bugreport_dir; /* root dir for all files copied as-is into the bugreport. */ extern const std::string ZIP_ROOT_DIR; /* Checkes whether dumpstate is generating a zipped bugreport. */ bool is_zipping(); /* adds a new entry to the existing zip file. */ bool add_zip_entry(const std::string& entry_name, const std::string& entry_path); Loading cmds/installd/commands.cpp +104 −13 Original line number Diff line number Diff line Loading @@ -99,23 +99,69 @@ static std::string create_primary_profile(const std::string& profile_dir) { return StringPrintf("%s/%s", profile_dir.c_str(), PRIMARY_PROFILE_NAME); } static int prepare_app_dir(const std::string& path, mode_t target_mode, uid_t uid, const char* pkgname, const char* seinfo) { /** * Perform restorecon of the given path, but only perform recursive restorecon * if the label of that top-level file actually changed. This can save us * significant time by avoiding no-op traversals of large filesystem trees. */ static int restorecon_app_data_lazy(const std::string& path, const char* seinfo, uid_t uid) { int res = 0; char* before = nullptr; char* after = nullptr; // Note that SELINUX_ANDROID_RESTORECON_DATADATA flag is set by // libselinux. Not needed here. if (lgetfilecon(path.c_str(), &before) < 0) { PLOG(ERROR) << "Failed before getfilecon for " << path; goto fail; } if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, 0) < 0) { PLOG(ERROR) << "Failed top-level restorecon for " << path; goto fail; } if (lgetfilecon(path.c_str(), &after) < 0) { PLOG(ERROR) << "Failed after getfilecon for " << path; goto fail; } // If the initial top-level restorecon above changed the label, then go // back and restorecon everything recursively if (strcmp(before, after)) { LOG(DEBUG) << "Detected label change from " << before << " to " << after << " at " << path << "; running recursive restorecon"; if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, SELINUX_ANDROID_RESTORECON_RECURSE) < 0) { PLOG(ERROR) << "Failed recursive restorecon for " << path; goto fail; } } goto done; fail: res = -1; done: free(before); free(after); return res; } static int restorecon_app_data_lazy(const std::string& parent, const char* name, const char* seinfo, uid_t uid) { return restorecon_app_data_lazy(StringPrintf("%s/%s", parent.c_str(), name), seinfo, uid); } static int prepare_app_dir(const std::string& path, mode_t target_mode, uid_t uid) { if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, uid) != 0) { PLOG(ERROR) << "Failed to prepare " << path; return -1; } if (selinux_android_setfilecon(path.c_str(), pkgname, seinfo, uid) < 0) { PLOG(ERROR) << "Failed to setfilecon " << path; return -1; } return 0; } static int prepare_app_dir(const std::string& parent, const char* name, mode_t target_mode, uid_t uid, const char* pkgname, const char* seinfo) { return prepare_app_dir(StringPrintf("%s/%s", parent.c_str(), name), target_mode, uid, pkgname, seinfo); uid_t uid) { return prepare_app_dir(StringPrintf("%s/%s", parent.c_str(), name), target_mode, uid); } int create_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags, Loading @@ -124,9 +170,16 @@ int create_app_data(const char *uuid, const char *pkgname, userid_t userid, int mode_t target_mode = target_sdk_version >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751; if (flags & FLAG_STORAGE_CE) { auto path = create_data_user_ce_package_path(uuid, userid, pkgname); if (prepare_app_dir(path, target_mode, uid, pkgname, seinfo) || prepare_app_dir(path, "cache", 0771, uid, pkgname, seinfo) || prepare_app_dir(path, "code_cache", 0771, uid, pkgname, seinfo)) { if (prepare_app_dir(path, target_mode, uid) || prepare_app_dir(path, "cache", 0771, uid) || prepare_app_dir(path, "code_cache", 0771, uid)) { return -1; } // Consider restorecon over contents if label changed if (restorecon_app_data_lazy(path, seinfo, uid) || restorecon_app_data_lazy(path, "cache", seinfo, uid) || restorecon_app_data_lazy(path, "code_cache", seinfo, uid)) { return -1; } Loading @@ -139,11 +192,16 @@ int create_app_data(const char *uuid, const char *pkgname, userid_t userid, int } if (flags & FLAG_STORAGE_DE) { auto path = create_data_user_de_package_path(uuid, userid, pkgname); if (prepare_app_dir(path, target_mode, uid, pkgname, seinfo)) { if (prepare_app_dir(path, target_mode, uid)) { // TODO: include result once 25796509 is fixed return 0; } // Consider restorecon over contents if label changed if (restorecon_app_data_lazy(path, seinfo, uid)) { return -1; } if (property_get_bool("dalvik.vm.usejitprofiles")) { const std::string profile_path = create_data_user_profile_package_path(userid, pkgname); // read-write-execute only for the app user. Loading Loading @@ -2186,6 +2244,9 @@ int move_ab(const char* apk_path, const char* instruction_set, const char* oat_d bool art_success = true; if (!a_image_path.empty()) { art_success = move_ab_path(b_image_path, a_image_path); if (!art_success) { unlink(a_image_path.c_str()); } } success = art_success || kIgnoreAppImageFailure; Loading @@ -2199,5 +2260,35 @@ int move_ab(const char* apk_path, const char* instruction_set, const char* oat_d return success ? 0 : -1; } bool delete_odex(const char *apk_path, const char *instruction_set, const char *oat_dir) { // Delete the oat/odex file. char out_path[PKG_PATH_MAX]; if (!create_oat_out_path(apk_path, instruction_set, oat_dir, out_path)) { return false; } // In case of a permission failure report the issue. Otherwise just print a warning. auto unlink_and_check = [](const char* path) -> bool { int result = unlink(path); if (result != 0) { if (errno == EACCES || errno == EPERM) { PLOG(ERROR) << "Could not unlink " << path; return false; } PLOG(WARNING) << "Could not unlink " << path; } return true; }; // Delete the oat/odex file. bool return_value_oat = unlink_and_check(out_path); // Derive and delete the app image. bool return_value_art = unlink_and_check(create_image_filename(out_path).c_str()); // Report success. return return_value_oat && return_value_art; } } // namespace installd } // namespace android Loading
cmds/atrace/atrace.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -102,6 +102,7 @@ static const TracingCategory k_categories[] = { { "pm", "Package Manager", ATRACE_TAG_PACKAGE_MANAGER, { } }, { "ss", "System Server", ATRACE_TAG_SYSTEM_SERVER, { } }, { "database", "Database", ATRACE_TAG_DATABASE, { } }, { "network", "Network", ATRACE_TAG_NETWORK, { } }, { k_coreServiceCategory, "Core services", 0, { } }, { "sched", "CPU Scheduling", 0, { { REQ, "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" }, Loading
cmds/atrace/atrace.rc +1 −1 Original line number Diff line number Diff line ## Permissions to allow system-wide tracing to the kernel trace buffer. ## on boot on fs # Allow writing to the kernel trace log. chmod 0222 /sys/kernel/debug/tracing/trace_marker Loading
cmds/dumpstate/dumpstate.cpp +25 −13 Original line number Diff line number Diff line Loading @@ -149,7 +149,7 @@ void do_mountinfo(int pid, const char *name) { } void add_mountinfo() { if (!zip_writer) return; if (!is_zipping()) return; const char *title = "MOUNT INFO"; mount_points.clear(); DurationReporter duration_reporter(title, NULL); Loading Loading @@ -180,8 +180,8 @@ static void dump_dev_files(const char *title, const char *driverpath, const char } static void dump_systrace() { if (!zip_writer) { MYLOGD("Not dumping systrace because zip_writer is not set\n"); if (!is_zipping()) { MYLOGD("Not dumping systrace because dumpstate is not zipping\n"); return; } std::string systrace_path = bugreport_dir + "/systrace-" + suffix + ".txt"; Loading Loading @@ -237,7 +237,7 @@ static void dump_raft() { return; } if (!zip_writer) { if (!is_zipping()) { // Write compressed and encoded raft logs to stdout if not zip_writer. run_command("RAFT LOGS", 600, "logcompressor", "-r", RAFT_DIR, NULL); return; Loading Loading @@ -578,8 +578,8 @@ static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = { }; bool add_zip_entry_from_fd(const std::string& entry_name, int fd) { if (!zip_writer) { MYLOGD("Not adding zip entry %s from fd because zip_writer is not set\n", if (!is_zipping()) { MYLOGD("Not adding entry %s from fd because dumpstate is not zipping\n", entry_name.c_str()); return false; } Loading Loading @@ -648,8 +648,8 @@ static int _add_file_from_fd(const char *title, const char *path, int fd) { // TODO: move to util.cpp void add_dir(const char *dir, bool recursive) { if (!zip_writer) { MYLOGD("Not adding dir %s because zip_writer is not set\n", dir); if (!is_zipping()) { MYLOGD("Not adding dir %s because dumpstate is not zipping\n", dir); return; } MYLOGD("Adding dir %s (recursive: %d)\n", dir, recursive); Loading @@ -657,10 +657,14 @@ void add_dir(const char *dir, bool recursive) { dump_files(NULL, dir, recursive ? skip_none : is_dir, _add_file_from_fd); } bool is_zipping() { return zip_writer != nullptr; } /* adds a text entry entry to the existing zip file. */ static bool add_text_zip_entry(const std::string& entry_name, const std::string& content) { if (!zip_writer) { MYLOGD("Not adding text zip entry %s because zip_writer is not set\n", entry_name.c_str()); if (!is_zipping()) { MYLOGD("Not adding text entry %s because dumpstate is not zipping\n", entry_name.c_str()); return false; } MYLOGD("Adding zip text entry %s\n", entry_name.c_str()); Loading Loading @@ -690,10 +694,12 @@ static bool add_text_zip_entry(const std::string& entry_name, const std::string& static void dump_iptables() { run_command("IPTABLES", 10, "iptables", "-L", "-nvx", NULL); run_command("IP6TABLES", 10, "ip6tables", "-L", "-nvx", NULL); run_command("IPTABLE NAT", 10, "iptables", "-t", "nat", "-L", "-nvx", NULL); run_command("IPTABLES NAT", 10, "iptables", "-t", "nat", "-L", "-nvx", NULL); /* no ip6 nat */ run_command("IPTABLE RAW", 10, "iptables", "-t", "raw", "-L", "-nvx", NULL); run_command("IP6TABLE RAW", 10, "ip6tables", "-t", "raw", "-L", "-nvx", NULL); run_command("IPTABLES MANGLE", 10, "iptables", "-t", "mangle", "-L", "-nvx", NULL); run_command("IP6TABLES MANGLE", 10, "ip6tables", "-t", "mangle", "-L", "-nvx", NULL); run_command("IPTABLES RAW", 10, "iptables", "-t", "raw", "-L", "-nvx", NULL); run_command("IP6TABLES RAW", 10, "ip6tables", "-t", "raw", "-L", "-nvx", NULL); } static void dumpstate(const std::string& screenshot_path, const std::string& version) { Loading Loading @@ -1374,6 +1380,12 @@ int main(int argc, char *argv[]) { add_mountinfo(); dump_iptables(); // Capture any IPSec policies in play. No keys are exposed here. run_command("IP XFRM POLICY", 10, "ip", "xfrm", "policy", nullptr); // Run ss as root so we can see socket marks. run_command("DETAILED SOCKET STATE", 10, "ss", "-eionptu", NULL); if (!drop_root_user()) { return -1; } Loading
cmds/dumpstate/dumpstate.h +3 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,9 @@ extern std::string bugreport_dir; /* root dir for all files copied as-is into the bugreport. */ extern const std::string ZIP_ROOT_DIR; /* Checkes whether dumpstate is generating a zipped bugreport. */ bool is_zipping(); /* adds a new entry to the existing zip file. */ bool add_zip_entry(const std::string& entry_name, const std::string& entry_path); Loading
cmds/installd/commands.cpp +104 −13 Original line number Diff line number Diff line Loading @@ -99,23 +99,69 @@ static std::string create_primary_profile(const std::string& profile_dir) { return StringPrintf("%s/%s", profile_dir.c_str(), PRIMARY_PROFILE_NAME); } static int prepare_app_dir(const std::string& path, mode_t target_mode, uid_t uid, const char* pkgname, const char* seinfo) { /** * Perform restorecon of the given path, but only perform recursive restorecon * if the label of that top-level file actually changed. This can save us * significant time by avoiding no-op traversals of large filesystem trees. */ static int restorecon_app_data_lazy(const std::string& path, const char* seinfo, uid_t uid) { int res = 0; char* before = nullptr; char* after = nullptr; // Note that SELINUX_ANDROID_RESTORECON_DATADATA flag is set by // libselinux. Not needed here. if (lgetfilecon(path.c_str(), &before) < 0) { PLOG(ERROR) << "Failed before getfilecon for " << path; goto fail; } if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, 0) < 0) { PLOG(ERROR) << "Failed top-level restorecon for " << path; goto fail; } if (lgetfilecon(path.c_str(), &after) < 0) { PLOG(ERROR) << "Failed after getfilecon for " << path; goto fail; } // If the initial top-level restorecon above changed the label, then go // back and restorecon everything recursively if (strcmp(before, after)) { LOG(DEBUG) << "Detected label change from " << before << " to " << after << " at " << path << "; running recursive restorecon"; if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, SELINUX_ANDROID_RESTORECON_RECURSE) < 0) { PLOG(ERROR) << "Failed recursive restorecon for " << path; goto fail; } } goto done; fail: res = -1; done: free(before); free(after); return res; } static int restorecon_app_data_lazy(const std::string& parent, const char* name, const char* seinfo, uid_t uid) { return restorecon_app_data_lazy(StringPrintf("%s/%s", parent.c_str(), name), seinfo, uid); } static int prepare_app_dir(const std::string& path, mode_t target_mode, uid_t uid) { if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, uid) != 0) { PLOG(ERROR) << "Failed to prepare " << path; return -1; } if (selinux_android_setfilecon(path.c_str(), pkgname, seinfo, uid) < 0) { PLOG(ERROR) << "Failed to setfilecon " << path; return -1; } return 0; } static int prepare_app_dir(const std::string& parent, const char* name, mode_t target_mode, uid_t uid, const char* pkgname, const char* seinfo) { return prepare_app_dir(StringPrintf("%s/%s", parent.c_str(), name), target_mode, uid, pkgname, seinfo); uid_t uid) { return prepare_app_dir(StringPrintf("%s/%s", parent.c_str(), name), target_mode, uid); } int create_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags, Loading @@ -124,9 +170,16 @@ int create_app_data(const char *uuid, const char *pkgname, userid_t userid, int mode_t target_mode = target_sdk_version >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751; if (flags & FLAG_STORAGE_CE) { auto path = create_data_user_ce_package_path(uuid, userid, pkgname); if (prepare_app_dir(path, target_mode, uid, pkgname, seinfo) || prepare_app_dir(path, "cache", 0771, uid, pkgname, seinfo) || prepare_app_dir(path, "code_cache", 0771, uid, pkgname, seinfo)) { if (prepare_app_dir(path, target_mode, uid) || prepare_app_dir(path, "cache", 0771, uid) || prepare_app_dir(path, "code_cache", 0771, uid)) { return -1; } // Consider restorecon over contents if label changed if (restorecon_app_data_lazy(path, seinfo, uid) || restorecon_app_data_lazy(path, "cache", seinfo, uid) || restorecon_app_data_lazy(path, "code_cache", seinfo, uid)) { return -1; } Loading @@ -139,11 +192,16 @@ int create_app_data(const char *uuid, const char *pkgname, userid_t userid, int } if (flags & FLAG_STORAGE_DE) { auto path = create_data_user_de_package_path(uuid, userid, pkgname); if (prepare_app_dir(path, target_mode, uid, pkgname, seinfo)) { if (prepare_app_dir(path, target_mode, uid)) { // TODO: include result once 25796509 is fixed return 0; } // Consider restorecon over contents if label changed if (restorecon_app_data_lazy(path, seinfo, uid)) { return -1; } if (property_get_bool("dalvik.vm.usejitprofiles")) { const std::string profile_path = create_data_user_profile_package_path(userid, pkgname); // read-write-execute only for the app user. Loading Loading @@ -2186,6 +2244,9 @@ int move_ab(const char* apk_path, const char* instruction_set, const char* oat_d bool art_success = true; if (!a_image_path.empty()) { art_success = move_ab_path(b_image_path, a_image_path); if (!art_success) { unlink(a_image_path.c_str()); } } success = art_success || kIgnoreAppImageFailure; Loading @@ -2199,5 +2260,35 @@ int move_ab(const char* apk_path, const char* instruction_set, const char* oat_d return success ? 0 : -1; } bool delete_odex(const char *apk_path, const char *instruction_set, const char *oat_dir) { // Delete the oat/odex file. char out_path[PKG_PATH_MAX]; if (!create_oat_out_path(apk_path, instruction_set, oat_dir, out_path)) { return false; } // In case of a permission failure report the issue. Otherwise just print a warning. auto unlink_and_check = [](const char* path) -> bool { int result = unlink(path); if (result != 0) { if (errno == EACCES || errno == EPERM) { PLOG(ERROR) << "Could not unlink " << path; return false; } PLOG(WARNING) << "Could not unlink " << path; } return true; }; // Delete the oat/odex file. bool return_value_oat = unlink_and_check(out_path); // Derive and delete the app image. bool return_value_art = unlink_and_check(create_image_filename(out_path).c_str()); // Report success. return return_value_oat && return_value_art; } } // namespace installd } // namespace android