Set capabilities sooner.
Bug 3135433.
Change-Id: I22fde728bd5d65774f8fdf1fa45956fe18358c4c
diff --git a/vm/native/dalvik_system_Zygote.c b/vm/native/dalvik_system_Zygote.c
index c762f51..bcc2313 100644
--- a/vm/native/dalvik_system_Zygote.c
+++ b/vm/native/dalvik_system_Zygote.c
@@ -324,9 +324,37 @@
}
/*
+ * Set Linux capability flags.
+ *
+ * Returns 0 on success, errno on failure.
+ */
+static int setCapabilities(int64_t permitted, int64_t effective)
+{
+#ifdef HAVE_ANDROID_OS
+ struct __user_cap_header_struct capheader;
+ struct __user_cap_data_struct capdata;
+
+ memset(&capheader, 0, sizeof(capheader));
+ memset(&capdata, 0, sizeof(capdata));
+
+ capheader.version = _LINUX_CAPABILITY_VERSION;
+ capheader.pid = 0;
+
+ capdata.effective = effective;
+ capdata.permitted = permitted;
+
+ LOGV("CAPSET perm=%llx eff=%llx\n", permitted, effective);
+ if (capset(&capheader, &capdata) != 0)
+ return errno;
+#endif /*HAVE_ANDROID_OS*/
+
+ return 0;
+}
+
+/*
* Utility routine to fork zygote and specialize the child process.
*/
-static pid_t forkAndSpecializeCommon(const u4* args)
+static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer)
{
pid_t pid;
@@ -335,6 +363,21 @@
ArrayObject* gids = (ArrayObject *)args[2];
u4 debugFlags = args[3];
ArrayObject *rlimits = (ArrayObject *)args[4];
+ int64_t permittedCapabilities, effectiveCapabilities;
+
+ if (isSystemServer) {
+ /*
+ * Don't use GET_ARG_LONG here for now. gcc is generating code
+ * that uses register d8 as a temporary, and that's coming out
+ * scrambled in the child process. b/3138621
+ */
+ //permittedCapabilities = GET_ARG_LONG(args, 5);
+ //effectiveCapabilities = GET_ARG_LONG(args, 7);
+ permittedCapabilities = args[5] | (int64_t) args[6] << 32;
+ effectiveCapabilities = args[7] | (int64_t) args[8] << 32;
+ } else {
+ permittedCapabilities = effectiveCapabilities = 0;
+ }
if (!gDvm.zygote) {
dvmThrowException("Ljava/lang/IllegalStateException;",
@@ -399,6 +442,13 @@
dvmAbort();
}
+ err = setCapabilities(permittedCapabilities, effectiveCapabilities);
+ if (err != 0) {
+ LOGE("cannot set capabilities (%llx,%llx): %s\n",
+ permittedCapabilities, effectiveCapabilities, strerror(err));
+ dvmAbort();
+ }
+
/*
* Our system thread ID has changed. Get the new one.
*/
@@ -429,19 +479,20 @@
{
pid_t pid;
- pid = forkAndSpecializeCommon(args);
+ pid = forkAndSpecializeCommon(args, false);
RETURN_INT(pid);
}
/* native public static int forkSystemServer(int uid, int gid,
- * int[] gids, int debugFlags);
+ * int[] gids, int debugFlags, long permittedCapabilities,
+ * long effectiveCapabilities);
*/
static void Dalvik_dalvik_system_Zygote_forkSystemServer(
const u4* args, JValue* pResult)
{
pid_t pid;
- pid = forkAndSpecializeCommon(args);
+ pid = forkAndSpecializeCommon(args, true);
/* The zygote process checks whether the child process has died or not. */
if (pid > 0) {
@@ -466,7 +517,7 @@
Dalvik_dalvik_system_Zygote_fork },
{ "forkAndSpecialize", "(II[II[[I)I",
Dalvik_dalvik_system_Zygote_forkAndSpecialize },
- { "forkSystemServer", "(II[II[[I)I",
+ { "forkSystemServer", "(II[II[[IJJ)I",
Dalvik_dalvik_system_Zygote_forkSystemServer },
{ NULL, NULL, NULL },
};