Merge "Add "enableGwpAsan" tag to android manifest." into rvc-dev

This commit is contained in:
Evgenii Stepanov
2020-03-12 21:13:25 +00:00
committed by Android (Google) Code Review
18 changed files with 351 additions and 42 deletions

View File

@@ -572,6 +572,7 @@ package android {
field public static final int elevation = 16843840; // 0x1010440 field public static final int elevation = 16843840; // 0x1010440
field public static final int ellipsize = 16842923; // 0x10100ab field public static final int ellipsize = 16842923; // 0x10100ab
field public static final int ems = 16843096; // 0x1010158 field public static final int ems = 16843096; // 0x1010158
field public static final int enableGwpAsan = 16844310; // 0x1010616
field public static final int enableVrMode = 16844069; // 0x1010525 field public static final int enableVrMode = 16844069; // 0x1010525
field public static final int enabled = 16842766; // 0x101000e field public static final int enabled = 16842766; // 0x101000e
field public static final int end = 16843996; // 0x10104dc field public static final int end = 16843996; // 0x10104dc
@@ -11439,6 +11440,7 @@ package android.content.pm {
method public int describeContents(); method public int describeContents();
method public void dump(android.util.Printer, String); method public void dump(android.util.Printer, String);
method public static CharSequence getCategoryTitle(android.content.Context, int); method public static CharSequence getCategoryTitle(android.content.Context, int);
method @Nullable public Boolean isGwpAsanEnabled();
method public boolean isProfileableByShell(); method public boolean isProfileableByShell();
method public boolean isResourceOverlay(); method public boolean isResourceOverlay();
method public boolean isVirtualPreload(); method public boolean isVirtualPreload();

View File

@@ -25,6 +25,7 @@ import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage; import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ProcessInfo;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Build; import android.os.Build;
@@ -38,6 +39,8 @@ import android.util.SparseArray;
import android.util.proto.ProtoOutputStream; import android.util.proto.ProtoOutputStream;
import com.android.internal.util.ArrayUtils; import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Parcelling;
import com.android.internal.util.Parcelling.BuiltIn.ForBoolean;
import com.android.server.SystemConfig; import com.android.server.SystemConfig;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
@@ -56,7 +59,8 @@ import java.util.UUID;
* <application> tag. * <application> tag.
*/ */
public class ApplicationInfo extends PackageItemInfo implements Parcelable { public class ApplicationInfo extends PackageItemInfo implements Parcelable {
private static ForBoolean sForBoolean = Parcelling.Cache.getOrCreate(ForBoolean.class);
/** /**
* Default task affinity of all activities in this application. See * Default task affinity of all activities in this application. See
* {@link ActivityInfo#taskAffinity} for more information. This comes * {@link ActivityInfo#taskAffinity} for more information. This comes
@@ -1272,6 +1276,14 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
/** @hide */ /** @hide */
public String zygotePreloadName; public String zygotePreloadName;
/**
* Indicates if the application has requested GWP-ASan to be enabled, disabled, or left
* unspecified. Processes can override this setting.
* @hide
*/
@Nullable
public Boolean enableGwpAsan;
/** /**
* Represents the default policy. The actual policy used will depend on other properties of * Represents the default policy. The actual policy used will depend on other properties of
* the application, e.g. the target SDK version. * the application, e.g. the target SDK version.
@@ -1413,6 +1425,9 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
pw.println(prefix + "usesNonSdkApi=" + usesNonSdkApi()); pw.println(prefix + "usesNonSdkApi=" + usesNonSdkApi());
pw.println(prefix + "allowsPlaybackCapture=" pw.println(prefix + "allowsPlaybackCapture="
+ (isAudioPlaybackCaptureAllowed() ? "true" : "false")); + (isAudioPlaybackCaptureAllowed() ? "true" : "false"));
if (enableGwpAsan != null) {
pw.println(prefix + "enableGwpAsan=" + enableGwpAsan);
}
} }
super.dumpBack(pw, prefix); super.dumpBack(pw, prefix);
} }
@@ -1511,6 +1526,9 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
if (category != CATEGORY_UNDEFINED) { if (category != CATEGORY_UNDEFINED) {
proto.write(ApplicationInfoProto.Detail.CATEGORY, category); proto.write(ApplicationInfoProto.Detail.CATEGORY, category);
} }
if (enableGwpAsan != null) {
proto.write(ApplicationInfoProto.Detail.ENABLE_GWP_ASAN, enableGwpAsan);
}
proto.end(detailToken); proto.end(detailToken);
} }
proto.end(token); proto.end(token);
@@ -1620,6 +1638,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
mHiddenApiPolicy = orig.mHiddenApiPolicy; mHiddenApiPolicy = orig.mHiddenApiPolicy;
hiddenUntilInstalled = orig.hiddenUntilInstalled; hiddenUntilInstalled = orig.hiddenUntilInstalled;
zygotePreloadName = orig.zygotePreloadName; zygotePreloadName = orig.zygotePreloadName;
enableGwpAsan = orig.enableGwpAsan;
} }
public String toString() { public String toString() {
@@ -1703,6 +1722,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
dest.writeInt(mHiddenApiPolicy); dest.writeInt(mHiddenApiPolicy);
dest.writeInt(hiddenUntilInstalled ? 1 : 0); dest.writeInt(hiddenUntilInstalled ? 1 : 0);
dest.writeString(zygotePreloadName); dest.writeString(zygotePreloadName);
sForBoolean.parcel(enableGwpAsan, dest, parcelableFlags);
} }
public static final @android.annotation.NonNull Parcelable.Creator<ApplicationInfo> CREATOR public static final @android.annotation.NonNull Parcelable.Creator<ApplicationInfo> CREATOR
@@ -1783,6 +1803,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
mHiddenApiPolicy = source.readInt(); mHiddenApiPolicy = source.readInt();
hiddenUntilInstalled = source.readInt() != 0; hiddenUntilInstalled = source.readInt() != 0;
zygotePreloadName = source.readString(); zygotePreloadName = source.readString();
enableGwpAsan = sForBoolean.unparcel(source);
} }
/** /**
@@ -2161,6 +2182,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
/** {@hide} */ public void setResourcePath(String resourcePath) { scanPublicSourceDir = resourcePath; } /** {@hide} */ public void setResourcePath(String resourcePath) { scanPublicSourceDir = resourcePath; }
/** {@hide} */ public void setBaseResourcePath(String baseResourcePath) { publicSourceDir = baseResourcePath; } /** {@hide} */ public void setBaseResourcePath(String baseResourcePath) { publicSourceDir = baseResourcePath; }
/** {@hide} */ public void setSplitResourcePaths(String[] splitResourcePaths) { splitPublicSourceDirs = splitResourcePaths; } /** {@hide} */ public void setSplitResourcePaths(String[] splitResourcePaths) { splitPublicSourceDirs = splitResourcePaths; }
/** {@hide} */ public void setGwpAsanEnabled(@Nullable Boolean value) { enableGwpAsan = value; }
/** {@hide} */ /** {@hide} */
@UnsupportedAppUsage @UnsupportedAppUsage
@@ -2172,4 +2194,6 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
@UnsupportedAppUsage @UnsupportedAppUsage
public String getBaseResourcePath() { return publicSourceDir; } public String getBaseResourcePath() { return publicSourceDir; }
/** {@hide} */ public String[] getSplitResourcePaths() { return splitPublicSourceDirs; } /** {@hide} */ public String[] getSplitResourcePaths() { return splitPublicSourceDirs; }
@Nullable
public Boolean isGwpAsanEnabled() { return enableGwpAsan; }
} }

View File

@@ -23,66 +23,157 @@ import android.os.Parcelable;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.ArraySet; import android.util.ArraySet;
import com.android.internal.util.DataClass;
import com.android.internal.util.Parcelling;
/** /**
* Information about a process an app may run. This corresponds to information collected from the * Information about a process an app may run. This corresponds to information collected from the
* AndroidManifest.xml's &lt;permission-group&gt; tags. * AndroidManifest.xml's &lt;permission-group&gt; tags.
* @hide * @hide
*/ */
@DataClass(genGetters = true, genSetters = false, genParcelable = true, genAidl = false,
genBuilder = false)
public class ProcessInfo implements Parcelable { public class ProcessInfo implements Parcelable {
/** /**
* The name of the process, fully-qualified based on the app's package name. * The name of the process, fully-qualified based on the app's package name.
*/ */
@NonNull
public String name; public String name;
/** /**
* If non-null, these are permissions that are not allowed in this process. * If non-null, these are permissions that are not allowed in this process.
*/ */
@Nullable @Nullable
@DataClass.ParcelWith(Parcelling.BuiltIn.ForInternedStringArraySet.class)
public ArraySet<String> deniedPermissions; public ArraySet<String> deniedPermissions;
public ProcessInfo(String name, ArraySet<String> deniedPermissions) { /**
this.name = name; * Indicates if the process has requested GWP-ASan to be enabled, disabled, or left unspecified.
this.deniedPermissions = deniedPermissions; */
} @Nullable
public Boolean enableGwpAsan;
@Deprecated @Deprecated
public ProcessInfo(@NonNull ProcessInfo orig) { public ProcessInfo(@NonNull ProcessInfo orig) {
this.name = orig.name; this.name = orig.name;
this.deniedPermissions = orig.deniedPermissions; this.deniedPermissions = orig.deniedPermissions;
this.enableGwpAsan = orig.enableGwpAsan;
} }
public int describeContents() {
return 0;
// Code below generated by codegen v1.0.15.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
//
// To regenerate run:
// $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/ProcessInfo.java
//
// To exclude the generated code from IntelliJ auto-formatting enable (one-time):
// Settings > Editor > Code Style > Formatter Control
//@formatter:off
/**
* Creates a new ProcessInfo.
*
* @param name
* The name of the process, fully-qualified based on the app's package name.
* @param deniedPermissions
* If non-null, these are permissions that are not allowed in this process.
* @param enableGwpAsan
* Indicates if the process has requested GWP-ASan to be enabled, disabled, or left unspecified.
*/
@DataClass.Generated.Member
public ProcessInfo(
@NonNull String name,
@Nullable ArraySet<String> deniedPermissions,
@Nullable Boolean enableGwpAsan) {
this.name = name;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, name);
this.deniedPermissions = deniedPermissions;
this.enableGwpAsan = enableGwpAsan;
// onConstructed(); // You can define this method to get a callback
} }
public void writeToParcel(Parcel dest, int parcelableFlags) { @DataClass.Generated.Member
dest.writeString(this.name); static Parcelling<ArraySet<String>> sParcellingForDeniedPermissions =
final int numDenied = this.deniedPermissions != null Parcelling.Cache.get(
? this.deniedPermissions.size() : 0; Parcelling.BuiltIn.ForInternedStringArraySet.class);
dest.writeInt(numDenied); static {
for (int i = 0; i < numDenied; i++) { if (sParcellingForDeniedPermissions == null) {
dest.writeString(this.deniedPermissions.valueAt(i)); sParcellingForDeniedPermissions = Parcelling.Cache.put(
new Parcelling.BuiltIn.ForInternedStringArraySet());
} }
} }
public static final @NonNull Creator<ProcessInfo> CREATOR = @Override
new Creator<ProcessInfo>() { @DataClass.Generated.Member
public ProcessInfo createFromParcel(Parcel source) { public void writeToParcel(@NonNull Parcel dest, int flags) {
return new ProcessInfo(source); // You can override field parcelling by defining methods like:
} // void parcelFieldName(Parcel dest, int flags) { ... }
public ProcessInfo[] newArray(int size) {
return new ProcessInfo[size];
}
};
private ProcessInfo(Parcel source) { byte flg = 0;
this.name = source.readString(); if (deniedPermissions != null) flg |= 0x2;
final int numDenied = source.readInt(); if (enableGwpAsan != null) flg |= 0x4;
if (numDenied > 0) { dest.writeByte(flg);
this.deniedPermissions = new ArraySet<>(numDenied); dest.writeString(name);
for (int i = numDenied - 1; i >= 0; i--) { sParcellingForDeniedPermissions.parcel(deniedPermissions, dest, flags);
this.deniedPermissions.add(TextUtils.safeIntern(source.readString())); if (enableGwpAsan != null) dest.writeBoolean(enableGwpAsan);
}
}
} }
@Override
@DataClass.Generated.Member
public int describeContents() { return 0; }
/** @hide */
@SuppressWarnings({"unchecked", "RedundantCast"})
@DataClass.Generated.Member
protected ProcessInfo(@NonNull Parcel in) {
// You can override field unparcelling by defining methods like:
// static FieldType unparcelFieldName(Parcel in) { ... }
byte flg = in.readByte();
String _name = in.readString();
ArraySet<String> _deniedPermissions = sParcellingForDeniedPermissions.unparcel(in);
Boolean _enableGwpAsan = (flg & 0x4) == 0 ? null : (Boolean) in.readBoolean();
this.name = _name;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, name);
this.deniedPermissions = _deniedPermissions;
this.enableGwpAsan = _enableGwpAsan;
// onConstructed(); // You can define this method to get a callback
}
@DataClass.Generated.Member
public static final @NonNull Parcelable.Creator<ProcessInfo> CREATOR
= new Parcelable.Creator<ProcessInfo>() {
@Override
public ProcessInfo[] newArray(int size) {
return new ProcessInfo[size];
}
@Override
public ProcessInfo createFromParcel(@NonNull Parcel in) {
return new ProcessInfo(in);
}
};
@DataClass.Generated(
time = 1582840056156L,
codegenVersion = "1.0.15",
sourceFile = "frameworks/base/core/java/android/content/pm/ProcessInfo.java",
inputSignatures = "public @android.annotation.NonNull java.lang.String name\npublic @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedStringArraySet.class) android.util.ArraySet<java.lang.String> deniedPermissions\npublic @android.annotation.Nullable java.lang.Boolean enableGwpAsan\nclass ProcessInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=false, genParcelable=true, genAidl=false, genBuilder=false)")
@Deprecated
private void __metadata() {}
//@formatter:on
// End of generated code
} }

