Merge "Fix memory flags in external services and secondary zygotes." into tm-dev am: 951aa29f72

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16989014

Change-Id: Ifdab9053602186f63979ec62b053368f55b42a71
This commit is contained in:
TreeHugger Robot
2022-03-02 01:21:05 +00:00
committed by Automerger Merge Worker
9 changed files with 349 additions and 243 deletions

View File

@@ -17,9 +17,11 @@
package android.os;
import android.content.pm.ApplicationInfo;
import android.content.pm.ProcessInfo;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.Zygote;
import dalvik.system.VMRuntime;
@@ -45,8 +47,6 @@ public class AppZygote {
// Last UID/GID of the range the AppZygote can setuid()/setgid() to
private final int mZygoteUidGidMax;
private final int mZygoteRuntimeFlags;
private final Object mLock = new Object();
/**
@@ -57,14 +57,15 @@ public class AppZygote {
private ChildZygoteProcess mZygote;
private final ApplicationInfo mAppInfo;
private final ProcessInfo mProcessInfo;
public AppZygote(ApplicationInfo appInfo, int zygoteUid, int uidGidMin, int uidGidMax,
int runtimeFlags) {
public AppZygote(ApplicationInfo appInfo, ProcessInfo processInfo, int zygoteUid, int uidGidMin,
int uidGidMax) {
mAppInfo = appInfo;
mProcessInfo = processInfo;
mZygoteUid = zygoteUid;
mZygoteUidGidMin = uidGidMin;
mZygoteUidGidMax = uidGidMax;
mZygoteRuntimeFlags = runtimeFlags;
}
/**
@@ -108,13 +109,15 @@ public class AppZygote {
String abi = mAppInfo.primaryCpuAbi != null ? mAppInfo.primaryCpuAbi :
Build.SUPPORTED_ABIS[0];
try {
int runtimeFlags = Zygote.getMemorySafetyRuntimeFlagsForSecondaryZygote(
mAppInfo, mProcessInfo);
mZygote = Process.ZYGOTE_PROCESS.startChildZygote(
"com.android.internal.os.AppZygoteInit",
mAppInfo.processName + "_zygote",
mZygoteUid,
mZygoteUid,
null, // gids
mZygoteRuntimeFlags, // runtimeFlags
runtimeFlags,
"app_zygote", // seInfo
abi, // abi
abi, // acceptedAbiList

View File

@@ -25,6 +25,7 @@ import android.text.TextUtils;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.Zygote;
/** @hide */
public class WebViewZygote {
@@ -127,13 +128,15 @@ public class WebViewZygote {
try {
String abi = sPackage.applicationInfo.primaryCpuAbi;
int runtimeFlags = Zygote.getMemorySafetyRuntimeFlagsForSecondaryZygote(
sPackage.applicationInfo, null);
sZygote = Process.ZYGOTE_PROCESS.startChildZygote(
"com.android.internal.os.WebViewZygoteInit",
"webview_zygote",
Process.WEBVIEW_ZYGOTE_UID,
Process.WEBVIEW_ZYGOTE_UID,
null, // gids
0, // runtimeFlags
runtimeFlags,
"webview_zygote", // seInfo
abi, // abi
TextUtils.join(",", Build.SUPPORTED_ABIS),

View File

@@ -20,13 +20,21 @@ import static android.system.OsConstants.O_CLOEXEC;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.ChangeId;
import android.compat.annotation.Disabled;
import android.compat.annotation.EnabledAfter;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.ProcessInfo;
import android.net.Credentials;
import android.net.LocalServerSocket;
import android.net.LocalSocket;
import android.os.Build;
import android.os.FactoryTest;
import android.os.IVold;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.Trace;
import android.provider.DeviceConfig;
@@ -34,6 +42,7 @@ import android.system.ErrnoException;
import android.system.Os;
import android.util.Log;
import com.android.internal.compat.IPlatformCompat;
import com.android.internal.net.NetworkUtilsInternal;
import dalvik.annotation.optimization.CriticalNative;
@@ -125,6 +134,7 @@ public final class Zygote {
public static final int MEMORY_TAG_LEVEL_MASK = (1 << 19) | (1 << 20);
public static final int MEMORY_TAG_LEVEL_NONE = 0;
/**
* Enable pointer tagging in this process.
* Tags are checked during memory deallocation, but not on access.
@@ -170,10 +180,8 @@ public final class Zygote {
*/
public static final int GWP_ASAN_LEVEL_ALWAYS = 1 << 22;
/**
* Enable automatic zero-initialization of native heap memory allocations.
*/
public static final int NATIVE_HEAP_ZERO_INIT = 1 << 23;
/** Enable automatic zero-initialization of native heap memory allocations. */
public static final int NATIVE_HEAP_ZERO_INIT_ENABLED = 1 << 23;
/**
* Enable profiling from system services. This loads profiling related plugins in ART.
@@ -1170,4 +1178,251 @@ public final class Zygote {
* we failed to determine the level.
*/
public static native int nativeCurrentTaggingLevel();
/**
* Native heap allocations will now have a non-zero tag in the most significant byte.
*
* @see <a href="https://source.android.com/devices/tech/debug/tagged-pointers">Tagged
* Pointers</a>
*/
@ChangeId
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
private static final long NATIVE_HEAP_POINTER_TAGGING = 135754954; // This is a bug id.
/**
* Native heap allocations in AppZygote process and its descendants will now have a non-zero tag
* in the most significant byte.
*
* @see <a href="https://source.android.com/devices/tech/debug/tagged-pointers">Tagged
* Pointers</a>
*/
@ChangeId
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S)
private static final long NATIVE_HEAP_POINTER_TAGGING_SECONDARY_ZYGOTE = 207557677;
/**
* Enable asynchronous (ASYNC) memory tag checking in this process. This flag will only have an
* effect on hardware supporting the ARM Memory Tagging Extension (MTE).
*/
@ChangeId @Disabled
private static final long NATIVE_MEMTAG_ASYNC = 135772972; // This is a bug id.
/**
* Enable synchronous (SYNC) memory tag checking in this process. This flag will only have an
* effect on hardware supporting the ARM Memory Tagging Extension (MTE). If both
* NATIVE_MEMTAG_ASYNC and this option is selected, this option takes preference and MTE is
* enabled in SYNC mode.
*/
@ChangeId @Disabled
private static final long NATIVE_MEMTAG_SYNC = 177438394; // This is a bug id.
/** Enable automatic zero-initialization of native heap memory allocations. */
@ChangeId @Disabled
private static final long NATIVE_HEAP_ZERO_INIT = 178038272; // This is a bug id.
/**
* Enable sampled memory bug detection in the app.
*
* @see <a href="https://source.android.com/devices/tech/debug/gwp-asan">GWP-ASan</a>.
*/
@ChangeId @Disabled private static final long GWP_ASAN = 135634846; // This is a bug id.
private static int memtagModeToZygoteMemtagLevel(int memtagMode) {
switch (memtagMode) {
case ApplicationInfo.MEMTAG_ASYNC:
return MEMORY_TAG_LEVEL_ASYNC;
case ApplicationInfo.MEMTAG_SYNC:
return MEMORY_TAG_LEVEL_SYNC;
default:
return MEMORY_TAG_LEVEL_NONE;
}
}
private static boolean isCompatChangeEnabled(
long change,
@NonNull ApplicationInfo info,
@Nullable IPlatformCompat platformCompat,
int enabledAfter) {
try {
if (platformCompat != null) return platformCompat.isChangeEnabled(change, info);
} catch (RemoteException ignore) {
}
return enabledAfter > 0 && info.targetSdkVersion > enabledAfter;
}
// Returns the requested memory tagging level.
private static int getRequestedMemtagLevel(
@NonNull ApplicationInfo info,
@Nullable ProcessInfo processInfo,
@Nullable IPlatformCompat platformCompat) {
// Look at the process attribute first.
if (processInfo != null && processInfo.memtagMode != ApplicationInfo.MEMTAG_DEFAULT) {
return memtagModeToZygoteMemtagLevel(processInfo.memtagMode);
}
// Then at the application attribute.
if (info.getMemtagMode() != ApplicationInfo.MEMTAG_DEFAULT) {
return memtagModeToZygoteMemtagLevel(info.getMemtagMode());
}
if (isCompatChangeEnabled(NATIVE_MEMTAG_SYNC, info, platformCompat, 0)) {
return MEMORY_TAG_LEVEL_SYNC;
}
if (isCompatChangeEnabled(NATIVE_MEMTAG_ASYNC, info, platformCompat, 0)) {
return MEMORY_TAG_LEVEL_ASYNC;
}
// Check to ensure the app hasn't explicitly opted-out of TBI via. the manifest attribute.
if (!info.allowsNativeHeapPointerTagging()) {
return MEMORY_TAG_LEVEL_NONE;
}
String defaultLevel = SystemProperties.get("persist.arm64.memtag.app_default");
if ("sync".equals(defaultLevel)) {
return MEMORY_TAG_LEVEL_SYNC;
} else if ("async".equals(defaultLevel)) {
return MEMORY_TAG_LEVEL_ASYNC;
}
// Check to see that the compat feature for TBI is enabled.
if (isCompatChangeEnabled(
NATIVE_HEAP_POINTER_TAGGING, info, platformCompat, Build.VERSION_CODES.Q)) {
return MEMORY_TAG_LEVEL_TBI;
}
return MEMORY_TAG_LEVEL_NONE;
}
private static int decideTaggingLevel(
@NonNull ApplicationInfo info,
@Nullable ProcessInfo processInfo,
@Nullable IPlatformCompat platformCompat) {
// Get the desired tagging level (app manifest + compat features).
int level = getRequestedMemtagLevel(info, processInfo, platformCompat);
// Take into account the hardware capabilities.
if (nativeSupportsMemoryTagging()) {
// MTE devices can not do TBI, because the Zygote process already has live MTE
// allocations. Downgrade TBI to NONE.
if (level == MEMORY_TAG_LEVEL_TBI) {
level = MEMORY_TAG_LEVEL_NONE;
}
} else if (nativeSupportsTaggedPointers()) {
// TBI-but-not-MTE devices downgrade MTE modes to TBI.
// The idea is that if an app opts into full hardware tagging (MTE), it must be ok with
// the "fake" pointer tagging (TBI).
if (level == MEMORY_TAG_LEVEL_ASYNC || level == MEMORY_TAG_LEVEL_SYNC) {
level = MEMORY_TAG_LEVEL_TBI;
}
} else {
// Otherwise disable all tagging.
level = MEMORY_TAG_LEVEL_NONE;
}
return level;
}
private static int decideGwpAsanLevel(
@NonNull ApplicationInfo info,
@Nullable ProcessInfo processInfo,
@Nullable IPlatformCompat platformCompat) {
// Look at the process attribute first.
if (processInfo != null && processInfo.gwpAsanMode != ApplicationInfo.GWP_ASAN_DEFAULT) {
return processInfo.gwpAsanMode == ApplicationInfo.GWP_ASAN_ALWAYS
? GWP_ASAN_LEVEL_ALWAYS
: GWP_ASAN_LEVEL_NEVER;
}
// Then at the application attribute.
if (info.getGwpAsanMode() != ApplicationInfo.GWP_ASAN_DEFAULT) {
return info.getGwpAsanMode() == ApplicationInfo.GWP_ASAN_ALWAYS
? GWP_ASAN_LEVEL_ALWAYS
: GWP_ASAN_LEVEL_NEVER;
}
// If the app does not specify gwpAsanMode, the default behavior is lottery among the
// system apps, and disabled for user apps, unless overwritten by the compat feature.
if (isCompatChangeEnabled(GWP_ASAN, info, platformCompat, 0)) {
return GWP_ASAN_LEVEL_ALWAYS;
}
if ((info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
return GWP_ASAN_LEVEL_LOTTERY;
}
return GWP_ASAN_LEVEL_NEVER;
}
private static boolean enableNativeHeapZeroInit(
@NonNull ApplicationInfo info,
@Nullable ProcessInfo processInfo,
@Nullable IPlatformCompat platformCompat) {
// Look at the process attribute first.
if (processInfo != null
&& processInfo.nativeHeapZeroInitialized != ApplicationInfo.ZEROINIT_DEFAULT) {
return processInfo.nativeHeapZeroInitialized == ApplicationInfo.ZEROINIT_ENABLED;
}
// Then at the application attribute.
if (info.getNativeHeapZeroInitialized() != ApplicationInfo.ZEROINIT_DEFAULT) {
return info.getNativeHeapZeroInitialized() == ApplicationInfo.ZEROINIT_ENABLED;
}
// Compat feature last.
if (isCompatChangeEnabled(NATIVE_HEAP_ZERO_INIT, info, platformCompat, 0)) {
return true;
}
return false;
}
/**
* Returns Zygote runtimeFlags for memory safety features (MTE, GWP-ASan, nativeHeadZeroInit)
* for a given app.
*/
public static int getMemorySafetyRuntimeFlags(
@NonNull ApplicationInfo info,
@Nullable ProcessInfo processInfo,
@Nullable String instructionSet,
@Nullable IPlatformCompat platformCompat) {
int runtimeFlags = decideGwpAsanLevel(info, processInfo, platformCompat);
// If instructionSet is non-null, this indicates that the system_server is spawning a
// process with an ISA that may be different from its own. System (kernel and hardware)
// compatibility for these features is checked in the decideTaggingLevel in the
// system_server process (not the child process). As both MTE and TBI are only supported
// in aarch64, we can simply ensure that the new process is also aarch64. This prevents
// the mismatch where a 64-bit system server spawns a 32-bit child that thinks it should
// enable some tagging variant. Theoretically, a 32-bit system server could exist that
// spawns 64-bit processes, in which case the new process won't get any tagging. This is
// fine as we haven't seen this configuration in practice, and we can reasonable assume
// that if tagging is desired, the system server will be 64-bit.
if (instructionSet == null || instructionSet.equals("arm64")) {
runtimeFlags |= decideTaggingLevel(info, processInfo, platformCompat);
}
if (enableNativeHeapZeroInit(info, processInfo, platformCompat)) {
runtimeFlags |= NATIVE_HEAP_ZERO_INIT_ENABLED;
}
return runtimeFlags;
}
/**
* Returns Zygote runtimeFlags for memory safety features (MTE, GWP-ASan, nativeHeadZeroInit)
* for a secondary zygote (AppZygote or WebViewZygote).
*/
public static int getMemorySafetyRuntimeFlagsForSecondaryZygote(
@NonNull ApplicationInfo info, @Nullable ProcessInfo processInfo) {
final IPlatformCompat platformCompat =
IPlatformCompat.Stub.asInterface(
ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
int runtimeFlags =
getMemorySafetyRuntimeFlags(
info, processInfo, null /*instructionSet*/, platformCompat);
// TBI ("fake" pointer tagging) in AppZygote is controlled by a separate compat feature.
if ((runtimeFlags & MEMORY_TAG_LEVEL_MASK) == MEMORY_TAG_LEVEL_TBI
&& isCompatChangeEnabled(
NATIVE_HEAP_POINTER_TAGGING_SECONDARY_ZYGOTE,
info,
platformCompat,
Build.VERSION_CODES.S)) {
// Reset memory tag level to NONE.
runtimeFlags &= ~MEMORY_TAG_LEVEL_MASK;
runtimeFlags |= MEMORY_TAG_LEVEL_NONE;
}
return runtimeFlags;
}
}

View File

@@ -346,7 +346,7 @@ enum RuntimeFlags : uint32_t {
GWP_ASAN_LEVEL_NEVER = 0 << 21,
GWP_ASAN_LEVEL_LOTTERY = 1 << 21,
GWP_ASAN_LEVEL_ALWAYS = 2 << 21,
NATIVE_HEAP_ZERO_INIT = 1 << 23,
NATIVE_HEAP_ZERO_INIT_ENABLED = 1 << 23,
PROFILEABLE = 1 << 24,
};
@@ -1709,13 +1709,13 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,
// 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)) {
if (!(runtime_flags & RuntimeFlags::NATIVE_HEAP_ZERO_INIT_ENABLED)) {
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;
runtime_flags &= ~RuntimeFlags::NATIVE_HEAP_ZERO_INIT_ENABLED;
bool forceEnableGwpAsan = false;
switch (runtime_flags & RuntimeFlags::GWP_ASAN_LEVEL_MASK) {

View File

@@ -4139,7 +4139,8 @@ public final class ActiveServices {
final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
final String procName = r.processName;
HostingRecord hostingRecord = new HostingRecord("service", r.instanceName);
HostingRecord hostingRecord = new HostingRecord("service", r.instanceName,
r.definingPackageName, r.definingUid, r.serviceInfo.processName);
ProcessRecord app;
if (!isolated) {
@@ -4177,11 +4178,12 @@ public final class ActiveServices {
app = r.isolationHostProc;
if (WebViewZygote.isMultiprocessEnabled()
&& r.serviceInfo.packageName.equals(WebViewZygote.getPackageName())) {
hostingRecord = HostingRecord.byWebviewZygote(r.instanceName);
hostingRecord = HostingRecord.byWebviewZygote(r.instanceName, r.definingPackageName,
r.definingUid, r.serviceInfo.processName);
}
if ((r.serviceInfo.flags & ServiceInfo.FLAG_USE_APP_ZYGOTE) != 0) {
hostingRecord = HostingRecord.byAppZygote(r.instanceName, r.definingPackageName,
r.definingUid);
r.definingUid, r.serviceInfo.processName);
}
}

View File

@@ -56,19 +56,27 @@ public final class HostingRecord {
private final String mDefiningPackageName;
private final int mDefiningUid;
private final boolean mIsTopApp;
private final String mDefiningProcessName;
public HostingRecord(String hostingType) {
this(hostingType, null /* hostingName */, REGULAR_ZYGOTE, null /* definingPackageName */,
-1 /* mDefiningUid */, false /* isTopApp */);
-1 /* mDefiningUid */, false /* isTopApp */, null /* definingProcessName */);
}
public HostingRecord(String hostingType, ComponentName hostingName) {
this(hostingType, hostingName, REGULAR_ZYGOTE);
}
public HostingRecord(String hostingType, ComponentName hostingName, String definingPackageName,
int definingUid, String definingProcessName) {
this(hostingType, hostingName.toShortString(), REGULAR_ZYGOTE, definingPackageName,
definingUid, false /* isTopApp */, definingProcessName);
}
public HostingRecord(String hostingType, ComponentName hostingName, boolean isTopApp) {
this(hostingType, hostingName.toShortString(), REGULAR_ZYGOTE,
null /* definingPackageName */, -1 /* mDefiningUid */, isTopApp /* isTopApp */);
null /* definingPackageName */, -1 /* mDefiningUid */, isTopApp /* isTopApp */,
null /* definingProcessName */);
}
public HostingRecord(String hostingType, String hostingName) {
@@ -81,17 +89,19 @@ public final class HostingRecord {
private HostingRecord(String hostingType, String hostingName, int hostingZygote) {
this(hostingType, hostingName, hostingZygote, null /* definingPackageName */,
-1 /* mDefiningUid */, false /* isTopApp */);
-1 /* mDefiningUid */, false /* isTopApp */, null /* definingProcessName */);
}
private HostingRecord(String hostingType, String hostingName, int hostingZygote,
String definingPackageName, int definingUid, boolean isTopApp) {
String definingPackageName, int definingUid, boolean isTopApp,
String definingProcessName) {
mHostingType = hostingType;
mHostingName = hostingName;
mHostingZygote = hostingZygote;
mDefiningPackageName = definingPackageName;
mDefiningUid = definingUid;
mIsTopApp = isTopApp;
mDefiningProcessName = definingProcessName;
}
public String getType() {
@@ -126,13 +136,25 @@ public final class HostingRecord {
return mDefiningPackageName;
}
/**
* Returns the processName of the component we want to start as specified in the defining app's
* manifest.
*
* @return the processName of the process in the hosting application
*/
public String getDefiningProcessName() {
return mDefiningProcessName;
}
/**
* Creates a HostingRecord for a process that must spawn from the webview zygote
* @param hostingName name of the component to be hosted in this process
* @return The constructed HostingRecord
*/
public static HostingRecord byWebviewZygote(ComponentName hostingName) {
return new HostingRecord("", hostingName.toShortString(), WEBVIEW_ZYGOTE);
public static HostingRecord byWebviewZygote(ComponentName hostingName,
String definingPackageName, int definingUid, String definingProcessName) {
return new HostingRecord("", hostingName.toShortString(), WEBVIEW_ZYGOTE,
definingPackageName, definingUid, false /* isTopApp */, definingProcessName);
}
/**
@@ -143,9 +165,9 @@ public final class HostingRecord {
* @return The constructed HostingRecord
*/
public static HostingRecord byAppZygote(ComponentName hostingName, String definingPackageName,
int definingUid) {
int definingUid, String definingProcessName) {
return new HostingRecord("", hostingName.toShortString(), APP_ZYGOTE,
definingPackageName, definingUid, false /* isTopApp */);
definingPackageName, definingUid, false /* isTopApp */, definingProcessName);
}
/**

View File

@@ -70,7 +70,6 @@ import android.app.IApplicationThread;
import android.app.IProcessObserver;
import android.app.IUidObserver;
import android.compat.annotation.ChangeId;
import android.compat.annotation.Disabled;
import android.compat.annotation.EnabledAfter;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -362,59 +361,6 @@ public final class ProcessList {
// lmkd reconnect delay in msecs
private static final long LMKD_RECONNECT_DELAY_MS = 1000;
/**
* Native heap allocations will now have a non-zero tag in the most significant byte.
* @see <a href="https://source.android.com/devices/tech/debug/tagged-pointers">Tagged
* Pointers</a>
*/
@ChangeId
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
private static final long NATIVE_HEAP_POINTER_TAGGING = 135754954; // This is a bug id.
/**
* Native heap allocations in AppZygote process and its descendants will now have a
* non-zero tag in the most significant byte.
* @see <a href="https://source.android.com/devices/tech/debug/tagged-pointers">Tagged
* Pointers</a>
*/
@ChangeId
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S)
private static final long NATIVE_HEAP_POINTER_TAGGING_APP_ZYGOTE = 207557677;
/**
* Enable asynchronous (ASYNC) memory tag checking in this process. This
* flag will only have an effect on hardware supporting the ARM Memory
* Tagging Extension (MTE).
*/
@ChangeId
@Disabled
private static final long NATIVE_MEMTAG_ASYNC = 135772972; // This is a bug id.
/**
* Enable synchronous (SYNC) memory tag checking in this process. This flag
* will only have an effect on hardware supporting the ARM Memory Tagging
* Extension (MTE). If both NATIVE_MEMTAG_ASYNC and this option is selected,
* this option takes preference and MTE is enabled in SYNC mode.
*/
@ChangeId
@Disabled
private static final long NATIVE_MEMTAG_SYNC = 177438394; // This is a bug id.
/**
* Enable automatic zero-initialization of native heap memory allocations.
*/
@ChangeId
@Disabled
private static final long NATIVE_HEAP_ZERO_INIT = 178038272; // This is a bug id.
/**
* Enable sampled memory bug detection in the app.
* @see <a href="https://source.android.com/devices/tech/debug/gwp-asan">GWP-ASan</a>.
*/
@ChangeId
@Disabled
private static final long GWP_ASAN = 135634846; // This is a bug id.
/**
* Apps have no access to the private data directories of any other app, even if the other
* app has made them world-readable.
@@ -1681,136 +1627,6 @@ public final class ProcessList {
return gidArray;
}
private int memtagModeToZygoteMemtagLevel(int memtagMode) {
switch (memtagMode) {
case ApplicationInfo.MEMTAG_ASYNC:
return Zygote.MEMORY_TAG_LEVEL_ASYNC;
case ApplicationInfo.MEMTAG_SYNC:
return Zygote.MEMORY_TAG_LEVEL_SYNC;
default:
return Zygote.MEMORY_TAG_LEVEL_NONE;
}
}
// Returns the requested memory tagging level.
private int getRequestedMemtagLevel(ProcessRecord app) {
// Look at the process attribute first.
if (app.processInfo != null
&& app.processInfo.memtagMode != ApplicationInfo.MEMTAG_DEFAULT) {
return memtagModeToZygoteMemtagLevel(app.processInfo.memtagMode);
}
// Then at the application attribute.
if (app.info.getMemtagMode() != ApplicationInfo.MEMTAG_DEFAULT) {
return memtagModeToZygoteMemtagLevel(app.info.getMemtagMode());
}
if (mPlatformCompat.isChangeEnabled(NATIVE_MEMTAG_SYNC, app.info)) {
return Zygote.MEMORY_TAG_LEVEL_SYNC;
}
if (mPlatformCompat.isChangeEnabled(NATIVE_MEMTAG_ASYNC, app.info)) {
return Zygote.MEMORY_TAG_LEVEL_ASYNC;
}
// Check to ensure the app hasn't explicitly opted-out of TBI via. the manifest attribute.
if (!app.info.allowsNativeHeapPointerTagging()) {
return Zygote.MEMORY_TAG_LEVEL_NONE;
}
String defaultLevel = SystemProperties.get("persist.arm64.memtag.app_default");
if ("sync".equals(defaultLevel)) {
return Zygote.MEMORY_TAG_LEVEL_SYNC;
} else if ("async".equals(defaultLevel)) {
return Zygote.MEMORY_TAG_LEVEL_ASYNC;
}
// Check to see that the compat feature for TBI is enabled.
if (mPlatformCompat.isChangeEnabled(NATIVE_HEAP_POINTER_TAGGING, app.info)) {
return Zygote.MEMORY_TAG_LEVEL_TBI;
}
return Zygote.MEMORY_TAG_LEVEL_NONE;
}
private int decideTaggingLevel(ProcessRecord app) {
// Get the desired tagging level (app manifest + compat features).
int level = getRequestedMemtagLevel(app);
// Take into account the hardware capabilities.
if (Zygote.nativeSupportsMemoryTagging()) {
// MTE devices can not do TBI, because the Zygote process already has live MTE
// allocations. Downgrade TBI to NONE.
if (level == Zygote.MEMORY_TAG_LEVEL_TBI) {
level = Zygote.MEMORY_TAG_LEVEL_NONE;
}
} else if (Zygote.nativeSupportsTaggedPointers()) {
// TBI-but-not-MTE devices downgrade MTE modes to TBI.
// The idea is that if an app opts into full hardware tagging (MTE), it must be ok with
// the "fake" pointer tagging (TBI).
if (level == Zygote.MEMORY_TAG_LEVEL_ASYNC || level == Zygote.MEMORY_TAG_LEVEL_SYNC) {
level = Zygote.MEMORY_TAG_LEVEL_TBI;
}
} else {
// Otherwise disable all tagging.
level = Zygote.MEMORY_TAG_LEVEL_NONE;
}
return level;
}
private int decideTaggingLevelForAppZygote(ProcessRecord app) {
int level = decideTaggingLevel(app);
// TBI ("fake" pointer tagging) in AppZygote is controlled by a separate compat feature.
if (!mPlatformCompat.isChangeEnabled(NATIVE_HEAP_POINTER_TAGGING_APP_ZYGOTE, app.info)
&& level == Zygote.MEMORY_TAG_LEVEL_TBI) {
level = Zygote.MEMORY_TAG_LEVEL_NONE;
}
return level;
}
private int decideGwpAsanLevel(ProcessRecord app) {
// Look at the process attribute first.
if (app.processInfo != null
&& app.processInfo.gwpAsanMode != ApplicationInfo.GWP_ASAN_DEFAULT) {
return app.processInfo.gwpAsanMode == ApplicationInfo.GWP_ASAN_ALWAYS
? Zygote.GWP_ASAN_LEVEL_ALWAYS
: Zygote.GWP_ASAN_LEVEL_NEVER;
}
// Then at the application attribute.
if (app.info.getGwpAsanMode() != ApplicationInfo.GWP_ASAN_DEFAULT) {
return app.info.getGwpAsanMode() == ApplicationInfo.GWP_ASAN_ALWAYS
? Zygote.GWP_ASAN_LEVEL_ALWAYS
: Zygote.GWP_ASAN_LEVEL_NEVER;
}
// If the app does not specify gwpAsanMode, the default behavior is lottery among the
// system apps, and disabled for user apps, unless overwritten by the compat feature.
if (mPlatformCompat.isChangeEnabled(GWP_ASAN, app.info)) {
return Zygote.GWP_ASAN_LEVEL_ALWAYS;
}
if ((app.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
return Zygote.GWP_ASAN_LEVEL_LOTTERY;
}
return Zygote.GWP_ASAN_LEVEL_NEVER;
}
private boolean enableNativeHeapZeroInit(ProcessRecord app) {
// Look at the process attribute first.
if (app.processInfo != null
&& app.processInfo.nativeHeapZeroInitialized != ApplicationInfo.ZEROINIT_DEFAULT) {
return app.processInfo.nativeHeapZeroInitialized == ApplicationInfo.ZEROINIT_ENABLED;
}
// Then at the application attribute.
if (app.info.getNativeHeapZeroInitialized() != ApplicationInfo.ZEROINIT_DEFAULT) {
return app.info.getNativeHeapZeroInitialized() == ApplicationInfo.ZEROINIT_ENABLED;
}
// Compat feature last.
if (mPlatformCompat.isChangeEnabled(NATIVE_HEAP_ZERO_INIT, app.info)) {
return true;
}
return false;
}
/**
* @return {@code true} if process start is successful, false otherwise.
*/
@@ -1992,8 +1808,6 @@ public final class ProcessList {
runtimeFlags |= Zygote.USE_APP_IMAGE_STARTUP_CACHE;
}
runtimeFlags |= decideGwpAsanLevel(app);
String invokeWith = null;
if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
// Debuggable apps may include a wrapper script with their library directory.
@@ -2024,23 +1838,21 @@ public final class ProcessList {
app.setRequiredAbi(requiredAbi);
app.setInstructionSet(instructionSet);
// If instructionSet is non-null, this indicates that the system_server is spawning a
// process with an ISA that may be different from its own. System (kernel and hardware)
// compatibility for these features is checked in the decideTaggingLevel in the
// system_server process (not the child process). As both MTE and TBI are only supported
// in aarch64, we can simply ensure that the new process is also aarch64. This prevents
// the mismatch where a 64-bit system server spawns a 32-bit child that thinks it should
// enable some tagging variant. Theoretically, a 32-bit system server could exist that
// spawns 64-bit processes, in which case the new process won't get any tagging. This is
// fine as we haven't seen this configuration in practice, and we can reasonable assume
// that if tagging is desired, the system server will be 64-bit.
if (instructionSet == null || instructionSet.equals("arm64")) {
runtimeFlags |= decideTaggingLevel(app);
// If this was an external service, the package name and uid in the passed in
// ApplicationInfo have been changed to match those of the calling package;
// that will incorrectly apply compat feature overrides for the calling package instead
// of the defining one.
ApplicationInfo definingAppInfo;
if (hostingRecord.getDefiningPackageName() != null) {
definingAppInfo = new ApplicationInfo(app.info);
definingAppInfo.packageName = hostingRecord.getDefiningPackageName();
definingAppInfo.uid = uid;
} else {
definingAppInfo = app.info;
}
if (enableNativeHeapZeroInit(app)) {
runtimeFlags |= Zygote.NATIVE_HEAP_ZERO_INIT;
}
runtimeFlags |= Zygote.getMemorySafetyRuntimeFlags(
definingAppInfo, app.processInfo, instructionSet, mPlatformCompat);
// the per-user SELinux context must be set
if (TextUtils.isEmpty(app.info.seInfoUser)) {
@@ -2299,8 +2111,7 @@ public final class ProcessList {
// not the calling one.
appInfo.packageName = app.getHostingRecord().getDefiningPackageName();
appInfo.uid = uid;
int runtimeFlags = decideTaggingLevelForAppZygote(app);
appZygote = new AppZygote(appInfo, uid, firstUid, lastUid, runtimeFlags);
appZygote = new AppZygote(appInfo, app.processInfo, uid, firstUid, lastUid);
mAppZygotes.put(app.info.processName, uid, appZygote);
zygoteProcessList = new ArrayList<ProcessRecord>();
mAppZygoteProcesses.put(appZygote, zygoteProcessList);
@@ -3158,7 +2969,8 @@ public final class ProcessList {
FrameworkStatsLog.write(FrameworkStatsLog.ISOLATED_UID_CHANGED, info.uid, uid,
FrameworkStatsLog.ISOLATED_UID_CHANGED__EVENT__CREATED);
}
final ProcessRecord r = new ProcessRecord(mService, info, proc, uid);
final ProcessRecord r = new ProcessRecord(mService, info, proc, uid,
hostingRecord.getDefiningUid(), hostingRecord.getDefiningProcessName());
final ProcessStateRecord state = r.mState;
if (!mService.mBooted && !mService.mBooting

View File

@@ -492,24 +492,33 @@ class ProcessRecord implements WindowProcessListener {
ProcessRecord(ActivityManagerService _service, ApplicationInfo _info, String _processName,
int _uid) {
this(_service, _info, _processName, _uid, -1, null);
}
ProcessRecord(ActivityManagerService _service, ApplicationInfo _info, String _processName,
int _uid, int _definingUid, String _definingProcessName) {
mService = _service;
mProcLock = _service.mProcLock;
info = _info;
ProcessInfo procInfo = null;
if (_service.mPackageManagerInt != null) {
ArrayMap<String, ProcessInfo> processes =
_service.mPackageManagerInt.getProcessesForUid(_uid);
if (processes != null) {
procInfo = processes.get(_processName);
if (procInfo != null && procInfo.deniedPermissions == null
&& procInfo.gwpAsanMode == ApplicationInfo.GWP_ASAN_DEFAULT
&& procInfo.memtagMode == ApplicationInfo.MEMTAG_DEFAULT
&& procInfo.nativeHeapZeroInitialized == ApplicationInfo.ZEROINIT_DEFAULT) {
// If this process hasn't asked for permissions to be denied, or for a
// non-default GwpAsan mode, or any other non-default setting, then we don't
// care about it.
procInfo = null;
}
if (_definingUid > 0) {
ArrayMap<String, ProcessInfo> processes =
_service.mPackageManagerInt.getProcessesForUid(_definingUid);
if (processes != null) procInfo = processes.get(_definingProcessName);
} else {
ArrayMap<String, ProcessInfo> processes =
_service.mPackageManagerInt.getProcessesForUid(_uid);
if (processes != null) procInfo = processes.get(_processName);
}
if (procInfo != null && procInfo.deniedPermissions == null
&& procInfo.gwpAsanMode == ApplicationInfo.GWP_ASAN_DEFAULT
&& procInfo.memtagMode == ApplicationInfo.MEMTAG_DEFAULT
&& procInfo.nativeHeapZeroInitialized == ApplicationInfo.ZEROINIT_DEFAULT) {
// If this process hasn't asked for permissions to be denied, or for a
// non-default GwpAsan mode, or any other non-default setting, then we don't
// care about it.
procInfo = null;
}
}
processInfo = procInfo;

View File

@@ -1000,7 +1000,7 @@ public class ApplicationExitInfoTest {
final String dummyPackageName = "com.android.test";
final String dummyClassName = ".Foo";
app.setHostingRecord(HostingRecord.byAppZygote(new ComponentName(
dummyPackageName, dummyClassName), "", definingUid));
dummyPackageName, dummyClassName), "", definingUid, ""));
}
app.mServices.setConnectionGroup(connectionGroup);
app.mState.setReportedProcState(procState);