Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e986bc4c authored by Ricky Wai's avatar Ricky Wai
Browse files

Apply app data isolation on isolated or app zygote processes

Fix: 158088415
Test: atest AppDataIsolationTests
Change-Id: Ic55464397039645938822ac20eb12e375bbe4a72
parent 3b648e41
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -1318,15 +1318,15 @@ public class ZygoteProcess {

        Process.ProcessStartResult result;
        try {
            // As app zygote is for generating isolated process, at the end it can't access
            // apps data, so doesn't need to its data info.
            // We will bind mount app data dirs so app zygote can't access /data/data, while
            // we don't need to bind mount storage dirs as /storage won't be mounted.
            result = startViaZygote(processClass, niceName, uid, gid,
                    gids, runtimeFlags, 0 /* mountExternal */, 0 /* targetSdkVersion */, seInfo,
                    abi, instructionSet, null /* appDataDir */, null /* invokeWith */,
                    true /* startChildZygote */, null /* packageName */,
                    ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS /* zygotePolicyFlags */, false /* isTopApp */,
                    null /* disabledCompatChanges */, null /* pkgDataInfoMap */,
                    null /* whitelistedDataInfoMap */, false /* bindMountAppsData*/,
                    null /* whitelistedDataInfoMap */, true /* bindMountAppsData*/,
                    /* bindMountAppStorageDirs */ false, extraArgs);

        } catch (ZygoteStartFailedEx ex) {
+8 −15
Original line number Diff line number Diff line
@@ -1351,7 +1351,13 @@ static void isolateAppData(JNIEnv* env, const std::vector<std::string>& merged_d
  }
  closedir(dir);

  bool legacySymlinkCreated = false;
  // Prepare default dirs for user 0 as user 0 always exists.
  int result = symlink("/data/data", "/data/user/0");
  if (result != 0) {
    fail_fn(CREATE_ERROR("Failed to create symlink /data/user/0 %s", strerror(errno)));
  }
  PrepareDirIfNotPresent("/data/user_de/0", DEFAULT_DATA_DIR_PERMISSION,
      AID_ROOT, AID_ROOT, fail_fn);

  for (int i = 0; i < size; i += 3) {
    std::string const & packageName = merged_data_info_list[i];
@@ -1392,17 +1398,8 @@ static void isolateAppData(JNIEnv* env, const std::vector<std::string>& merged_d
      char internalDeUserPath[PATH_MAX];
      snprintf(internalCeUserPath, PATH_MAX, "/data/user/%d", userId);
      snprintf(internalDeUserPath, PATH_MAX, "/data/user_de/%d", userId);
      // If it's user 0, create a symlink /data/user/0 -> /data/data,
      // otherwise create /data/user/$USER
      // If it's not user 0, create /data/user/$USER.
      if (userId == 0) {
        if (!legacySymlinkCreated) {
          legacySymlinkCreated = true;
          int result = symlink(internalLegacyCePath, internalCeUserPath);
          if (result != 0) {
             fail_fn(CREATE_ERROR("Failed to create symlink %s %s", internalCeUserPath,
              strerror(errno)));
          }
        }
        actualCePath = internalLegacyCePath;
      } else {
        PrepareDirIfNotPresent(internalCeUserPath, DEFAULT_DATA_DIR_PERMISSION,
@@ -1579,10 +1576,6 @@ static void BindMountStorageDirs(JNIEnv* env, jobjectArray pkg_data_info_list,
  // Fuse is ready, so we can start using fuse path.
  int size = (pkg_data_info_list != nullptr) ? env->GetArrayLength(pkg_data_info_list) : 0;

  if (size == 0) {
    fail_fn(CREATE_ERROR("Data package list cannot be empty"));
  }

  // Create tmpfs on Android/obb and Android/data so these 2 dirs won't enter fuse anymore.
  std::string androidObbDir = StringPrintf("/storage/emulated/%d/Android/obb", user_id);
  MountAppDataTmpFs(androidObbDir, fail_fn);
+12 −4
Original line number Diff line number Diff line
@@ -2214,11 +2214,11 @@ public final class ProcessList {
                app.setHasForegroundActivities(true);
            }

            final Map<String, Pair<String, Long>> pkgDataInfoMap;
            final Map<String, Pair<String, Long>> whitelistedAppDataInfoMap;
            Map<String, Pair<String, Long>> pkgDataInfoMap;
            Map<String, Pair<String, Long>> whitelistedAppDataInfoMap;
            boolean bindMountAppStorageDirs = false;
            boolean bindMountAppsData = mAppDataIsolationEnabled
                    && UserHandle.isApp(app.uid)
                    && (UserHandle.isApp(app.uid) || UserHandle.isIsolated(app.uid))
                    && mPlatformCompat.isChangeEnabled(APP_DATA_DIRECTORY_ISOLATION, app.info);

            // Get all packages belongs to the same shared uid. sharedPackages is empty array
@@ -2266,6 +2266,13 @@ public final class ProcessList {
                }
            }

            // If it's an isolated process, it should not even mount its own app data directories,
            // since it has no access to them anyway.
            if (app.isolated) {
                pkgDataInfoMap = null;
                whitelistedAppDataInfoMap = null;
            }

            final Process.ProcessStartResult startResult;
            if (hostingRecord.usesWebviewZygote()) {
                startResult = startWebView(entryPoint,
@@ -2276,13 +2283,14 @@ public final class ProcessList {
            } else if (hostingRecord.usesAppZygote()) {
                final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);

                // We can't isolate app data and storage data as parent zygote already did that.
                startResult = appZygote.getProcess().start(entryPoint,
                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, null, app.info.packageName,
                        /*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,
                        app.mDisabledCompatChanges, pkgDataInfoMap, whitelistedAppDataInfoMap,
                        bindMountAppsData, bindMountAppStorageDirs,
                        false, false,
                        new String[]{PROC_START_SEQ_IDENT + app.startSeq});
            } else {
                startResult = Process.start(entryPoint,