diff options
| author | 2021-03-04 21:09:52 +0000 | |
|---|---|---|
| committer | 2021-03-04 21:09:52 +0000 | |
| commit | db6628bb7d6e7ae73ebaffc05eb0480efeb769cf (patch) | |
| tree | 8b9e164f6314437cc65f22e5d243954b7d149914 | |
| parent | 067b3dffa46b340260d44ebb1827c91ba77982d6 (diff) | |
| parent | 074e16404c2b32822bdb8b47c4e3ed35a3ec05af (diff) | |
Merge changes I04ac8fba,Ia0a8548f
* changes:
Autoformatter changes.
Inclusivity cleanup of the Zygote.
| -rw-r--r-- | core/java/android/os/ZygoteProcess.java | 18 | ||||
| -rw-r--r-- | core/java/com/android/internal/os/Zygote.java | 20 | ||||
| -rw-r--r-- | core/java/com/android/internal/os/ZygoteArguments.java | 6 | ||||
| -rw-r--r-- | core/java/com/android/internal/os/ZygoteConnection.java | 2 | ||||
| -rw-r--r-- | core/jni/com_android_internal_os_Zygote.cpp | 469 | ||||
| -rw-r--r-- | core/jni/fd_utils.cpp | 199 | ||||
| -rw-r--r-- | core/jni/fd_utils.h | 44 |
7 files changed, 373 insertions, 385 deletions
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java index 9ffc5aa0022c..bf2898137967 100644 --- a/core/java/android/os/ZygoteProcess.java +++ b/core/java/android/os/ZygoteProcess.java @@ -333,7 +333,7 @@ public class ZygoteProcess { * started. * @param pkgDataInfoMap Map from related package names to private data directory * volume UUID and inode number. - * @param whitelistedDataInfoMap Map from allowlisted package names to private data directory + * @param allowlistedDataInfoList Map from allowlisted 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. @@ -359,7 +359,7 @@ public class ZygoteProcess { @Nullable Map<String, Pair<String, Long>> pkgDataInfoMap, @Nullable Map<String, Pair<String, Long>> - whitelistedDataInfoMap, + allowlistedDataInfoList, boolean bindMountAppsData, boolean bindMountAppStorageDirs, @Nullable String[] zygoteArgs) { @@ -373,7 +373,7 @@ public class ZygoteProcess { runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false, packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges, - pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData, + pkgDataInfoMap, allowlistedDataInfoList, bindMountAppsData, bindMountAppStorageDirs, zygoteArgs); } catch (ZygoteStartFailedEx ex) { Log.e(LOG_TAG, @@ -615,7 +615,7 @@ public class ZygoteProcess { * @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 * and inode number. - * @param whitelistedDataInfoMap Map from allowlisted package names to private data directory + * @param allowlistedDataInfoList Map from allowlisted 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. @@ -642,7 +642,7 @@ public class ZygoteProcess { @Nullable Map<String, Pair<String, Long>> pkgDataInfoMap, @Nullable Map<String, Pair<String, Long>> - whitelistedDataInfoMap, + allowlistedDataInfoList, boolean bindMountAppsData, boolean bindMountAppStorageDirs, @Nullable String[] extraArgs) @@ -733,12 +733,12 @@ public class ZygoteProcess { } argsForZygote.add(sb.toString()); } - if (whitelistedDataInfoMap != null && whitelistedDataInfoMap.size() > 0) { + if (allowlistedDataInfoList != null && allowlistedDataInfoList.size() > 0) { StringBuilder sb = new StringBuilder(); - sb.append(Zygote.WHITELISTED_DATA_INFO_MAP); + sb.append(Zygote.ALLOWLISTED_DATA_INFO_MAP); sb.append("="); boolean started = false; - for (Map.Entry<String, Pair<String, Long>> entry : whitelistedDataInfoMap.entrySet()) { + for (Map.Entry<String, Pair<String, Long>> entry : allowlistedDataInfoList.entrySet()) { if (started) { sb.append(','); } @@ -1318,7 +1318,7 @@ public class ZygoteProcess { true /* startChildZygote */, null /* packageName */, ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS /* zygotePolicyFlags */, false /* isTopApp */, null /* disabledCompatChanges */, null /* pkgDataInfoMap */, - null /* whitelistedDataInfoMap */, true /* bindMountAppsData*/, + null /* allowlistedDataInfoList */, true /* bindMountAppsData*/, /* bindMountAppStorageDirs */ false, extraArgs); } catch (ZygoteStartFailedEx ex) { diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index 1c4e4a2b119e..644e032103b8 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -202,7 +202,7 @@ public final class Zygote { public static final String PKG_DATA_INFO_MAP = "--pkg-data-info-map"; /** List of allowlisted packages and its app data info: volume uuid and inode. */ - public static final String WHITELISTED_DATA_INFO_MAP = "--whitelisted-data-info-map"; + public static final String ALLOWLISTED_DATA_INFO_MAP = "--allowlisted-data-info-map"; /** Bind mount app storage dirs to lower fs not via fuse */ public static final String BIND_MOUNT_APP_STORAGE_DIRS = "--bind-mount-storage-dirs"; @@ -324,7 +324,7 @@ public final class Zygote { * @param isTopApp true if the process is for top (high priority) application. * @param pkgDataInfoList A list that stores related packages and its app data * info: volume uuid and inode. - * @param whitelistedDataInfoList Like pkgDataInfoList, but it's for allowlisted apps. + * @param allowlistedDataInfoList Like pkgDataInfoList, but it's for allowlisted apps. * @param bindMountAppDataDirs True if the zygote needs to mount data dirs. * @param bindMountAppStorageDirs True if the zygote needs to mount storage dirs. * @@ -334,14 +334,14 @@ public final class Zygote { static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir, - boolean isTopApp, String[] pkgDataInfoList, String[] whitelistedDataInfoList, + boolean isTopApp, String[] pkgDataInfoList, String[] allowlistedDataInfoList, boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) { ZygoteHooks.preFork(); int pid = nativeForkAndSpecialize( uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp, - pkgDataInfoList, whitelistedDataInfoList, bindMountAppDataDirs, + pkgDataInfoList, allowlistedDataInfoList, bindMountAppDataDirs, bindMountAppStorageDirs); if (pid == 0) { // Note that this event ends at the end of handleChildProc, @@ -364,7 +364,7 @@ public final class Zygote { int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp, String[] pkgDataInfoList, - String[] whitelistedDataInfoList, boolean bindMountAppDataDirs, + String[] allowlistedDataInfoList, boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs); /** @@ -392,18 +392,18 @@ public final class Zygote { * 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_b_ce_inode, ...]; - * @param whitelistedDataInfoList Like pkgDataInfoList, but it's for allowlisted apps. + * @param allowlistedDataInfoList Like pkgDataInfoList, but it's for allowlisted apps. * @param bindMountAppDataDirs True if the zygote needs to mount data dirs. * @param bindMountAppStorageDirs True if the zygote needs to mount storage dirs. */ private static void specializeAppProcess(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp, - String[] pkgDataInfoList, String[] whitelistedDataInfoList, + String[] pkgDataInfoList, String[] allowlistedDataInfoList, boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) { nativeSpecializeAppProcess(uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, startChildZygote, instructionSet, appDataDir, isTopApp, - pkgDataInfoList, whitelistedDataInfoList, + pkgDataInfoList, allowlistedDataInfoList, bindMountAppDataDirs, bindMountAppStorageDirs); // Note that this event ends at the end of handleChildProc. @@ -428,7 +428,7 @@ public final class Zygote { private static native void nativeSpecializeAppProcess(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp, - String[] pkgDataInfoList, String[] whitelistedDataInfoList, + String[] pkgDataInfoList, String[] allowlistedDataInfoList, boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs); /** @@ -807,7 +807,7 @@ public final class Zygote { args.mRuntimeFlags, rlimits, args.mMountExternal, args.mSeInfo, args.mNiceName, args.mStartChildZygote, args.mInstructionSet, args.mAppDataDir, args.mIsTopApp, - args.mPkgDataInfoList, args.mWhitelistedDataInfoList, + args.mPkgDataInfoList, args.mAllowlistedDataInfoList, args.mBindMountAppDataDirs, args.mBindMountAppStorageDirs); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); diff --git a/core/java/com/android/internal/os/ZygoteArguments.java b/core/java/com/android/internal/os/ZygoteArguments.java index 65b454d47db2..ef8398294c5b 100644 --- a/core/java/com/android/internal/os/ZygoteArguments.java +++ b/core/java/com/android/internal/os/ZygoteArguments.java @@ -230,7 +230,7 @@ class ZygoteArguments { * A list that stores all allowlisted app data info: volume uuid and inode. * Null if it does need to do app data isolation. */ - String[] mWhitelistedDataInfoList; + String[] mAllowlistedDataInfoList; /** * @see Zygote#BIND_MOUNT_APP_STORAGE_DIRS @@ -475,8 +475,8 @@ class ZygoteArguments { } } else if (arg.startsWith(Zygote.PKG_DATA_INFO_MAP)) { mPkgDataInfoList = getAssignmentList(arg); - } else if (arg.startsWith(Zygote.WHITELISTED_DATA_INFO_MAP)) { - mWhitelistedDataInfoList = getAssignmentList(arg); + } else if (arg.startsWith(Zygote.ALLOWLISTED_DATA_INFO_MAP)) { + mAllowlistedDataInfoList = getAssignmentList(arg); } else if (arg.equals(Zygote.BIND_MOUNT_APP_STORAGE_DIRS)) { mBindMountAppStorageDirs = true; } else if (arg.equals(Zygote.BIND_MOUNT_APP_DATA_DIRS)) { diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java index 37c75907061c..1673362028f9 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -265,7 +265,7 @@ class ZygoteConnection { fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote, parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mIsTopApp, parsedArgs.mPkgDataInfoList, - parsedArgs.mWhitelistedDataInfoList, parsedArgs.mBindMountAppDataDirs, + parsedArgs.mAllowlistedDataInfoList, parsedArgs.mBindMountAppDataDirs, parsedArgs.mBindMountAppStorageDirs); try { diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index bcfb06b15ab8..836074f1d5f7 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -1400,16 +1400,15 @@ static void insertPackagesToMergedList(JNIEnv* env, } 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) { - - 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); + jobjectArray allowlisted_data_info_list, uid_t uid, + const char* process_name, jstring managed_nice_name, fail_fn_t 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, allowlisted_data_info_list, process_name, + managed_nice_name, fail_fn); - isolateAppData(env, merged_data_info_list, uid, process_name, managed_nice_name, fail_fn); + isolateAppData(env, merged_data_info_list, uid, process_name, managed_nice_name, fail_fn); } /** @@ -1510,240 +1509,242 @@ static void BindMountStorageDirs(JNIEnv* env, jobjectArray pkg_data_info_list, } // Utility routine to specialize a zygote child process. -static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, - jint runtime_flags, jobjectArray rlimits, - jlong permitted_capabilities, jlong effective_capabilities, - jint mount_external, jstring managed_se_info, - jstring managed_nice_name, bool is_system_server, - bool is_child_zygote, jstring managed_instruction_set, - jstring managed_app_data_dir, bool is_top_app, - 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"; - 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); +static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, jint runtime_flags, + jobjectArray rlimits, jlong permitted_capabilities, + jlong effective_capabilities, jint mount_external, + jstring managed_se_info, jstring managed_nice_name, + bool is_system_server, bool is_child_zygote, + jstring managed_instruction_set, jstring managed_app_data_dir, + bool is_top_app, jobjectArray pkg_data_info_list, + jobjectArray allowlisted_data_info_list, bool mount_data_dirs, + bool mount_storage_dirs) { + const char* process_name = is_system_server ? "system_server" : "zygote"; + 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 se_info = extract_fn(managed_se_info); + auto nice_name = extract_fn(managed_nice_name); + auto instruction_set = extract_fn(managed_instruction_set); + auto app_data_dir = extract_fn(managed_app_data_dir); + + // Keep capabilities across UID change, unless we're staying root. + if (uid != 0) { + EnableKeepCapabilities(fail_fn); + } - auto se_info = extract_fn(managed_se_info); - auto nice_name = extract_fn(managed_nice_name); - auto instruction_set = extract_fn(managed_instruction_set); - auto app_data_dir = extract_fn(managed_app_data_dir); + SetInheritable(permitted_capabilities, fail_fn); - // Keep capabilities across UID change, unless we're staying root. - if (uid != 0) { - EnableKeepCapabilities(fail_fn); - } + DropCapabilitiesBoundingSet(fail_fn); - SetInheritable(permitted_capabilities, fail_fn); + bool need_pre_initialize_native_bridge = !is_system_server && instruction_set.has_value() && + android::NativeBridgeAvailable() && + // Native bridge may be already initialized if this + // is an app forked from app-zygote. + !android::NativeBridgeInitialized() && + android::NeedsNativeBridge(instruction_set.value().c_str()); - DropCapabilitiesBoundingSet(fail_fn); + MountEmulatedStorage(uid, mount_external, need_pre_initialize_native_bridge, fail_fn); - bool need_pre_initialize_native_bridge = - !is_system_server && - instruction_set.has_value() && - android::NativeBridgeAvailable() && - // Native bridge may be already initialized if this - // is an app forked from app-zygote. - !android::NativeBridgeInitialized() && - android::NeedsNativeBridge(instruction_set.value().c_str()); + // Make sure app is running in its own mount namespace before isolating its data directories. + ensureInAppMountNamespace(fail_fn); - MountEmulatedStorage(uid, mount_external, need_pre_initialize_native_bridge, fail_fn); + // Sandbox data and jit profile directories by overlaying a tmpfs on those dirs and bind + // mount all related packages separately. + if (mount_data_dirs) { + isolateAppData(env, pkg_data_info_list, allowlisted_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); + } + // MOUNT_EXTERNAL_INSTALLER, MOUNT_EXTERNAL_PASS_THROUGH, MOUNT_EXTERNAL_ANDROID_WRITABLE apps + // will have mount_storage_dirs == false here (set by ProcessList.needsStorageDataIsolation()), + // and hence they won't bind mount storage dirs. + if (mount_storage_dirs) { + BindMountStorageDirs(env, pkg_data_info_list, uid, process_name, managed_nice_name, + fail_fn); + } - // Make sure app is running in its own mount namespace before isolating its data directories. - ensureInAppMountNamespace(fail_fn); + // If this zygote isn't root, it won't be able to create a process group, + // since the directory is owned by root. + if (!is_system_server && getuid() == 0) { + const int rc = createProcessGroup(uid, getpid()); + if (rc == -EROFS) { + ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?"); + } else if (rc != 0) { + ALOGE("createProcessGroup(%d, %d) failed: %s", uid, /* pid= */ 0, strerror(-rc)); + } + } - // Sandbox data and jit profile directories by overlaying a tmpfs on those dirs and bind - // mount all related packages separately. - if (mount_data_dirs) { - isolateAppData(env, pkg_data_info_list, whitelisted_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); - } - // MOUNT_EXTERNAL_INSTALLER, MOUNT_EXTERNAL_PASS_THROUGH, MOUNT_EXTERNAL_ANDROID_WRITABLE apps - // will have mount_storage_dirs == false here (set by ProcessList.needsStorageDataIsolation()), - // and hence they won't bind mount storage dirs. - if (mount_storage_dirs) { - BindMountStorageDirs(env, pkg_data_info_list, uid, process_name, managed_nice_name, fail_fn); - } + SetGids(env, gids, is_child_zygote, fail_fn); + SetRLimits(env, rlimits, fail_fn); - // If this zygote isn't root, it won't be able to create a process group, - // since the directory is owned by root. - if (!is_system_server && getuid() == 0) { - const int rc = createProcessGroup(uid, getpid()); - if (rc == -EROFS) { - ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?"); - } else if (rc != 0) { - ALOGE("createProcessGroup(%d, %d) failed: %s", uid, /* pid= */ 0, strerror(-rc)); + if (need_pre_initialize_native_bridge) { + // Due to the logic behind need_pre_initialize_native_bridge we know that + // instruction_set contains a value. + android::PreInitializeNativeBridge(app_data_dir.has_value() ? app_data_dir.value().c_str() + : nullptr, + instruction_set.value().c_str()); } - } - SetGids(env, gids, is_child_zygote, fail_fn); - SetRLimits(env, rlimits, fail_fn); - - if (need_pre_initialize_native_bridge) { - // Due to the logic behind need_pre_initialize_native_bridge we know that - // instruction_set contains a value. - android::PreInitializeNativeBridge( - app_data_dir.has_value() ? app_data_dir.value().c_str() : nullptr, - instruction_set.value().c_str()); - } + if (setresgid(gid, gid, gid) == -1) { + fail_fn(CREATE_ERROR("setresgid(%d) failed: %s", gid, strerror(errno))); + } - if (setresgid(gid, gid, gid) == -1) { - fail_fn(CREATE_ERROR("setresgid(%d) failed: %s", gid, strerror(errno))); - } + // Must be called when the new process still has CAP_SYS_ADMIN, in this case, + // before changing uid from 0, which clears capabilities. The other + // alternative is to call prctl(PR_SET_NO_NEW_PRIVS, 1) afterward, but that + // breaks SELinux domain transition (see b/71859146). As the result, + // privileged syscalls used below still need to be accessible in app process. + SetUpSeccompFilter(uid, is_child_zygote); - // Must be called when the new process still has CAP_SYS_ADMIN, in this case, - // before changing uid from 0, which clears capabilities. The other - // alternative is to call prctl(PR_SET_NO_NEW_PRIVS, 1) afterward, but that - // breaks SELinux domain transition (see b/71859146). As the result, - // privileged syscalls used below still need to be accessible in app process. - SetUpSeccompFilter(uid, is_child_zygote); + // Must be called before losing the permission to set scheduler policy. + SetSchedulerPolicy(fail_fn, is_top_app); - // Must be called before losing the permission to set scheduler policy. - SetSchedulerPolicy(fail_fn, is_top_app); + if (setresuid(uid, uid, uid) == -1) { + fail_fn(CREATE_ERROR("setresuid(%d) failed: %s", uid, strerror(errno))); + } - if (setresuid(uid, uid, uid) == -1) { - fail_fn(CREATE_ERROR("setresuid(%d) failed: %s", uid, strerror(errno))); - } + // The "dumpable" flag of a process, which controls core dump generation, is + // overwritten by the value in /proc/sys/fs/suid_dumpable when the effective + // user or group ID changes. See proc(5) for possible values. In most cases, + // the value is 0, so core dumps are disabled for zygote children. However, + // when running in a Chrome OS container, the value is already set to 2, + // which allows the external crash reporter to collect all core dumps. Since + // only system crashes are interested, core dump is disabled for app + // processes. This also ensures compliance with CTS. + int dumpable = prctl(PR_GET_DUMPABLE); + if (dumpable == -1) { + ALOGE("prctl(PR_GET_DUMPABLE) failed: %s", strerror(errno)); + RuntimeAbort(env, __LINE__, "prctl(PR_GET_DUMPABLE) failed"); + } - // The "dumpable" flag of a process, which controls core dump generation, is - // overwritten by the value in /proc/sys/fs/suid_dumpable when the effective - // user or group ID changes. See proc(5) for possible values. In most cases, - // the value is 0, so core dumps are disabled for zygote children. However, - // when running in a Chrome OS container, the value is already set to 2, - // which allows the external crash reporter to collect all core dumps. Since - // only system crashes are interested, core dump is disabled for app - // processes. This also ensures compliance with CTS. - int dumpable = prctl(PR_GET_DUMPABLE); - if (dumpable == -1) { - ALOGE("prctl(PR_GET_DUMPABLE) failed: %s", strerror(errno)); - RuntimeAbort(env, __LINE__, "prctl(PR_GET_DUMPABLE) failed"); - } + if (dumpable == 2 && uid >= AID_APP) { + if (prctl(PR_SET_DUMPABLE, 0, 0, 0, 0) == -1) { + ALOGE("prctl(PR_SET_DUMPABLE, 0) failed: %s", strerror(errno)); + RuntimeAbort(env, __LINE__, "prctl(PR_SET_DUMPABLE, 0) failed"); + } + } - if (dumpable == 2 && uid >= AID_APP) { - if (prctl(PR_SET_DUMPABLE, 0, 0, 0, 0) == -1) { - ALOGE("prctl(PR_SET_DUMPABLE, 0) failed: %s", strerror(errno)); - RuntimeAbort(env, __LINE__, "prctl(PR_SET_DUMPABLE, 0) failed"); + // Set process properties to enable debugging if required. + if ((runtime_flags & RuntimeFlags::DEBUG_ENABLE_JDWP) != 0) { + EnableDebugger(); + } + if ((runtime_flags & RuntimeFlags::PROFILE_FROM_SHELL) != 0) { + // simpleperf needs the process to be dumpable to profile it. + if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) { + ALOGE("prctl(PR_SET_DUMPABLE) failed: %s", strerror(errno)); + RuntimeAbort(env, __LINE__, "prctl(PR_SET_DUMPABLE, 1) failed"); + } } - } - // Set process properties to enable debugging if required. - if ((runtime_flags & RuntimeFlags::DEBUG_ENABLE_JDWP) != 0) { - EnableDebugger(); - } - if ((runtime_flags & RuntimeFlags::PROFILE_FROM_SHELL) != 0) { - // simpleperf needs the process to be dumpable to profile it. - if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) { - ALOGE("prctl(PR_SET_DUMPABLE) failed: %s", strerror(errno)); - RuntimeAbort(env, __LINE__, "prctl(PR_SET_DUMPABLE, 1) failed"); + HeapTaggingLevel heap_tagging_level; + switch (runtime_flags & RuntimeFlags::MEMORY_TAG_LEVEL_MASK) { + case RuntimeFlags::MEMORY_TAG_LEVEL_TBI: + heap_tagging_level = M_HEAP_TAGGING_LEVEL_TBI; + break; + case RuntimeFlags::MEMORY_TAG_LEVEL_ASYNC: + heap_tagging_level = M_HEAP_TAGGING_LEVEL_ASYNC; + break; + case RuntimeFlags::MEMORY_TAG_LEVEL_SYNC: + heap_tagging_level = M_HEAP_TAGGING_LEVEL_SYNC; + break; + default: + heap_tagging_level = M_HEAP_TAGGING_LEVEL_NONE; + break; + } + mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, heap_tagging_level); + + // Now that we've used the flag, clear it so that we don't pass unknown flags to the ART + // runtime. + runtime_flags &= ~RuntimeFlags::MEMORY_TAG_LEVEL_MASK; + + // Avoid heap zero initialization for applications without MTE. Zero init may + // cause app compat problems, use more memory, or reduce performance. While it + // would be nice to have them for apps, we will have to wait until they are + // proven out, have more efficient hardware, and/or apply them only to new + // applications. + if (!(runtime_flags & RuntimeFlags::NATIVE_HEAP_ZERO_INIT)) { + mallopt(M_BIONIC_ZERO_INIT, 0); } - } - HeapTaggingLevel heap_tagging_level; - switch (runtime_flags & RuntimeFlags::MEMORY_TAG_LEVEL_MASK) { - case RuntimeFlags::MEMORY_TAG_LEVEL_TBI: - heap_tagging_level = M_HEAP_TAGGING_LEVEL_TBI; - break; - case RuntimeFlags::MEMORY_TAG_LEVEL_ASYNC: - heap_tagging_level = M_HEAP_TAGGING_LEVEL_ASYNC; - break; - case RuntimeFlags::MEMORY_TAG_LEVEL_SYNC: - heap_tagging_level = M_HEAP_TAGGING_LEVEL_SYNC; - break; - default: - heap_tagging_level = M_HEAP_TAGGING_LEVEL_NONE; - break; - } - mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, heap_tagging_level); + // Now that we've used the flag, clear it so that we don't pass unknown flags to the ART + // runtime. + runtime_flags &= ~RuntimeFlags::NATIVE_HEAP_ZERO_INIT; - // Now that we've used the flag, clear it so that we don't pass unknown flags to the ART runtime. - runtime_flags &= ~RuntimeFlags::MEMORY_TAG_LEVEL_MASK; + bool forceEnableGwpAsan = false; + switch (runtime_flags & RuntimeFlags::GWP_ASAN_LEVEL_MASK) { + default: + case RuntimeFlags::GWP_ASAN_LEVEL_NEVER: + break; + case RuntimeFlags::GWP_ASAN_LEVEL_ALWAYS: + forceEnableGwpAsan = true; + [[fallthrough]]; + case RuntimeFlags::GWP_ASAN_LEVEL_LOTTERY: + android_mallopt(M_INITIALIZE_GWP_ASAN, &forceEnableGwpAsan, sizeof(forceEnableGwpAsan)); + } + // Now that we've used the flag, clear it so that we don't pass unknown flags to the ART + // runtime. + runtime_flags &= ~RuntimeFlags::GWP_ASAN_LEVEL_MASK; + + if (NeedsNoRandomizeWorkaround()) { + // Work around ARM kernel ASLR lossage (http://b/5817320). + int old_personality = personality(0xffffffff); + int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE); + if (new_personality == -1) { + ALOGW("personality(%d) failed: %s", new_personality, strerror(errno)); + } + } - // Avoid heap zero initialization for applications without MTE. Zero init may - // cause app compat problems, use more memory, or reduce performance. While it - // would be nice to have them for apps, we will have to wait until they are - // proven out, have more efficient hardware, and/or apply them only to new - // applications. - if (!(runtime_flags & RuntimeFlags::NATIVE_HEAP_ZERO_INIT)) { - mallopt(M_BIONIC_ZERO_INIT, 0); - } + SetCapabilities(permitted_capabilities, effective_capabilities, permitted_capabilities, + fail_fn); - // Now that we've used the flag, clear it so that we don't pass unknown flags to the ART runtime. - runtime_flags &= ~RuntimeFlags::NATIVE_HEAP_ZERO_INIT; + __android_log_close(); + AStatsSocket_close(); - bool forceEnableGwpAsan = false; - switch (runtime_flags & RuntimeFlags::GWP_ASAN_LEVEL_MASK) { - default: - case RuntimeFlags::GWP_ASAN_LEVEL_NEVER: - break; - case RuntimeFlags::GWP_ASAN_LEVEL_ALWAYS: - forceEnableGwpAsan = true; - [[fallthrough]]; - case RuntimeFlags::GWP_ASAN_LEVEL_LOTTERY: - android_mallopt(M_INITIALIZE_GWP_ASAN, &forceEnableGwpAsan, sizeof(forceEnableGwpAsan)); - } - // Now that we've used the flag, clear it so that we don't pass unknown flags to the ART runtime. - runtime_flags &= ~RuntimeFlags::GWP_ASAN_LEVEL_MASK; + const char* se_info_ptr = se_info.has_value() ? se_info.value().c_str() : nullptr; + const char* nice_name_ptr = nice_name.has_value() ? nice_name.value().c_str() : nullptr; - if (NeedsNoRandomizeWorkaround()) { - // Work around ARM kernel ASLR lossage (http://b/5817320). - int old_personality = personality(0xffffffff); - int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE); - if (new_personality == -1) { - ALOGW("personality(%d) failed: %s", new_personality, strerror(errno)); + if (selinux_android_setcontext(uid, is_system_server, se_info_ptr, nice_name_ptr) == -1) { + fail_fn(CREATE_ERROR("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid, + is_system_server, se_info_ptr, nice_name_ptr)); } - } - - SetCapabilities(permitted_capabilities, effective_capabilities, permitted_capabilities, fail_fn); - - __android_log_close(); - AStatsSocket_close(); - - const char* se_info_ptr = se_info.has_value() ? se_info.value().c_str() : nullptr; - const char* nice_name_ptr = nice_name.has_value() ? nice_name.value().c_str() : nullptr; - if (selinux_android_setcontext(uid, is_system_server, se_info_ptr, nice_name_ptr) == -1) { - fail_fn(CREATE_ERROR("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", - uid, is_system_server, se_info_ptr, nice_name_ptr)); - } + // Make it easier to debug audit logs by setting the main thread's name to the + // nice name rather than "app_process". + if (nice_name.has_value()) { + SetThreadName(nice_name.value()); + } else if (is_system_server) { + SetThreadName("system_server"); + } - // Make it easier to debug audit logs by setting the main thread's name to the - // nice name rather than "app_process". - if (nice_name.has_value()) { - SetThreadName(nice_name.value()); - } else if (is_system_server) { - SetThreadName("system_server"); - } + // Unset the SIGCHLD handler, but keep ignoring SIGHUP (rationale in SetSignalHandlers). + UnsetChldSignalHandler(); - // Unset the SIGCHLD handler, but keep ignoring SIGHUP (rationale in SetSignalHandlers). - UnsetChldSignalHandler(); + if (is_system_server) { + env->CallStaticVoidMethod(gZygoteClass, gCallPostForkSystemServerHooks, runtime_flags); + if (env->ExceptionCheck()) { + fail_fn("Error calling post fork system server hooks."); + } - if (is_system_server) { - env->CallStaticVoidMethod(gZygoteClass, gCallPostForkSystemServerHooks, runtime_flags); - if (env->ExceptionCheck()) { - fail_fn("Error calling post fork system server hooks."); + // TODO(b/117874058): Remove hardcoded label here. + static const char* kSystemServerLabel = "u:r:system_server:s0"; + if (selinux_android_setcon(kSystemServerLabel) != 0) { + fail_fn(CREATE_ERROR("selinux_android_setcon(%s)", kSystemServerLabel)); + } } - // TODO(oth): Remove hardcoded label here (b/117874058). - static const char* kSystemServerLabel = "u:r:system_server:s0"; - if (selinux_android_setcon(kSystemServerLabel) != 0) { - fail_fn(CREATE_ERROR("selinux_android_setcon(%s)", kSystemServerLabel)); + if (is_child_zygote) { + initUnsolSocketToSystemServer(); } - } - if (is_child_zygote) { - initUnsolSocketToSystemServer(); - } + env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags, + is_system_server, is_child_zygote, managed_instruction_set); - env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags, - is_system_server, is_child_zygote, managed_instruction_set); + // Reset the process priority to the default value. + setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_DEFAULT); - // Reset the process priority to the default value. - setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_DEFAULT); - - if (env->ExceptionCheck()) { - fail_fn("Error calling post fork hooks."); - } + if (env->ExceptionCheck()) { + fail_fn("Error calling post fork hooks."); + } } static uint64_t GetEffectiveCapabilityMask(JNIEnv* env) { @@ -2068,12 +2069,11 @@ static void com_android_internal_os_Zygote_nativePreApplicationInit(JNIEnv*, jcl NO_PAC_FUNC static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( - JNIEnv* env, jclass, jint uid, jint gid, jintArray gids, - jint runtime_flags, jobjectArray rlimits, - jint mount_external, jstring se_info, jstring nice_name, + JNIEnv* env, jclass, jint uid, jint gid, jintArray gids, jint runtime_flags, + jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, 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, - jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list, + jobjectArray pkg_data_info_list, jobjectArray allowlisted_data_info_list, jboolean mount_data_dirs, jboolean mount_storage_dirs) { jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote); @@ -2108,14 +2108,11 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( pid_t pid = zygote::ForkCommon(env, false, fds_to_close, fds_to_ignore, true); if (pid == 0) { - SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, - capabilities, capabilities, - mount_external, se_info, nice_name, false, - is_child_zygote == JNI_TRUE, instruction_set, app_data_dir, - is_top_app == JNI_TRUE, pkg_data_info_list, - whitelisted_data_info_list, - mount_data_dirs == JNI_TRUE, - mount_storage_dirs == JNI_TRUE); + SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, capabilities, capabilities, + mount_external, se_info, nice_name, false, is_child_zygote == JNI_TRUE, + instruction_set, app_data_dir, is_top_app == JNI_TRUE, pkg_data_info_list, + allowlisted_data_info_list, mount_data_dirs == JNI_TRUE, + mount_storage_dirs == JNI_TRUE); } return pid; } @@ -2147,12 +2144,11 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer( if (pid == 0) { // System server prcoess does not need data isolation so no need to // know pkg_data_info_list. - SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, - permitted_capabilities, effective_capabilities, - MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true, + SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, permitted_capabilities, + effective_capabilities, MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true, false, nullptr, nullptr, /* is_top_app= */ false, /* pkg_data_info_list */ nullptr, - /* whitelisted_data_info_list */ nullptr, false, false); + /* allowlisted_data_info_list */ nullptr, false, false); } else if (pid > 0) { // The zygote process checks whether the child process has died or not. ALOGI("System server process %d has been created", pid); @@ -2260,7 +2256,7 @@ static void com_android_internal_os_Zygote_nativeAllowFileAcrossFork( if (!path_cstr) { RuntimeAbort(env, __LINE__, "path_cstr == nullptr"); } - FileDescriptorWhitelist::Get()->Allow(path_cstr); + FileDescriptorAllowlist::Get()->Allow(path_cstr); } static void com_android_internal_os_Zygote_nativeInstallSeccompUidGidFilter( @@ -2295,20 +2291,19 @@ static void com_android_internal_os_Zygote_nativeInstallSeccompUidGidFilter( * @param is_top_app If the process is for top (high priority) application */ static void com_android_internal_os_Zygote_nativeSpecializeAppProcess( - JNIEnv* env, jclass, jint uid, jint gid, jintArray gids, - jint runtime_flags, jobjectArray rlimits, - jint mount_external, jstring se_info, jstring nice_name, - jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app, - 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); - - SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, - capabilities, capabilities, - mount_external, se_info, nice_name, false, - is_child_zygote == JNI_TRUE, instruction_set, app_data_dir, - is_top_app == JNI_TRUE, pkg_data_info_list, whitelisted_data_info_list, - mount_data_dirs == JNI_TRUE, mount_storage_dirs == JNI_TRUE); + JNIEnv* env, jclass, jint uid, jint gid, jintArray gids, jint runtime_flags, + jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, + jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, + jboolean is_top_app, jobjectArray pkg_data_info_list, + jobjectArray allowlisted_data_info_list, jboolean mount_data_dirs, + jboolean mount_storage_dirs) { + jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote); + + SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, capabilities, capabilities, + mount_external, se_info, nice_name, false, is_child_zygote == JNI_TRUE, + instruction_set, app_data_dir, is_top_app == JNI_TRUE, pkg_data_info_list, + allowlisted_data_info_list, mount_data_dirs == JNI_TRUE, + mount_storage_dirs == JNI_TRUE); } /** diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp index c73aae58fe7f..eac1d9922c9a 100644 --- a/core/jni/fd_utils.cpp +++ b/core/jni/fd_utils.cpp @@ -31,8 +31,8 @@ #include <android-base/stringprintf.h> #include <android-base/strings.h> -// Static whitelist of open paths that the zygote is allowed to keep open. -static const char* kPathWhitelist[] = { +// Static allowlist of open paths that the zygote is allowed to keep open. +static const char* kPathAllowlist[] = { "/dev/null", "/dev/socket/zygote", "/dev/socket/zygote_secondary", @@ -51,118 +51,114 @@ static const char* kPathWhitelist[] = { static const char kFdPath[] = "/proc/self/fd"; // static -FileDescriptorWhitelist* FileDescriptorWhitelist::Get() { - if (instance_ == nullptr) { - instance_ = new FileDescriptorWhitelist(); - } - return instance_; +FileDescriptorAllowlist* FileDescriptorAllowlist::Get() { + if (instance_ == nullptr) { + instance_ = new FileDescriptorAllowlist(); + } + return instance_; } static bool IsArtMemfd(const std::string& path) { return android::base::StartsWith(path, "/memfd:/boot-image-methods.art"); } -bool FileDescriptorWhitelist::IsAllowed(const std::string& path) const { - // Check the static whitelist path. - for (const auto& whitelist_path : kPathWhitelist) { - if (path == whitelist_path) - return true; - } +bool FileDescriptorAllowlist::IsAllowed(const std::string& path) const { + // Check the static allowlist path. + for (const auto& allowlist_path : kPathAllowlist) { + if (path == allowlist_path) return true; + } - // Check any paths added to the dynamic whitelist. - for (const auto& whitelist_path : whitelist_) { - if (path == whitelist_path) - return true; - } + // Check any paths added to the dynamic allowlist. + for (const auto& allowlist_path : allowlist_) { + if (path == allowlist_path) return true; + } - // Framework jars are allowed. - static const char* kFrameworksPrefix[] = { - "/system/framework/", - "/system_ext/framework/", - }; + // Framework jars are allowed. + static const char* kFrameworksPrefix[] = { + "/system/framework/", + "/system_ext/framework/", + }; - static const char* kJarSuffix = ".jar"; + static const char* kJarSuffix = ".jar"; - for (const auto& frameworks_prefix : kFrameworksPrefix) { - if (android::base::StartsWith(path, frameworks_prefix) - && android::base::EndsWith(path, kJarSuffix)) { - return true; + for (const auto& frameworks_prefix : kFrameworksPrefix) { + if (android::base::StartsWith(path, frameworks_prefix) && + android::base::EndsWith(path, kJarSuffix)) { + return true; + } } - } - // Jars from APEXes are allowed. This matches /apex/**/javalib/*.jar. - static const char* kApexPrefix = "/apex/"; - static const char* kApexJavalibPathSuffix = "/javalib"; - if (android::base::StartsWith(path, kApexPrefix) && android::base::EndsWith(path, kJarSuffix) && - android::base::EndsWith(android::base::Dirname(path), kApexJavalibPathSuffix)) { - return true; - } + // Jars from APEXes are allowed. This matches /apex/**/javalib/*.jar. + static const char* kApexPrefix = "/apex/"; + static const char* kApexJavalibPathSuffix = "/javalib"; + if (android::base::StartsWith(path, kApexPrefix) && android::base::EndsWith(path, kJarSuffix) && + android::base::EndsWith(android::base::Dirname(path), kApexJavalibPathSuffix)) { + return true; + } - // the in-memory file created by ART through memfd_create is allowed. - if (IsArtMemfd(path)) { - return true; - } + // the in-memory file created by ART through memfd_create is allowed. + if (IsArtMemfd(path)) { + return true; + } - // Whitelist files needed for Runtime Resource Overlay, like these: - // /system/vendor/overlay/framework-res.apk - // /system/vendor/overlay-subdir/pg/framework-res.apk - // /vendor/overlay/framework-res.apk - // /vendor/overlay/PG/android-framework-runtime-resource-overlay.apk - // /data/resource-cache/system@vendor@overlay@framework-res.apk@idmap - // /data/resource-cache/system@vendor@overlay-subdir@pg@framework-res.apk@idmap - // See AssetManager.cpp for more details on overlay-subdir. - static const char* kOverlayDir = "/system/vendor/overlay/"; - static const char* kVendorOverlayDir = "/vendor/overlay"; - static const char* kVendorOverlaySubdir = "/system/vendor/overlay-subdir/"; - static const char* kSystemProductOverlayDir = "/system/product/overlay/"; - static const char* kProductOverlayDir = "/product/overlay"; - static const char* kSystemSystemExtOverlayDir = "/system/system_ext/overlay/"; - static const char* kSystemExtOverlayDir = "/system_ext/overlay"; - static const char* kSystemOdmOverlayDir = "/system/odm/overlay"; - static const char* kOdmOverlayDir = "/odm/overlay"; - static const char* kSystemOemOverlayDir = "/system/oem/overlay"; - static const char* kOemOverlayDir = "/oem/overlay"; - static const char* kApkSuffix = ".apk"; - - if ((android::base::StartsWith(path, kOverlayDir) - || android::base::StartsWith(path, kVendorOverlaySubdir) - || android::base::StartsWith(path, kVendorOverlayDir) - || android::base::StartsWith(path, kSystemProductOverlayDir) - || android::base::StartsWith(path, kProductOverlayDir) - || android::base::StartsWith(path, kSystemSystemExtOverlayDir) - || android::base::StartsWith(path, kSystemExtOverlayDir) - || android::base::StartsWith(path, kSystemOdmOverlayDir) - || android::base::StartsWith(path, kOdmOverlayDir) - || android::base::StartsWith(path, kSystemOemOverlayDir) - || android::base::StartsWith(path, kOemOverlayDir)) - && android::base::EndsWith(path, kApkSuffix) - && path.find("/../") == std::string::npos) { - return true; - } + // Allowlist files needed for Runtime Resource Overlay, like these: + // /system/vendor/overlay/framework-res.apk + // /system/vendor/overlay-subdir/pg/framework-res.apk + // /vendor/overlay/framework-res.apk + // /vendor/overlay/PG/android-framework-runtime-resource-overlay.apk + // /data/resource-cache/system@vendor@overlay@framework-res.apk@idmap + // /data/resource-cache/system@vendor@overlay-subdir@pg@framework-res.apk@idmap + // See AssetManager.cpp for more details on overlay-subdir. + static const char* kOverlayDir = "/system/vendor/overlay/"; + static const char* kVendorOverlayDir = "/vendor/overlay"; + static const char* kVendorOverlaySubdir = "/system/vendor/overlay-subdir/"; + static const char* kSystemProductOverlayDir = "/system/product/overlay/"; + static const char* kProductOverlayDir = "/product/overlay"; + static const char* kSystemSystemExtOverlayDir = "/system/system_ext/overlay/"; + static const char* kSystemExtOverlayDir = "/system_ext/overlay"; + static const char* kSystemOdmOverlayDir = "/system/odm/overlay"; + static const char* kOdmOverlayDir = "/odm/overlay"; + static const char* kSystemOemOverlayDir = "/system/oem/overlay"; + static const char* kOemOverlayDir = "/oem/overlay"; + static const char* kApkSuffix = ".apk"; + + if ((android::base::StartsWith(path, kOverlayDir) || + android::base::StartsWith(path, kVendorOverlaySubdir) || + android::base::StartsWith(path, kVendorOverlayDir) || + android::base::StartsWith(path, kSystemProductOverlayDir) || + android::base::StartsWith(path, kProductOverlayDir) || + android::base::StartsWith(path, kSystemSystemExtOverlayDir) || + android::base::StartsWith(path, kSystemExtOverlayDir) || + android::base::StartsWith(path, kSystemOdmOverlayDir) || + android::base::StartsWith(path, kOdmOverlayDir) || + android::base::StartsWith(path, kSystemOemOverlayDir) || + android::base::StartsWith(path, kOemOverlayDir)) && + android::base::EndsWith(path, kApkSuffix) && path.find("/../") == std::string::npos) { + return true; + } - static const char* kOverlayIdmapPrefix = "/data/resource-cache/"; - static const char* kOverlayIdmapSuffix = ".apk@idmap"; - if (android::base::StartsWith(path, kOverlayIdmapPrefix) - && android::base::EndsWith(path, kOverlayIdmapSuffix) - && path.find("/../") == std::string::npos) { - return true; - } + static const char* kOverlayIdmapPrefix = "/data/resource-cache/"; + static const char* kOverlayIdmapSuffix = ".apk@idmap"; + if (android::base::StartsWith(path, kOverlayIdmapPrefix) && + android::base::EndsWith(path, kOverlayIdmapSuffix) && + path.find("/../") == std::string::npos) { + return true; + } - // All regular files that are placed under this path are whitelisted automatically. - static const char* kZygoteWhitelistPath = "/vendor/zygote_whitelist/"; - if (android::base::StartsWith(path, kZygoteWhitelistPath) - && path.find("/../") == std::string::npos) { - return true; - } + // All regular files that are placed under this path are allowlisted + // automatically. The directory name is maintained for compatibility. + static const char* kZygoteAllowlistPath = "/vendor/zygote_whitelist/"; + if (android::base::StartsWith(path, kZygoteAllowlistPath) && + path.find("/../") == std::string::npos) { + return true; + } - return false; + return false; } -FileDescriptorWhitelist::FileDescriptorWhitelist() - : whitelist_() { -} +FileDescriptorAllowlist::FileDescriptorAllowlist() : allowlist_() {} -FileDescriptorWhitelist* FileDescriptorWhitelist::instance_ = nullptr; +FileDescriptorAllowlist* FileDescriptorAllowlist::instance_ = nullptr; // Keeps track of all relevant information (flags, offset etc.) of an // open zygote file descriptor. @@ -215,7 +211,7 @@ FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd, fail_fn_t fail_fn) fail_fn(android::base::StringPrintf("Unable to stat %d", fd)); } - const FileDescriptorWhitelist* whitelist = FileDescriptorWhitelist::Get(); + const FileDescriptorAllowlist* allowlist = FileDescriptorAllowlist::Get(); if (S_ISSOCK(f_stat.st_mode)) { std::string socket_name; @@ -223,16 +219,15 @@ FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd, fail_fn_t fail_fn) fail_fn("Unable to get socket name"); } - if (!whitelist->IsAllowed(socket_name)) { - fail_fn(android::base::StringPrintf("Socket name not whitelisted : %s (fd=%d)", - socket_name.c_str(), - fd)); + if (!allowlist->IsAllowed(socket_name)) { + fail_fn(android::base::StringPrintf("Socket name not allowlisted : %s (fd=%d)", + socket_name.c_str(), fd)); } return new FileDescriptorInfo(fd); } - // We only handle whitelisted regular files and character devices. Whitelisted + // We only handle allowlisted regular files and character devices. Allowlisted // character devices must provide a guarantee of sensible behaviour when // reopened. // @@ -266,8 +261,8 @@ FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd, fail_fn_t fail_fn) strerror(errno))); } - if (!whitelist->IsAllowed(file_path)) { - fail_fn(android::base::StringPrintf("Not whitelisted (%d): %s", fd, file_path.c_str())); + if (!allowlist->IsAllowed(file_path)) { + fail_fn(android::base::StringPrintf("Not allowlisted (%d): %s", fd, file_path.c_str())); } // File descriptor flags : currently on FD_CLOEXEC. We can set these diff --git a/core/jni/fd_utils.h b/core/jni/fd_utils.h index 2caf1575981a..14c318e8e84a 100644 --- a/core/jni/fd_utils.h +++ b/core/jni/fd_utils.h @@ -33,42 +33,40 @@ class FileDescriptorInfo; // This type is duplicated in com_android_internal_os_Zygote.cpp typedef const std::function<void(std::string)>& fail_fn_t; -// Whitelist of open paths that the zygote is allowed to keep open. +// Allowlist of open paths that the zygote is allowed to keep open. // -// In addition to the paths listed in kPathWhitelist in file_utils.cpp, and +// In addition to the paths listed in kPathAllowlist in file_utils.cpp, and // paths dynamically added with Allow(), all files ending with ".jar" -// under /system/framework" are whitelisted. See IsAllowed() for the canonical +// under /system/framework" are allowlisted. See IsAllowed() for the canonical // definition. // -// If the whitelisted path is associated with a regular file or a +// If the allowlisted path is associated with a regular file or a // character device, the file is reopened after a fork with the same -// offset and mode. If the whilelisted path is associated with a +// offset and mode. If the allowlisted path is associated with a // AF_UNIX socket, the socket will refer to /dev/null after each // fork, and all operations on it will fail. -class FileDescriptorWhitelist { - public: - // Lazily creates the global whitelist. - static FileDescriptorWhitelist* Get(); +class FileDescriptorAllowlist { +public: + // Lazily creates the global allowlist. + static FileDescriptorAllowlist* Get(); - // Adds a path to the whitelist. - void Allow(const std::string& path) { - whitelist_.push_back(path); - } + // Adds a path to the allowlist. + void Allow(const std::string& path) { allowlist_.push_back(path); } - // Returns true iff. a given path is whitelisted. A path is whitelisted - // if it belongs to the whitelist (see kPathWhitelist) or if it's a path - // under /system/framework that ends with ".jar" or if it is a system - // framework overlay. - bool IsAllowed(const std::string& path) const; + // Returns true iff. a given path is allowlisted. A path is allowlisted + // if it belongs to the allowlist (see kPathAllowlist) or if it's a path + // under /system/framework that ends with ".jar" or if it is a system + // framework overlay. + bool IsAllowed(const std::string& path) const; - private: - FileDescriptorWhitelist(); +private: + FileDescriptorAllowlist(); - static FileDescriptorWhitelist* instance_; + static FileDescriptorAllowlist* instance_; - std::vector<std::string> whitelist_; + std::vector<std::string> allowlist_; - DISALLOW_COPY_AND_ASSIGN(FileDescriptorWhitelist); + DISALLOW_COPY_AND_ASSIGN(FileDescriptorAllowlist); }; // A FileDescriptorTable is a collection of FileDescriptorInfo objects |