#include <errno.h>
#include <paths.h>
#include <sys/personality.h>
+#include <sys/mount.h>
+#include <linux/fs.h>
#include <cutils/sched_policy.h>
+#include <cutils/multiuser.h>
+#include <sched.h>
+
+#include <private/android_filesystem_config.h>
#if defined(HAVE_PRCTL)
# include <sys/prctl.h>
DEBUG_ENABLE_JNI_LOGGING = 1 << 4,
};
+/* must match values in dalvik.system.Zygote */
+enum {
+ MOUNT_EXTERNAL_NONE = 0,
+ MOUNT_EXTERNAL_SINGLEUSER = 1,
+ MOUNT_EXTERNAL_MULTIUSER = 2,
+};
+
/*
* This signal handler is for zygote mode, since the zygote
* must reap its children
return 0;
}
+/*
+ * Create private mount space for this process and mount SD card
+ * into it, based on active user.
+ */
+static int mountExternalStorage(uid_t uid, u4 mountExternal) {
+ userid_t userid = multiuser_getUserId(uid);
+
+ // Create private mount namespace for our process
+ if (unshare(CLONE_NEWNS) == -1) {
+ SLOGE("Failed to unshare(): %s", strerror(errno));
+ return -1;
+ }
+
+ // Mark rootfs as being a slave in our process so that changes
+ // from parent namespace flow into our process.
+ if (mount("rootfs", "/", NULL, (MS_SLAVE | MS_REC), NULL) == -1) {
+ SLOGE("Failed to mount() rootfs as MS_SLAVE: %s", strerror(errno));
+ return -1;
+ }
+
+ // Create bind mount from specific path
+ if (mountExternal == MOUNT_EXTERNAL_SINGLEUSER) {
+ if (mount(EXTERNAL_STORAGE_SYSTEM, EXTERNAL_STORAGE_APP, "none", MS_BIND, NULL) == -1) {
+ SLOGE("Failed to mount() from %s: %s", EXTERNAL_STORAGE_SYSTEM, strerror(errno));
+ return -1;
+ }
+
+ } else if (mountExternal == MOUNT_EXTERNAL_MULTIUSER) {
+ // Assume path has already been created by installd
+ std::string source_path(StringPrintf("%s/%d", EXTERNAL_STORAGE_SYSTEM, userid));
+ if (mount(source_path.c_str(), EXTERNAL_STORAGE_APP, "none", MS_BIND, NULL) == -1) {
+ SLOGE("Failed to mount() from %s: %s", source_path.c_str(), strerror(errno));
+ return -1;
+ }
+
+ } else {
+ SLOGE("Mount mode %d unsupported", mountExternal);
+ return -1;
+ }
+
+ return 0;
+}
+
/* native public static int fork(); */
static void Dalvik_dalvik_system_Zygote_fork(const u4* args, JValue* pResult)
{
ArrayObject* gids = (ArrayObject *)args[2];
u4 debugFlags = args[3];
ArrayObject *rlimits = (ArrayObject *)args[4];
+ u4 mountExternal = MOUNT_EXTERNAL_NONE;
int64_t permittedCapabilities, effectiveCapabilities;
#ifdef HAVE_SELINUX
char *seInfo = NULL;
permittedCapabilities = args[5] | (int64_t) args[6] << 32;
effectiveCapabilities = args[7] | (int64_t) args[8] << 32;
} else {
+ mountExternal = args[5];
permittedCapabilities = effectiveCapabilities = 0;
#ifdef HAVE_SELINUX
- StringObject* seInfoObj = (StringObject*)args[5];
+ StringObject* seInfoObj = (StringObject*)args[6];
if (seInfoObj) {
seInfo = dvmCreateCstrFromString(seInfoObj);
if (!seInfo) {
dvmAbort();
}
}
- StringObject* niceNameObj = (StringObject*)args[6];
+ StringObject* niceNameObj = (StringObject*)args[7];
if (niceNameObj) {
niceName = dvmCreateCstrFromString(niceNameObj);
if (!niceName) {
#endif /* HAVE_ANDROID_OS */
- err = setgroupsIntarray(gids);
+ if (mountExternal != MOUNT_EXTERNAL_NONE) {
+ err = mountExternalStorage(uid, mountExternal);
+ if (err < 0) {
+ ALOGE("cannot mountExternalStorage(): %s", strerror(errno));
+ dvmAbort();
+ }
+ }
+ err = setgroupsIntarray(gids);
if (err < 0) {
ALOGE("cannot setgroups(): %s", strerror(errno));
dvmAbort();
}
err = setrlimitsFromArray(rlimits);
-
if (err < 0) {
ALOGE("cannot setrlimit(): %s", strerror(errno));
dvmAbort();
return pid;
}
-/* native public static int forkAndSpecialize(int uid, int gid,
- * int[] gids, int debugFlags, String seInfo, String niceName);
+/*
+ * native public static int nativeForkAndSpecialize(int uid, int gid,
+ * int[] gids, int debugFlags, int[][] rlimits, int mountExternal,
+ * String seInfo, String niceName);
*/
static void Dalvik_dalvik_system_Zygote_forkAndSpecialize(const u4* args,
JValue* pResult)
RETURN_INT(pid);
}
-/* native public static int forkSystemServer(int uid, int gid,
- * int[] gids, int debugFlags, long permittedCapabilities,
- * long effectiveCapabilities);
+/*
+ * native public static int nativeForkSystemServer(int uid, int gid,
+ * int[] gids, int debugFlags, int[][] rlimits,
+ * long permittedCapabilities, long effectiveCapabilities);
*/
static void Dalvik_dalvik_system_Zygote_forkSystemServer(
const u4* args, JValue* pResult)
const DalvikNativeMethod dvm_dalvik_system_Zygote[] = {
{ "nativeFork", "()I",
Dalvik_dalvik_system_Zygote_fork },
- { "nativeForkAndSpecialize", "(II[II[[ILjava/lang/String;Ljava/lang/String;)I",
+ { "nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;)I",
Dalvik_dalvik_system_Zygote_forkAndSpecialize },
{ "nativeForkSystemServer", "(II[II[[IJJ)I",
Dalvik_dalvik_system_Zygote_forkSystemServer },