Autoformatter changes.

This CL contains changes made by the autoformatter to make these files
conform to the C++ style guide.

BYPASS_INCLUSIVE_LANGUAGE_REASON="compatability with vendor files"

Test: None
Change-Id: I04ac8fba3a2038133689c456a8d8e2c7bd856541
This commit is contained in:
Chris Wailes
2021-03-03 14:12:39 -08:00
parent a6f8803c85
commit 074e16404c
3 changed files with 349 additions and 362 deletions

View File

@@ -1400,16 +1400,15 @@ static void insertPackagesToMergedList(JNIEnv* env,
}
static void isolateAppData(JNIEnv* env, jobjectArray pkg_data_info_list,
jobjectArray allowlisted_data_info_list, uid_t uid, const char* process_name,
jstring managed_nice_name, fail_fn_t 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);
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 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);
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);
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);
}
SetInheritable(permitted_capabilities, fail_fn);
DropCapabilitiesBoundingSet(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());
MountEmulatedStorage(uid, mount_external, need_pre_initialize_native_bridge, fail_fn);
// Make sure app is running in its own mount namespace before isolating its data directories.
ensureInAppMountNamespace(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);
}
// 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));
// Keep capabilities across UID change, unless we're staying root.
if (uid != 0) {
EnableKeepCapabilities(fail_fn);
}
}
SetGids(env, gids, is_child_zygote, fail_fn);
SetRLimits(env, rlimits, fail_fn);
SetInheritable(permitted_capabilities, 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());
}
DropCapabilitiesBoundingSet(fail_fn);
if (setresgid(gid, gid, gid) == -1) {
fail_fn(CREATE_ERROR("setresgid(%d) failed: %s", gid, strerror(errno)));
}
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());
// 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);
MountEmulatedStorage(uid, mount_external, need_pre_initialize_native_bridge, fail_fn);
// Must be called before losing the permission to set scheduler policy.
SetSchedulerPolicy(fail_fn, is_top_app);
// Make sure app is running in its own mount namespace before isolating its data directories.
ensureInAppMountNamespace(fail_fn);
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");
}
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");
// 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);
}
}
// 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");
// 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);
}
}
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);
}
// 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;
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));
// 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));
}
}
}
SetCapabilities(permitted_capabilities, effective_capabilities, permitted_capabilities, fail_fn);
SetGids(env, gids, is_child_zygote, fail_fn);
SetRLimits(env, rlimits, fail_fn);
__android_log_close();
AStatsSocket_close();
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());
}
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 (setresgid(gid, gid, gid) == -1) {
fail_fn(CREATE_ERROR("setresgid(%d) failed: %s", gid, 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));
}
// 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);
// 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");
}
// Must be called before losing the permission to set scheduler policy.
SetSchedulerPolicy(fail_fn, is_top_app);
// Unset the SIGCHLD handler, but keep ignoring SIGHUP (rationale in SetSignalHandlers).
UnsetChldSignalHandler();
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");
}
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");
}
}
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);
}
// 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;
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));
}
}
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");
}
// 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.");
}
// 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));
}
}
if (is_child_zygote) {
initUnsolSocketToSystemServer();
}
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);
if (is_system_server) {
env->CallStaticVoidMethod(gZygoteClass, gCallPostForkSystemServerHooks, runtime_flags);
if (env->ExceptionCheck()) {
fail_fn("Error calling post fork system server hooks.");
fail_fn("Error calling post fork hooks.");
}
// 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();
}
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);
if (env->ExceptionCheck()) {
fail_fn("Error calling post fork hooks.");
}
}
static uint64_t GetEffectiveCapabilityMask(JNIEnv* env) {
@@ -2068,9 +2069,8 @@ 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 allowlisted_data_info_list,
@@ -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,
allowlisted_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,9 +2144,8 @@ 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,
/* allowlisted_data_info_list */ nullptr, false, false);
@@ -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 allowlisted_data_info_list,
jboolean mount_data_dirs, jboolean mount_storage_dirs) {
jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
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);
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);
}
/**

View File

@@ -52,10 +52,10 @@ static const char kFdPath[] = "/proc/self/fd";
// static
FileDescriptorAllowlist* FileDescriptorAllowlist::Get() {
if (instance_ == nullptr) {
instance_ = new FileDescriptorAllowlist();
}
return instance_;
if (instance_ == nullptr) {
instance_ = new FileDescriptorAllowlist();
}
return instance_;
}
static bool IsArtMemfd(const std::string& path) {
@@ -63,105 +63,100 @@ static bool IsArtMemfd(const std::string& path) {
}
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 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/",
};
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;
// Check the static allowlist path.
for (const auto& allowlist_path : kPathAllowlist) {
if (path == allowlist_path) 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;
}
// Check any paths added to the dynamic allowlist.
for (const auto& allowlist_path : allowlist_) {
if (path == allowlist_path) return true;
}
// the in-memory file created by ART through memfd_create is allowed.
if (IsArtMemfd(path)) {
return true;
}
// Framework jars are allowed.
static const char* kFrameworksPrefix[] = {
"/system/framework/",
"/system_ext/framework/",
};
// 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";
static const char* kJarSuffix = ".jar";
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;
}
for (const auto& frameworks_prefix : kFrameworksPrefix) {
if (android::base::StartsWith(path, frameworks_prefix) &&
android::base::EndsWith(path, kJarSuffix)) {
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;
}
// 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;
}
// 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;
}
// the in-memory file created by ART through memfd_create is allowed.
if (IsArtMemfd(path)) {
return true;
}
return false;
// 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;
}
// 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;
}
FileDescriptorAllowlist::FileDescriptorAllowlist()
: allowlist_() {
}
FileDescriptorAllowlist::FileDescriptorAllowlist() : allowlist_() {}
FileDescriptorAllowlist* FileDescriptorAllowlist::instance_ = nullptr;
@@ -225,9 +220,8 @@ FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd, fail_fn_t fail_fn)
}
if (!allowlist->IsAllowed(socket_name)) {
fail_fn(android::base::StringPrintf("Socket name not allowlisted : %s (fd=%d)",
socket_name.c_str(),
fd));
fail_fn(android::base::StringPrintf("Socket name not allowlisted : %s (fd=%d)",
socket_name.c_str(), fd));
}
return new FileDescriptorInfo(fd);
@@ -268,7 +262,7 @@ FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd, fail_fn_t fail_fn)
}
if (!allowlist->IsAllowed(file_path)) {
fail_fn(android::base::StringPrintf("Not allowlisted (%d): %s", fd, file_path.c_str()));
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

View File

@@ -46,29 +46,27 @@ typedef const std::function<void(std::string)>& fail_fn_t;
// AF_UNIX socket, the socket will refer to /dev/null after each
// fork, and all operations on it will fail.
class FileDescriptorAllowlist {
public:
// Lazily creates the global allowlist.
static FileDescriptorAllowlist* Get();
public:
// Lazily creates the global allowlist.
static FileDescriptorAllowlist* Get();
// Adds a path to the allowlist.
void Allow(const std::string& path) {
allowlist_.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 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;
// 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:
FileDescriptorAllowlist();
private:
FileDescriptorAllowlist();
static FileDescriptorAllowlist* instance_;
static FileDescriptorAllowlist* instance_;
std::vector<std::string> allowlist_;
std::vector<std::string> allowlist_;
DISALLOW_COPY_AND_ASSIGN(FileDescriptorAllowlist);
DISALLOW_COPY_AND_ASSIGN(FileDescriptorAllowlist);
};
// A FileDescriptorTable is a collection of FileDescriptorInfo objects