summaryrefslogtreecommitdiffstats
path: root/cmds
diff options
context:
space:
mode:
authorNick Kralevich <nnk@google.com>2012-08-31 16:08:06 -0700
committerNick Kralevich <nnk@google.com>2012-09-04 14:58:22 -0700
commit812b19a425b8304ac9e5408cc8ceb9f363c72559 (patch)
tree6463a4310d8e3f715988788833bfa51e6ea62689 /cmds
parente94831e5ed4aa3b1ebc5444cc1b16cdab8cb92f8 (diff)
downloadframeworks_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.c23
-rw-r--r--cmds/installd/installd.c46
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));