View File

@@ -236,6 +236,8 @@ public interface ParsingPackage extends ParsingPackageRead {
ParsingPackage setEnabled(boolean enabled); ParsingPackage setEnabled(boolean enabled);
ParsingPackage setGwpAsanEnabled(Boolean enableGwpAsan);
ParsingPackage setCrossProfile(boolean crossProfile); ParsingPackage setCrossProfile(boolean crossProfile);
ParsingPackage setFullBackupContent(int fullBackupContent); ParsingPackage setFullBackupContent(int fullBackupContent);

View File

@@ -30,6 +30,7 @@ import android.content.pm.FeatureGroupInfo;
import android.content.pm.FeatureInfo; import android.content.pm.FeatureInfo;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageParser; import android.content.pm.PackageParser;
import android.content.pm.ProcessInfo;
import android.content.pm.parsing.component.ParsedActivity; import android.content.pm.parsing.component.ParsedActivity;
import android.content.pm.parsing.component.ParsedComponent; import android.content.pm.parsing.component.ParsedComponent;
import android.content.pm.parsing.component.ParsedFeature; import android.content.pm.parsing.component.ParsedFeature;
@@ -406,6 +407,10 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
private boolean allowNativeHeapPointerTagging; private boolean allowNativeHeapPointerTagging;
private boolean preserveLegacyExternalStorage; private boolean preserveLegacyExternalStorage;
@Nullable
@DataClass.ParcelWith(ForBoolean.class)
protected Boolean enableGwpAsan = null;
// TODO(chiuwinson): Non-null // TODO(chiuwinson): Non-null
@Nullable @Nullable
private ArraySet<String> mimeGroups; private ArraySet<String> mimeGroups;
@@ -904,7 +909,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
appInfo.volumeUuid = volumeUuid; appInfo.volumeUuid = volumeUuid;
appInfo.zygotePreloadName = zygotePreloadName; appInfo.zygotePreloadName = zygotePreloadName;
appInfo.crossProfile = isCrossProfile(); appInfo.crossProfile = isCrossProfile();
appInfo.setGwpAsanEnabled(enableGwpAsan);
appInfo.setBaseCodePath(baseCodePath); appInfo.setBaseCodePath(baseCodePath);
appInfo.setBaseResourcePath(baseCodePath); appInfo.setBaseResourcePath(baseCodePath);
appInfo.setCodePath(codePath); appInfo.setCodePath(codePath);
@@ -1086,6 +1091,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
dest.writeBoolean(this.allowNativeHeapPointerTagging); dest.writeBoolean(this.allowNativeHeapPointerTagging);
dest.writeBoolean(this.preserveLegacyExternalStorage); dest.writeBoolean(this.preserveLegacyExternalStorage);
dest.writeArraySet(this.mimeGroups); dest.writeArraySet(this.mimeGroups);
sForBoolean.parcel(this.enableGwpAsan, dest, flags);
} }
public ParsingPackageImpl(Parcel in) { public ParsingPackageImpl(Parcel in) {
@@ -1243,6 +1249,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
this.allowNativeHeapPointerTagging = in.readBoolean(); this.allowNativeHeapPointerTagging = in.readBoolean();
this.preserveLegacyExternalStorage = in.readBoolean(); this.preserveLegacyExternalStorage = in.readBoolean();
this.mimeGroups = (ArraySet<String>) in.readArraySet(boot); this.mimeGroups = (ArraySet<String>) in.readArraySet(boot);
this.enableGwpAsan = sForBoolean.unparcel(in);
} }
public static final Parcelable.Creator<ParsingPackageImpl> CREATOR = public static final Parcelable.Creator<ParsingPackageImpl> CREATOR =
@@ -1964,6 +1971,12 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
return directBootAware; return directBootAware;
} }
@Override
@Nullable
public Boolean isGwpAsanEnabled() {
return enableGwpAsan;
}
@Override @Override
public boolean isPartiallyDirectBootAware() { public boolean isPartiallyDirectBootAware() {
return partiallyDirectBootAware; return partiallyDirectBootAware;
@@ -2419,6 +2432,12 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
return this; return this;
} }
@Override
public ParsingPackageImpl setGwpAsanEnabled(@Nullable Boolean value) {
enableGwpAsan = value;
return this;
}
@Override @Override
public ParsingPackageImpl setPartiallyDirectBootAware(boolean value) { public ParsingPackageImpl setPartiallyDirectBootAware(boolean value) {
partiallyDirectBootAware = value; partiallyDirectBootAware = value;

View File

@@ -840,6 +840,13 @@ public interface ParsingPackageRead extends Parcelable {
@Nullable @Nullable
Set<String> getMimeGroups(); Set<String> getMimeGroups();
/**
* @see ApplicationInfo#enableGwpAsan
* @see R.styleable#AndroidManifest_enableGwpAsan
*/
@Nullable
public Boolean isGwpAsanEnabled();
// TODO(b/135203078): Hide and enforce going through PackageInfoUtils // TODO(b/135203078): Hide and enforce going through PackageInfoUtils
ApplicationInfo toAppInfoWithoutState(); ApplicationInfo toAppInfoWithoutState();
} }

View File

@@ -40,6 +40,7 @@ import android.content.pm.ConfigurationInfo;
import android.content.pm.FeatureGroupInfo; import android.content.pm.FeatureGroupInfo;
import android.content.pm.FeatureInfo; import android.content.pm.FeatureInfo;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.PackageParser; import android.content.pm.PackageParser;
import android.content.pm.PackageParser.PackageParserException; import android.content.pm.PackageParser.PackageParserException;
@@ -1660,6 +1661,11 @@ public class ParsingPackageUtils {
&& !ClassLoaderFactory.isValidClassLoaderName(classLoaderName)) { && !ClassLoaderFactory.isValidClassLoaderName(classLoaderName)) {
return input.error("Invalid class loader name: " + classLoaderName); return input.error("Invalid class loader name: " + classLoaderName);
} }
if (sa.hasValue(R.styleable.AndroidManifestApplication_enableGwpAsan)) {
pkg.setGwpAsanEnabled(
sa.getBoolean(R.styleable.AndroidManifestApplication_enableGwpAsan, false));
}
} finally { } finally {
sa.recycle(); sa.recycle();
} }

