Merge "Revert "Revert "Do not mount whitelisted package in storage data and obb dirs""" into rvc-dev

This commit is contained in:
TreeHugger Robot
2020-04-08 14:48:39 +00:00
committed by Android (Google) Code Review
8 changed files with 211 additions and 93 deletions

View File

@@ -607,6 +607,9 @@ public class Process {
* started. * started.
* @param pkgDataInfoMap Map from related package names to private data directory * @param pkgDataInfoMap Map from related package names to private data directory
* volume UUID and inode number. * volume UUID and inode number.
* @param whitelistedDataInfoMap Map from whitelisted package names to private data directory
* volume UUID and inode number.
* @param bindMountAppsData whether zygote needs to mount CE and DE data.
* @param bindMountAppStorageDirs whether zygote needs to mount Android/obb and Android/data. * @param bindMountAppStorageDirs whether zygote needs to mount Android/obb and Android/data.
* @param zygoteArgs Additional arguments to supply to the zygote process. * @param zygoteArgs Additional arguments to supply to the zygote process.
* @return An object that describes the result of the attempt to start the process. * @return An object that describes the result of the attempt to start the process.
@@ -631,13 +634,17 @@ public class Process {
@Nullable long[] disabledCompatChanges, @Nullable long[] disabledCompatChanges,
@Nullable Map<String, Pair<String, Long>> @Nullable Map<String, Pair<String, Long>>
pkgDataInfoMap, pkgDataInfoMap,
@Nullable Map<String, Pair<String, Long>>
whitelistedDataInfoMap,
boolean bindMountAppsData,
boolean bindMountAppStorageDirs, boolean bindMountAppStorageDirs,
@Nullable String[] zygoteArgs) { @Nullable String[] zygoteArgs) {
return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids, return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo, runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, packageName, abi, instructionSet, appDataDir, invokeWith, packageName,
zygotePolicyFlags, isTopApp, disabledCompatChanges, zygotePolicyFlags, isTopApp, disabledCompatChanges,
pkgDataInfoMap, bindMountAppStorageDirs, zygoteArgs); pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData,
bindMountAppStorageDirs, zygoteArgs);
} }
/** @hide */ /** @hide */
@@ -661,7 +668,8 @@ public class Process {
runtimeFlags, mountExternal, targetSdkVersion, seInfo, runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, packageName, abi, instructionSet, appDataDir, invokeWith, packageName,
/*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, /*isTopApp=*/ false, /*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, /*isTopApp=*/ false,
disabledCompatChanges, /* pkgDataInfoMap */ null, false, zygoteArgs); disabledCompatChanges, /* pkgDataInfoMap */ null,
/* whitelistedDataInfoMap */ null, false, false, zygoteArgs);
} }
/** /**

View File

@@ -333,6 +333,9 @@ public class ZygoteProcess {
* started. * started.
* @param pkgDataInfoMap Map from related package names to private data directory * @param pkgDataInfoMap Map from related package names to private data directory
* volume UUID and inode number. * volume UUID and inode number.
* @param whitelistedDataInfoMap Map from whitelisted package names to private data directory
* volume UUID and inode number.
* @param bindMountAppsData whether zygote needs to mount CE and DE data.
* @param bindMountAppStorageDirs whether zygote needs to mount Android/obb and Android/data. * @param bindMountAppStorageDirs whether zygote needs to mount Android/obb and Android/data.
* *
* @param zygoteArgs Additional arguments to supply to the Zygote process. * @param zygoteArgs Additional arguments to supply to the Zygote process.
@@ -355,6 +358,9 @@ public class ZygoteProcess {
@Nullable long[] disabledCompatChanges, @Nullable long[] disabledCompatChanges,
@Nullable Map<String, Pair<String, Long>> @Nullable Map<String, Pair<String, Long>>
pkgDataInfoMap, pkgDataInfoMap,
@Nullable Map<String, Pair<String, Long>>
whitelistedDataInfoMap,
boolean bindMountAppsData,
boolean bindMountAppStorageDirs, boolean bindMountAppStorageDirs,
@Nullable String[] zygoteArgs) { @Nullable String[] zygoteArgs) {
// TODO (chriswailes): Is there a better place to check this value? // TODO (chriswailes): Is there a better place to check this value?
@@ -367,7 +373,8 @@ public class ZygoteProcess {
runtimeFlags, mountExternal, targetSdkVersion, seInfo, runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false, abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges, packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges,
pkgDataInfoMap, bindMountAppStorageDirs, zygoteArgs); pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData,
bindMountAppStorageDirs, zygoteArgs);
} catch (ZygoteStartFailedEx ex) { } catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG, Log.e(LOG_TAG,
"Starting VM process through Zygote failed"); "Starting VM process through Zygote failed");
@@ -608,6 +615,9 @@ public class ZygoteProcess {
* @param disabledCompatChanges a list of disabled compat changes for the process being started. * @param disabledCompatChanges a list of disabled compat changes for the process being started.
* @param pkgDataInfoMap Map from related package names to private data directory volume UUID * @param pkgDataInfoMap Map from related package names to private data directory volume UUID
* and inode number. * and inode number.
* @param whitelistedDataInfoMap Map from whitelisted package names to private data directory
* volume UUID and inode number.
* @param bindMountAppsData whether zygote needs to mount CE and DE data.
* @param bindMountAppStorageDirs whether zygote needs to mount Android/obb and Android/data. * @param bindMountAppStorageDirs whether zygote needs to mount Android/obb and Android/data.
* @param extraArgs Additional arguments to supply to the zygote process. * @param extraArgs Additional arguments to supply to the zygote process.
* @return An object that describes the result of the attempt to start the process. * @return An object that describes the result of the attempt to start the process.
@@ -631,6 +641,9 @@ public class ZygoteProcess {
@Nullable long[] disabledCompatChanges, @Nullable long[] disabledCompatChanges,
@Nullable Map<String, Pair<String, Long>> @Nullable Map<String, Pair<String, Long>>
pkgDataInfoMap, pkgDataInfoMap,
@Nullable Map<String, Pair<String, Long>>
whitelistedDataInfoMap,
boolean bindMountAppsData,
boolean bindMountAppStorageDirs, boolean bindMountAppStorageDirs,
@Nullable String[] extraArgs) @Nullable String[] extraArgs)
throws ZygoteStartFailedEx { throws ZygoteStartFailedEx {
@@ -728,11 +741,33 @@ public class ZygoteProcess {
} }
argsForZygote.add(sb.toString()); argsForZygote.add(sb.toString());
} }
if (whitelistedDataInfoMap != null && whitelistedDataInfoMap.size() > 0) {
StringBuilder sb = new StringBuilder();
sb.append(Zygote.WHITELISTED_DATA_INFO_MAP);
sb.append("=");
boolean started = false;
for (Map.Entry<String, Pair<String, Long>> entry : whitelistedDataInfoMap.entrySet()) {
if (started) {
sb.append(',');
}
started = true;
sb.append(entry.getKey());
sb.append(',');
sb.append(entry.getValue().first);
sb.append(',');
sb.append(entry.getValue().second);
}
argsForZygote.add(sb.toString());
}
if (bindMountAppStorageDirs) { if (bindMountAppStorageDirs) {
argsForZygote.add(Zygote.BIND_MOUNT_APP_STORAGE_DIRS); argsForZygote.add(Zygote.BIND_MOUNT_APP_STORAGE_DIRS);
} }
if (bindMountAppsData) {
argsForZygote.add(Zygote.BIND_MOUNT_APP_DATA_DIRS);
}
if (disabledCompatChanges != null && disabledCompatChanges.length > 0) { if (disabledCompatChanges != null && disabledCompatChanges.length > 0) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("--disabled-compat-changes="); sb.append("--disabled-compat-changes=");
@@ -1291,6 +1326,7 @@ public class ZygoteProcess {
true /* startChildZygote */, null /* packageName */, true /* startChildZygote */, null /* packageName */,
ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS /* zygotePolicyFlags */, false /* isTopApp */, ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS /* zygotePolicyFlags */, false /* isTopApp */,
null /* disabledCompatChanges */, null /* pkgDataInfoMap */, null /* disabledCompatChanges */, null /* pkgDataInfoMap */,
null /* whitelistedDataInfoMap */, false /* bindMountAppsData*/,
/* bindMountAppStorageDirs */ false, extraArgs); /* bindMountAppStorageDirs */ false, extraArgs);
} catch (ZygoteStartFailedEx ex) { } catch (ZygoteStartFailedEx ex) {

View File

@@ -205,9 +205,15 @@ public final class Zygote {
/** List of packages with the same uid, and its app data info: volume uuid and inode. */ /** List of packages with the same uid, and its app data info: volume uuid and inode. */
public static final String PKG_DATA_INFO_MAP = "--pkg-data-info-map"; public static final String PKG_DATA_INFO_MAP = "--pkg-data-info-map";
/** List of whitelisted packages and its app data info: volume uuid and inode. */
public static final String WHITELISTED_DATA_INFO_MAP = "--whitelisted-data-info-map";
/** Bind mount app storage dirs to lower fs not via fuse */ /** Bind mount app storage dirs to lower fs not via fuse */
public static final String BIND_MOUNT_APP_STORAGE_DIRS = "--bind-mount-storage-dirs"; public static final String BIND_MOUNT_APP_STORAGE_DIRS = "--bind-mount-storage-dirs";
/** Bind mount app storage dirs to lower fs not via fuse */
public static final String BIND_MOUNT_APP_DATA_DIRS = "--bind-mount-data-dirs";
/** /**
* An extraArg passed when a zygote process is forking a child-zygote, specifying a name * An extraArg passed when a zygote process is forking a child-zygote, specifying a name
* in the abstract socket namespace. This socket name is what the new child zygote * in the abstract socket namespace. This socket name is what the new child zygote
@@ -313,6 +319,8 @@ public final class Zygote {
* @param isTopApp true if the process is for top (high priority) application. * @param isTopApp true if the process is for top (high priority) application.
* @param pkgDataInfoList A list that stores related packages and its app data * @param pkgDataInfoList A list that stores related packages and its app data
* info: volume uuid and inode. * info: volume uuid and inode.
* @param whitelistedDataInfoList Like pkgDataInfoList, but it's for whitelisted apps.
* @param bindMountAppDataDirs True if the zygote needs to mount data dirs.
* @param bindMountAppStorageDirs True if the zygote needs to mount storage dirs. * @param bindMountAppStorageDirs True if the zygote needs to mount storage dirs.
* *
* @return 0 if this is the child, pid of the child * @return 0 if this is the child, pid of the child
@@ -321,13 +329,15 @@ public final class Zygote {
static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags, static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
boolean isTopApp, String[] pkgDataInfoList, boolean bindMountAppStorageDirs) { boolean isTopApp, String[] pkgDataInfoList, String[] whitelistedDataInfoList,
boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) {
ZygoteHooks.preFork(); ZygoteHooks.preFork();
int pid = nativeForkAndSpecialize( int pid = nativeForkAndSpecialize(
uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp, fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp,
pkgDataInfoList, bindMountAppStorageDirs); pkgDataInfoList, whitelistedDataInfoList, bindMountAppDataDirs,
bindMountAppStorageDirs);
if (pid == 0) { if (pid == 0) {
// Note that this event ends at the end of handleChildProc, // Note that this event ends at the end of handleChildProc,
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork"); Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
@@ -344,6 +354,7 @@ public final class Zygote {
int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet,
String appDataDir, boolean isTopApp, String[] pkgDataInfoList, String appDataDir, boolean isTopApp, String[] pkgDataInfoList,
String[] whitelistedDataInfoList, boolean bindMountAppDataDirs,
boolean bindMountAppStorageDirs); boolean bindMountAppStorageDirs);
/** /**
@@ -371,15 +382,19 @@ public final class Zygote {
* volume uuid and CE dir inode. For example, pkgDataInfoList = [app_a_pkg_name, * volume uuid and CE dir inode. For example, pkgDataInfoList = [app_a_pkg_name,
* app_a_data_volume_uuid, app_a_ce_inode, app_b_pkg_name, app_b_data_volume_uuid, * app_a_data_volume_uuid, app_a_ce_inode, app_b_pkg_name, app_b_data_volume_uuid,
* app_b_ce_inode, ...]; * app_b_ce_inode, ...];
* @param whitelistedDataInfoList Like pkgDataInfoList, but it's for whitelisted apps.
* @param bindMountAppDataDirs True if the zygote needs to mount data dirs.
* @param bindMountAppStorageDirs True if the zygote needs to mount storage dirs. * @param bindMountAppStorageDirs True if the zygote needs to mount storage dirs.
*/ */
private static void specializeAppProcess(int uid, int gid, int[] gids, int runtimeFlags, private static void specializeAppProcess(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[][] rlimits, int mountExternal, String seInfo, String niceName,
boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp, boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp,
String[] pkgDataInfoList, boolean bindMountAppStorageDirs) { String[] pkgDataInfoList, String[] whitelistedDataInfoList,
boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) {
nativeSpecializeAppProcess(uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, nativeSpecializeAppProcess(uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo,
niceName, startChildZygote, instructionSet, appDataDir, isTopApp, niceName, startChildZygote, instructionSet, appDataDir, isTopApp,
pkgDataInfoList, bindMountAppStorageDirs); pkgDataInfoList, whitelistedDataInfoList,
bindMountAppDataDirs, bindMountAppStorageDirs);
// Note that this event ends at the end of handleChildProc. // Note that this event ends at the end of handleChildProc.
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork"); Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
@@ -399,7 +414,8 @@ public final class Zygote {
private static native void nativeSpecializeAppProcess(int uid, int gid, int[] gids, private static native void nativeSpecializeAppProcess(int uid, int gid, int[] gids,
int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp, boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp,
String[] pkgDataInfoList, boolean bindMountAppStorageDirs); String[] pkgDataInfoList, String[] whitelistedDataInfoList,
boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs);
/** /**
* Called to do any initialization before starting an application. * Called to do any initialization before starting an application.
@@ -724,7 +740,8 @@ public final class Zygote {
args.mRuntimeFlags, rlimits, args.mMountExternal, args.mRuntimeFlags, rlimits, args.mMountExternal,
args.mSeInfo, args.mNiceName, args.mStartChildZygote, args.mSeInfo, args.mNiceName, args.mStartChildZygote,
args.mInstructionSet, args.mAppDataDir, args.mIsTopApp, args.mInstructionSet, args.mAppDataDir, args.mIsTopApp,
args.mPkgDataInfoList, args.mBindMountAppStorageDirs); args.mPkgDataInfoList, args.mWhitelistedDataInfoList,
args.mBindMountAppDataDirs, args.mBindMountAppStorageDirs);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

View File

@@ -226,11 +226,22 @@ class ZygoteArguments {
*/ */
String[] mPkgDataInfoList; String[] mPkgDataInfoList;
/**
* A list that stores all whitelisted app data info: volume uuid and inode.
* Null if it does need to do app data isolation.
*/
String[] mWhitelistedDataInfoList;
/** /**
* @see Zygote#BIND_MOUNT_APP_STORAGE_DIRS * @see Zygote#BIND_MOUNT_APP_STORAGE_DIRS
*/ */
boolean mBindMountAppStorageDirs; boolean mBindMountAppStorageDirs;
/**
* @see Zygote#BIND_MOUNT_APP_DATA_DIRS
*/
boolean mBindMountAppDataDirs;
/** /**
* Constructs instance and parses args * Constructs instance and parses args
* *
@@ -452,8 +463,12 @@ class ZygoteArguments {
} }
} else if (arg.startsWith(Zygote.PKG_DATA_INFO_MAP)) { } else if (arg.startsWith(Zygote.PKG_DATA_INFO_MAP)) {
mPkgDataInfoList = getAssignmentList(arg); mPkgDataInfoList = getAssignmentList(arg);
} else if (arg.startsWith(Zygote.WHITELISTED_DATA_INFO_MAP)) {
mWhitelistedDataInfoList = getAssignmentList(arg);
} else if (arg.equals(Zygote.BIND_MOUNT_APP_STORAGE_DIRS)) { } else if (arg.equals(Zygote.BIND_MOUNT_APP_STORAGE_DIRS)) {
mBindMountAppStorageDirs = true; mBindMountAppStorageDirs = true;
} else if (arg.equals(Zygote.BIND_MOUNT_APP_DATA_DIRS)) {
mBindMountAppDataDirs = true;
} else { } else {
break; break;
} }

View File

@@ -258,7 +258,8 @@ class ZygoteConnection {
parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo, parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote, parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mIsTopApp, parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mIsTopApp,
parsedArgs.mPkgDataInfoList, parsedArgs.mBindMountAppStorageDirs); parsedArgs.mPkgDataInfoList, parsedArgs.mWhitelistedDataInfoList,
parsedArgs.mBindMountAppDataDirs, parsedArgs.mBindMountAppStorageDirs);
try { try {
if (pid == 0) { if (pid == 0) {

View File

@@ -110,7 +110,6 @@ using android::base::StringAppendF;
using android::base::StringPrintf; using android::base::StringPrintf;
using android::base::WriteStringToFile; using android::base::WriteStringToFile;
using android::base::GetBoolProperty; using android::base::GetBoolProperty;
using android::base::GetProperty;
#define CREATE_ERROR(...) StringPrintf("%s:%d: ", __FILE__, __LINE__). \ #define CREATE_ERROR(...) StringPrintf("%s:%d: ", __FILE__, __LINE__). \
append(StringPrintf(__VA_ARGS__)) append(StringPrintf(__VA_ARGS__))
@@ -170,18 +169,6 @@ static int gSystemServerSocketFd = -1;
static constexpr int DEFAULT_DATA_DIR_PERMISSION = 0751; static constexpr int DEFAULT_DATA_DIR_PERMISSION = 0751;
/**
* Property to control if app data isolation is enabled.
*/
static const std::string ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY =
"persist.zygote.app_data_isolation";
/**
* Property to enable app data isolation for sdcard obb or data in vold.
*/
static const std::string ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY =
"persist.sys.vold_app_data_isolation_enabled";
static constexpr const uint64_t UPPER_HALF_WORD_MASK = 0xFFFF'FFFF'0000'0000; static constexpr const uint64_t UPPER_HALF_WORD_MASK = 0xFFFF'FFFF'0000'0000;
static constexpr const uint64_t LOWER_HALF_WORD_MASK = 0x0000'0000'FFFF'FFFF; static constexpr const uint64_t LOWER_HALF_WORD_MASK = 0x0000'0000'FFFF'FFFF;
@@ -1319,20 +1306,13 @@ static void relabelAllDirs(const char* path, security_context_t context, fail_fn
* be decrypted after storage is decrypted. * be decrypted after storage is decrypted.
* *
*/ */
static void isolateAppData(JNIEnv* env, jobjectArray pkg_data_info_list, static void isolateAppData(JNIEnv* env, const std::vector<std::string>& merged_data_info_list,
uid_t uid, const char* process_name, jstring managed_nice_name, uid_t uid, const char* process_name,
fail_fn_t fail_fn) { jstring managed_nice_name, fail_fn_t fail_fn) {
const userid_t userId = multiuser_get_user_id(uid); const userid_t userId = multiuser_get_user_id(uid);
auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1); int size = merged_data_info_list.size();
int size = (pkg_data_info_list != nullptr) ? env->GetArrayLength(pkg_data_info_list) : 0;
// Size should be a multiple of 3, as it contains list of <package_name, volume_uuid, inode>
if ((size % 3) != 0) {
fail_fn(CREATE_ERROR("Wrong pkg_inode_list size %d", size));
}
ensureInAppMountNamespace(fail_fn);
// Mount tmpfs on all possible data directories, so app no longer see the original apps data. // Mount tmpfs on all possible data directories, so app no longer see the original apps data.
char internalCePath[PATH_MAX]; char internalCePath[PATH_MAX];
@@ -1377,14 +1357,10 @@ static void isolateAppData(JNIEnv* env, jobjectArray pkg_data_info_list,
bool legacySymlinkCreated = false; bool legacySymlinkCreated = false;
for (int i = 0; i < size; i += 3) { for (int i = 0; i < size; i += 3) {
jstring package_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i)); std::string const & packageName = merged_data_info_list[i];
std::string packageName = extract_fn(package_str).value(); std::string const & volUuid = merged_data_info_list[i + 1];
std::string const & inode = merged_data_info_list[i + 2];
jstring vol_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i + 1));
std::string volUuid = extract_fn(vol_str).value();
jstring inode_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i + 2));
std::string inode = extract_fn(inode_str).value();
std::string::size_type sz; std::string::size_type sz;
long long ceDataInode = std::stoll(inode, &sz); long long ceDataInode = std::stoll(inode, &sz);
@@ -1482,6 +1458,48 @@ static void isolateAppData(JNIEnv* env, jobjectArray pkg_data_info_list,
freecon(dataDataContext); freecon(dataDataContext);
} }
static void insertPackagesToMergedList(JNIEnv* env,
std::vector<std::string>& merged_data_info_list,
jobjectArray data_info_list, const char* process_name,
jstring managed_nice_name, fail_fn_t fail_fn) {
auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);
int size = (data_info_list != nullptr) ? env->GetArrayLength(data_info_list) : 0;
// Size should be a multiple of 3, as it contains list of <package_name, volume_uuid, inode>
if ((size % 3) != 0) {
fail_fn(CREATE_ERROR("Wrong data_info_list size %d", size));
}
for (int i = 0; i < size; i += 3) {
jstring package_str = (jstring) (env->GetObjectArrayElement(data_info_list, i));
std::string packageName = extract_fn(package_str).value();
merged_data_info_list.push_back(packageName);
jstring vol_str = (jstring) (env->GetObjectArrayElement(data_info_list, i + 1));
std::string volUuid = extract_fn(vol_str).value();
merged_data_info_list.push_back(volUuid);
jstring inode_str = (jstring) (env->GetObjectArrayElement(data_info_list, i + 2));
std::string inode = extract_fn(inode_str).value();
merged_data_info_list.push_back(inode);
}
}
static void isolateAppData(JNIEnv* env, jobjectArray pkg_data_info_list,
jobjectArray whitelisted_data_info_list, uid_t uid, const char* process_name,
jstring managed_nice_name, fail_fn_t fail_fn) {
ensureInAppMountNamespace(fail_fn);
std::vector<std::string> merged_data_info_list;
insertPackagesToMergedList(env, merged_data_info_list, pkg_data_info_list,
process_name, managed_nice_name, fail_fn);
insertPackagesToMergedList(env, merged_data_info_list, whitelisted_data_info_list,
process_name, managed_nice_name, fail_fn);
isolateAppData(env, merged_data_info_list, uid, process_name, managed_nice_name, fail_fn);
}
/** /**
* Like isolateAppData(), isolate jit profile directories, so apps don't see what * Like isolateAppData(), isolate jit profile directories, so apps don't see what
* other apps are installed by reading content inside /data/misc/profiles/cur. * other apps are installed by reading content inside /data/misc/profiles/cur.
@@ -1594,7 +1612,9 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,
jstring managed_nice_name, bool is_system_server, jstring managed_nice_name, bool is_system_server,
bool is_child_zygote, jstring managed_instruction_set, bool is_child_zygote, jstring managed_instruction_set,
jstring managed_app_data_dir, bool is_top_app, jstring managed_app_data_dir, bool is_top_app,
jobjectArray pkg_data_info_list, bool mount_storage_dirs) { jobjectArray pkg_data_info_list,
jobjectArray whitelisted_data_info_list,
bool mount_data_dirs, bool mount_storage_dirs) {
const char* process_name = is_system_server ? "system_server" : "zygote"; const char* process_name = is_system_server ? "system_server" : "zygote";
auto fail_fn = std::bind(ZygoteFailure, env, process_name, managed_nice_name, _1); auto fail_fn = std::bind(ZygoteFailure, env, process_name, managed_nice_name, _1);
auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1); auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);
@@ -1628,9 +1648,9 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,
// give a null in same_uid_pkgs and private_volumes so they don't need app data isolation. // give a null in same_uid_pkgs and private_volumes so they don't need app data isolation.
// Isolated process / webview / app zygote should be gated by SELinux and file permission // Isolated process / webview / app zygote should be gated by SELinux and file permission
// so they can't even traverse CE / DE directories. // so they can't even traverse CE / DE directories.
if (pkg_data_info_list != nullptr if (mount_data_dirs) {
&& GetBoolProperty(ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY, true)) { isolateAppData(env, pkg_data_info_list, whitelisted_data_info_list,
isolateAppData(env, pkg_data_info_list, uid, process_name, managed_nice_name, fail_fn); uid, process_name, managed_nice_name, fail_fn);
isolateJitProfile(env, pkg_data_info_list, uid, process_name, managed_nice_name, fail_fn); isolateJitProfile(env, pkg_data_info_list, uid, process_name, managed_nice_name, fail_fn);
} }
if ((mount_external != MOUNT_EXTERNAL_INSTALLER) && mount_storage_dirs) { if ((mount_external != MOUNT_EXTERNAL_INSTALLER) && mount_storage_dirs) {
@@ -2003,7 +2023,8 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
jint mount_external, jstring se_info, jstring nice_name, jint mount_external, jstring se_info, jstring nice_name,
jintArray managed_fds_to_close, jintArray managed_fds_to_ignore, jboolean is_child_zygote, jintArray managed_fds_to_close, jintArray managed_fds_to_ignore, jboolean is_child_zygote,
jstring instruction_set, jstring app_data_dir, jboolean is_top_app, jstring instruction_set, jstring app_data_dir, jboolean is_top_app,
jobjectArray pkg_data_info_list, jboolean mount_storage_dirs) { jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list,
jboolean mount_data_dirs, jboolean mount_storage_dirs) {
jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote); jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
if (UNLIKELY(managed_fds_to_close == nullptr)) { if (UNLIKELY(managed_fds_to_close == nullptr)) {
@@ -2041,6 +2062,8 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
mount_external, se_info, nice_name, false, mount_external, se_info, nice_name, false,
is_child_zygote == JNI_TRUE, instruction_set, app_data_dir, is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
is_top_app == JNI_TRUE, pkg_data_info_list, is_top_app == JNI_TRUE, pkg_data_info_list,
whitelisted_data_info_list,
mount_data_dirs == JNI_TRUE,
mount_storage_dirs == JNI_TRUE); mount_storage_dirs == JNI_TRUE);
} }
return pid; return pid;
@@ -2076,7 +2099,8 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer(
permitted_capabilities, effective_capabilities, permitted_capabilities, effective_capabilities,
MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true, MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,
false, nullptr, nullptr, /* is_top_app= */ false, false, nullptr, nullptr, /* is_top_app= */ false,
/* pkg_data_info_list */ nullptr, false); /* pkg_data_info_list */ nullptr,
/* whitelisted_data_info_list */ nullptr, false, false);
} else if (pid > 0) { } else if (pid > 0) {
// The zygote process checks whether the child process has died or not. // The zygote process checks whether the child process has died or not.
ALOGI("System server process %d has been created", pid); ALOGI("System server process %d has been created", pid);
@@ -2206,15 +2230,16 @@ static void com_android_internal_os_Zygote_nativeSpecializeAppProcess(
jint runtime_flags, jobjectArray rlimits, jint runtime_flags, jobjectArray rlimits,
jint mount_external, jstring se_info, jstring nice_name, jint mount_external, jstring se_info, jstring nice_name,
jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app,
jobjectArray pkg_data_info_list, jboolean mount_storage_dirs) { jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list,
jboolean mount_data_dirs, jboolean mount_storage_dirs) {
jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote); jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
capabilities, capabilities, capabilities, capabilities,
mount_external, se_info, nice_name, false, mount_external, se_info, nice_name, false,
is_child_zygote == JNI_TRUE, instruction_set, app_data_dir, is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
is_top_app == JNI_TRUE, pkg_data_info_list, is_top_app == JNI_TRUE, pkg_data_info_list, whitelisted_data_info_list,
mount_storage_dirs == JNI_TRUE); mount_data_dirs == JNI_TRUE, mount_storage_dirs == JNI_TRUE);
} }
/** /**
@@ -2417,7 +2442,7 @@ static jboolean com_android_internal_os_Zygote_nativeSupportsTaggedPointers(JNIE
static const JNINativeMethod gMethods[] = { static const JNINativeMethod gMethods[] = {
{"nativeForkAndSpecialize", {"nativeForkAndSpecialize",
"(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/" "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/"
"String;Z[Ljava/lang/String;Z)I", "String;Z[Ljava/lang/String;[Ljava/lang/String;ZZ)I",
(void*)com_android_internal_os_Zygote_nativeForkAndSpecialize}, (void*)com_android_internal_os_Zygote_nativeForkAndSpecialize},
{"nativeForkSystemServer", "(II[II[[IJJ)I", {"nativeForkSystemServer", "(II[II[[IJJ)I",
(void*)com_android_internal_os_Zygote_nativeForkSystemServer}, (void*)com_android_internal_os_Zygote_nativeForkSystemServer},
@@ -2430,7 +2455,7 @@ static const JNINativeMethod gMethods[] = {
{"nativeForkUsap", "(II[IZ)I", (void*)com_android_internal_os_Zygote_nativeForkUsap}, {"nativeForkUsap", "(II[IZ)I", (void*)com_android_internal_os_Zygote_nativeForkUsap},
{"nativeSpecializeAppProcess", {"nativeSpecializeAppProcess",
"(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/" "(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/"
"String;Z[Ljava/lang/String;Z)V", "String;Z[Ljava/lang/String;[Ljava/lang/String;ZZ)V",
(void*)com_android_internal_os_Zygote_nativeSpecializeAppProcess}, (void*)com_android_internal_os_Zygote_nativeSpecializeAppProcess},
{"nativeInitNativeState", "(Z)V", {"nativeInitNativeState", "(Z)V",
(void*)com_android_internal_os_Zygote_nativeInitNativeState}, (void*)com_android_internal_os_Zygote_nativeInitNativeState},

View File

@@ -4468,9 +4468,8 @@ class StorageManagerService extends IStorageManager.Stub
String.format("/storage/emulated/%d/Android/data/%s/", String.format("/storage/emulated/%d/Android/data/%s/",
userId, pkg); userId, pkg);
int appUid =
UserHandle.getUid(userId, mPmInternal.getPackage(pkg).getUid());
// Create package obb and data dir if it doesn't exist. // Create package obb and data dir if it doesn't exist.
int appUid = UserHandle.getUid(userId, mPmInternal.getPackage(pkg).getUid());
File file = new File(packageObbDir); File file = new File(packageObbDir);
if (!file.exists()) { if (!file.exists()) {
vold.setupAppDir(packageObbDir, appUid); vold.setupAppDir(packageObbDir, appUid);

View File

@@ -97,6 +97,7 @@ import android.os.storage.StorageManagerInternal;
import android.system.Os; import android.system.Os;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.EventLog; import android.util.EventLog;
import android.util.LongSparseArray; import android.util.LongSparseArray;
import android.util.Pair; import android.util.Pair;
@@ -137,6 +138,7 @@ import java.util.BitSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* Activity manager code dealing with processes. * Activity manager code dealing with processes.
@@ -2129,18 +2131,11 @@ public final class ProcessList {
for (String packageName : packages) { for (String packageName : packages) {
String volumeUuid = pmInt.getPackage(packageName).getVolumeUuid(); String volumeUuid = pmInt.getPackage(packageName).getVolumeUuid();
long inode = pmInt.getCeDataInode(packageName, userId); long inode = pmInt.getCeDataInode(packageName, userId);
if (inode != 0) { if (inode == 0) {
result.put(packageName, Pair.create(volumeUuid, inode)); Slog.w(TAG, packageName + " inode == 0 (b/152760674)");
} return null;
}
if (mAppDataIsolationWhitelistedApps != null) {
for (String packageName : mAppDataIsolationWhitelistedApps) {
String volumeUuid = pmInt.getPackage(packageName).getVolumeUuid();
long inode = pmInt.getCeDataInode(packageName, userId);
if (inode != 0) {
result.put(packageName, Pair.create(volumeUuid, inode));
}
} }
result.put(packageName, Pair.create(volumeUuid, inode));
} }
return result; return result;
@@ -2162,35 +2157,56 @@ public final class ProcessList {
app.setHasForegroundActivities(true); app.setHasForegroundActivities(true);
} }
final Map<String, Pair<String, Long>> pkgDataInfoMap;
final Map<String, Pair<String, Long>> whitelistedAppDataInfoMap;
boolean bindMountAppStorageDirs = false;
boolean bindMountAppsData = mAppDataIsolationEnabled
&& UserHandle.isApp(app.uid)
&& mPlatformCompat.isChangeEnabled(APP_DATA_DIRECTORY_ISOLATION, app.info);
// Get all packages belongs to the same shared uid. sharedPackages is empty array
// if it doesn't have shared uid.
final PackageManagerInternal pmInt = mService.getPackageManagerInternalLocked();
final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage(
app.info.packageName, app.userId);
final String[] targetPackagesList = sharedPackages.length == 0
? new String[]{app.info.packageName} : sharedPackages;
pkgDataInfoMap = getPackageAppDataInfoMap(pmInt, targetPackagesList, uid);
if (pkgDataInfoMap == null) {
// TODO(b/152760674): Handle inode == 0 case properly, now we just give it a
// tmp free pass.
bindMountAppsData = false;
}
// Remove all packages in pkgDataInfoMap from mAppDataIsolationWhitelistedApps, so
// it won't be mounted twice.
final Set<String> whitelistedApps = new ArraySet<>(mAppDataIsolationWhitelistedApps);
for (String pkg : targetPackagesList) {
whitelistedApps.remove(pkg);
}
whitelistedAppDataInfoMap = getPackageAppDataInfoMap(pmInt,
whitelistedApps.toArray(new String[0]), uid);
if (whitelistedAppDataInfoMap == null) {
// TODO(b/152760674): Handle inode == 0 case properly, now we just give it a
// tmp free pass.
bindMountAppsData = false;
}
int userId = UserHandle.getUserId(uid);
StorageManagerInternal storageManagerInternal = LocalServices.getService( StorageManagerInternal storageManagerInternal = LocalServices.getService(
StorageManagerInternal.class); StorageManagerInternal.class);
final Map<String, Pair<String, Long>> pkgDataInfoMap; if (mVoldAppDataIsolationEnabled && UserHandle.isApp(app.uid)
boolean bindMountAppStorageDirs = false; && !storageManagerInternal.isExternalStorageService(uid)) {
bindMountAppStorageDirs = true;
if (mAppDataIsolationEnabled && UserHandle.isApp(app.uid) if (!storageManagerInternal.prepareStorageDirs(userId, pkgDataInfoMap.keySet(),
&& mPlatformCompat.isChangeEnabled(APP_DATA_DIRECTORY_ISOLATION, app.info)) { app.processName)) {
// Get all packages belongs to the same shared uid. sharedPackages is empty array // Cannot prepare Android/app and Android/obb directory,
// if it doesn't have shared uid. // so we won't mount it in zygote.
final PackageManagerInternal pmInt = mService.getPackageManagerInternalLocked(); app.bindMountPending = true;
final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage( bindMountAppStorageDirs = false;
app.info.packageName, app.userId);
pkgDataInfoMap = getPackageAppDataInfoMap(pmInt, sharedPackages.length == 0
? new String[]{app.info.packageName} : sharedPackages, uid);
int userId = UserHandle.getUserId(uid);
if (mVoldAppDataIsolationEnabled
&& !storageManagerInternal.isExternalStorageService(uid)) {
bindMountAppStorageDirs = true;
if (!storageManagerInternal.prepareStorageDirs(userId, pkgDataInfoMap.keySet(),
app.processName)) {
// Cannot prepare Android/app and Android/obb directory,
// so we won't mount it in zygote.
app.bindMountPending = true;
bindMountAppStorageDirs = false;
}
} }
} else {
pkgDataInfoMap = null;
} }
final Process.ProcessStartResult startResult; final Process.ProcessStartResult startResult;
@@ -2208,7 +2224,8 @@ public final class ProcessList {
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, app.info.packageName, app.info.dataDir, null, app.info.packageName,
/*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp, /*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,
app.mDisabledCompatChanges, pkgDataInfoMap, bindMountAppStorageDirs, app.mDisabledCompatChanges, pkgDataInfoMap, whitelistedAppDataInfoMap,
bindMountAppsData, bindMountAppStorageDirs,
new String[]{PROC_START_SEQ_IDENT + app.startSeq}); new String[]{PROC_START_SEQ_IDENT + app.startSeq});
} else { } else {
startResult = Process.start(entryPoint, startResult = Process.start(entryPoint,
@@ -2216,7 +2233,7 @@ public final class ProcessList {
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags, app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags,
isTopApp, app.mDisabledCompatChanges, pkgDataInfoMap, isTopApp, app.mDisabledCompatChanges, pkgDataInfoMap,
bindMountAppStorageDirs, whitelistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,
new String[]{PROC_START_SEQ_IDENT + app.startSeq}); new String[]{PROC_START_SEQ_IDENT + app.startSeq});
} }
checkSlow(startTime, "startProcess: returned from zygote!"); checkSlow(startTime, "startProcess: returned from zygote!");