Merge "Hookup renounced permissions" into sc-dev

This commit is contained in:
Svetoslav Ganov
2021-04-05 00:55:30 +00:00
committed by Android (Google) Code Review
12 changed files with 59 additions and 34 deletions

View File

@@ -9935,9 +9935,9 @@ package android.content {
public static final class AttributionSource.Builder {
ctor public AttributionSource.Builder(int);
method @NonNull public android.content.AttributionSource build();
method @NonNull public android.content.AttributionSource.Builder setAttributionTag(@NonNull String);
method @NonNull public android.content.AttributionSource.Builder setNext(@NonNull android.content.AttributionSource);
method @NonNull public android.content.AttributionSource.Builder setPackageName(@NonNull String);
method @NonNull public android.content.AttributionSource.Builder setAttributionTag(@Nullable String);
method @NonNull public android.content.AttributionSource.Builder setNext(@Nullable android.content.AttributionSource);
method @NonNull public android.content.AttributionSource.Builder setPackageName(@Nullable String);
}
public abstract class BroadcastReceiver {

View File

@@ -2235,7 +2235,7 @@ package android.content {
}
public static final class AttributionSource.Builder {
method @NonNull @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS) public android.content.AttributionSource.Builder setRenouncedPermissions(@NonNull java.util.Set<java.lang.String>);
method @NonNull @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS) public android.content.AttributionSource.Builder setRenouncedPermissions(@Nullable java.util.Set<java.lang.String>);
}
public abstract class BroadcastReceiver {

View File

@@ -666,6 +666,7 @@ package android.content {
public final class AttributionSource implements android.os.Parcelable {
ctor public AttributionSource(int, @Nullable String, @Nullable String);
ctor public AttributionSource(int, @Nullable String, @Nullable String, @Nullable android.content.AttributionSource);
ctor public AttributionSource(int, @Nullable String, @Nullable String, @Nullable java.util.Set<java.lang.String>, @Nullable android.content.AttributionSource);
}
public final class AutofillOptions implements android.os.Parcelable {
@@ -1985,6 +1986,7 @@ package android.permission {
public final class PermissionManager {
method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.permission.PermGroupUsage> getIndicatorAppOpUsageData();
method @NonNull public android.content.AttributionSource registerAttributionSource(@NonNull android.content.AttributionSource);
}
}

View File

@@ -5254,32 +5254,17 @@ public class Activity extends ContextThemeWrapper
return;
}
List<String> filteredPermissions = null;
if (!getAttributionSource().getRenouncedPermissions().isEmpty()) {
final int permissionCount = permissions.length;
for (int i = 0; i < permissionCount; i++) {
if (getAttributionSource().getRenouncedPermissions().contains(permissions[i])) {
if (filteredPermissions == null) {
filteredPermissions = new ArrayList<>(i);
for (int j = 0; j < i; j++) {
filteredPermissions.add(permissions[i]);
}
}
} else if (filteredPermissions != null) {
filteredPermissions.add(permissions[i]);
throw new IllegalArgumentException("Cannot request renounced permission: "
+ permissions[i]);
}
}
}
final Intent intent;
if (filteredPermissions == null) {
intent = getPackageManager().buildRequestPermissionsIntent(permissions);
} else {
intent = getPackageManager().buildRequestPermissionsIntent(
filteredPermissions.toArray(new String[0]));
}
final Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);
startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);
mHasCurrentPermissionsRequest = true;
}

View File

