Merge "Revert^2 "Verify that the component is exported""
This commit is contained in:
committed by
Android (Google) Code Review
commit
8378ff9423
@@ -4216,13 +4216,23 @@ public class ActivityManager {
|
||||
}
|
||||
}*/
|
||||
|
||||
/** @hide
|
||||
* Determines whether the given UID can access unexported components
|
||||
* @param uid the calling UID
|
||||
* @return true if the calling UID is ROOT or SYSTEM
|
||||
*/
|
||||
public static boolean canAccessUnexportedComponents(int uid) {
|
||||
final int appId = UserHandle.getAppId(uid);
|
||||
return (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@UnsupportedAppUsage
|
||||
public static int checkComponentPermission(String permission, int uid,
|
||||
int owningUid, boolean exported) {
|
||||
// Root, system server get to do everything.
|
||||
final int appId = UserHandle.getAppId(uid);
|
||||
if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID) {
|
||||
if (canAccessUnexportedComponents(uid)) {
|
||||
return PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
// Isolated processes don't get any permissions.
|
||||
|
||||
@@ -576,6 +576,14 @@ public abstract class PackageManagerInternal {
|
||||
@PrivateResolveFlags long privateResolveFlags, int userId, boolean resolveForStart,
|
||||
int filterCallingUid);
|
||||
|
||||
/**
|
||||
* Resolves an exported activity intent, allowing instant apps to be resolved.
|
||||
*/
|
||||
public abstract ResolveInfo resolveIntentExported(Intent intent, String resolvedType,
|
||||
@PackageManager.ResolveInfoFlagsBits long flags,
|
||||
@PrivateResolveFlags long privateResolveFlags, int userId, boolean resolveForStart,
|
||||
int filterCallingUid);
|
||||
|
||||
/**
|
||||
* Resolves a service intent, allowing instant apps to be resolved.
|
||||
*/
|
||||
|
||||
@@ -215,6 +215,7 @@ import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetManagerInternal;
|
||||
import android.compat.annotation.ChangeId;
|
||||
import android.compat.annotation.Disabled;
|
||||
import android.compat.annotation.EnabledAfter;
|
||||
import android.content.AttributionSource;
|
||||
import android.content.AutofillOptions;
|
||||
import android.content.BroadcastReceiver;
|
||||
@@ -584,6 +585,17 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
@Disabled
|
||||
private static final long DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED = 161145287L;
|
||||
|
||||
/**
|
||||
* Apps targeting Android U and above will need to export components in order to invoke them
|
||||
* through implicit intents.
|
||||
*
|
||||
* If a component is not exported and invoked, it will be removed from the list of receivers.
|
||||
* This applies specifically to activities and broadcasts.
|
||||
*/
|
||||
@ChangeId
|
||||
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
|
||||
public static final long IMPLICIT_INTENTS_ONLY_MATCH_EXPORTED_COMPONENTS = 229362273;
|
||||
|
||||
/**
|
||||
* The maximum number of bytes that {@link #setProcessStateSummary} accepts.
|
||||
*
|
||||
@@ -12378,6 +12390,58 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters out non-exported components in a given list of broadcast filters
|
||||
* @param intent the original intent
|
||||
* @param callingUid the calling UID
|
||||
* @param query the list of broadcast filters
|
||||
* @param platformCompat the instance of platform compat
|
||||
*/
|
||||
private static void filterNonExportedComponents(Intent intent, int callingUid,
|
||||
List query, PlatformCompat platformCompat, String callerPackage) {
|
||||
if (query == null
|
||||
|| intent.getPackage() != null
|
||||
|| intent.getComponent() != null
|
||||
|| ActivityManager.canAccessUnexportedComponents(callingUid)) {
|
||||
return;
|
||||
}
|
||||
for (int i = query.size() - 1; i >= 0; i--) {
|
||||
String componentInfo;
|
||||
ResolveInfo resolveInfo;
|
||||
BroadcastFilter broadcastFilter;
|
||||
if (query.get(i) instanceof ResolveInfo) {
|
||||
resolveInfo = (ResolveInfo) query.get(i);
|
||||
if (resolveInfo.getComponentInfo().exported) {
|
||||
continue;
|
||||
}
|
||||
componentInfo = resolveInfo.getComponentInfo()
|
||||
.getComponentName().flattenToShortString();
|
||||
} else if (query.get(i) instanceof BroadcastFilter) {
|
||||
broadcastFilter = (BroadcastFilter) query.get(i);
|
||||
if (broadcastFilter.exported) {
|
||||
continue;
|
||||
}
|
||||
componentInfo = broadcastFilter.packageName;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
if (!platformCompat.isChangeEnabledByUid(
|
||||
IMPLICIT_INTENTS_ONLY_MATCH_EXPORTED_COMPONENTS, callingUid)) {
|
||||
Slog.w(TAG, "Non-exported component not filtered out "
|
||||
+ "(will be filtered out once the app targets U+)- intent: "
|
||||
+ intent.getAction() + ", component: "
|
||||
+ componentInfo + ", sender: "
|
||||
+ callerPackage);
|
||||
return;
|
||||
}
|
||||
Slog.w(TAG, "Non-exported component filtered out - intent: "
|
||||
+ intent.getAction() + ", component: "
|
||||
+ componentInfo + ", sender: "
|
||||
+ callerPackage);
|
||||
query.remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main code for cleaning up a process when it has gone away. This is
|
||||
* called both as a result of the process dying, or directly when stopping
|
||||
@@ -14217,6 +14281,8 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
filterNonExportedComponents(intent, callingUid, registeredReceivers,
|
||||
mPlatformCompat, callerPackage);
|
||||
int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
|
||||
if (!ordered && NR > 0) {
|
||||
// If we are not serializing this broadcast, then send the
|
||||
@@ -14319,6 +14385,8 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
if ((receivers != null && receivers.size() > 0)
|
||||
|| resultTo != null) {
|
||||
BroadcastQueue queue = broadcastQueueForIntent(intent);
|
||||
filterNonExportedComponents(intent, callingUid, receivers,
|
||||
mPlatformCompat, callerPackage);
|
||||
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
|
||||
callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
|
||||
requiredPermissions, excludedPermissions, excludedPackages, appOp, brOptions,
|
||||
|
||||
@@ -465,6 +465,20 @@ abstract class PackageManagerInternalBase extends PackageManagerInternal {
|
||||
filterCallingUid);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated similar to {@link resolveIntent} but limits the matches to exported components.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public final ResolveInfo resolveIntentExported(Intent intent, String resolvedType,
|
||||
@PackageManager.ResolveInfoFlagsBits long flags,
|
||||
@PackageManagerInternal.PrivateResolveFlags long privateResolveFlags, int userId,
|
||||
boolean resolveForStart, int filterCallingUid) {
|
||||
return getResolveIntentHelper().resolveIntentInternal(snapshot(),
|
||||
intent, resolvedType, flags, privateResolveFlags, userId, resolveForStart,
|
||||
filterCallingUid, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public final ResolveInfo resolveService(Intent intent, String resolvedType,
|
||||
|
||||
@@ -52,6 +52,7 @@ import android.util.Slog;
|
||||
|
||||
import com.android.internal.app.ResolverActivity;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.server.am.ActivityManagerService;
|
||||
import com.android.server.compat.PlatformCompat;
|
||||
import com.android.server.pm.pkg.AndroidPackage;
|
||||
import com.android.server.pm.pkg.PackageStateInternal;
|
||||
@@ -100,6 +101,38 @@ final class ResolveIntentHelper {
|
||||
mInstantAppInstallerActivitySupplier = instantAppInstallerActivitySupplier;
|
||||
}
|
||||
|
||||
private static void filterNonExportedComponents(Intent intent, int filterCallingUid,
|
||||
List<ResolveInfo> query, PlatformCompat platformCompat, Computer computer) {
|
||||
if (query == null
|
||||
|| intent.getPackage() != null
|
||||
|| intent.getComponent() != null
|
||||
|| ActivityManager.canAccessUnexportedComponents(filterCallingUid)) {
|
||||
return;
|
||||
}
|
||||
AndroidPackage caller = computer.getPackage(filterCallingUid);
|
||||
String callerPackage = caller == null ? "Not specified" : caller.getPackageName();
|
||||
for (int i = query.size() - 1; i >= 0; i--) {
|
||||
if (!query.get(i).getComponentInfo().exported) {
|
||||
if (!platformCompat.isChangeEnabledByUid(
|
||||
ActivityManagerService.IMPLICIT_INTENTS_ONLY_MATCH_EXPORTED_COMPONENTS,
|
||||
filterCallingUid)) {
|
||||
Slog.w(TAG, "Non-exported component not filtered out "
|
||||
+ "(will be filtered out once the app targets U+)- intent: "
|
||||
+ intent.getAction() + ", component: "
|
||||
+ query.get(i).getComponentInfo()
|
||||
.getComponentName().flattenToShortString()
|
||||
+ ", starter: " + callerPackage);
|
||||
return;
|
||||
}
|
||||
Slog.w(TAG, "Non-exported component filtered out - intent: "
|
||||
+ intent.getAction() + ", component: "
|
||||
+ query.get(i).getComponentInfo().getComponentName().flattenToShortString()
|
||||
+ ", starter: " + callerPackage);
|
||||
query.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Normally instant apps can only be resolved when they're visible to the caller.
|
||||
* However, if {@code resolveForStart} is {@code true}, all instant apps are visible
|
||||
@@ -109,6 +142,20 @@ final class ResolveIntentHelper {
|
||||
@PackageManager.ResolveInfoFlagsBits long flags,
|
||||
@PackageManagerInternal.PrivateResolveFlags long privateResolveFlags, int userId,
|
||||
boolean resolveForStart, int filterCallingUid) {
|
||||
return resolveIntentInternal(computer, intent, resolvedType, flags,
|
||||
privateResolveFlags, userId, resolveForStart, filterCallingUid, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normally instant apps can only be resolved when they're visible to the caller.
|
||||
* However, if {@code resolveForStart} is {@code true}, all instant apps are visible
|
||||
* since we need to allow the system to start any installed application.
|
||||
* Allows picking exported components only.
|
||||
*/
|
||||
public ResolveInfo resolveIntentInternal(Computer computer, Intent intent, String resolvedType,
|
||||
@PackageManager.ResolveInfoFlagsBits long flags,
|
||||
@PackageManagerInternal.PrivateResolveFlags long privateResolveFlags, int userId,
|
||||
boolean resolveForStart, int filterCallingUid, boolean exportedComponentsOnly) {
|
||||
try {
|
||||
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent");
|
||||
|
||||
@@ -124,6 +171,10 @@ final class ResolveIntentHelper {
|
||||
final List<ResolveInfo> query = computer.queryIntentActivitiesInternal(intent,
|
||||
resolvedType, flags, privateResolveFlags, filterCallingUid, userId,
|
||||
resolveForStart, true /*allowDynamicSplits*/);
|
||||
if (exportedComponentsOnly) {
|
||||
filterNonExportedComponents(intent, filterCallingUid, query,
|
||||
mPlatformCompat, computer);
|
||||
}
|
||||
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
|
||||
|
||||
final boolean queryMayBeFiltered =
|
||||
|
||||
@@ -744,7 +744,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
|
||||
// (e.g. AMS.startActivityAsUser).
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return mService.getPackageManagerInternalLocked().resolveIntent(
|
||||
return mService.getPackageManagerInternalLocked().resolveIntentExported(
|
||||
intent, resolvedType, modifiedFlags, privateResolveFlags, userId, true,
|
||||
filterCallingUid);
|
||||
} finally {
|
||||
|
||||
@@ -379,6 +379,8 @@ public class ActivityStarterTests extends WindowTestsBase {
|
||||
doReturn(false).when(mMockPackageManager).isInstantAppInstallerComponent(any());
|
||||
doReturn(null).when(mMockPackageManager).resolveIntent(any(), any(), anyLong(), anyLong(),
|
||||
anyInt(), anyBoolean(), anyInt());
|
||||
doReturn(null).when(mMockPackageManager).resolveIntentExported(any(), any(),
|
||||
anyLong(), anyLong(), anyInt(), anyBoolean(), anyInt());
|
||||
doReturn(new ComponentName("", "")).when(mMockPackageManager).getSystemUiServiceComponent();
|
||||
|
||||
// Never review permissions
|
||||
|
||||
Reference in New Issue
Block a user