diff options
author | Nick Kralevich <nnk@google.com> | 2012-08-31 16:08:06 -0700 |
---|---|---|
committer | Nick Kralevich <nnk@google.com> | 2012-09-04 14:58:22 -0700 |
commit | 812b19a425b8304ac9e5408cc8ceb9f363c72559 (patch) | |
tree | 6463a4310d8e3f715988788833bfa51e6ea62689 /cmds | |
parent | e94831e5ed4aa3b1ebc5444cc1b16cdab8cb92f8 (diff) | |
download | frameworks_base-812b19a425b8304ac9e5408cc8ceb9f363c72559.zip frameworks_base-812b19a425b8304ac9e5408cc8ceb9f363c72559.tar.gz frameworks_base-812b19a425b8304ac9e5408cc8ceb9f363c72559.tar.bz2 |
installd: reduce privileges.
Make installd run with fewer privileges. This will help make
exploitation of installd based vulnerabilities more difficult
to perform.
installd now runs with the following privileges:
* CAP_DAC_OVERRIDE
* CAP_CHOWN
These two capabilities are needed to add and remove files
from application's home directories.
* CAP_SETUID
* CAP_SETGID
These permissions are needed to further drop privileges when
running dexopt as the application UID.
"installd" no longer runs with full root privileges. It cannot,
for example, mount and unmount filesystems, install modules,
perform direct I/O, etc.
Change-Id: Ib407e41e5e4c95f35a5c6a154812c5e8ae3006ed
Diffstat (limited to 'cmds')
-rw-r--r-- | cmds/installd/commands.c | 23 | ||||
-rw-r--r-- | cmds/installd/installd.c | 46 |
2 files changed, 63 insertions, 6 deletions
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c index ab64747..9e83a67 100644 --- a/cmds/installd/commands.c +++ b/cmds/installd/commands.c @@ -14,6 +14,7 @@ ** limitations under the License. */ +#include <linux/capability.h> #include "installd.h" #include <diskusage/dirsize.h> @@ -665,16 +666,16 @@ int dexopt(const char *apk_path, uid_t uid, int is_public) ALOGE("dexopt cannot open '%s' for output\n", dex_path); goto fail; } - if (fchown(odex_fd, AID_SYSTEM, uid) < 0) { - ALOGE("dexopt cannot chown '%s'\n", dex_path); - goto fail; - } if (fchmod(odex_fd, S_IRUSR|S_IWUSR|S_IRGRP | (is_public ? S_IROTH : 0)) < 0) { ALOGE("dexopt cannot chmod '%s'\n", dex_path); goto fail; } + if (fchown(odex_fd, AID_SYSTEM, uid) < 0) { + ALOGE("dexopt cannot chown '%s'\n", dex_path); + goto fail; + } ALOGV("DexInv: --- BEGIN '%s' ---\n", apk_path); @@ -690,13 +691,23 @@ int dexopt(const char *apk_path, uid_t uid, int is_public) ALOGE("setuid(%d) during dexopt\n", uid); exit(65); } + // drop capabilities + 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; + if (capset(&capheader, &capdata[0]) < 0) { + ALOGE("capset failed: %s\n", strerror(errno)); + exit(66); + } if (flock(odex_fd, LOCK_EX | LOCK_NB) != 0) { ALOGE("flock(%s) failed: %s\n", dex_path, strerror(errno)); - exit(66); + exit(67); } run_dexopt(zip_fd, odex_fd, apk_path, dexopt_flags); - exit(67); /* only get here on exec failure */ + exit(68); /* only get here on exec failure */ } else { res = wait_dexopt(pid, apk_path); if (res != 0) { diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c index d559639..652543fd 100644 --- a/cmds/installd/installd.c +++ b/cmds/installd/installd.c @@ -14,6 +14,9 @@ ** limitations under the License. */ +#include <linux/capability.h> +#include <linux/prctl.h> + #include "installd.h" @@ -491,12 +494,53 @@ fail: return res; } +static void drop_privileges() { + if (prctl(PR_SET_KEEPCAPS, 1) < 0) { + ALOGE("prctl(PR_SET_KEEPCAPS) failed: %s\n", strerror(errno)); + exit(1); + } + + if (setgid(AID_INSTALL) < 0) { + ALOGE("setgid() can't drop privileges; exiting.\n"); + exit(1); + } + + if (setuid(AID_INSTALL) < 0) { + ALOGE("setuid() can't drop privileges; exiting.\n"); + exit(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_DAC_OVERRIDE)].permitted |= CAP_TO_MASK(CAP_DAC_OVERRIDE); + capdata[CAP_TO_INDEX(CAP_CHOWN)].permitted |= CAP_TO_MASK(CAP_CHOWN); + capdata[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID); + capdata[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID); + + capdata[0].effective = capdata[0].permitted; + capdata[1].effective = capdata[1].permitted; + capdata[0].inheritable = 0; + capdata[1].inheritable = 0; + + if (capset(&capheader, &capdata[0]) < 0) { + ALOGE("capset failed: %s\n", strerror(errno)); + exit(1); + } +} + int main(const int argc, const char *argv[]) { char buf[BUFFER_MAX]; struct sockaddr addr; socklen_t alen; int lsocket, s, count; + ALOGI("installd firing up\n"); + if (initialize_globals() < 0) { ALOGE("Could not initialize globals; exiting.\n"); exit(1); @@ -507,6 +551,8 @@ int main(const int argc, const char *argv[]) { exit(1); } + drop_privileges(); + lsocket = android_get_control_socket(SOCKET_PATH); if (lsocket < 0) { ALOGE("Failed to get socket from environment: %s\n", strerror(errno)); |