diff options
author | Josh Gao <jmgao@google.com> | 2017-02-09 14:42:38 -0800 |
---|---|---|
committer | Josh Gao <jmgao@google.com> | 2017-02-14 14:40:47 -0800 |
commit | d2069632bd560cc9c2e27284108024a8a0ced3e4 (patch) | |
tree | 959f311dddcfe9147565bcc42f20ed44b3d67417 /debuggerd/handler/debuggerd_handler.cpp | |
parent | 91ad653c8247b9e41a9ae500cbe376f61b56c9e9 (diff) |
debuggerd_handler: raise capabilities before running crash_dump.
Raise CapInh and CapAmb after forking to exec crash_dump, so that it
can ptrace us.
Bug: http://b/35174939
Test: debuggerd -b `pidof surfaceflinger`
Change-Id: I32567010a3603cfa494aae9dc0e3ce73fb86b590
Diffstat (limited to 'debuggerd/handler/debuggerd_handler.cpp')
-rw-r--r-- | debuggerd/handler/debuggerd_handler.cpp | 40 |
1 files changed, 36 insertions, 4 deletions
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp index 353f642a8..cb8f0172f 100644 --- a/debuggerd/handler/debuggerd_handler.cpp +++ b/debuggerd/handler/debuggerd_handler.cpp @@ -174,6 +174,41 @@ static bool have_siginfo(int signum) { return (old_action.sa_flags & SA_SIGINFO) != 0; } +static void raise_caps() { + // Raise CapInh to match CapPrm, so that we can set the ambient bits. + __user_cap_header_struct capheader; + memset(&capheader, 0, sizeof(capheader)); + capheader.version = _LINUX_CAPABILITY_VERSION_3; + capheader.pid = 0; + + __user_cap_data_struct capdata[2]; + if (capget(&capheader, &capdata[0]) == -1) { + fatal_errno("capget failed"); + } + + if (capdata[0].permitted != capdata[0].inheritable || + capdata[1].permitted != capdata[1].inheritable) { + capdata[0].inheritable = capdata[0].permitted; + capdata[1].inheritable = capdata[1].permitted; + + if (capset(&capheader, &capdata[0]) == -1) { + __libc_format_log(ANDROID_LOG_ERROR, "libc", "capset failed: %s", strerror(errno)); + } + } + + // Set the ambient capability bits so that crash_dump gets all of our caps and can ptrace us. + uint64_t capmask = capdata[0].inheritable; + capmask |= static_cast<uint64_t>(capdata[1].inheritable) << 32; + for (unsigned long i = 0; i < 64; ++i) { + if (capmask & (1 << i)) { + if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, i, 0, 0) != 0) { + __libc_format_log(ANDROID_LOG_ERROR, "libc", "failed to raise ambient capability %lu: %s", + i, strerror(errno)); + } + } + } +} + struct debugger_thread_info { bool crash_dump_started; pid_t crashing_tid; @@ -217,10 +252,7 @@ static int debuggerd_dispatch_pseudothread(void* arg) { close(pipefds[0]); close(pipefds[1]); - // Set all of the ambient capability bits we can, so that crash_dump can ptrace us. - for (unsigned long i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) != -1; ++i) { - prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, i, 0, 0); - } + raise_caps(); char buf[10]; snprintf(buf, sizeof(buf), "%d", thread_info->crashing_tid); |