diff options
author | Nick Kralevich <nnk@google.com> | 2011-11-28 14:48:18 -0800 |
---|---|---|
committer | Nick Kralevich <nnk@google.com> | 2011-11-29 13:19:18 -0800 |
commit | ed089c77ad9187ae4e1dc1404087c66bb7bb58e7 (patch) | |
tree | 3b7a402ef9f29274d87975e1229c10131acfdeab /cmds | |
parent | 1e773932a1658128b80508f081de3c80655465d2 (diff) | |
download | frameworks_base-ed089c77ad9187ae4e1dc1404087c66bb7bb58e7.zip frameworks_base-ed089c77ad9187ae4e1dc1404087c66bb7bb58e7.tar.gz frameworks_base-ed089c77ad9187ae4e1dc1404087c66bb7bb58e7.tar.bz2 |
allow dumpstate to work with dmesg_restrict=1
Ensure that dumpstate has the CAP_SYSLOG permission, so that
it can always read the kernel syslog buffer. This is needed
to ensure that "adb bugreport" shows the dmesg log buffer.
Bug: 5585365
Change-Id: I4b561b77ada83dc875de80fe3ed15743c5958d09
Diffstat (limited to 'cmds')
-rw-r--r-- | cmds/dumpstate/dumpstate.c | 27 | ||||
-rw-r--r-- | cmds/dumpstate/dumpstate.h | 3 | ||||
-rw-r--r-- | cmds/dumpstate/utils.c | 25 |
3 files changed, 54 insertions, 1 deletions
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c index 399e668..d5d65c1 100644 --- a/cmds/dumpstate/dumpstate.c +++ b/cmds/dumpstate/dumpstate.c @@ -25,6 +25,8 @@ #include <sys/time.h> #include <sys/wait.h> #include <unistd.h> +#include <linux/capability.h> +#include <linux/prctl.h> #include <cutils/properties.h> @@ -169,7 +171,7 @@ static void dumpstate() { print_properties(); - run_command("KERNEL LOG", 20, "dmesg", NULL); + do_dmesg(); dump_file("KERNEL WAKELOCKS", "/proc/wakelocks"); dump_file("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state"); @@ -192,6 +194,7 @@ static void dumpstate() { dump_file("PACKAGE SETTINGS", "/data/system/packages.xml"); dump_file("PACKAGE UID ERRORS", "/data/system/uiderrors.txt"); + /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */ dump_file("LAST KMSG", "/proc/last_kmsg"); run_command("LAST RADIO LOG", 10, "parse_radio_log", "/proc/last_radio_log", NULL); dump_file("LAST PANIC CONSOLE", "/data/dontpanic/apanic_console"); @@ -315,6 +318,11 @@ int main(int argc, char *argv[]) { } if (getuid() == 0) { + if (prctl(PR_SET_KEEPCAPS, 1) < 0) { + LOGE("prctl(PR_SET_KEEPCAPS) failed: %s\n", strerror(errno)); + return -1; + } + /* switch to non-root user and group */ gid_t groups[] = { AID_LOG, AID_SDCARD_RW, AID_MOUNT, AID_INET }; if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) { @@ -329,6 +337,23 @@ int main(int argc, char *argv[]) { LOGE("Unable to setuid, aborting: %s\n", strerror(errno)); return -1; } + + struct __user_cap_header_struct capheader; + struct __user_cap_data_struct capdata[2]; + memset(&capheader, 0, sizeof(capheader)); + memset(&capdata, 0, sizeof(capdata)); + capheader.version = _LINUX_CAPABILITY_VERSION_3; + capheader.pid = 0; + + capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = CAP_TO_MASK(CAP_SYSLOG); + capdata[CAP_TO_INDEX(CAP_SYSLOG)].effective = CAP_TO_MASK(CAP_SYSLOG); + capdata[0].inheritable = 0; + capdata[1].inheritable = 0; + + if (capset(&capheader, &capdata[0]) < 0) { + LOGE("capset failed: %s\n", strerror(errno)); + return -1; + } } char path[PATH_MAX], tmp_path[PATH_MAX]; diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h index 6d66b1b..b02db0b 100644 --- a/cmds/dumpstate/dumpstate.h +++ b/cmds/dumpstate/dumpstate.h @@ -48,6 +48,9 @@ void show_wchan(int pid, const char *name); /* Runs "showmap" for a process */ void do_showmap(int pid, const char *name); +/* Gets the dmesg output for the kernel */ +void do_dmesg(); + /* Play a sound via Stagefright */ void play_sound(const char* path); diff --git a/cmds/dumpstate/utils.c b/cmds/dumpstate/utils.c index 14984ec..21526f9 100644 --- a/cmds/dumpstate/utils.c +++ b/cmds/dumpstate/utils.c @@ -28,6 +28,7 @@ #include <sys/stat.h> #include <sys/time.h> #include <sys/wait.h> +#include <sys/klog.h> #include <time.h> #include <unistd.h> @@ -96,6 +97,30 @@ out_close: return; } +void do_dmesg() { + printf("------ KERNEL LOG (dmesg) ------\n"); + int size = klogctl(10, NULL, 0); /* Get size of kernel buffer */ + if (size <= 0) { + printf("Unexpected klogctl return value: %d\n\n", size); + return; + } + char *buf = (char *) malloc(size + 1); + if (buf == NULL) { + printf("memory allocation failed\n\n"); + return; + } + int retval = klogctl(KLOG_READ_ALL, buf, size); + if (retval < 0) { + printf("klogctl failure\n\n"); + free(buf); + return; + } + buf[retval] = '\0'; + printf("%s\n\n", buf); + free(buf); + return; +} + void do_showmap(int pid, const char *name) { char title[255]; char arg[255]; |