system/core
リビジョン | acd1876a1e313632d7554585c314552c2d809848 (tree) |
---|---|
日時 | 2016-09-15 18:07:50 |
作者 | Linux Build Service Account <lnxbuild@loca...> |
コミッター | Linux Build Service Account |
Promotion of android-framework.lnx.2.0-00009.
CRs Change ID Subject
1059099 I4dfe1ea30e2c211d2389321bd66e3684dd757591 debuggerd: verify that traced threads belong to the righ
1065271 I7878b89a32f0950aa43d3157943982d403632502 init: Add support for slow devices
1064124 I842ce6f62a85b19a79bef4c082e132d1c9649485 init: Fix for handling -p argument in the write command
1050321 I43d0eb850cfff24bbd61b0b1e0f43f591b71e3fe init : start time_daemon when trigger_restart_min_framew
Change-Id: I176768c33df59eb04f34b01cad67fffa0169bdc0
CRs-Fixed: 1059099, 1050321, 1065271, 1064124
@@ -183,6 +183,16 @@ out: | ||
183 | 183 | return allowed; |
184 | 184 | } |
185 | 185 | |
186 | +static bool pid_contains_tid(pid_t pid, pid_t tid) { | |
187 | + char task_path[PATH_MAX]; | |
188 | + if (snprintf(task_path, PATH_MAX, "/proc/%d/task/%d", pid, tid) >= PATH_MAX) { | |
189 | + ALOGE("debuggerd: task path overflow (pid = %d, tid = %d)\n", pid, tid); | |
190 | + exit(1); | |
191 | + } | |
192 | + | |
193 | + return access(task_path, F_OK) == 0; | |
194 | +} | |
195 | + | |
186 | 196 | static int read_request(int fd, debugger_request_t* out_request) { |
187 | 197 | ucred cr; |
188 | 198 | socklen_t len = sizeof(cr); |
@@ -227,16 +237,13 @@ static int read_request(int fd, debugger_request_t* out_request) { | ||
227 | 237 | |
228 | 238 | if (msg.action == DEBUGGER_ACTION_CRASH) { |
229 | 239 | // Ensure that the tid reported by the crashing process is valid. |
230 | - char buf[64]; | |
231 | - struct stat s; | |
232 | - snprintf(buf, sizeof buf, "/proc/%d/task/%d", out_request->pid, out_request->tid); | |
233 | - if (stat(buf, &s)) { | |
234 | - ALOGE("tid %d does not exist in pid %d. ignoring debug request\n", | |
235 | - out_request->tid, out_request->pid); | |
240 | + // This check needs to happen again after ptracing the requested thread to prevent a race. | |
241 | + if (!pid_contains_tid(out_request->pid, out_request->tid)) { | |
242 | + ALOGE("tid %d does not exist in pid %d. ignoring debug request\n", out_request->tid, | |
243 | + out_request->pid); | |
236 | 244 | return -1; |
237 | 245 | } |
238 | - } else if (cr.uid == 0 | |
239 | - || (cr.uid == AID_SYSTEM && msg.action == DEBUGGER_ACTION_DUMP_BACKTRACE)) { | |
246 | + } else if (cr.uid == 0 || (cr.uid == AID_SYSTEM && msg.action == DEBUGGER_ACTION_DUMP_BACKTRACE)) { | |
240 | 247 | // Only root or system can ask us to attach to any process and dump it explicitly. |
241 | 248 | // However, system is only allowed to collect backtraces but cannot dump tombstones. |
242 | 249 | status = get_process_info(out_request->tid, &out_request->pid, |
@@ -413,10 +420,31 @@ static void redirect_to_32(int fd, debugger_request_t* request) { | ||
413 | 420 | } |
414 | 421 | #endif |
415 | 422 | |
423 | +// Attach to a thread, and verify that it's still a member of the given process | |
424 | +static bool ptrace_attach_thread(pid_t pid, pid_t tid) { | |
425 | + if (ptrace(PTRACE_ATTACH, tid, 0, 0) != 0) { | |
426 | + return false; | |
427 | + } | |
428 | + | |
429 | + // Make sure that the task we attached to is actually part of the pid we're dumping. | |
430 | + if (!pid_contains_tid(pid, tid)) { | |
431 | + if (ptrace(PTRACE_DETACH, tid, 0, 0) != 0) { | |
432 | + ALOGE("debuggerd: failed to detach from thread '%d'", tid); | |
433 | + exit(1); | |
434 | + } | |
435 | + return false; | |
436 | + } | |
437 | + | |
438 | + return true; | |
439 | +} | |
440 | + | |
416 | 441 | static void ptrace_siblings(pid_t pid, pid_t main_tid, std::set<pid_t>& tids) { |
417 | - char task_path[64]; | |
442 | + char task_path[PATH_MAX]; | |
418 | 443 | |
419 | - snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid); | |
444 | + if (snprintf(task_path, PATH_MAX, "/proc/%d/task", pid) >= PATH_MAX) { | |
445 | + ALOGE("debuggerd: task path overflow (pid = %d)\n", pid); | |
446 | + abort(); | |
447 | + } | |
420 | 448 | |
421 | 449 | std::unique_ptr<DIR, int (*)(DIR*)> d(opendir(task_path), closedir); |
422 | 450 |
@@ -443,7 +471,7 @@ static void ptrace_siblings(pid_t pid, pid_t main_tid, std::set<pid_t>& tids) { | ||
443 | 471 | continue; |
444 | 472 | } |
445 | 473 | |
446 | - if (ptrace(PTRACE_ATTACH, tid, 0, 0) < 0) { | |
474 | + if (!ptrace_attach_thread(pid, tid)) { | |
447 | 475 | ALOGE("debuggerd: ptrace attach to %d failed: %s", tid, strerror(errno)); |
448 | 476 | continue; |
449 | 477 | } |
@@ -568,11 +596,33 @@ static void worker_process(int fd, debugger_request_t& request) { | ||
568 | 596 | // debugger_signal_handler(). |
569 | 597 | |
570 | 598 | // Attach to the target process. |
571 | - if (ptrace(PTRACE_ATTACH, request.tid, 0, 0) != 0) { | |
599 | + if (!ptrace_attach_thread(request.pid, request.tid)) { | |
572 | 600 | ALOGE("debuggerd: ptrace attach failed: %s", strerror(errno)); |
573 | 601 | exit(1); |
574 | 602 | } |
575 | 603 | |
604 | + // DEBUGGER_ACTION_CRASH requests can come from arbitrary processes and the tid field in the | |
605 | + // request is sent from the other side. If an attacker can cause a process to be spawned with the | |
606 | + // pid of their process, they could trick debuggerd into dumping that process by exiting after | |
607 | + // sending the request. Validate the trusted request.uid/gid to defend against this. | |
608 | + if (request.action == DEBUGGER_ACTION_CRASH) { | |
609 | + pid_t pid; | |
610 | + uid_t uid; | |
611 | + gid_t gid; | |
612 | + if (get_process_info(request.tid, &pid, &uid, &gid) != 0) { | |
613 | + ALOGE("debuggerd: failed to get process info for tid '%d'", request.tid); | |
614 | + exit(1); | |
615 | + } | |
616 | + | |
617 | + if (pid != request.pid || uid != request.uid || gid != request.gid) { | |
618 | + ALOGE( | |
619 | + "debuggerd: attached task %d does not match request: " | |
620 | + "expected pid=%d,uid=%d,gid=%d, actual pid=%d,uid=%d,gid=%d", | |
621 | + request.tid, request.pid, request.uid, request.gid, pid, uid, gid); | |
622 | + exit(1); | |
623 | + } | |
624 | + } | |
625 | + | |
576 | 626 | // Don't attach to the sibling threads if we want to attach gdb. |
577 | 627 | // Supposedly, it makes the process less reliable. |
578 | 628 | bool attach_gdb = should_attach_gdb(request); |
@@ -12,6 +12,14 @@ endif | ||
12 | 12 | |
13 | 13 | init_options += -DLOG_UEVENTS=0 |
14 | 14 | |
15 | +ifneq ($(TARGET_INIT_COLDBOOT_TIMEOUT),) | |
16 | +init_options += -DCOLDBOOT_TIMEOUT_OVERRIDE=$(TARGET_INIT_COLDBOOT_TIMEOUT) | |
17 | +endif | |
18 | + | |
19 | +ifneq ($(TARGET_INIT_CONSOLE_TIMEOUT),) | |
20 | +init_options += -DCONSOLE_TIMEOUT_SEC=$(TARGET_INIT_CONSOLE_TIMEOUT) | |
21 | +endif | |
22 | + | |
15 | 23 | init_cflags += \ |
16 | 24 | $(init_options) \ |
17 | 25 | -Wall -Wextra \ |
@@ -822,8 +822,8 @@ static int do_write(const std::vector<std::string>& args) { | ||
822 | 822 | break; |
823 | 823 | } else { |
824 | 824 | //Value at current index is -p. The next index would |
825 | - //be the prefix.Skip beyond that. | |
826 | - i+=2; | |
825 | + //be the prefix.Skip it. | |
826 | + i++; | |
827 | 827 | } |
828 | 828 | } |
829 | 829 | if (!path || !value) { |
@@ -160,15 +160,19 @@ void handle_control_message(const std::string& msg, const std::string& name) { | ||
160 | 160 | |
161 | 161 | static int wait_for_coldboot_done_action(const std::vector<std::string>& args) { |
162 | 162 | Timer t; |
163 | - | |
163 | + int timeout = 0; | |
164 | +#ifdef COLDBOOT_TIMEOUT_OVERRIDE | |
165 | + timeout = COLDBOOT_TIMEOUT_OVERRIDE; | |
166 | +#else | |
167 | + timeout = 5; | |
168 | +#endif | |
164 | 169 | NOTICE("Waiting for %s...\n", COLDBOOT_DONE); |
165 | 170 | // Any longer than 1s is an unreasonable length of time to delay booting. |
166 | 171 | // If you're hitting this timeout, check that you didn't make your |
167 | 172 | // sepolicy regular expressions too expensive (http://b/19899875). |
168 | - if (wait_for_file(COLDBOOT_DONE, 5)) { | |
173 | + if (wait_for_file(COLDBOOT_DONE, timeout)) { | |
169 | 174 | ERROR("Timed out waiting for %s\n", COLDBOOT_DONE); |
170 | 175 | } |
171 | - | |
172 | 176 | NOTICE("Waiting for %s took %.2fs.\n", COLDBOOT_DONE, t.duration()); |
173 | 177 | return 0; |
174 | 178 | } |
@@ -258,15 +262,31 @@ static int keychord_init_action(const std::vector<std::string>& args) | ||
258 | 262 | |
259 | 263 | static int console_init_action(const std::vector<std::string>& args) |
260 | 264 | { |
265 | + int fd = -1; | |
261 | 266 | std::string console = property_get("ro.boot.console"); |
262 | 267 | if (!console.empty()) { |
263 | 268 | console_name = "/dev/" + console; |
264 | 269 | } |
265 | - | |
266 | - int fd = open(console_name.c_str(), O_RDWR | O_CLOEXEC); | |
270 | + fd = open(console_name.c_str(), O_RDWR | O_CLOEXEC); | |
271 | +#ifdef CONSOLE_TIMEOUT_SEC | |
272 | + int num_console_retries = 0; | |
273 | + while ((fd < 0) && num_console_retries++ < CONSOLE_TIMEOUT_SEC) { | |
274 | + ERROR("Failed to open console device %s(%s)..Retrying\n", | |
275 | + console_name.c_str(), strerror(errno)); | |
276 | + sleep(1); | |
277 | + fd = open(console_name.c_str(), O_RDWR | O_CLOEXEC); | |
278 | + } | |
267 | 279 | if (fd >= 0) |
280 | + INFO("Console device located"); | |
281 | +#endif | |
282 | + if (fd >= 0) { | |
268 | 283 | have_console = 1; |
269 | - close(fd); | |
284 | + close(fd); | |
285 | + } else { | |
286 | + ERROR("console init failed. Open on Console device %s failed(%s)\n", | |
287 | + console.c_str(), strerror(errno)); | |
288 | + return 0; | |
289 | + } | |
270 | 290 | |
271 | 291 | fd = open("/dev/tty0", O_WRONLY | O_CLOEXEC); |
272 | 292 | if (fd >= 0) { |
@@ -580,6 +580,7 @@ on property:vold.decrypt=trigger_restart_min_framework | ||
580 | 580 | # A/B update verifier that marks a successful boot. |
581 | 581 | exec - root -- /system/bin/update_verifier trigger_restart_min_framework |
582 | 582 | class_start main |
583 | + start time_daemon | |
583 | 584 | |
584 | 585 | on property:vold.decrypt=trigger_restart_framework |
585 | 586 | # A/B update verifier that marks a successful boot. |