From 7bc3a70966f17bf16acbf4fe640dab0698866d72 Mon Sep 17 00:00:00 2001 From: Todd Kennedy Date: Thu, 8 Dec 2016 14:54:48 -0800 Subject: [PATCH] Scope package manager queries for ephemeral apps Ephemeral apps can only see their own components or those components exposed via the "visibleToEphemeral" XML attribute. Normal apps can only see other normal apps. There is no way to expose ephemeral components to normal apps. Bug: 33458220 Test: Manually install ephemeral/normal apps and ensure they can only see appropriate components Change-Id: I6ae65fd2a6ddc9aa9691f02cd55d4953048966b0 --- api/current.txt | 1 + api/system-current.txt | 1 + api/test-current.txt | 1 + core/java/android/content/IntentFilter.java | 22 +++ .../java/android/content/pm/ActivityInfo.java | 6 + .../android/content/pm/PackageManager.java | 14 ++ .../android/content/pm/PackageParser.java | 62 +++++++-- .../java/android/content/pm/ProviderInfo.java | 6 + core/java/android/content/pm/ServiceInfo.java | 6 + core/res/res/values/attrs_manifest.xml | 9 +- core/res/res/values/public.xml | 1 + .../com/android/server/IntentResolver.java | 37 +++-- .../server/am/ActivityManagerService.java | 6 +- .../server/firewall/IntentFirewall.java | 3 +- .../android/server/pm/EphemeralResolver.java | 5 +- .../server/pm/PackageManagerService.java | 129 ++++++++++++++---- 16 files changed, 254 insertions(+), 55 deletions(-) diff --git a/api/current.txt b/api/current.txt index 5a2df57e23277..583ca92c215e6 100644 --- a/api/current.txt +++ b/api/current.txt @@ -1425,6 +1425,7 @@ package android { field public static final int viewportWidth = 16843778; // 0x1010402 field public static final int visibility = 16842972; // 0x10100dc field public static final int visible = 16843156; // 0x1010194 + field public static final int visibleToEphemeral = 16844095; // 0x101053f field public static final int vmSafeMode = 16843448; // 0x10102b8 field public static final int voiceIcon = 16843908; // 0x1010484 field public static final int voiceLanguage = 16843349; // 0x1010255 diff --git a/api/system-current.txt b/api/system-current.txt index 9d113dbb06851..c49dcb413cb59 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1536,6 +1536,7 @@ package android { field public static final int viewportWidth = 16843778; // 0x1010402 field public static final int visibility = 16842972; // 0x10100dc field public static final int visible = 16843156; // 0x1010194 + field public static final int visibleToEphemeral = 16844095; // 0x101053f field public static final int vmSafeMode = 16843448; // 0x10102b8 field public static final int voiceIcon = 16843908; // 0x1010484 field public static final int voiceLanguage = 16843349; // 0x1010255 diff --git a/api/test-current.txt b/api/test-current.txt index 20b723da4db21..3eaa381e9a1c2 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -1425,6 +1425,7 @@ package android { field public static final int viewportWidth = 16843778; // 0x1010402 field public static final int visibility = 16842972; // 0x10100dc field public static final int visible = 16843156; // 0x1010194 + field public static final int visibleToEphemeral = 16844095; // 0x101053f field public static final int vmSafeMode = 16843448; // 0x10102b8 field public static final int voiceIcon = 16843908; // 0x1010484 field public static final int voiceLanguage = 16843349; // 0x1010255 diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java index f5a79c8c13eb3..2c97ec42591f9 100644 --- a/core/java/android/content/IntentFilter.java +++ b/core/java/android/content/IntentFilter.java @@ -282,6 +282,10 @@ public class IntentFilter implements Parcelable { private int mVerifyState; + /** Whether or not the intent filter is visible to ephemeral apps. */ + private boolean mVisibleToEphemeral; + /** Whether or not the intent filter is part of an ephemeral app. */ + private boolean mEphemeral; // These functions are the start of more optimized code for managing // the string sets... not yet implemented. @@ -647,6 +651,24 @@ public class IntentFilter implements Parcelable { if (verified) mVerifyState |= STATE_VERIFIED; } + /** @hide */ + public void setVisibleToEphemeral(boolean visibleToEmphemeral) { + mVisibleToEphemeral = visibleToEmphemeral; + } + /** @hide */ + public boolean isVisibleToEphemeral() { + return mVisibleToEphemeral; + } + + /** @hide */ + public void setEphemeral(boolean ephemeral) { + mEphemeral = ephemeral; + } + /** @hide */ + public boolean isEphemeral() { + return mEphemeral; + } + /** * Add a new Intent action to match against. If any actions are included * in the filter, then an Intent's action must be one of those values for diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index 5d90acc068573..44dff002fa01a 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -362,6 +362,12 @@ public class ActivityInfo extends ComponentInfo */ public static final int FLAG_ON_TOP_LAUNCHER = 0x80000; + /** + * Bit in {@link #flags} indicating if the activity is visible to ephemeral applications. + * @hide + */ + public static final int FLAG_VISIBLE_TO_EPHEMERAL = 0x100000; + /** * @hide Bit in {@link #flags}: If set, this component will only be seen * by the system user. Only works with broadcast receivers. Set from the diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 3f052d38a2c67..b4e60d8e913dc 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -448,6 +448,20 @@ public abstract class PackageManager { */ public static final int MATCH_KNOWN_PACKAGES = MATCH_UNINSTALLED_PACKAGES | MATCH_ANY_USER; + /** + * Internal {@link PackageInfo} flag: include components that are part of an + * ephemeral app. By default, ephemeral components are not matched. + * @hide + */ + public static final int MATCH_EPHEMERAL = 0x00800000; + + /** + * Internal {@link PackageInfo} flag: include only components that are exposed to + * ephemeral apps. + * @hide + */ + public static final int MATCH_VISIBLE_TO_EPHEMERAL_ONLY = 0x01000000; + /** * Internal flag used to indicate that a system component has done their * homework and verified that they correctly handle packages and components diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 9b2dd68d2676a..d7c3722a1d556 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -3780,6 +3780,13 @@ public class PackageParser { ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE; } + final boolean isEphemeral = ((flags & PARSE_IS_EPHEMERAL) != 0); + final boolean visibleToEphemeral = isEphemeral + || sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToEphemeral, false); + if (visibleToEphemeral) { + a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL; + } + sa.recycle(); if (receiver && (owner.applicationInfo.privateFlags @@ -3806,9 +3813,12 @@ public class PackageParser { if (parser.getName().equals("intent-filter")) { ActivityIntentInfo intent = new ActivityIntentInfo(a); - if (!parseIntent(res, parser, true, true, intent, outError)) { + if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/, + intent, outError)) { return null; } + intent.setEphemeral(isEphemeral); + intent.setVisibleToEphemeral(visibleToEphemeral); if (intent.countActions() == 0) { Slog.w(TAG, "No actions in intent filter at " + mArchiveSourcePath + " " @@ -3818,9 +3828,12 @@ public class PackageParser { } } else if (!receiver && parser.getName().equals("preferred")) { ActivityIntentInfo intent = new ActivityIntentInfo(a); - if (!parseIntent(res, parser, false, false, intent, outError)) { + if (!parseIntent(res, parser, false /*allowGlobs*/, false /*allowAutoVerify*/, + intent, outError)) { return null; } + intent.setEphemeral(isEphemeral); + intent.setVisibleToEphemeral(visibleToEphemeral); if (intent.countActions() == 0) { Slog.w(TAG, "No actions in preferred at " + mArchiveSourcePath + " " @@ -4071,6 +4084,10 @@ public class PackageParser { } } + final boolean isEphemeral = ((flags & PARSE_IS_EPHEMERAL) != 0); + final boolean visibleToEphemeral = isEphemeral + || ((a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) != 0); + sa.recycle(); if (outError[0] != null) { @@ -4088,7 +4105,8 @@ public class PackageParser { if (parser.getName().equals("intent-filter")) { ActivityIntentInfo intent = new ActivityIntentInfo(a); - if (!parseIntent(res, parser, true, true, intent, outError)) { + if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/, + intent, outError)) { return null; } if (intent.countActions() == 0) { @@ -4096,6 +4114,8 @@ public class PackageParser { + mArchiveSourcePath + " " + parser.getPositionDescription()); } else { + intent.setEphemeral(isEphemeral); + intent.setVisibleToEphemeral(visibleToEphemeral); a.intents.add(intent); } } else if (parser.getName().equals("meta-data")) { @@ -4233,6 +4253,13 @@ public class PackageParser { ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE; } + final boolean isEphemeral = ((flags & PARSE_IS_EPHEMERAL) != 0); + final boolean visibleToEphemeral = isEphemeral + || sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToEphemeral, false); + if (visibleToEphemeral) { + p.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL; + } + sa.recycle(); if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) @@ -4255,15 +4282,15 @@ public class PackageParser { } p.info.authority = cpname.intern(); - if (!parseProviderTags(res, parser, p, outError)) { + if (!parseProviderTags(res, parser, isEphemeral, visibleToEphemeral, p, outError)) { return null; } return p; } - private boolean parseProviderTags(Resources res, - XmlResourceParser parser, Provider outInfo, String[] outError) + private boolean parseProviderTags(Resources res, XmlResourceParser parser, + boolean isEphemeral, boolean visibleToEphemeral, Provider outInfo, String[] outError) throws XmlPullParserException, IOException { int outerDepth = parser.getDepth(); int type; @@ -4276,9 +4303,12 @@ public class PackageParser { if (parser.getName().equals("intent-filter")) { ProviderIntentInfo intent = new ProviderIntentInfo(outInfo); - if (!parseIntent(res, parser, true, false, intent, outError)) { + if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/, + intent, outError)) { return false; } + intent.setEphemeral(isEphemeral); + intent.setVisibleToEphemeral(visibleToEphemeral); outInfo.intents.add(intent); } else if (parser.getName().equals("meta-data")) { @@ -4526,6 +4556,13 @@ public class PackageParser { ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE; } + final boolean isEphemeral = ((flags & PARSE_IS_EPHEMERAL) != 0); + final boolean visibleToEphemeral = isEphemeral + || sa.getBoolean(R.styleable.AndroidManifestService_visibleToEphemeral, false); + if (visibleToEphemeral) { + s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_EPHEMERAL; + } + sa.recycle(); if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) @@ -4549,9 +4586,12 @@ public class PackageParser { if (parser.getName().equals("intent-filter")) { ServiceIntentInfo intent = new ServiceIntentInfo(s); - if (!parseIntent(res, parser, true, false, intent, outError)) { + if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/, + intent, outError)) { return null; } + intent.setEphemeral(isEphemeral); + intent.setVisibleToEphemeral(visibleToEphemeral); s.intents.add(intent); } else if (parser.getName().equals("meta-data")) { @@ -4755,9 +4795,9 @@ public class PackageParser { private static final String ANDROID_RESOURCES = "http://schemas.android.com/apk/res/android"; - private boolean parseIntent(Resources res, XmlResourceParser parser, - boolean allowGlobs, boolean allowAutoVerify, IntentInfo outInfo, String[] outError) - throws XmlPullParserException, IOException { + private boolean parseIntent(Resources res, XmlResourceParser parser, boolean allowGlobs, + boolean allowAutoVerify, IntentInfo outInfo, String[] outError) + throws XmlPullParserException, IOException { TypedArray sa = res.obtainAttributes(parser, com.android.internal.R.styleable.AndroidManifestIntentFilter); diff --git a/core/java/android/content/pm/ProviderInfo.java b/core/java/android/content/pm/ProviderInfo.java index 7e7b32f03fd19..8c21563198abb 100644 --- a/core/java/android/content/pm/ProviderInfo.java +++ b/core/java/android/content/pm/ProviderInfo.java @@ -75,6 +75,12 @@ public final class ProviderInfo extends ComponentInfo * running in the same process. Higher goes first. */ public int initOrder = 0; + /** + * Bit in {@link #flags} indicating if the provider is visible to ephemeral applications. + * @hide + */ + public static final int FLAG_VISIBLE_TO_EPHEMERAL = 0x100000; + /** * Bit in {@link #flags}: If set, a single instance of the provider will * run for all users on the device. Set from the diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java index 6bd285a6c3942..f0766beb5d3f7 100644 --- a/core/java/android/content/pm/ServiceInfo.java +++ b/core/java/android/content/pm/ServiceInfo.java @@ -55,6 +55,12 @@ public class ServiceInfo extends ComponentInfo */ public static final int FLAG_EXTERNAL_SERVICE = 0x0004; + /** + * Bit in {@link #flags} indicating if the service is visible to ephemeral applications. + * @hide + */ + public static final int FLAG_VISIBLE_TO_EPHEMERAL = 0x100000; + /** * Bit in {@link #flags}: If set, a single instance of the service will * run for all users on the device. Set from the diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 967c4ad340ece..c91f0a51d5bda 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -1209,6 +1209,10 @@ --> + + + @@ -1731,6 +1735,7 @@ + + - + +