Loading core/jni/com_android_internal_os_Zygote.cpp +59 −34 Original line number Diff line number Diff line Loading @@ -665,8 +665,9 @@ static void EnableKeepCapabilities(fail_fn_t fail_fn) { } } static void DropCapabilitiesBoundingSet(fail_fn_t fail_fn) { static void DropCapabilitiesBoundingSet(fail_fn_t fail_fn, jlong bounding_capabilities) { for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {; if ((1LL << i) & bounding_capabilities) continue; if (prctl(PR_CAPBSET_DROP, i, 0, 0, 0) == -1) { if (errno == EINVAL) { ALOGE("prctl(PR_CAPBSET_DROP) failed with EINVAL. Please verify " Loading @@ -678,6 +679,27 @@ static void DropCapabilitiesBoundingSet(fail_fn_t fail_fn) { } } static bool MatchGid(JNIEnv* env, jintArray gids, jint gid, jint gid_to_find) { if (gid == gid_to_find) return true; if (gids == nullptr) return false; jsize gids_num = env->GetArrayLength(gids); ScopedIntArrayRO native_gid_proxy(env, gids); if (native_gid_proxy.get() == nullptr) { RuntimeAbort(env, __LINE__, "Bad gids array"); } for (int gids_index = 0; gids_index < gids_num; ++gids_index) { if (native_gid_proxy[gids_index] == gid_to_find) { return true; } } return false; } static void SetInheritable(uint64_t inheritable, fail_fn_t fail_fn) { __user_cap_header_struct capheader; memset(&capheader, 0, sizeof(capheader)); Loading Loading @@ -1742,9 +1764,9 @@ 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, jlong effective_capabilities, jlong bounding_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, Loading @@ -1758,6 +1780,9 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, auto instruction_set = extract_fn(managed_instruction_set); auto app_data_dir = extract_fn(managed_app_data_dir); // Permit bounding capabilities permitted_capabilities |= bounding_capabilities; // Keep capabilities across UID change, unless we're staying root. if (uid != 0) { EnableKeepCapabilities(fail_fn); Loading @@ -1765,7 +1790,7 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, SetInheritable(permitted_capabilities, fail_fn); DropCapabilitiesBoundingSet(fail_fn); DropCapabilitiesBoundingSet(fail_fn, bounding_capabilities); bool need_pre_initialize_native_bridge = !is_system_server && instruction_set.has_value() && android::NativeBridgeAvailable() && Loading Loading @@ -2028,6 +2053,23 @@ static uint64_t GetEffectiveCapabilityMask(JNIEnv* env) { return capdata[0].effective | (static_cast<uint64_t>(capdata[1].effective) << 32); } static jlong CalculateBoundingCapabilities(JNIEnv* env, jint uid, jint gid, jintArray gids) { jlong capabilities = 0; /* * Grant CAP_SYS_NICE to CapInh/CapPrm/CapBnd for processes that can spawn * VMs. This enables processes to execve on binaries with elevated * capabilities if its file capability bits are set. This does not grant * capability to the parent process(that spawns the VM) as the effective * bits are not set. */ if (MatchGid(env, gids, gid, AID_VIRTUALMACHINE)) { capabilities |= (1LL << CAP_SYS_NICE); } return capabilities; } static jlong CalculateCapabilities(JNIEnv* env, jint uid, jint gid, jintArray gids, bool is_child_zygote) { jlong capabilities = 0; Loading Loading @@ -2061,26 +2103,7 @@ static jlong CalculateCapabilities(JNIEnv* env, jint uid, jint gid, jintArray gi * Grant CAP_BLOCK_SUSPEND to processes that belong to GID "wakelock" */ bool gid_wakelock_found = false; if (gid == AID_WAKELOCK) { gid_wakelock_found = true; } else if (gids != nullptr) { jsize gids_num = env->GetArrayLength(gids); ScopedIntArrayRO native_gid_proxy(env, gids); if (native_gid_proxy.get() == nullptr) { RuntimeAbort(env, __LINE__, "Bad gids array"); } for (int gids_index = 0; gids_index < gids_num; ++gids_index) { if (native_gid_proxy[gids_index] == AID_WAKELOCK) { gid_wakelock_found = true; break; } } } if (gid_wakelock_found) { if (MatchGid(env, gids, gid, AID_WAKELOCK)) { capabilities |= (1LL << CAP_BLOCK_SUSPEND); } Loading Loading @@ -2357,6 +2380,7 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( 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); jlong bounding_capabilities = CalculateBoundingCapabilities(env, uid, gid, gids); if (UNLIKELY(managed_fds_to_close == nullptr)) { zygote::ZygoteFailure(env, "zygote", nice_name, Loading Loading @@ -2395,10 +2419,10 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( 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, allowlisted_data_info_list, mount_data_dirs == JNI_TRUE, mount_storage_dirs == JNI_TRUE); bounding_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; } Loading Loading @@ -2431,7 +2455,7 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer( // 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, effective_capabilities, 0, MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true, false, nullptr, nullptr, /* is_top_app= */ false, /* pkg_data_info_list */ nullptr, /* allowlisted_data_info_list */ nullptr, false, false); Loading Loading @@ -2588,12 +2612,13 @@ static void com_android_internal_os_Zygote_nativeSpecializeAppProcess( jobjectArray allowlisted_data_info_list, jboolean mount_data_dirs, jboolean mount_storage_dirs) { jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote); jlong bounding_capabilities = CalculateBoundingCapabilities(env, uid, gid, gids); 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); bounding_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); } /** Loading data/etc/platform.xml +4 −0 Original line number Diff line number Diff line Loading @@ -124,6 +124,10 @@ <group gid="security_log_writer" /> </permission> <permission name="android.permission.MANAGE_VIRTUAL_MACHINE"> <group gid="virtualmachine" /> </permission> <!-- These are permissions that were mapped to gids but we need to keep them here until an upgrade from L to the current version is to be supported. These permissions are built-in Loading Loading
core/jni/com_android_internal_os_Zygote.cpp +59 −34 Original line number Diff line number Diff line Loading @@ -665,8 +665,9 @@ static void EnableKeepCapabilities(fail_fn_t fail_fn) { } } static void DropCapabilitiesBoundingSet(fail_fn_t fail_fn) { static void DropCapabilitiesBoundingSet(fail_fn_t fail_fn, jlong bounding_capabilities) { for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {; if ((1LL << i) & bounding_capabilities) continue; if (prctl(PR_CAPBSET_DROP, i, 0, 0, 0) == -1) { if (errno == EINVAL) { ALOGE("prctl(PR_CAPBSET_DROP) failed with EINVAL. Please verify " Loading @@ -678,6 +679,27 @@ static void DropCapabilitiesBoundingSet(fail_fn_t fail_fn) { } } static bool MatchGid(JNIEnv* env, jintArray gids, jint gid, jint gid_to_find) { if (gid == gid_to_find) return true; if (gids == nullptr) return false; jsize gids_num = env->GetArrayLength(gids); ScopedIntArrayRO native_gid_proxy(env, gids); if (native_gid_proxy.get() == nullptr) { RuntimeAbort(env, __LINE__, "Bad gids array"); } for (int gids_index = 0; gids_index < gids_num; ++gids_index) { if (native_gid_proxy[gids_index] == gid_to_find) { return true; } } return false; } static void SetInheritable(uint64_t inheritable, fail_fn_t fail_fn) { __user_cap_header_struct capheader; memset(&capheader, 0, sizeof(capheader)); Loading Loading @@ -1742,9 +1764,9 @@ 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, jlong effective_capabilities, jlong bounding_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, Loading @@ -1758,6 +1780,9 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, auto instruction_set = extract_fn(managed_instruction_set); auto app_data_dir = extract_fn(managed_app_data_dir); // Permit bounding capabilities permitted_capabilities |= bounding_capabilities; // Keep capabilities across UID change, unless we're staying root. if (uid != 0) { EnableKeepCapabilities(fail_fn); Loading @@ -1765,7 +1790,7 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, SetInheritable(permitted_capabilities, fail_fn); DropCapabilitiesBoundingSet(fail_fn); DropCapabilitiesBoundingSet(fail_fn, bounding_capabilities); bool need_pre_initialize_native_bridge = !is_system_server && instruction_set.has_value() && android::NativeBridgeAvailable() && Loading Loading @@ -2028,6 +2053,23 @@ static uint64_t GetEffectiveCapabilityMask(JNIEnv* env) { return capdata[0].effective | (static_cast<uint64_t>(capdata[1].effective) << 32); } static jlong CalculateBoundingCapabilities(JNIEnv* env, jint uid, jint gid, jintArray gids) { jlong capabilities = 0; /* * Grant CAP_SYS_NICE to CapInh/CapPrm/CapBnd for processes that can spawn * VMs. This enables processes to execve on binaries with elevated * capabilities if its file capability bits are set. This does not grant * capability to the parent process(that spawns the VM) as the effective * bits are not set. */ if (MatchGid(env, gids, gid, AID_VIRTUALMACHINE)) { capabilities |= (1LL << CAP_SYS_NICE); } return capabilities; } static jlong CalculateCapabilities(JNIEnv* env, jint uid, jint gid, jintArray gids, bool is_child_zygote) { jlong capabilities = 0; Loading Loading @@ -2061,26 +2103,7 @@ static jlong CalculateCapabilities(JNIEnv* env, jint uid, jint gid, jintArray gi * Grant CAP_BLOCK_SUSPEND to processes that belong to GID "wakelock" */ bool gid_wakelock_found = false; if (gid == AID_WAKELOCK) { gid_wakelock_found = true; } else if (gids != nullptr) { jsize gids_num = env->GetArrayLength(gids); ScopedIntArrayRO native_gid_proxy(env, gids); if (native_gid_proxy.get() == nullptr) { RuntimeAbort(env, __LINE__, "Bad gids array"); } for (int gids_index = 0; gids_index < gids_num; ++gids_index) { if (native_gid_proxy[gids_index] == AID_WAKELOCK) { gid_wakelock_found = true; break; } } } if (gid_wakelock_found) { if (MatchGid(env, gids, gid, AID_WAKELOCK)) { capabilities |= (1LL << CAP_BLOCK_SUSPEND); } Loading Loading @@ -2357,6 +2380,7 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( 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); jlong bounding_capabilities = CalculateBoundingCapabilities(env, uid, gid, gids); if (UNLIKELY(managed_fds_to_close == nullptr)) { zygote::ZygoteFailure(env, "zygote", nice_name, Loading Loading @@ -2395,10 +2419,10 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( 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, allowlisted_data_info_list, mount_data_dirs == JNI_TRUE, mount_storage_dirs == JNI_TRUE); bounding_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; } Loading Loading @@ -2431,7 +2455,7 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer( // 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, effective_capabilities, 0, MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true, false, nullptr, nullptr, /* is_top_app= */ false, /* pkg_data_info_list */ nullptr, /* allowlisted_data_info_list */ nullptr, false, false); Loading Loading @@ -2588,12 +2612,13 @@ static void com_android_internal_os_Zygote_nativeSpecializeAppProcess( jobjectArray allowlisted_data_info_list, jboolean mount_data_dirs, jboolean mount_storage_dirs) { jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote); jlong bounding_capabilities = CalculateBoundingCapabilities(env, uid, gid, gids); 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); bounding_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); } /** Loading
data/etc/platform.xml +4 −0 Original line number Diff line number Diff line Loading @@ -124,6 +124,10 @@ <group gid="security_log_writer" /> </permission> <permission name="android.permission.MANAGE_VIRTUAL_MACHINE"> <group gid="virtualmachine" /> </permission> <!-- These are permissions that were mapped to gids but we need to keep them here until an upgrade from L to the current version is to be supported. These permissions are built-in Loading