From be0045aafdbc2ec2ee448be86952082361f5d672 Mon Sep 17 00:00:00 2001 From: Mike Lockwood Date: Wed, 2 Sep 2009 18:06:17 -0400 Subject: [PATCH 1/3] adb: "adb bugreport" now runs dumpstate via init rather than execing it in the shell. This allows dumpstate to run as root even if adbd is not. Change-Id: I04bda1ee0c8de91677149a2a9eda713c85067aa4 Signed-off-by: Mike Lockwood --- adb/commandline.c | 10 +--------- adb/services.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/adb/commandline.c b/adb/commandline.c index 411bb82a..66034521 100644 --- a/adb/commandline.c +++ b/adb/commandline.c @@ -929,7 +929,7 @@ int adb_commandline(int argc, char **argv) if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot") || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb") - || !strcmp(argv[0], "root")) { + || !strcmp(argv[0], "root") || !strcmp(argv[0], "bugreport")) { char command[100]; if (argc > 1) snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]); @@ -945,14 +945,6 @@ int adb_commandline(int argc, char **argv) return 1; } - if(!strcmp(argv[0], "bugreport")) { - if (argc != 1) { - return 1; - } - do_cmd(ttype, serial, "shell", "dumpstate", "-", 0); - return 0; - } - /* adb_command() wrapper commands */ if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) { diff --git a/adb/services.c b/adb/services.c index 2864ac97..447c11b5 100644 --- a/adb/services.c +++ b/adb/services.c @@ -188,6 +188,43 @@ void reboot_service(int fd, void *arg) adb_close(fd); } +void bugreport_service(int fd, void *cookie) +{ + char buffer[MAX_PAYLOAD]; + int i, s; + + /* start the dumpstate service */ + property_set("ctl.start", "dumpstate"); + + /* socket will not be available until service starts */ + for (i = 0; i < 10; i++) { + s = socket_local_client("dumpstate", + ANDROID_SOCKET_NAMESPACE_RESERVED, + SOCK_STREAM); + if (s >= 0) + break; + /* try again in 1 second */ + sleep(1); + } + + if (s < 0) { + const char* failed = "Failed to connect to dumpstate service\n"; + writex(fd, failed, strlen(failed)); + adb_close(fd); + return; + } + + while (1) { + int length = adb_read(s, buffer, sizeof(buffer)); + if (length <= 0) + break; + if (adb_write(fd, buffer, length) <= 0) + break; + } + adb_close(s); + adb_close(fd); +} + #endif #if 0 @@ -469,6 +506,8 @@ int service_to_fd(const char *name) ret = create_service_thread(restart_tcp_service, (void *)port); } else if(!strncmp(name, "usb:", 4)) { ret = create_service_thread(restart_usb_service, NULL); + } else if(!strncmp(name, "bugreport:", 10)) { + ret = create_service_thread(bugreport_service, NULL); #endif #if 0 } else if(!strncmp(name, "echo:", 5)){ From c5e7ef24308f5a993ecfd5ac438d347e786f5e42 Mon Sep 17 00:00:00 2001 From: Mike Lockwood Date: Wed, 2 Sep 2009 18:08:52 -0400 Subject: [PATCH 2/3] init: Add support for enforcing setprop by caller's group. Change-Id: Ic96e139c4c596882adb38b8863ac6157e0ac17b5 Signed-off-by: Mike Lockwood --- init/property_service.c | 68 ++++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/init/property_service.c b/init/property_service.c index 35929f0a..7db7c2cb 100644 --- a/init/property_service.c +++ b/init/property_service.c @@ -52,31 +52,32 @@ static int persistent_properties_loaded = 0; struct { const char *prefix; unsigned int uid; + unsigned int gid; } property_perms[] = { - { "net.rmnet0.", AID_RADIO }, - { "net.gprs.", AID_RADIO }, - { "net.ppp", AID_RADIO }, - { "ril.", AID_RADIO }, - { "gsm.", AID_RADIO }, - { "persist.radio", AID_RADIO }, - { "net.dns", AID_RADIO }, - { "net.", AID_SYSTEM }, - { "dev.", AID_SYSTEM }, - { "runtime.", AID_SYSTEM }, - { "hw.", AID_SYSTEM }, - { "sys.", AID_SYSTEM }, - { "service.", AID_SYSTEM }, - { "wlan.", AID_SYSTEM }, - { "dhcp.", AID_SYSTEM }, - { "dhcp.", AID_DHCP }, - { "vpn.", AID_SYSTEM }, - { "vpn.", AID_VPN }, - { "debug.", AID_SHELL }, - { "log.", AID_SHELL }, - { "service.adb.root", AID_SHELL }, - { "persist.sys.", AID_SYSTEM }, - { "persist.service.", AID_SYSTEM }, - { NULL, 0 } + { "net.rmnet0.", AID_RADIO, 0 }, + { "net.gprs.", AID_RADIO, 0 }, + { "net.ppp", AID_RADIO, 0 }, + { "ril.", AID_RADIO, 0 }, + { "gsm.", AID_RADIO, 0 }, + { "persist.radio", AID_RADIO, 0 }, + { "net.dns", AID_RADIO, 0 }, + { "net.", AID_SYSTEM, 0 }, + { "dev.", AID_SYSTEM, 0 }, + { "runtime.", AID_SYSTEM, 0 }, + { "hw.", AID_SYSTEM, 0 }, + { "sys.", AID_SYSTEM, 0 }, + { "service.", AID_SYSTEM, 0 }, + { "wlan.", AID_SYSTEM, 0 }, + { "dhcp.", AID_SYSTEM, 0 }, + { "dhcp.", AID_DHCP, 0 }, + { "vpn.", AID_SYSTEM, 0 }, + { "vpn.", AID_VPN, 0 }, + { "debug.", AID_SHELL, 0 }, + { "log.", AID_SHELL, 0 }, + { "service.adb.root", AID_SHELL, 0 }, + { "persist.sys.", AID_SYSTEM, 0 }, + { "persist.service.", AID_SYSTEM, 0 }, + { NULL, 0, 0 } }; /* @@ -86,8 +87,10 @@ struct { struct { const char *service; unsigned int uid; + unsigned int gid; } control_perms[] = { - {NULL, 0 } + { "dumpstate",AID_SHELL, AID_LOG }, + {NULL, 0, 0 } }; typedef struct { @@ -183,7 +186,7 @@ static int property_write(prop_info *pi, const char *value) * * Returns 1 if uid allowed, 0 otherwise. */ -static int check_control_perms(const char *name, int uid) { +static int check_control_perms(const char *name, int uid, int gid) { int i; if (uid == AID_SYSTEM || uid == AID_ROOT) return 1; @@ -191,8 +194,10 @@ static int check_control_perms(const char *name, int uid) { /* Search the ACL */ for (i = 0; control_perms[i].service; i++) { if (strcmp(control_perms[i].service, name) == 0) { - if (control_perms[i].uid == uid) + if ((uid && control_perms[i].uid == uid) || + (gid && control_perms[i].gid == gid)) { return 1; + } } } return 0; @@ -202,7 +207,7 @@ static int check_control_perms(const char *name, int uid) { * Checks permissions for setting system properties. * Returns 1 if uid allowed, 0 otherwise. */ -static int check_perms(const char *name, unsigned int uid) +static int check_perms(const char *name, unsigned int uid, int gid) { int i; if (uid == 0) @@ -215,7 +220,8 @@ static int check_perms(const char *name, unsigned int uid) int tmp; if (strncmp(property_perms[i].prefix, name, strlen(property_perms[i].prefix)) == 0) { - if (property_perms[i].uid == uid) { + if ((uid && property_perms[i].uid == uid) || + (gid && property_perms[i].gid == gid)) { return 1; } } @@ -373,14 +379,14 @@ void handle_property_set_fd(int fd) msg.value[PROP_VALUE_MAX-1] = 0; if(memcmp(msg.name,"ctl.",4) == 0) { - if (check_control_perms(msg.value, cr.uid)) { + if (check_control_perms(msg.value, cr.uid, cr.gid)) { handle_control_message((char*) msg.name + 4, (char*) msg.value); } else { ERROR("sys_prop: Unable to %s service ctl [%s] uid: %d pid:%d\n", msg.name + 4, msg.value, cr.uid, cr.pid); } } else { - if (check_perms(msg.name, cr.uid)) { + if (check_perms(msg.name, cr.uid, cr.gid)) { property_set((char*) msg.name, (char*) msg.value); } else { ERROR("sys_prop: permission denied uid:%d name:%s\n", From abe3a9c30595846b7e3d705dd4b0aca37fb2f748 Mon Sep 17 00:00:00 2001 From: Mike Lockwood Date: Wed, 2 Sep 2009 18:09:26 -0400 Subject: [PATCH 3/3] init.rc: Add dumpstate service Change-Id: Iaf7094dd4693c47566c1acf860b750b762af840c Signed-off-by: Mike Lockwood --- rootdir/init.rc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rootdir/init.rc b/rootdir/init.rc index 03563c35..7d9869f8 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -352,3 +352,7 @@ service keystore /system/bin/keystore group keystore socket keystore stream 666 +service dumpstate /system/bin/dumpstate -s + socket dumpstate stream 0660 shell log + disabled + oneshot