Support for a Context to "renounce" permissions.

Different logical components within an app may have no intention of
interacting with data or services that are protected by specific
permissions.

The new overload added in this change provides the initial mechanism
for a logical component to indicate a set of permissions that should
be treated as "renounced".  Interactions performed through the
returned Context will ideally be treated as if the renounced
permissions have not actually been granted to the application,
regardless of their actual grant status.

This is a low-risk change from a security standpoint, since it can
only reduce the set of permissions that might have been granted to
an app; it can never be used to expand the set of permissions.

Note that this change only provides an initial implementation which
only applies to local permission checks within the app; future
changes will begin wiring this up across process boundaries.

Bug: 181812281
Test: atest CtsContentTestCases:android.content.cts.ContextTest
Change-Id: I96439e5344c85300fb6a0f03e572746c3c96ee95
This commit is contained in:
Jeff Sharkey
2021-03-04 12:52:52 -07:00
parent e41ad67f66
commit ba2974c8a9
7 changed files with 154 additions and 35 deletions

View File

@@ -888,6 +888,14 @@ public abstract class Context {
return getAttributionTag();
}
/**
* Return the set of parameters which this Context was created with, if it
* was created via {@link #createContext(ContextParams)}.
*/
public @Nullable ContextParams getParams() {
return null;
}
/** Return the full application info for this context's package. */
public abstract ApplicationInfo getApplicationInfo();

View File

@@ -18,6 +18,13 @@ package android.content;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import java.util.Collections;
import java.util.Objects;
import java.util.Set;
/**
* This class represents rules around how a context being created via
@@ -48,9 +55,19 @@ import android.annotation.Nullable;
* @see Context#createContext(ContextParams)
*/
public final class ContextParams {
private final String mAttributionTag;
private final String mReceiverPackage;
private final String mReceiverAttributionTag;
private final Set<String> mRenouncedPermissions;
private ContextParams() {
/* hide ctor */
/** {@hide} */
public static final ContextParams EMPTY = new ContextParams.Builder().build();
private ContextParams(@NonNull ContextParams.Builder builder) {
mAttributionTag = builder.mAttributionTag;
mReceiverPackage = builder.mReceiverPackage;
mReceiverAttributionTag = builder.mReceiverAttributionTag;
mRenouncedPermissions = builder.mRenouncedPermissions;
}
/**
@@ -58,7 +75,7 @@ public final class ContextParams {
*/
@Nullable
public String getAttributionTag() {
return null;
return mAttributionTag;
}
/**
@@ -66,7 +83,7 @@ public final class ContextParams {
*/
@Nullable
public String getReceiverPackage() {
return null;
return mReceiverPackage;
}
/**
@@ -74,13 +91,33 @@ public final class ContextParams {
*/
@Nullable
public String getReceiverAttributionTag() {
return null;
return mReceiverAttributionTag;
}
/**
* @return The set of permissions to treat as renounced.
* @hide
*/
@SystemApi
@SuppressLint("NullableCollection")
@RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS)
public @Nullable Set<String> getRenouncedPermissions() {
return mRenouncedPermissions;
}
/** @hide */
public boolean isRenouncedPermission(@NonNull String permission) {
return mRenouncedPermissions != null && mRenouncedPermissions.contains(permission);
}
/**
* Builder for creating a {@link ContextParams}.
*/
public static final class Builder {
private String mAttributionTag;
private String mReceiverPackage;
private String mReceiverAttributionTag;
private Set<String> mRenouncedPermissions;
/**
* Sets an attribution tag against which to track permission accesses.
@@ -90,6 +127,7 @@ public final class ContextParams {
*/
@NonNull
public Builder setAttributionTag(@NonNull String attributionTag) {
mAttributionTag = Objects.requireNonNull(attributionTag);
return this;
}
@@ -104,18 +142,46 @@ public final class ContextParams {
@NonNull
public Builder setReceiverPackage(@NonNull String packageName,
@Nullable String attributionTag) {
mReceiverPackage = Objects.requireNonNull(packageName);
mReceiverAttributionTag = attributionTag;
return this;
}
/**
* Creates a new instance. You need to either specify an attribution tag
* or a receiver package or both.
* Sets permissions which have been voluntarily "renounced" by the
* calling app.
* <p>
* Interactions performed through the created Context will ideally be
* treated as if these "renounced" permissions have not actually been
* granted to the app, regardless of their actual grant status.
* <p>
* This is designed for use by separate logical components within an app
* which have no intention of interacting with data or services that are
* protected by the renounced permissions.
* <p>
* Note that only {@link PermissionInfo#PROTECTION_DANGEROUS}
* permissions are supported by this mechanism.
*
* @param renouncedPermissions The set of permissions to treat as
* renounced.
* @return This builder.
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS)
public @NonNull Builder setRenouncedPermissions(@NonNull Set<String> renouncedPermissions) {
mRenouncedPermissions = Collections.unmodifiableSet(renouncedPermissions);
return this;
}
/**
* Creates a new instance.
*
* @return The new instance.
*/
@NonNull
public ContextParams build() {
return new ContextParams();
return new ContextParams(this);
}
}
}

View File

@@ -171,6 +171,11 @@ public class ContextWrapper extends Context {
return mBase.getAttributionTag();
}
@Override
public @Nullable ContextParams getParams() {
return mBase.getParams();
}
@Override
public ApplicationInfo getApplicationInfo() {
return mBase.getApplicationInfo();
@@ -1044,6 +1049,12 @@ public class ContextWrapper extends Context {
return mBase.createWindowContext(display, type, options);
}
@Override
@NonNull
public Context createContext(@NonNull ContextParams contextParams) {
return mBase.createContext(contextParams);
}
@Override
public @NonNull Context createAttributionContext(@Nullable String attributionTag) {
return mBase.createAttributionContext(attributionTag);