OSDN Git Service

Add extra groups and capabilities to shell user
authorMike Lockwood <lockwood@google.com>
Thu, 29 Dec 2011 19:42:46 +0000 (14:42 -0500)
committerMike Lockwood <lockwood@google.com>
Wed, 8 Feb 2012 18:13:07 +0000 (10:13 -0800)
This allows things like logcat, reboot, internet, SD card access, etc. to
work in an ssh shell like it would in an adb shell.

Change-Id: I6c921d9900a09394250c7b1ae0512d1eef3c1187
Signed-off-by: Mike Lockwood <lockwood@google.com>
uidswap.c

index 8376483..bc6194e 100644 (file)
--- a/uidswap.c
+++ b/uidswap.c
 #include "uidswap.h"
 #include "xmalloc.h"
 
+#ifdef ANDROID
+#include <private/android_filesystem_config.h>
+#include <linux/capability.h>
+#include <linux/prctl.h>
+#endif
+
 /*
  * Note: all these functions must work in all of the following cases:
  *    1. euid=0, ruid=0
@@ -212,6 +218,10 @@ permanently_set_uid(struct passwd *pw)
 {
        uid_t old_uid = getuid();
        gid_t old_gid = getgid();
+#ifdef ANDROID
+       struct __user_cap_header_struct header;
+       struct __user_cap_data_struct cap;
+#endif
 
        if (pw == NULL)
                fatal("permanently_set_uid: no user given");
@@ -220,6 +230,27 @@ permanently_set_uid(struct passwd *pw)
        debug("permanently_set_uid: %u/%u", (u_int)pw->pw_uid,
            (u_int)pw->pw_gid);
 
+#ifdef ANDROID
+       if (pw->pw_uid == AID_SHELL) {
+               prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+
+               /* add extra groups needed for shell user:
+               ** AID_LOG to read system logs (adb logcat)
+               ** AID_INPUT to diagnose input issues (getevent)
+               ** AID_INET to diagnose network issues (netcfg, ping)
+               ** AID_GRAPHICS to access the frame buffer
+               ** AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump)
+               ** AID_SDCARD_RW to allow writing to the SD card
+               ** AID_MOUNT to allow unmounting the SD card before rebooting
+               ** AID_NET_BW_STATS to read out qtaguid statistics
+               */
+               gid_t groups[] = { AID_LOG, AID_INPUT, AID_INET, AID_GRAPHICS,
+                                                  AID_NET_BT, AID_NET_BT_ADMIN, AID_SDCARD_RW,
+                                                  AID_MOUNT, AID_NET_BW_STATS };
+               setgroups(sizeof(groups)/sizeof(groups[0]), groups);
+       }
+#endif
+
 #if defined(HAVE_SETRESGID) && !defined(BROKEN_SETRESGID)
        if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) < 0)
                fatal("setresgid %u: %.100s", (u_int)pw->pw_gid, strerror(errno));
@@ -285,4 +316,16 @@ permanently_set_uid(struct passwd *pw)
                    __func__, (u_int)getuid(), (u_int)geteuid(),
                    (u_int)pw->pw_uid);
        }
+
+#ifdef ANDROID
+       if (pw->pw_uid == AID_SHELL) {
+               /* set CAP_SYS_BOOT capability, so "adb reboot" will succeed */
+               header.version = _LINUX_CAPABILITY_VERSION;
+               header.pid = 0;
+               cap.effective = cap.permitted = (1 << CAP_SYS_BOOT);
+               cap.inheritable = 0;
+               capset(&header, &cap);
+       }
+#endif
+
 }