Merge changes 23694,23695,23696 into eclair
* changes:
init.rc: Add dumpstate service
init: Add support for enforcing setprop by caller's group.
adb: "adb bugreport" now runs dumpstate via init rather than execing it in the shell.
diff --git a/adb/commandline.c b/adb/commandline.c
index 411bb82..6603452 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -929,7 +929,7 @@
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 @@
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 2864ac9..447c11b 100644
--- a/adb/services.c
+++ b/adb/services.c
@@ -188,6 +188,43 @@
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 @@
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)){
diff --git a/init/property_service.c b/init/property_service.c
index 35929f0..7db7c2c 100644
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -52,31 +52,32 @@
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 {
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 @@
*
* 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 @@
/* 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 @@
* 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 @@
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 @@
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",
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 03563c3..7d9869f 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -352,3 +352,7 @@
group keystore
socket keystore stream 666
+service dumpstate /system/bin/dumpstate -s
+ socket dumpstate stream 0660 shell log
+ disabled
+ oneshot