summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Gao2018-01-19 20:45:37 -0600
committerGerrit Code Review2018-01-19 20:45:37 -0600
commitfd0e0db391f9fab1f8dea7e658769d25f6a81784 (patch)
treedb222b08ae91061d7dc25a291eac5d64a8ed847e /debuggerd
parent658e4ddd0398ca65936359b26390cb293d202899 (diff)
parente04ca2794a49a9d20f7d99a7aa1a068934386351 (diff)
downloadplatform-system-core-fd0e0db391f9fab1f8dea7e658769d25f6a81784.tar.gz
platform-system-core-fd0e0db391f9fab1f8dea7e658769d25f6a81784.tar.xz
platform-system-core-fd0e0db391f9fab1f8dea7e658769d25f6a81784.zip
Merge "debuggerd: add seccomp policies and tests."
Diffstat (limited to 'debuggerd')
-rw-r--r--debuggerd/Android.bp1
-rw-r--r--debuggerd/Android.mk23
-rw-r--r--debuggerd/debuggerd_test.cpp143
-rw-r--r--debuggerd/seccomp_policy/crash_dump.arm.policy37
-rw-r--r--debuggerd/seccomp_policy/crash_dump.arm64.policy36
-rw-r--r--debuggerd/seccomp_policy/crash_dump.policy.def64
-rw-r--r--debuggerd/seccomp_policy/crash_dump.x86.policy37
-rw-r--r--debuggerd/seccomp_policy/crash_dump.x86_64.policy36
-rwxr-xr-xdebuggerd/seccomp_policy/generate.sh10
9 files changed, 384 insertions, 3 deletions
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 7fec47dae..fb8a20577 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -195,6 +195,7 @@ cc_test {
195 "libcutils", 195 "libcutils",
196 "libdebuggerd_client", 196 "libdebuggerd_client",
197 "liblog", 197 "liblog",
198 "libminijail",
198 "libnativehelper" 199 "libnativehelper"
199 ], 200 ],
200 201
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
new file mode 100644
index 000000000..3bc174250
--- /dev/null
+++ b/debuggerd/Android.mk
@@ -0,0 +1,23 @@
1LOCAL_PATH := $(call my-dir)
2
3include $(CLEAR_VARS)
4LOCAL_MODULE := crash_dump.policy
5LOCAL_MODULE_CLASS := ETC
6LOCAL_MULTILIB := both
7
8ifeq ($(TARGET_ARCH), $(filter $(TARGET_ARCH), arm arm64))
9LOCAL_MODULE_STEM_32 := crash_dump.arm.policy
10LOCAL_MODULE_STEM_64 := crash_dump.arm64.policy
11endif
12
13ifeq ($(TARGET_ARCH), $(filter $(TARGET_ARCH), x86 x86_64))
14LOCAL_MODULE_STEM_32 := crash_dump.x86.policy
15LOCAL_MODULE_STEM_64 := crash_dump.x86_64.policy
16endif
17
18LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/seccomp_policy
19LOCAL_SRC_FILES_arm := seccomp_policy/crash_dump.arm.policy
20LOCAL_SRC_FILES_arm64 := seccomp_policy/crash_dump.arm64.policy
21LOCAL_SRC_FILES_x86 := seccomp_policy/crash_dump.x86.policy
22LOCAL_SRC_FILES_x86_64 := seccomp_policy/crash_dump.x86_64.policy
23include $(BUILD_PREBUILT)
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 939f4d257..f8b4bad6e 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -41,6 +41,9 @@
41#include <cutils/sockets.h> 41#include <cutils/sockets.h>
42#include <gtest/gtest.h> 42#include <gtest/gtest.h>
43 43
44#include <libminijail.h>
45#include <scoped_minijail.h>
46
44#include "debuggerd/handler.h" 47#include "debuggerd/handler.h"
45#include "protocol.h" 48#include "protocol.h"
46#include "tombstoned/tombstoned.h" 49#include "tombstoned/tombstoned.h"
@@ -76,9 +79,8 @@ constexpr char kWaitForGdbKey[] = "debug.debuggerd.wait_for_gdb";
76 return value; \ 79 return value; \
77 }() 80 }()
78 81
79#define ASSERT_BACKTRACE_FRAME(result, frame_name) \ 82#define ASSERT_BACKTRACE_FRAME(result, frame_name) \
80 ASSERT_MATCH(result, R"(#\d\d pc [0-9a-f]+\s+ /system/lib)" ARCH_SUFFIX \ 83 ASSERT_MATCH(result, R"(#\d\d pc [0-9a-f]+\s+ \S+ \()" frame_name R"(\+)");
81 R"(/libc.so \()" frame_name R"(\+)")
82 84
83static void tombstoned_intercept(pid_t target_pid, unique_fd* intercept_fd, unique_fd* output_fd, 85static void tombstoned_intercept(pid_t target_pid, unique_fd* intercept_fd, unique_fd* output_fd,
84 InterceptStatus* status, DebuggerdDumpType intercept_type) { 86 InterceptStatus* status, DebuggerdDumpType intercept_type) {
@@ -565,6 +567,141 @@ TEST_F(CrasherTest, fake_pid) {
565 ASSERT_BACKTRACE_FRAME(result, "tgkill"); 567 ASSERT_BACKTRACE_FRAME(result, "tgkill");
566} 568}
567 569
570static const char* const kDebuggerdSeccompPolicy =
571 "/system/etc/seccomp_policy/crash_dump." ABI_STRING ".policy";
572
573pid_t seccomp_fork() {
574 unique_fd policy_fd(open(kDebuggerdSeccompPolicy, O_RDONLY | O_CLOEXEC));
575 if (policy_fd == -1) {
576 LOG(FATAL) << "failed to open policy " << kDebuggerdSeccompPolicy;
577 }
578
579 ScopedMinijail jail{minijail_new()};
580 if (!jail) {
581 LOG(FATAL) << "failed to create minijail";
582 }
583
584 minijail_no_new_privs(jail.get());
585 minijail_log_seccomp_filter_failures(jail.get());
586 minijail_use_seccomp_filter(jail.get());
587 minijail_parse_seccomp_filters_from_fd(jail.get(), policy_fd.release());
588
589 pid_t result = fork();
590 if (result == -1) {
591 return result;
592 } else if (result != 0) {
593 return result;
594 }
595
596 // Spawn and detach a thread that spins forever.
597 std::atomic<bool> thread_ready(false);
598 std::thread thread([&jail, &thread_ready]() {
599 minijail_enter(jail.get());
600 thread_ready = true;
601 for (;;)
602 ;
603 });
604 thread.detach();
605
606 while (!thread_ready) {
607 continue;
608 }
609
610 minijail_enter(jail.get());
611 return result;
612}
613
614TEST_F(CrasherTest, seccomp_crash) {
615 int intercept_result;
616 unique_fd output_fd;
617
618 StartProcess([]() { abort(); }, &seccomp_fork);
619
620 StartIntercept(&output_fd);
621 FinishCrasher();
622 AssertDeath(SIGABRT);
623 FinishIntercept(&intercept_result);
624 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
625
626 std::string result;
627 ConsumeFd(std::move(output_fd), &result);
628 ASSERT_BACKTRACE_FRAME(result, "abort");
629}
630
631__attribute__((noinline)) extern "C" bool raise_debugger_signal(DebuggerdDumpType dump_type) {
632 siginfo_t siginfo;
633 siginfo.si_code = SI_QUEUE;
634 siginfo.si_pid = getpid();
635 siginfo.si_uid = getuid();
636
637 if (dump_type != kDebuggerdNativeBacktrace && dump_type != kDebuggerdTombstone) {
638 PLOG(FATAL) << "invalid dump type";
639 }
640
641 siginfo.si_value.sival_int = dump_type == kDebuggerdNativeBacktrace;
642
643 if (syscall(__NR_rt_tgsigqueueinfo, getpid(), gettid(), DEBUGGER_SIGNAL, &siginfo) != 0) {
644 PLOG(ERROR) << "libdebuggerd_client: failed to send signal to self";
645 return false;
646 }
647
648 return true;
649}
650
651TEST_F(CrasherTest, seccomp_tombstone) {
652 int intercept_result;
653 unique_fd output_fd;
654
655 static const auto dump_type = kDebuggerdTombstone;
656 StartProcess(
657 []() {
658 raise_debugger_signal(dump_type);
659 _exit(0);
660 },
661 &seccomp_fork);
662
663 StartIntercept(&output_fd, dump_type);
664 FinishCrasher();
665 AssertDeath(0);
666 FinishIntercept(&intercept_result);
667 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
668
669 std::string result;
670 ConsumeFd(std::move(output_fd), &result);
671 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
672}
673
674TEST_F(CrasherTest, seccomp_backtrace) {
675 int intercept_result;
676 unique_fd output_fd;
677
678 static const auto dump_type = kDebuggerdNativeBacktrace;
679 StartProcess(
680 []() {
681 raise_debugger_signal(dump_type);
682 _exit(0);
683 },
684 &seccomp_fork);
685
686 StartIntercept(&output_fd, dump_type);
687 FinishCrasher();
688 AssertDeath(0);
689 FinishIntercept(&intercept_result);
690 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
691
692 std::string result;
693 ConsumeFd(std::move(output_fd), &result);
694 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
695}
696
697TEST_F(CrasherTest, seccomp_crash_logcat) {
698 StartProcess([]() { abort(); }, &seccomp_fork);
699 FinishCrasher();
700
701 // Make sure we don't get SIGSYS when trying to dump a crash to logcat.
702 AssertDeath(SIGABRT);
703}
704
568TEST_F(CrasherTest, competing_tracer) { 705TEST_F(CrasherTest, competing_tracer) {
569 int intercept_result; 706 int intercept_result;
570 unique_fd output_fd; 707 unique_fd output_fd;
diff --git a/debuggerd/seccomp_policy/crash_dump.arm.policy b/debuggerd/seccomp_policy/crash_dump.arm.policy
new file mode 100644
index 000000000..c64e28824
--- /dev/null
+++ b/debuggerd/seccomp_policy/crash_dump.arm.policy
@@ -0,0 +1,37 @@
1read: 1
2write: 1
3exit: 1
4rt_sigreturn: 1
5sigreturn: 1
6exit_group: 1
7clock_gettime: 1
8gettimeofday: 1
9futex: 1
10getrandom: 1
11getpid: 1
12gettid: 1
13ppoll: 1
14pipe2: 1
15openat: 1
16dup: 1
17close: 1
18lseek: 1
19getdents64: 1
20faccessat: 1
21recvmsg: 1
22process_vm_readv: 1
23tgkill: 1
24rt_sigprocmask: 1
25rt_tgsigqueueinfo: 1
26prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41
27madvise: 1
28mprotect: arg2 in PROT_READ|PROT_WRITE
29munmap: 1
30getuid32: 1
31fstat64: 1
32mmap2: arg2 in PROT_READ|PROT_WRITE
33sigaction: 1
34geteuid32: 1
35getgid32: 1
36getegid32: 1
37getgroups32: 1
diff --git a/debuggerd/seccomp_policy/crash_dump.arm64.policy b/debuggerd/seccomp_policy/crash_dump.arm64.policy
new file mode 100644
index 000000000..0c689bbd6
--- /dev/null
+++ b/debuggerd/seccomp_policy/crash_dump.arm64.policy
@@ -0,0 +1,36 @@
1read: 1
2write: 1
3exit: 1
4rt_sigreturn: 1
5exit_group: 1
6clock_gettime: 1
7gettimeofday: 1
8futex: 1
9getrandom: 1
10getpid: 1
11gettid: 1
12ppoll: 1
13pipe2: 1
14openat: 1
15dup: 1
16close: 1
17lseek: 1
18getdents64: 1
19faccessat: 1
20recvmsg: 1
21process_vm_readv: 1
22tgkill: 1
23rt_sigprocmask: 1
24rt_tgsigqueueinfo: 1
25prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41
26madvise: 1
27mprotect: arg2 in PROT_READ|PROT_WRITE
28munmap: 1
29getuid: 1
30fstat: 1
31mmap: arg2 in PROT_READ|PROT_WRITE
32rt_sigaction: 1
33geteuid: 1
34getgid: 1
35getegid: 1
36getgroups: 1
diff --git a/debuggerd/seccomp_policy/crash_dump.policy.def b/debuggerd/seccomp_policy/crash_dump.policy.def
new file mode 100644
index 000000000..dadffac8d
--- /dev/null
+++ b/debuggerd/seccomp_policy/crash_dump.policy.def
@@ -0,0 +1,64 @@
1// SECCOMP_MODE_STRICT
2read: 1
3write: 1
4exit: 1
5rt_sigreturn: 1
6#if !defined(__LP64__)
7sigreturn: 1
8#endif
9
10exit_group: 1
11clock_gettime: 1
12gettimeofday: 1
13futex: 1
14getrandom: 1
15getpid: 1
16gettid: 1
17
18ppoll: 1
19pipe2: 1
20openat: 1
21dup: 1
22close: 1
23lseek: 1
24getdents64: 1
25faccessat: 1
26recvmsg: 1
27
28process_vm_readv: 1
29
30tgkill: 1
31rt_sigprocmask: 1
32rt_tgsigqueueinfo: 1
33
34#define PR_SET_VMA 0x53564d41
35prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == PR_SET_VMA
36
37madvise: 1
38mprotect: arg2 in PROT_READ|PROT_WRITE
39munmap: 1
40
41#if defined(__LP64__)
42getuid: 1
43fstat: 1
44mmap: arg2 in PROT_READ|PROT_WRITE
45rt_sigaction: 1
46#else
47getuid32: 1
48fstat64: 1
49mmap2: arg2 in PROT_READ|PROT_WRITE
50sigaction: 1
51#endif
52
53// Needed for logging.
54#if defined(__LP64__)
55geteuid: 1
56getgid: 1
57getegid: 1
58getgroups: 1
59#else
60geteuid32: 1
61getgid32: 1
62getegid32: 1
63getgroups32: 1
64#endif
diff --git a/debuggerd/seccomp_policy/crash_dump.x86.policy b/debuggerd/seccomp_policy/crash_dump.x86.policy
new file mode 100644
index 000000000..c64e28824
--- /dev/null
+++ b/debuggerd/seccomp_policy/crash_dump.x86.policy
@@ -0,0 +1,37 @@
1read: 1
2write: 1
3exit: 1
4rt_sigreturn: 1
5sigreturn: 1
6exit_group: 1
7clock_gettime: 1
8gettimeofday: 1
9futex: 1
10getrandom: 1
11getpid: 1
12gettid: 1
13ppoll: 1
14pipe2: 1
15openat: 1
16dup: 1
17close: 1
18lseek: 1
19getdents64: 1
20faccessat: 1
21recvmsg: 1
22process_vm_readv: 1
23tgkill: 1
24rt_sigprocmask: 1
25rt_tgsigqueueinfo: 1
26prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41
27madvise: 1
28mprotect: arg2 in PROT_READ|PROT_WRITE
29munmap: 1
30getuid32: 1
31fstat64: 1
32mmap2: arg2 in PROT_READ|PROT_WRITE
33sigaction: 1
34geteuid32: 1
35getgid32: 1
36getegid32: 1
37getgroups32: 1
diff --git a/debuggerd/seccomp_policy/crash_dump.x86_64.policy b/debuggerd/seccomp_policy/crash_dump.x86_64.policy
new file mode 100644
index 000000000..0c689bbd6
--- /dev/null
+++ b/debuggerd/seccomp_policy/crash_dump.x86_64.policy
@@ -0,0 +1,36 @@
1read: 1
2write: 1
3exit: 1
4rt_sigreturn: 1
5exit_group: 1
6clock_gettime: 1
7gettimeofday: 1
8futex: 1
9getrandom: 1
10getpid: 1
11gettid: 1
12ppoll: 1
13pipe2: 1
14openat: 1
15dup: 1
16close: 1
17lseek: 1
18getdents64: 1
19faccessat: 1
20recvmsg: 1
21process_vm_readv: 1
22tgkill: 1
23rt_sigprocmask: 1
24rt_tgsigqueueinfo: 1
25prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41
26madvise: 1
27mprotect: arg2 in PROT_READ|PROT_WRITE
28munmap: 1
29getuid: 1
30fstat: 1
31mmap: arg2 in PROT_READ|PROT_WRITE
32rt_sigaction: 1
33geteuid: 1
34getgid: 1
35getegid: 1
36getgroups: 1
diff --git a/debuggerd/seccomp_policy/generate.sh b/debuggerd/seccomp_policy/generate.sh
new file mode 100755
index 000000000..8c58b052f
--- /dev/null
+++ b/debuggerd/seccomp_policy/generate.sh
@@ -0,0 +1,10 @@
1#!/bin/bash
2
3set -ex
4
5cd "$(dirname "$0")"
6CPP='cpp -undef -E -P crash_dump.policy.def'
7$CPP -D__arm__ -o crash_dump.arm.policy
8$CPP -D__aarch64__ -D__LP64__ -o crash_dump.arm64.policy
9$CPP -D__i386__ -o crash_dump.x86.policy
10$CPP -D__x86_64__ -D__LP64__ -o crash_dump.x86_64.policy