Loading debuggerd/libdebuggerd/include/libdebuggerd/types.h +3 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,9 @@ struct ThreadInfo { std::unique_ptr<unwindstack::Regs> registers; pid_t uid; pid_t tid; std::string thread_name; Loading debuggerd/libdebuggerd/test/tombstone_test.cpp +10 −0 Original line number Diff line number Diff line Loading @@ -343,6 +343,16 @@ TEST_F(TombstoneTest, dump_header_info) { ASSERT_STREQ(expected.c_str(), amfd_data_.c_str()); } TEST_F(TombstoneTest, dump_thread_info_uid) { dump_thread_info(&log_, ThreadInfo{.uid = 1, .pid = 2, .tid = 3, .thread_name = "some_thread", .process_name = "some_process"}); std::string expected = "pid: 2, tid: 3, name: some_thread >>> some_process <<<\nuid: 1\n"; ASSERT_STREQ(expected.c_str(), amfd_data_.c_str()); } TEST_F(TombstoneTest, dump_timestamp) { setenv("TZ", "UTC", 1); tzset(); Loading debuggerd/libdebuggerd/tombstone.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -151,6 +151,7 @@ static void dump_thread_info(log_t* log, const ThreadInfo& thread_info) { _LOG(log, logtype::HEADER, "pid: %d, tid: %d, name: %s >>> %s <<<\n", thread_info.pid, thread_info.tid, thread_info.thread_name.c_str(), thread_info.process_name.c_str()); _LOG(log, logtype::HEADER, "uid: %d\n", thread_info.uid); } static void dump_stack_segment(log_t* log, unwindstack::Maps* maps, unwindstack::Memory* memory, Loading Loading @@ -615,6 +616,7 @@ static void dump_logs(log_t* log, pid_t pid, unsigned int tail) { void engrave_tombstone_ucontext(int tombstone_fd, uint64_t abort_msg_address, siginfo_t* siginfo, ucontext_t* ucontext) { pid_t uid = getuid(); pid_t pid = getpid(); pid_t tid = gettid(); Loading @@ -636,6 +638,7 @@ void engrave_tombstone_ucontext(int tombstone_fd, uint64_t abort_msg_address, si std::map<pid_t, ThreadInfo> threads; threads[gettid()] = ThreadInfo{ .registers = std::move(regs), .uid = uid, .tid = tid, .thread_name = thread_name, .pid = pid, Loading init/README.md +13 −1 Original line number Diff line number Diff line Loading @@ -191,7 +191,7 @@ runs the service. `critical` > This is a device-critical service. If it exits more than four times in four minutes, the device will reboot into bootloader. four minutes or before boot completes, the device will reboot into bootloader. `disabled` > This service will not automatically start with its class. Loading Loading @@ -412,6 +412,10 @@ Commands not already running. See the start entry for more information on starting services. `class_start_post_data <serviceclass>` > Like `class_start`, but only considers services that were started after /data was mounted. Only used for FDE devices. `class_stop <serviceclass>` > Stop and disable all services of the specified class if they are currently running. Loading @@ -421,6 +425,10 @@ Commands currently running, without disabling them. They can be restarted later using `class_start`. `class_reset_post_data <serviceclass>` > Like `class_reset`, but only considers services that were started after /data was mounted. Only used for FDE devices. `class_restart <serviceclass>` > Restarts all services of the specified class. Loading Loading @@ -490,6 +498,10 @@ Commands `loglevel <level>` > Sets the kernel log level to level. Properties are expanded within _level_. `mark_post_data` > Used to mark the point right after /data is mounted. Used to implement the `class_reset_post_data` and `class_start_post_data` commands. `mkdir <path> [mode] [owner] [group]` > Create a directory at _path_, optionally with the given mode, owner, and group. If not provided, the directory is created with permissions 755 and Loading init/builtins.cpp +35 −4 Original line number Diff line number Diff line Loading @@ -104,23 +104,37 @@ static void ForEachServiceInClass(const std::string& classname, F function) { } } static Result<Success> do_class_start(const BuiltinArguments& args) { static Result<Success> class_start(const std::string& class_name, bool post_data_only) { // Do not start a class if it has a property persist.dont_start_class.CLASS set to 1. if (android::base::GetBoolProperty("persist.init.dont_start_class." + args[1], false)) if (android::base::GetBoolProperty("persist.init.dont_start_class." + class_name, false)) return Success(); // Starting a class does not start services which are explicitly disabled. // They must be started individually. for (const auto& service : ServiceList::GetInstance()) { if (service->classnames().count(args[1])) { if (service->classnames().count(class_name)) { if (post_data_only && !service->is_post_data()) { continue; } if (auto result = service->StartIfNotDisabled(); !result) { LOG(ERROR) << "Could not start service '" << service->name() << "' as part of class '" << args[1] << "': " << result.error(); << "' as part of class '" << class_name << "': " << result.error(); } } } return Success(); } static Result<Success> do_class_start(const BuiltinArguments& args) { return class_start(args[1], false /* post_data_only */); } static Result<Success> do_class_start_post_data(const BuiltinArguments& args) { if (args.context != kInitContext) { return Error() << "command 'class_start_post_data' only available in init context"; } return class_start(args[1], true /* post_data_only */); } static Result<Success> do_class_stop(const BuiltinArguments& args) { ForEachServiceInClass(args[1], &Service::Stop); return Success(); Loading @@ -131,6 +145,14 @@ static Result<Success> do_class_reset(const BuiltinArguments& args) { return Success(); } static Result<Success> do_class_reset_post_data(const BuiltinArguments& args) { if (args.context != kInitContext) { return Error() << "command 'class_reset_post_data' only available in init context"; } ForEachServiceInClass(args[1], &Service::ResetIfPostData); return Success(); } static Result<Success> do_class_restart(const BuiltinArguments& args) { // Do not restart a class if it has a property persist.dont_start_class.CLASS set to 1. if (android::base::GetBoolProperty("persist.init.dont_start_class." + args[1], false)) Loading Loading @@ -1119,6 +1141,12 @@ static Result<Success> do_init_user0(const BuiltinArguments& args) { {{"exec", "/system/bin/vdc", "--wait", "cryptfs", "init_user0"}, args.context}); } static Result<Success> do_mark_post_data(const BuiltinArguments& args) { ServiceList::GetInstance().MarkPostData(); return Success(); } static Result<Success> do_parse_apex_configs(const BuiltinArguments& args) { glob_t glob_result; // @ is added to filter out the later paths, which are bind mounts of the places Loading Loading @@ -1170,8 +1198,10 @@ const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const { {"chmod", {2, 2, {true, do_chmod}}}, {"chown", {2, 3, {true, do_chown}}}, {"class_reset", {1, 1, {false, do_class_reset}}}, {"class_reset_post_data", {1, 1, {false, do_class_reset_post_data}}}, {"class_restart", {1, 1, {false, do_class_restart}}}, {"class_start", {1, 1, {false, do_class_start}}}, {"class_start_post_data", {1, 1, {false, do_class_start_post_data}}}, {"class_stop", {1, 1, {false, do_class_stop}}}, {"copy", {2, 2, {true, do_copy}}}, {"domainname", {1, 1, {true, do_domainname}}}, Loading @@ -1191,6 +1221,7 @@ const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const { {"load_persist_props", {0, 0, {false, do_load_persist_props}}}, {"load_system_props", {0, 0, {false, do_load_system_props}}}, {"loglevel", {1, 1, {false, do_loglevel}}}, {"mark_post_data", {0, 0, {false, do_mark_post_data}}}, {"mkdir", {1, 4, {true, do_mkdir}}}, // TODO: Do mount operations in vendor_init. // mount_all is currently too complex to run in vendor_init as it queues action triggers, Loading Loading
debuggerd/libdebuggerd/include/libdebuggerd/types.h +3 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,9 @@ struct ThreadInfo { std::unique_ptr<unwindstack::Regs> registers; pid_t uid; pid_t tid; std::string thread_name; Loading
debuggerd/libdebuggerd/test/tombstone_test.cpp +10 −0 Original line number Diff line number Diff line Loading @@ -343,6 +343,16 @@ TEST_F(TombstoneTest, dump_header_info) { ASSERT_STREQ(expected.c_str(), amfd_data_.c_str()); } TEST_F(TombstoneTest, dump_thread_info_uid) { dump_thread_info(&log_, ThreadInfo{.uid = 1, .pid = 2, .tid = 3, .thread_name = "some_thread", .process_name = "some_process"}); std::string expected = "pid: 2, tid: 3, name: some_thread >>> some_process <<<\nuid: 1\n"; ASSERT_STREQ(expected.c_str(), amfd_data_.c_str()); } TEST_F(TombstoneTest, dump_timestamp) { setenv("TZ", "UTC", 1); tzset(); Loading
debuggerd/libdebuggerd/tombstone.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -151,6 +151,7 @@ static void dump_thread_info(log_t* log, const ThreadInfo& thread_info) { _LOG(log, logtype::HEADER, "pid: %d, tid: %d, name: %s >>> %s <<<\n", thread_info.pid, thread_info.tid, thread_info.thread_name.c_str(), thread_info.process_name.c_str()); _LOG(log, logtype::HEADER, "uid: %d\n", thread_info.uid); } static void dump_stack_segment(log_t* log, unwindstack::Maps* maps, unwindstack::Memory* memory, Loading Loading @@ -615,6 +616,7 @@ static void dump_logs(log_t* log, pid_t pid, unsigned int tail) { void engrave_tombstone_ucontext(int tombstone_fd, uint64_t abort_msg_address, siginfo_t* siginfo, ucontext_t* ucontext) { pid_t uid = getuid(); pid_t pid = getpid(); pid_t tid = gettid(); Loading @@ -636,6 +638,7 @@ void engrave_tombstone_ucontext(int tombstone_fd, uint64_t abort_msg_address, si std::map<pid_t, ThreadInfo> threads; threads[gettid()] = ThreadInfo{ .registers = std::move(regs), .uid = uid, .tid = tid, .thread_name = thread_name, .pid = pid, Loading
init/README.md +13 −1 Original line number Diff line number Diff line Loading @@ -191,7 +191,7 @@ runs the service. `critical` > This is a device-critical service. If it exits more than four times in four minutes, the device will reboot into bootloader. four minutes or before boot completes, the device will reboot into bootloader. `disabled` > This service will not automatically start with its class. Loading Loading @@ -412,6 +412,10 @@ Commands not already running. See the start entry for more information on starting services. `class_start_post_data <serviceclass>` > Like `class_start`, but only considers services that were started after /data was mounted. Only used for FDE devices. `class_stop <serviceclass>` > Stop and disable all services of the specified class if they are currently running. Loading @@ -421,6 +425,10 @@ Commands currently running, without disabling them. They can be restarted later using `class_start`. `class_reset_post_data <serviceclass>` > Like `class_reset`, but only considers services that were started after /data was mounted. Only used for FDE devices. `class_restart <serviceclass>` > Restarts all services of the specified class. Loading Loading @@ -490,6 +498,10 @@ Commands `loglevel <level>` > Sets the kernel log level to level. Properties are expanded within _level_. `mark_post_data` > Used to mark the point right after /data is mounted. Used to implement the `class_reset_post_data` and `class_start_post_data` commands. `mkdir <path> [mode] [owner] [group]` > Create a directory at _path_, optionally with the given mode, owner, and group. If not provided, the directory is created with permissions 755 and Loading
init/builtins.cpp +35 −4 Original line number Diff line number Diff line Loading @@ -104,23 +104,37 @@ static void ForEachServiceInClass(const std::string& classname, F function) { } } static Result<Success> do_class_start(const BuiltinArguments& args) { static Result<Success> class_start(const std::string& class_name, bool post_data_only) { // Do not start a class if it has a property persist.dont_start_class.CLASS set to 1. if (android::base::GetBoolProperty("persist.init.dont_start_class." + args[1], false)) if (android::base::GetBoolProperty("persist.init.dont_start_class." + class_name, false)) return Success(); // Starting a class does not start services which are explicitly disabled. // They must be started individually. for (const auto& service : ServiceList::GetInstance()) { if (service->classnames().count(args[1])) { if (service->classnames().count(class_name)) { if (post_data_only && !service->is_post_data()) { continue; } if (auto result = service->StartIfNotDisabled(); !result) { LOG(ERROR) << "Could not start service '" << service->name() << "' as part of class '" << args[1] << "': " << result.error(); << "' as part of class '" << class_name << "': " << result.error(); } } } return Success(); } static Result<Success> do_class_start(const BuiltinArguments& args) { return class_start(args[1], false /* post_data_only */); } static Result<Success> do_class_start_post_data(const BuiltinArguments& args) { if (args.context != kInitContext) { return Error() << "command 'class_start_post_data' only available in init context"; } return class_start(args[1], true /* post_data_only */); } static Result<Success> do_class_stop(const BuiltinArguments& args) { ForEachServiceInClass(args[1], &Service::Stop); return Success(); Loading @@ -131,6 +145,14 @@ static Result<Success> do_class_reset(const BuiltinArguments& args) { return Success(); } static Result<Success> do_class_reset_post_data(const BuiltinArguments& args) { if (args.context != kInitContext) { return Error() << "command 'class_reset_post_data' only available in init context"; } ForEachServiceInClass(args[1], &Service::ResetIfPostData); return Success(); } static Result<Success> do_class_restart(const BuiltinArguments& args) { // Do not restart a class if it has a property persist.dont_start_class.CLASS set to 1. if (android::base::GetBoolProperty("persist.init.dont_start_class." + args[1], false)) Loading Loading @@ -1119,6 +1141,12 @@ static Result<Success> do_init_user0(const BuiltinArguments& args) { {{"exec", "/system/bin/vdc", "--wait", "cryptfs", "init_user0"}, args.context}); } static Result<Success> do_mark_post_data(const BuiltinArguments& args) { ServiceList::GetInstance().MarkPostData(); return Success(); } static Result<Success> do_parse_apex_configs(const BuiltinArguments& args) { glob_t glob_result; // @ is added to filter out the later paths, which are bind mounts of the places Loading Loading @@ -1170,8 +1198,10 @@ const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const { {"chmod", {2, 2, {true, do_chmod}}}, {"chown", {2, 3, {true, do_chown}}}, {"class_reset", {1, 1, {false, do_class_reset}}}, {"class_reset_post_data", {1, 1, {false, do_class_reset_post_data}}}, {"class_restart", {1, 1, {false, do_class_restart}}}, {"class_start", {1, 1, {false, do_class_start}}}, {"class_start_post_data", {1, 1, {false, do_class_start_post_data}}}, {"class_stop", {1, 1, {false, do_class_stop}}}, {"copy", {2, 2, {true, do_copy}}}, {"domainname", {1, 1, {true, do_domainname}}}, Loading @@ -1191,6 +1221,7 @@ const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const { {"load_persist_props", {0, 0, {false, do_load_persist_props}}}, {"load_system_props", {0, 0, {false, do_load_system_props}}}, {"loglevel", {1, 1, {false, do_loglevel}}}, {"mark_post_data", {0, 0, {false, do_mark_post_data}}}, {"mkdir", {1, 4, {true, do_mkdir}}}, // TODO: Do mount operations in vendor_init. // mount_all is currently too complex to run in vendor_init as it queues action triggers, Loading