diff --git a/uidswap.c b/uidswap.c index 8376483967a9f609f089a1879423ee6b3ea4d4d0..bc6194ec0a3d78bfafbfc5f487896f57f95760d8 100644 --- a/uidswap.c +++ b/uidswap.c @@ -27,6 +27,12 @@ #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 + }