View File

@@ -41,6 +41,9 @@ public class ParsedProcess implements Parcelable {
@DataClass.ParcelWith(Parcelling.BuiltIn.ForInternedStringSet.class) @DataClass.ParcelWith(Parcelling.BuiltIn.ForInternedStringSet.class)
protected Set<String> deniedPermissions = emptySet(); protected Set<String> deniedPermissions = emptySet();
@Nullable
protected Boolean enableGwpAsan = null;
public ParsedProcess() { public ParsedProcess() {
} }
@@ -71,13 +74,15 @@ public class ParsedProcess implements Parcelable {
@DataClass.Generated.Member @DataClass.Generated.Member
public ParsedProcess( public ParsedProcess(
@NonNull String name, @NonNull String name,
@NonNull Set<String> deniedPermissions) { @NonNull Set<String> deniedPermissions,
@Nullable Boolean enableGwpAsan) {
this.name = name; this.name = name;
com.android.internal.util.AnnotationValidations.validate( com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, name); NonNull.class, null, name);
this.deniedPermissions = deniedPermissions; this.deniedPermissions = deniedPermissions;
com.android.internal.util.AnnotationValidations.validate( com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, deniedPermissions); NonNull.class, null, deniedPermissions);
this.enableGwpAsan = enableGwpAsan;
// onConstructed(); // You can define this method to get a callback // onConstructed(); // You can define this method to get a callback
} }
@@ -92,6 +97,11 @@ public class ParsedProcess implements Parcelable {
return deniedPermissions; return deniedPermissions;
} }
@DataClass.Generated.Member
public @Nullable Boolean getEnableGwpAsan() {
return enableGwpAsan;
}
@DataClass.Generated.Member @DataClass.Generated.Member
static Parcelling<Set<String>> sParcellingForDeniedPermissions = static Parcelling<Set<String>> sParcellingForDeniedPermissions =
Parcelling.Cache.get( Parcelling.Cache.get(
@@ -109,8 +119,12 @@ public class ParsedProcess implements Parcelable {
// You can override field parcelling by defining methods like: // You can override field parcelling by defining methods like:
// void parcelFieldName(Parcel dest, int flags) { ... } // void parcelFieldName(Parcel dest, int flags) { ... }
byte flg = 0;
if (enableGwpAsan != null) flg |= 0x4;
dest.writeByte(flg);
dest.writeString(name); dest.writeString(name);
sParcellingForDeniedPermissions.parcel(deniedPermissions, dest, flags); sParcellingForDeniedPermissions.parcel(deniedPermissions, dest, flags);
if (enableGwpAsan != null) dest.writeBoolean(enableGwpAsan);
} }
@Override @Override
@@ -124,8 +138,10 @@ public class ParsedProcess implements Parcelable {
// You can override field unparcelling by defining methods like: // You can override field unparcelling by defining methods like:
// static FieldType unparcelFieldName(Parcel in) { ... } // static FieldType unparcelFieldName(Parcel in) { ... }
byte flg = in.readByte();
String _name = in.readString(); String _name = in.readString();
Set<String> _deniedPermissions = sParcellingForDeniedPermissions.unparcel(in); Set<String> _deniedPermissions = sParcellingForDeniedPermissions.unparcel(in);
Boolean _enableGwpAsan = (flg & 0x4) == 0 ? null : (Boolean) in.readBoolean();
this.name = _name; this.name = _name;
com.android.internal.util.AnnotationValidations.validate( com.android.internal.util.AnnotationValidations.validate(
@@ -133,6 +149,7 @@ public class ParsedProcess implements Parcelable {
this.deniedPermissions = _deniedPermissions; this.deniedPermissions = _deniedPermissions;
com.android.internal.util.AnnotationValidations.validate( com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, deniedPermissions); NonNull.class, null, deniedPermissions);
this.enableGwpAsan = _enableGwpAsan;
// onConstructed(); // You can define this method to get a callback // onConstructed(); // You can define this method to get a callback
} }
@@ -152,10 +169,10 @@ public class ParsedProcess implements Parcelable {
}; };
@DataClass.Generated( @DataClass.Generated(
time = 1581452315946L, time = 1582589960479L,
codegenVersion = "1.0.14", codegenVersion = "1.0.14",
sourceFile = "frameworks/base/core/java/android/content/pm/parsing/component/ParsedProcess.java", sourceFile = "frameworks/base/core/java/android/content/pm/parsing/component/ParsedProcess.java",
inputSignatures = "protected @android.annotation.NonNull java.lang.String name\nprotected @android.annotation.NonNull @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedStringSet.class) java.util.Set<java.lang.String> deniedPermissions\npublic void addStateFrom(android.content.pm.parsing.component.ParsedProcess)\nclass ParsedProcess extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=false, genParcelable=true, genAidl=false, genBuilder=false)") inputSignatures = "protected @android.annotation.NonNull java.lang.String name\nprotected @android.annotation.NonNull @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedStringSet.class) java.util.Set<java.lang.String> deniedPermissions\nprotected @android.annotation.Nullable java.lang.Boolean enableGwpAsan\npublic void addStateFrom(android.content.pm.parsing.component.ParsedProcess)\nclass ParsedProcess extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=false, genParcelable=true, genAidl=false, genBuilder=false)")
@Deprecated @Deprecated
private void __metadata() {} private void __metadata() {}

View File

@@ -103,6 +103,11 @@ public class ParsedProcessUtils {
if (proc.name == null || proc.name.length() <= 0) { if (proc.name == null || proc.name.length() <= 0) {
return input.error("<process> does not specify android:process"); return input.error("<process> does not specify android:process");
} }
if (sa.hasValue(R.styleable.AndroidManifestProcess_enableGwpAsan)) {
proc.enableGwpAsan =
sa.getBoolean(R.styleable.AndroidManifestProcess_enableGwpAsan, false);
}
} finally { } finally {
sa.recycle(); sa.recycle();
} }

