Skip to content

Commit 0116136

Browse files
nickkralAndroid (Google) Code Review
authored andcommitted
Merge "installd: reduce privileges." into jb-mr1-dev
2 parents 2ecaedd + 812b19a commit 0116136

File tree

2 files changed

+63
-6
lines changed

2 files changed

+63
-6
lines changed

cmds/installd/commands.c

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
** limitations under the License.
1515
*/
1616

17+
#include <linux/capability.h>
1718
#include "installd.h"
1819
#include <diskusage/dirsize.h>
1920

@@ -665,16 +666,16 @@ int dexopt(const char *apk_path, uid_t uid, int is_public)
665666
ALOGE("dexopt cannot open '%s' for output\n", dex_path);
666667
goto fail;
667668
}
668-
if (fchown(odex_fd, AID_SYSTEM, uid) < 0) {
669-
ALOGE("dexopt cannot chown '%s'\n", dex_path);
670-
goto fail;
671-
}
672669
if (fchmod(odex_fd,
673670
S_IRUSR|S_IWUSR|S_IRGRP |
674671
(is_public ? S_IROTH : 0)) < 0) {
675672
ALOGE("dexopt cannot chmod '%s'\n", dex_path);
676673
goto fail;
677674
}
675+
if (fchown(odex_fd, AID_SYSTEM, uid) < 0) {
676+
ALOGE("dexopt cannot chown '%s'\n", dex_path);
677+
goto fail;
678+
}
678679

679680
ALOGV("DexInv: --- BEGIN '%s' ---\n", apk_path);
680681

@@ -690,13 +691,23 @@ int dexopt(const char *apk_path, uid_t uid, int is_public)
690691
ALOGE("setuid(%d) during dexopt\n", uid);
691692
exit(65);
692693
}
694+
// drop capabilities
695+
struct __user_cap_header_struct capheader;
696+
struct __user_cap_data_struct capdata[2];
697+
memset(&capheader, 0, sizeof(capheader));
698+
memset(&capdata, 0, sizeof(capdata));
699+
capheader.version = _LINUX_CAPABILITY_VERSION_3;
700+
if (capset(&capheader, &capdata[0]) < 0) {
701+
ALOGE("capset failed: %s\n", strerror(errno));
702+
exit(66);
703+
}
693704
if (flock(odex_fd, LOCK_EX | LOCK_NB) != 0) {
694705
ALOGE("flock(%s) failed: %s\n", dex_path, strerror(errno));
695-
exit(66);
706+
exit(67);
696707
}
697708

698709
run_dexopt(zip_fd, odex_fd, apk_path, dexopt_flags);
699-
exit(67); /* only get here on exec failure */
710+
exit(68); /* only get here on exec failure */
700711
} else {
701712
res = wait_dexopt(pid, apk_path);
702713
if (res != 0) {

cmds/installd/installd.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
** limitations under the License.
1515
*/
1616

17+
#include <linux/capability.h>
18+
#include <linux/prctl.h>
19+
1720
#include "installd.h"
1821

1922

@@ -491,12 +494,53 @@ int initialize_directories() {
491494
return res;
492495
}
493496

497+
static void drop_privileges() {
498+
if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
499+
ALOGE("prctl(PR_SET_KEEPCAPS) failed: %s\n", strerror(errno));
500+
exit(1);
501+
}
502+
503+
if (setgid(AID_INSTALL) < 0) {
504+
ALOGE("setgid() can't drop privileges; exiting.\n");
505+
exit(1);
506+
}
507+
508+
if (setuid(AID_INSTALL) < 0) {
509+
ALOGE("setuid() can't drop privileges; exiting.\n");
510+
exit(1);
511+
}
512+
513+
struct __user_cap_header_struct capheader;
514+
struct __user_cap_data_struct capdata[2];
515+
memset(&capheader, 0, sizeof(capheader));
516+
memset(&capdata, 0, sizeof(capdata));
517+
capheader.version = _LINUX_CAPABILITY_VERSION_3;
518+
capheader.pid = 0;
519+
520+
capdata[CAP_TO_INDEX(CAP_DAC_OVERRIDE)].permitted |= CAP_TO_MASK(CAP_DAC_OVERRIDE);
521+
capdata[CAP_TO_INDEX(CAP_CHOWN)].permitted |= CAP_TO_MASK(CAP_CHOWN);
522+
capdata[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
523+
capdata[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
524+
525+
capdata[0].effective = capdata[0].permitted;
526+
capdata[1].effective = capdata[1].permitted;
527+
capdata[0].inheritable = 0;
528+
capdata[1].inheritable = 0;
529+
530+
if (capset(&capheader, &capdata[0]) < 0) {
531+
ALOGE("capset failed: %s\n", strerror(errno));
532+
exit(1);
533+
}
534+
}
535+
494536
int main(const int argc, const char *argv[]) {
495537
char buf[BUFFER_MAX];
496538
struct sockaddr addr;
497539
socklen_t alen;
498540
int lsocket, s, count;
499541

542+
ALOGI("installd firing up\n");
543+
500544
if (initialize_globals() < 0) {
501545
ALOGE("Could not initialize globals; exiting.\n");
502546
exit(1);
@@ -507,6 +551,8 @@ int main(const int argc, const char *argv[]) {
507551
exit(1);
508552
}
509553

554+
drop_privileges();
555+
510556
lsocket = android_get_control_socket(SOCKET_PATH);
511557
if (lsocket < 0) {
512558
ALOGE("Failed to get socket from environment: %s\n", strerror(errno));

0 commit comments

Comments
 (0)