Skip to content

Commit 8d6ae2d

Browse files
committed
Fix potential use-after-free bug in reboot
Instead of operating on raw pointers, init now uses name of the services as it's primary identifier. Only place that still uses vector<Service*> is StopServices. In addition, ServiceList::services() function is removed, which should help avoiding similar bugs in the future. Bug: 170315126 Bug: 174335499 Test: adb reboot Test: atest CtsInitTestCases Change-Id: I73ecd7a8c58c2ec3732934c595b7f7db814b7034 Ignore-AOSP-First: fixing security vulnerability
1 parent c57f61a commit 8d6ae2d

File tree

4 files changed

+36
-31
lines changed

4 files changed

+36
-31
lines changed

init/lmkd_service.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ static bool UnregisterProcess(pid_t pid) {
7979
}
8080

8181
static void RegisterServices(pid_t exclude_pid) {
82-
for (const auto& service : ServiceList::GetInstance().services()) {
82+
for (const auto& service : ServiceList::GetInstance()) {
8383
auto svc = service.get();
8484
if (svc->oom_score_adjust() != DEFAULT_OOM_SCORE_ADJUST) {
8585
// skip if process is excluded or not yet forked (pid==0)

init/reboot.cpp

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,11 @@ static bool shutting_down = false;
8585

8686
static const std::set<std::string> kDebuggingServices{"tombstoned", "logd", "adbd", "console"};
8787

88-
static std::vector<Service*> GetDebuggingServices(bool only_post_data) {
89-
std::vector<Service*> ret;
90-
ret.reserve(kDebuggingServices.size());
88+
static std::set<std::string> GetPostDataDebuggingServices() {
89+
std::set<std::string> ret;
9190
for (const auto& s : ServiceList::GetInstance()) {
92-
if (kDebuggingServices.count(s->name()) && (!only_post_data || s->is_post_data())) {
93-
ret.push_back(s.get());
91+
if (kDebuggingServices.count(s->name()) && s->is_post_data()) {
92+
ret.insert(s->name());
9493
}
9594
}
9695
return ret;
@@ -503,13 +502,18 @@ static Result<void> KillZramBackingDevice() {
503502

504503
// Stops given services, waits for them to be stopped for |timeout| ms.
505504
// If terminate is true, then SIGTERM is sent to services, otherwise SIGKILL is sent.
506-
static void StopServices(const std::vector<Service*>& services, std::chrono::milliseconds timeout,
505+
// Note that services are stopped in order given by |ServiceList::services_in_shutdown_order|
506+
// function.
507+
static void StopServices(const std::set<std::string>& services, std::chrono::milliseconds timeout,
507508
bool terminate) {
508509
LOG(INFO) << "Stopping " << services.size() << " services by sending "
509510
<< (terminate ? "SIGTERM" : "SIGKILL");
510511
std::vector<pid_t> pids;
511512
pids.reserve(services.size());
512-
for (const auto& s : services) {
513+
for (const auto& s : ServiceList::GetInstance().services_in_shutdown_order()) {
514+
if (services.count(s->name()) == 0) {
515+
continue;
516+
}
513517
if (s->pid() > 0) {
514518
pids.push_back(s->pid());
515519
}
@@ -529,12 +533,12 @@ static void StopServices(const std::vector<Service*>& services, std::chrono::mil
529533

530534
// Like StopServices, but also logs all the services that failed to stop after the provided timeout.
531535
// Returns number of violators.
532-
static int StopServicesAndLogViolations(const std::vector<Service*>& services,
536+
static int StopServicesAndLogViolations(const std::set<std::string>& services,
533537
std::chrono::milliseconds timeout, bool terminate) {
534538
StopServices(services, timeout, terminate);
535539
int still_running = 0;
536-
for (const auto& s : services) {
537-
if (s->IsRunning()) {
540+
for (const auto& s : ServiceList::GetInstance()) {
541+
if (s->IsRunning() && services.count(s->name())) {
538542
LOG(ERROR) << "[service-misbehaving] : service '" << s->name() << "' is still running "
539543
<< timeout.count() << "ms after receiving "
540544
<< (terminate ? "SIGTERM" : "SIGKILL");
@@ -620,8 +624,7 @@ static void DoReboot(unsigned int cmd, const std::string& reason, const std::str
620624

621625
// watchdogd is a vendor specific component but should be alive to complete shutdown safely.
622626
const std::set<std::string> to_starts{"watchdogd"};
623-
std::vector<Service*> stop_first;
624-
stop_first.reserve(ServiceList::GetInstance().services().size());
627+
std::set<std::string> stop_first;
625628
for (const auto& s : ServiceList::GetInstance()) {
626629
if (kDebuggingServices.count(s->name())) {
627630
// keep debugging tools until non critical ones are all gone.
@@ -639,7 +642,7 @@ static void DoReboot(unsigned int cmd, const std::string& reason, const std::str
639642
<< "': " << result.error();
640643
}
641644
} else {
642-
stop_first.push_back(s.get());
645+
stop_first.insert(s->name());
643646
}
644647
}
645648

@@ -702,7 +705,7 @@ static void DoReboot(unsigned int cmd, const std::string& reason, const std::str
702705
LOG(INFO) << "vold not running, skipping vold shutdown";
703706
}
704707
// logcat stopped here
705-
StopServices(GetDebuggingServices(false /* only_post_data */), 0ms, false /* SIGKILL */);
708+
StopServices(kDebuggingServices, 0ms, false /* SIGKILL */);
706709
// 4. sync, try umount, and optionally run fsck for user shutdown
707710
{
708711
Timer sync_timer;
@@ -784,17 +787,17 @@ static Result<void> DoUserspaceReboot() {
784787
sub_reason = "resetprop";
785788
return Error() << "Failed to reset sys.powerctl property";
786789
}
787-
std::vector<Service*> stop_first;
790+
std::set<std::string> stop_first;
788791
// Remember the services that were enabled. We will need to manually enable them again otherwise
789792
// triggers like class_start won't restart them.
790-
std::vector<Service*> were_enabled;
791-
stop_first.reserve(ServiceList::GetInstance().services().size());
793+
std::set<std::string> were_enabled;
792794
for (const auto& s : ServiceList::GetInstance().services_in_shutdown_order()) {
793795
if (s->is_post_data() && !kDebuggingServices.count(s->name())) {
794-
stop_first.push_back(s);
796+
stop_first.insert(s->name());
795797
}
798+
// TODO(ioffe): we should also filter out temporary services here.
796799
if (s->is_post_data() && s->IsEnabled()) {
797-
were_enabled.push_back(s);
800+
were_enabled.insert(s->name());
798801
}
799802
}
800803
{
@@ -814,8 +817,8 @@ static Result<void> DoUserspaceReboot() {
814817
r > 0) {
815818
auto fd = unique_fd(TEMP_FAILURE_RETRY(open(services_file_name.c_str(), flags, 0666)));
816819
android::base::WriteStringToFd("Post-data services still running: \n", fd);
817-
for (const auto& s : stop_first) {
818-
if (s->IsRunning()) {
820+
for (const auto& s : ServiceList::GetInstance()) {
821+
if (s->IsRunning() && stop_first.count(s->name())) {
819822
android::base::WriteStringToFd(s->name() + "\n", fd);
820823
}
821824
}
@@ -830,13 +833,14 @@ static Result<void> DoUserspaceReboot() {
830833
sub_reason = "vold_reset";
831834
return result;
832835
}
833-
if (int r = StopServicesAndLogViolations(GetDebuggingServices(true /* only_post_data */),
834-
sigkill_timeout, false /* SIGKILL */);
836+
const auto& debugging_services = GetPostDataDebuggingServices();
837+
if (int r = StopServicesAndLogViolations(debugging_services, sigkill_timeout,
838+
false /* SIGKILL */);
835839
r > 0) {
836840
auto fd = unique_fd(TEMP_FAILURE_RETRY(open(services_file_name.c_str(), flags, 0666)));
837841
android::base::WriteStringToFd("Debugging services still running: \n", fd);
838-
for (const auto& s : GetDebuggingServices(true)) {
839-
if (s->IsRunning()) {
842+
for (const auto& s : ServiceList::GetInstance()) {
843+
if (s->IsRunning() && debugging_services.count(s->name())) {
840844
android::base::WriteStringToFd(s->name() + "\n", fd);
841845
}
842846
}
@@ -866,9 +870,11 @@ static Result<void> DoUserspaceReboot() {
866870
return false;
867871
});
868872
// Re-enable services
869-
for (const auto& s : were_enabled) {
870-
LOG(INFO) << "Re-enabling service '" << s->name() << "'";
871-
s->Enable();
873+
for (const auto& s : ServiceList::GetInstance()) {
874+
if (were_enabled.count(s->name())) {
875+
LOG(INFO) << "Re-enabling service '" << s->name() << "'";
876+
s->Enable();
877+
}
872878
}
873879
ServiceList::GetInstance().ResetState();
874880
LeaveShutdown();

init/service_list.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ class ServiceList {
6666

6767
auto begin() const { return services_.begin(); }
6868
auto end() const { return services_.end(); }
69-
const std::vector<std::unique_ptr<Service>>& services() const { return services_; }
7069
const std::vector<Service*> services_in_shutdown_order() const;
7170

7271
void MarkPostData();

init/test_utils/service_utils.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ android::base::Result<ServiceInterfacesMap> GetOnDeviceServiceInterfacesMap() {
4444
}
4545

4646
ServiceInterfacesMap result;
47-
for (const auto& service : service_list.services()) {
47+
for (const auto& service : service_list) {
4848
// Create an entry for all services, including services that may not
4949
// have any declared interfaces.
5050
result[service->name()] = service->interfaces();

0 commit comments

Comments
 (0)