View File

@@ -140,6 +140,33 @@ public final class Zygote {
*/ */
public static final int MEMORY_TAG_LEVEL_SYNC = 3 << 19; public static final int MEMORY_TAG_LEVEL_SYNC = 3 << 19;
/**
* A two-bit field for GWP-ASan level of this process. See the possible values below.
*/
public static final int GWP_ASAN_LEVEL_MASK = (1 << 21) | (1 << 22);
/**
* Disable GWP-ASan in this process.
* GWP-ASan is a low-overhead memory bug detector using guard pages on a small
* subset of heap allocations.
*/
public static final int GWP_ASAN_LEVEL_NEVER = 0 << 21;
/**
* Enable GWP-ASan in this process with a small sampling rate.
* With approx. 1% chance GWP-ASan will be activated and apply its protection
* to a small subset of heap allocations.
* Otherwise (~99% chance) this process is unaffected.
*/
public static final int GWP_ASAN_LEVEL_LOTTERY = 1 << 21;
/**
* Always enable GWP-ASan in this process.
* GWP-ASan is activated unconditionally (but still, only a small subset of
* allocations is protected).
*/
public static final int GWP_ASAN_LEVEL_ALWAYS = 2 << 21;
/** No external storage should be mounted. */ /** No external storage should be mounted. */
public static final int MOUNT_EXTERNAL_NONE = IVold.REMOUNT_MODE_NONE; public static final int MOUNT_EXTERNAL_NONE = IVold.REMOUNT_MODE_NONE;
/** Default external storage should be mounted. */ /** Default external storage should be mounted. */

View File

@@ -221,6 +221,33 @@ public interface Parcelling<T> {
} }
} }
class ForInternedStringArraySet implements Parcelling<ArraySet<String>> {
@Override
public void parcel(ArraySet<String> item, Parcel dest, int parcelFlags) {
if (item == null) {
dest.writeInt(-1);
} else {
dest.writeInt(item.size());
for (String string : item) {
dest.writeString(string);
}
}
}
@Override
public ArraySet<String> unparcel(Parcel source) {
final int size = source.readInt();
if (size < 0) {
return null;
}
ArraySet<String> set = new ArraySet<>();
for (int count = 0; count < size; count++) {
set.add(TextUtils.safeIntern(source.readString()));
}
return set;
}
}
class ForBoolean implements Parcelling<Boolean> { class ForBoolean implements Parcelling<Boolean> {
@Override @Override
public void parcel(@Nullable Boolean item, Parcel dest, int parcelFlags) { public void parcel(@Nullable Boolean item, Parcel dest, int parcelFlags) {

View File

@@ -356,10 +356,14 @@ static const std::array<const std::string, MOUNT_EXTERNAL_COUNT> ExternalStorage
// Must match values in com.android.internal.os.Zygote. // Must match values in com.android.internal.os.Zygote.
enum RuntimeFlags : uint32_t { enum RuntimeFlags : uint32_t {
DEBUG_ENABLE_JDWP = 1, DEBUG_ENABLE_JDWP = 1,
PROFILE_FROM_SHELL = 1 << 15, PROFILE_FROM_SHELL = 1 << 15,
MEMORY_TAG_LEVEL_MASK = (1 << 19) | (1 << 20), MEMORY_TAG_LEVEL_MASK = (1 << 19) | (1 << 20),
MEMORY_TAG_LEVEL_TBI = 1 << 19, MEMORY_TAG_LEVEL_TBI = 1 << 19,
GWP_ASAN_LEVEL_MASK = (1 << 21) | (1 << 22),
GWP_ASAN_LEVEL_NEVER = 0 << 21,
GWP_ASAN_LEVEL_LOTTERY = 1 << 21,
GWP_ASAN_LEVEL_ALWAYS = 2 << 21,
}; };
enum UnsolicitedZygoteMessageTypes : uint32_t { enum UnsolicitedZygoteMessageTypes : uint32_t {
@@ -1741,6 +1745,18 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,
} }
android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &heap_tagging_level, sizeof(heap_tagging_level)); android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &heap_tagging_level, sizeof(heap_tagging_level));
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));
}
if (NeedsNoRandomizeWorkaround()) { if (NeedsNoRandomizeWorkaround()) {
// Work around ARM kernel ASLR lossage (http://b/5817320). // Work around ARM kernel ASLR lossage (http://b/5817320).
int old_personality = personality(0xffffffff); int old_personality = personality(0xffffffff);

View File

@@ -109,6 +109,7 @@ message ApplicationInfoProto {
} }
optional int32 network_security_config_res = 17; optional int32 network_security_config_res = 17;
optional int32 category = 18; optional int32 category = 18;
optional bool enable_gwp_asan = 19;
} }
optional Detail detail = 17; optional Detail detail = 17;
} }