@@ -115,6 +115,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executor;
class ReceiverRestrictedContext extends ContextWrapper {
@@ -3074,14 +3075,16 @@ class ContextImpl extends Context {
mOpPackageName = overrideOpPackageName != null ? overrideOpPackageName : opPackageName;
mParams = Objects.requireNonNull(params);
mAttributionSource = createAttributionSource(attributionTag, nextAttributionSource);
mAttributionSource = createAttributionSource(attributionTag, nextAttributionSource,
params.getRenouncedPermissions());
mContentResolver = new ApplicationContentResolver(this, mainThread);
}
private @NonNull AttributionSource createAttributionSource(@Nullable String attributionTag,
@Nullable AttributionSource nextAttributionSource) {
AttributionSource attributionSource = new AttributionSource(Process.myUid(), mOpPackageName,
attributionTag, nextAttributionSource);
@Nullable AttributionSource nextAttributionSource,
@Nullable Set<String> renouncedPermissions) {
AttributionSource attributionSource = new AttributionSource(Process.myUid(),
mOpPackageName, attributionTag, renouncedPermissions, nextAttributionSource);
// If we want to access protected data on behalf of another app we need to
// tell the OS that we opt in to participate in the attribution chain.
if (nextAttributionSource != null) {

View File

@@ -178,6 +178,15 @@ public final class AttributionSource implements Parcelable {
/*renouncedPermissions*/ null, next);
}
/** @hide */
@TestApi
public AttributionSource(int uid, @Nullable String packageName,
@Nullable String attributionTag, @Nullable Set<String> renouncedPermissions,
@Nullable AttributionSource next) {
this(uid, packageName, attributionTag, /*token*/ null,
renouncedPermissions, next);
}
/** @hide */
public AttributionSource(@NonNull AttributionSource current,
@Nullable AttributionSource next) {
@@ -526,7 +535,7 @@ public final class AttributionSource implements Parcelable {
/**
* The package that is accessing the permission protected data.
*/
public @NonNull Builder setPackageName(@NonNull String value) {
public @NonNull Builder setPackageName(@Nullable String value) {
checkNotUsed();
mBuilderFieldsSet |= 0x2;
mPackageName = value;
@@ -536,7 +545,7 @@ public final class AttributionSource implements Parcelable {
/**
* The attribution tag of the app accessing the permission protected data.
*/
public @NonNull Builder setAttributionTag(@NonNull String value) {
public @NonNull Builder setAttributionTag(@Nullable String value) {
checkNotUsed();
mBuilderFieldsSet |= 0x4;
mAttributionTag = value;
@@ -550,7 +559,7 @@ public final class AttributionSource implements Parcelable {
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS)
public @NonNull Builder setRenouncedPermissions(@NonNull Set<String> value) {
public @NonNull Builder setRenouncedPermissions(@Nullable Set<String> value) {
checkNotUsed();
mBuilderFieldsSet |= 0x10;
mRenouncedPermissions = value;
@@ -560,7 +569,7 @@ public final class AttributionSource implements Parcelable {
/**
* The next app to receive the permission protected data.
*/
public @NonNull Builder setNext(@NonNull AttributionSource value) {
public @NonNull Builder setNext(@Nullable AttributionSource value) {
checkNotUsed();
mBuilderFieldsSet |= 0x20;
mNext = value;

View File

@@ -16,10 +16,13 @@
package android.content;
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.app.ActivityThread;
import android.content.pm.PackageManager;
import java.util.Collections;
import java.util.Objects;
@@ -179,6 +182,13 @@ public final class ContextParams {
@RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS)
public @NonNull Builder setRenouncedPermissions(
@Nullable Set<String> renouncedPermissions) {
// This is not a security check but a fail fast - the OS enforces the permission too
if (renouncedPermissions != null && !renouncedPermissions.isEmpty()
&& ActivityThread.currentApplication().checkSelfPermission(Manifest.permission
.RENOUNCE_PERMISSIONS) != PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Renouncing permissions requires: "
+ Manifest.permission.RENOUNCE_PERMISSIONS);
}
mRenouncedPermissions = renouncedPermissions;
return this;
}

View File

@@ -979,7 +979,9 @@ public final class PermissionChecker {
int uid, @NonNull Set<String> renouncedPermissions) {
final boolean permissionGranted = context.checkPermission(permission, /*pid*/ -1,
uid) == PackageManager.PERMISSION_GRANTED;
if (permissionGranted && renouncedPermissions.contains(permission)) {
if (permissionGranted && renouncedPermissions.contains(permission)
&& context.checkPermission(Manifest.permission.RENOUNCE_PERMISSIONS,
/*pid*/ -1, uid) == PackageManager.PERMISSION_GRANTED) {
return false;
}
return permissionGranted;

View File

@@ -1114,6 +1114,7 @@ public final class PermissionManager {
*
* @hide
*/
@TestApi
public @NonNull AttributionSource registerAttributionSource(@NonNull AttributionSource source) {
try {
return mPermissionManager.registerAttributionSource(source);

View File

@@ -501,6 +501,8 @@ applications that come with the platform
<permission name="android.permission.SCHEDULE_PRIORITIZED_ALARM" />
<!-- Permission required for CTS test - SystemMediaRouter2Test -->
<permission name="android.permission.MODIFY_AUDIO_ROUTING"/>
<!-- Permission required for CTS test - CtsPermission5TestCases -->
<permission name="android.permission.RENOUNCE_PERMISSIONS" />
</privapp-permissions>
<privapp-permissions package="com.android.statementservice">

View File

@@ -449,6 +449,9 @@
<!-- Permission required for CTS test - ResourceObserverNativeTest -->
<uses-permission android:name="android.permission.REGISTER_MEDIA_RESOURCE_OBSERVER" />
<!-- Permission required for CTS test - CtsPermission5TestCases -->
<uses-permission android:name="android.permission.RENOUNCE_PERMISSIONS" />
<!-- Permission required for CTS test - android.widget.cts.ToastTest -->
<uses-permission android:name="android.permission.UNLIMITED_TOASTS" />

View File

@@ -258,8 +258,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
private final PermissionRegistry mRegistry = new PermissionRegistry();
@NonNull
private final AttributionSourceRegistry mAttributionSourceRegistry =
new AttributionSourceRegistry();
private final AttributionSourceRegistry mAttributionSourceRegistry;
@GuardedBy("mLock")
@Nullable
@@ -379,6 +378,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
mSystemPermissions = systemConfig.getSystemPermissions();
mGlobalGids = systemConfig.getGlobalGids();
mOnPermissionChangeListeners = new OnPermissionChangeListeners(FgThread.get().getLooper());
mAttributionSourceRegistry = new AttributionSourceRegistry(context);
// propagate permission configuration
final ArrayMap<String, SystemConfig.PermissionEntry> permConfig =
@@ -5294,6 +5294,12 @@ public class PermissionManagerService extends IPermissionManager.Stub {
private static final class AttributionSourceRegistry {
private final Object mLock = new Object();
private final Context mContext;
AttributionSourceRegistry(@NonNull Context context) {
mContext = context;
}
private final WeakHashMap<IBinder, AttributionSource> mAttributions = new WeakHashMap<>();
public @NonNull AttributionSource registerAttributionSource(
@@ -5321,7 +5327,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// app passing the source, in which case you must trust the other side;
final int callingUid = Binder.getCallingUid();
if (source.getUid() != callingUid) {
if (source.getUid() != callingUid && mContext.checkPermission(
Manifest.permission.UPDATE_APP_OPS_STATS, /*pid*/ -1, callingUid)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Cannot register attribution source for uid:"
+ source.getUid() + " from uid:" + callingUid);
}