• R/O
  • HTTP
  • SSH
  • HTTPS

コミット

タグ
未設定

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

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

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

変更サマリ

差分

--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -183,6 +183,16 @@ out:
183183 return allowed;
184184 }
185185
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+
186196 static int read_request(int fd, debugger_request_t* out_request) {
187197 ucred cr;
188198 socklen_t len = sizeof(cr);
@@ -227,16 +237,13 @@ static int read_request(int fd, debugger_request_t* out_request) {
227237
228238 if (msg.action == DEBUGGER_ACTION_CRASH) {
229239 // 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);
236244 return -1;
237245 }
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)) {
240247 // Only root or system can ask us to attach to any process and dump it explicitly.
241248 // However, system is only allowed to collect backtraces but cannot dump tombstones.
242249 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) {
413420 }
414421 #endif
415422
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+
416441 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];
418443
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+ }
420448
421449 std::unique_ptr<DIR, int (*)(DIR*)> d(opendir(task_path), closedir);
422450
@@ -443,7 +471,7 @@ static void ptrace_siblings(pid_t pid, pid_t main_tid, std::set<pid_t>& tids) {
443471 continue;
444472 }
445473
446- if (ptrace(PTRACE_ATTACH, tid, 0, 0) < 0) {
474+ if (!ptrace_attach_thread(pid, tid)) {
447475 ALOGE("debuggerd: ptrace attach to %d failed: %s", tid, strerror(errno));
448476 continue;
449477 }
@@ -568,11 +596,33 @@ static void worker_process(int fd, debugger_request_t& request) {
568596 // debugger_signal_handler().
569597
570598 // Attach to the target process.
571- if (ptrace(PTRACE_ATTACH, request.tid, 0, 0) != 0) {
599+ if (!ptrace_attach_thread(request.pid, request.tid)) {
572600 ALOGE("debuggerd: ptrace attach failed: %s", strerror(errno));
573601 exit(1);
574602 }
575603
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+
576626 // Don't attach to the sibling threads if we want to attach gdb.
577627 // Supposedly, it makes the process less reliable.
578628 bool attach_gdb = should_attach_gdb(request);
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -12,6 +12,14 @@ endif
1212
1313 init_options += -DLOG_UEVENTS=0
1414
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+
1523 init_cflags += \
1624 $(init_options) \
1725 -Wall -Wextra \
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -822,8 +822,8 @@ static int do_write(const std::vector<std::string>& args) {
822822 break;
823823 } else {
824824 //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++;
827827 }
828828 }
829829 if (!path || !value) {
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -160,15 +160,19 @@ void handle_control_message(const std::string& msg, const std::string& name) {
160160
161161 static int wait_for_coldboot_done_action(const std::vector<std::string>& args) {
162162 Timer t;
163-
163+ int timeout = 0;
164+#ifdef COLDBOOT_TIMEOUT_OVERRIDE
165+ timeout = COLDBOOT_TIMEOUT_OVERRIDE;
166+#else
167+ timeout = 5;
168+#endif
164169 NOTICE("Waiting for %s...\n", COLDBOOT_DONE);
165170 // Any longer than 1s is an unreasonable length of time to delay booting.
166171 // If you're hitting this timeout, check that you didn't make your
167172 // sepolicy regular expressions too expensive (http://b/19899875).
168- if (wait_for_file(COLDBOOT_DONE, 5)) {
173+ if (wait_for_file(COLDBOOT_DONE, timeout)) {
169174 ERROR("Timed out waiting for %s\n", COLDBOOT_DONE);
170175 }
171-
172176 NOTICE("Waiting for %s took %.2fs.\n", COLDBOOT_DONE, t.duration());
173177 return 0;
174178 }
@@ -258,15 +262,31 @@ static int keychord_init_action(const std::vector<std::string>& args)
258262
259263 static int console_init_action(const std::vector<std::string>& args)
260264 {
265+ int fd = -1;
261266 std::string console = property_get("ro.boot.console");
262267 if (!console.empty()) {
263268 console_name = "/dev/" + console;
264269 }
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+ }
267279 if (fd >= 0)
280+ INFO("Console device located");
281+#endif
282+ if (fd >= 0) {
268283 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+ }
270290
271291 fd = open("/dev/tty0", O_WRONLY | O_CLOEXEC);
272292 if (fd >= 0) {
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -580,6 +580,7 @@ on property:vold.decrypt=trigger_restart_min_framework
580580 # A/B update verifier that marks a successful boot.
581581 exec - root -- /system/bin/update_verifier trigger_restart_min_framework
582582 class_start main
583+ start time_daemon
583584
584585 on property:vold.decrypt=trigger_restart_framework
585586 # A/B update verifier that marks a successful boot.