View File

@@ -1541,6 +1541,28 @@
<flag name="microphone" value="0x80" /> <flag name="microphone" value="0x80" />
</attr> </attr>
<!-- Enable sampled memory bug detection in this process.
When enabled, a very small, random subset of native
memory allocations are protected with guard pages, providing an
ASan-like error report in case of a memory corruption bug.
GWP-ASan is a recursive acronym. It stands for “GWP-ASan Will Provide Allocation SANity”.
See the <a href="http://llvm.org/docs/GwpAsan.html">LLVM documentation</a>
for more information about this feature.
<p>This tag can be applied to any tag that allows
{@link android.R.styleable#AndroidManifestProcess process} tag:
{@link android.R.styleable#AndroidManifestApplication application} tag (to supply
a default setting for all application components), or with the
{@link android.R.styleable#AndroidManifestProvider provider},
{@link android.R.styleable#AndroidManifestService service},
{@link android.R.styleable#AndroidManifestReceiver receiver},
{@link android.R.styleable#AndroidManifestActivity activity} tag.
When multiple components run in the same process,
the first component to start determines the behavior of the entire process.
The default value is {@code false}. -->
<attr name="enableGwpAsan" format="boolean" />
<!-- The <code>manifest</code> tag is the root of an <!-- The <code>manifest</code> tag is the root of an
<code>AndroidManifest.xml</code> file, <code>AndroidManifest.xml</code> file,
@@ -1806,6 +1828,9 @@
The default value is {@code true}. --> The default value is {@code true}. -->
<attr name="allowNativeHeapPointerTagging" format="boolean" /> <attr name="allowNativeHeapPointerTagging" format="boolean" />
<attr name="enableGwpAsan" />
</declare-styleable> </declare-styleable>
<!-- The <code>feature</code> tag declares a feature. A feature is a logical part of an app. <!-- The <code>feature</code> tag declares a feature. A feature is a logical part of an app.
@@ -2312,6 +2337,7 @@
<declare-styleable name="AndroidManifestProcess" parent="AndroidManifestProcesses"> <declare-styleable name="AndroidManifestProcess" parent="AndroidManifestProcesses">
<!-- Required name of the process that is allowed --> <!-- Required name of the process that is allowed -->
<attr name="process" /> <attr name="process" />
<attr name="enableGwpAsan" />
</declare-styleable> </declare-styleable>
<!-- The <code>deny-permission</code> tag specifies that a permission is to be denied <!-- The <code>deny-permission</code> tag specifies that a permission is to be denied

View File

@@ -3015,6 +3015,7 @@
<public name="allowNativeHeapPointerTagging" /> <public name="allowNativeHeapPointerTagging" />
<public name="preserveLegacyExternalStorage" /> <public name="preserveLegacyExternalStorage" />
<public name="mimeGroup" /> <public name="mimeGroup" />
<public name="enableGwpAsan" />
</public-group> </public-group>
<public-group type="drawable" first-id="0x010800b5"> <public-group type="drawable" first-id="0x010800b5">

View File

@@ -61,6 +61,7 @@ import android.app.ApplicationExitInfo.SubReason;
import android.app.IApplicationThread; import android.app.IApplicationThread;
import android.app.IUidObserver; import android.app.IUidObserver;
import android.compat.annotation.ChangeId; import android.compat.annotation.ChangeId;
import android.compat.annotation.Disabled;
import android.compat.annotation.EnabledAfter; import android.compat.annotation.EnabledAfter;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.ComponentName; import android.content.ComponentName;
@@ -70,6 +71,7 @@ import android.content.IntentFilter;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager; import android.content.pm.IPackageManager;
import android.content.pm.PackageManagerInternal; import android.content.pm.PackageManagerInternal;
import android.content.pm.ProcessInfo;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Point; import android.graphics.Point;
import android.net.LocalSocket; import android.net.LocalSocket;
@@ -344,6 +346,14 @@ public final class ProcessList {
@EnabledAfter(targetSdkVersion = VersionCodes.Q) @EnabledAfter(targetSdkVersion = VersionCodes.Q)
private static final long NATIVE_HEAP_POINTER_TAGGING = 135754954; // This is a bug id. private static final long NATIVE_HEAP_POINTER_TAGGING = 135754954; // 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 * Apps have no access to the private data directories of any other app, even if the other
* app has made them world-readable. * app has made them world-readable.
@@ -1634,6 +1644,28 @@ public final class ProcessList {
return gidArray; return gidArray;
} }
private int decideGwpAsanLevel(ProcessRecord app) {
// Look at the process attribute first.
if (app.processInfo != null && app.processInfo.enableGwpAsan != null) {
return app.processInfo.enableGwpAsan ? Zygote.GWP_ASAN_LEVEL_ALWAYS
: Zygote.GWP_ASAN_LEVEL_NEVER;
}
// Then at the applicaton attribute.
if (app.info.isGwpAsanEnabled() != null) {
return app.info.isGwpAsanEnabled() ? Zygote.GWP_ASAN_LEVEL_ALWAYS
: Zygote.GWP_ASAN_LEVEL_NEVER;
}
// If the app does not specify enableGwpAsan, 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;
}
/** /**
* @return {@code true} if process start is successful, false otherwise. * @return {@code true} if process start is successful, false otherwise.
*/ */
@@ -1803,6 +1835,8 @@ public final class ProcessList {
runtimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI; runtimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI;
} }
runtimeFlags |= decideGwpAsanLevel(app);
String invokeWith = null; String invokeWith = null;
if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
// Debuggable apps may include a wrapper script with their library directory. // Debuggable apps may include a wrapper script with their library directory.

View File

@@ -384,6 +384,9 @@ class ProcessRecord implements WindowProcessListener {
pw.println(processInfo.deniedPermissions.valueAt(i)); pw.println(processInfo.deniedPermissions.valueAt(i));
} }
} }
if (processInfo.enableGwpAsan != null) {
pw.print(prefix); pw.println(" enableGwpAsan=" + processInfo.enableGwpAsan);
}
} }
pw.print(prefix); pw.print("mRequiredAbi="); pw.print(mRequiredAbi); pw.print(prefix); pw.print("mRequiredAbi="); pw.print(mRequiredAbi);
pw.print(" instructionSet="); pw.println(instructionSet); pw.print(" instructionSet="); pw.println(instructionSet);

View File

@@ -391,8 +391,9 @@ public class PackageInfoUtils {
ArrayMap<String, ProcessInfo> retProcs = new ArrayMap<>(numProcs); ArrayMap<String, ProcessInfo> retProcs = new ArrayMap<>(numProcs);
for (String key : procs.keySet()) { for (String key : procs.keySet()) {
ParsedProcess proc = procs.get(key); ParsedProcess proc = procs.get(key);
retProcs.put(proc.getName(), new ProcessInfo(proc.getName(), retProcs.put(proc.getName(),
new ArraySet<>(proc.getDeniedPermissions()))); new ProcessInfo(proc.getName(), new ArraySet<>(proc.getDeniedPermissions()),
proc.getEnableGwpAsan()));
} }
return retProcs; return retProcs;
} }