• R/O
  • HTTP
  • SSH
  • HTTPS

コミット

タグ
未設定

よく使われているワード(クリックで追加)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

system/corennnnn


コミットメタ情報

リビジョンb1471215a819a2a8c061620ce27fc9ddf7d73778 (tree)
日時2016-07-20 05:38:43
作者Josh Gao <jmgao@goog...>
コミッターandroid-build-merger

ログメッセージ

Merge \\\"DO NOT MERGE: debuggerd: verify that traced threads belong to the right process.\\\" into mnc-dev am: 73922b82ee am: 8a9e4369f6
am: ba143fd959

Change-Id: I7968a0d6d374c140c0b40a866d597dc6ca9ade25

変更サマリ

差分

--- a/debuggerd/backtrace.cpp
+++ b/debuggerd/backtrace.cpp
@@ -67,8 +67,8 @@ static void dump_process_footer(log_t* log, pid_t pid) {
6767 _LOG(log, logtype::BACKTRACE, "\n----- end %d -----\n", pid);
6868 }
6969
70-static void dump_thread(
71- log_t* log, pid_t tid, bool attached, bool* detach_failed, int* total_sleep_time_usec) {
70+static void dump_thread(log_t* log, pid_t pid, pid_t tid, bool attached,
71+ bool* detach_failed, int* total_sleep_time_usec) {
7272 char path[PATH_MAX];
7373 char threadnamebuf[1024];
7474 char* threadname = NULL;
@@ -88,7 +88,7 @@ static void dump_thread(
8888
8989 _LOG(log, logtype::BACKTRACE, "\n\"%s\" sysTid=%d\n", threadname ? threadname : "<unknown>", tid);
9090
91- if (!attached && ptrace(PTRACE_ATTACH, tid, 0, 0) < 0) {
91+ if (!attached && !ptrace_attach_thread(pid, tid)) {
9292 _LOG(log, logtype::BACKTRACE, "Could not attach to thread: %s\n", strerror(errno));
9393 return;
9494 }
@@ -117,7 +117,7 @@ void dump_backtrace(int fd, int amfd, pid_t pid, pid_t tid, bool* detach_failed,
117117 log.amfd = amfd;
118118
119119 dump_process_header(&log, pid);
120- dump_thread(&log, tid, true, detach_failed, total_sleep_time_usec);
120+ dump_thread(&log, pid, tid, true, detach_failed, total_sleep_time_usec);
121121
122122 char task_path[64];
123123 snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid);
@@ -135,7 +135,7 @@ void dump_backtrace(int fd, int amfd, pid_t pid, pid_t tid, bool* detach_failed,
135135 continue;
136136 }
137137
138- dump_thread(&log, new_tid, false, detach_failed, total_sleep_time_usec);
138+ dump_thread(&log, pid, new_tid, false, detach_failed, total_sleep_time_usec);
139139 }
140140 closedir(d);
141141 }
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -225,12 +225,10 @@ static int read_request(int fd, debugger_request_t* out_request) {
225225
226226 if (msg.action == DEBUGGER_ACTION_CRASH) {
227227 // Ensure that the tid reported by the crashing process is valid.
228- char buf[64];
229- struct stat s;
230- snprintf(buf, sizeof buf, "/proc/%d/task/%d", out_request->pid, out_request->tid);
231- if (stat(buf, &s)) {
228+ // This check needs to happen again after ptracing the requested thread to prevent a race.
229+ if (!pid_contains_tid(out_request->pid, out_request->tid)) {
232230 ALOGE("tid %d does not exist in pid %d. ignoring debug request\n",
233- out_request->tid, out_request->pid);
231+ out_request->tid, out_request->pid);
234232 return -1;
235233 }
236234 } else if (cr.uid == 0
@@ -380,9 +378,32 @@ static void handle_request(int fd) {
380378 // ensure that it can run as soon as we call PTRACE_CONT below.
381379 // See details in bionic/libc/linker/debugger.c, in function
382380 // debugger_signal_handler().
383- if (ptrace(PTRACE_ATTACH, request.tid, 0, 0)) {
381+ if (!ptrace_attach_thread(request.pid, request.tid)) {
384382 ALOGE("ptrace attach failed: %s\n", strerror(errno));
385383 } else {
384+ // DEBUGGER_ACTION_CRASH requests can come from arbitrary processes and the tid field in
385+ // the request is sent from the other side. If an attacker can cause a process to be
386+ // spawned with the pid of their process, they could trick debuggerd into dumping that
387+ // process by exiting after sending the request. Validate the trusted request.uid/gid
388+ // to defend against this.
389+ if (request.action == DEBUGGER_ACTION_CRASH) {
390+ pid_t pid;
391+ uid_t uid;
392+ gid_t gid;
393+ if (get_process_info(request.tid, &pid, &uid, &gid) != 0) {
394+ ALOGE("debuggerd: failed to get process info for tid '%d'", request.tid);
395+ exit(1);
396+ }
397+
398+ if (pid != request.pid || uid != request.uid || gid != request.gid) {
399+ ALOGE(
400+ "debuggerd: attached task %d does not match request: "
401+ "expected pid=%d,uid=%d,gid=%d, actual pid=%d,uid=%d,gid=%d",
402+ request.tid, request.pid, request.uid, request.gid, pid, uid, gid);
403+ exit(1);
404+ }
405+ }
406+
386407 bool detach_failed = false;
387408 bool tid_unresponsive = false;
388409 bool attach_gdb = should_attach_gdb(&request);
--- a/debuggerd/utility.cpp
+++ b/debuggerd/utility.cpp
@@ -20,6 +20,7 @@
2020
2121 #include <errno.h>
2222 #include <signal.h>
23+#include <stdlib.h>
2324 #include <string.h>
2425 #include <unistd.h>
2526 #include <sys/ptrace.h>
@@ -207,3 +208,31 @@ void dump_memory(log_t* log, Backtrace* backtrace, uintptr_t addr, const char* f
207208 _LOG(log, logtype::MEMORY, "%s %s\n", logline.c_str(), ascii.c_str());
208209 }
209210 }
211+
212+bool pid_contains_tid(pid_t pid, pid_t tid) {
213+ char task_path[PATH_MAX];
214+ if (snprintf(task_path, PATH_MAX, "/proc/%d/task/%d", pid, tid) >= PATH_MAX) {
215+ ALOGE("debuggerd: task path overflow (pid = %d, tid = %d)\n", pid, tid);
216+ exit(1);
217+ }
218+
219+ return access(task_path, F_OK) == 0;
220+}
221+
222+// Attach to a thread, and verify that it's still a member of the given process
223+bool ptrace_attach_thread(pid_t pid, pid_t tid) {
224+ if (ptrace(PTRACE_ATTACH, tid, 0, 0) != 0) {
225+ return false;
226+ }
227+
228+ // Make sure that the task we attached to is actually part of the pid we're dumping.
229+ if (!pid_contains_tid(pid, tid)) {
230+ if (ptrace(PTRACE_DETACH, tid, 0, 0) != 0) {
231+ ALOGE("debuggerd: failed to detach from thread '%d'", tid);
232+ exit(1);
233+ }
234+ return false;
235+ }
236+
237+ return true;
238+}
--- a/debuggerd/utility.h
+++ b/debuggerd/utility.h
@@ -79,4 +79,9 @@ int wait_for_sigstop(pid_t, int*, bool*);
7979
8080 void dump_memory(log_t* log, Backtrace* backtrace, uintptr_t addr, const char* fmt, ...);
8181
82+bool pid_contains_tid(pid_t pid, pid_t tid);
83+
84+// Attach to a thread, and verify that it's still a member of the given process
85+bool ptrace_attach_thread(pid_t pid, pid_t tid);
86+
8287 #endif // _DEBUGGERD_UTILITY_H