diff options
| author | Svet Ganov <svetoslavganov@google.com> | 2021-05-20 15:09:08 +0000 |
|---|---|---|
| committer | Svet Ganov <svetoslavganov@google.com> | 2021-06-01 23:43:29 +0000 |
| commit | 2eebf929650e0d320a21f0d13677a27d7ab278e9 (patch) | |
| tree | 128c1ee51e6101fb1e1d5d66a7ed9137ac71775d /core/java/android/content/AttributionSource.java | |
| parent | a6377c981697727240381f7e149da0d1d6f7b90f (diff) | |
Switch media fw permissions checks to AttributionSource
Attribution source is the abstraction to capture the data
flows for private data across apps. Checking permissions
for an attribution source does this for all apps in the
chain that would receive the data as well as the relevant
app ops are checked/noted/started as needed.
Teach speech recognition service about attribution
chains. If an implementation does nothing the OS
would enforce permisisons and do blame as always.
This apporach leads to double blaming and doesn't
support attribition chains where app calls into
the default recognizer which calls into the on
device recognizer (this nests recursively). If the
implementer takes advantage of the attribution chain
mechanims the permissions for the entire chain are
checked at mic access time and all apps are blamed
only once.
Fixed a few bugs around finishing ops for attribution
chains. Also ensured that any app death in a started
attribution chain would lead to finishing the op for
this app
bug: 158792096
Test: (added tests for speech reco)
atest CtsMediaTestCases
atest CtsPermissionTestCases
atest CtsPermission2TestCases
atest CtsPermission3TestCases
atest CtsPermission4TestCases
atest CtsPermission5TestCases
atest CtsAppOpsTestCases
atest CtsAppOps2TestCases
Merged-In: Ic92c7adc14bd2d135ac13b96f17a1b393dd562e4
Change-Id: Ic92c7adc14bd2d135ac13b96f17a1b393dd562e4
Diffstat (limited to 'core/java/android/content/AttributionSource.java')
| -rw-r--r-- | core/java/android/content/AttributionSource.java | 131 |
1 files changed, 99 insertions, 32 deletions
diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java index 7ab731f15ad2..1dda6374a474 100644 --- a/core/java/android/content/AttributionSource.java +++ b/core/java/android/content/AttributionSource.java @@ -21,6 +21,7 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.TestApi; +import android.app.ActivityThread; import android.os.Binder; import android.os.Build; import android.os.IBinder; @@ -94,14 +95,22 @@ public final class AttributionSource implements Parcelable { @TestApi public AttributionSource(int uid, @Nullable String packageName, @Nullable String attributionTag) { - this(uid, packageName, attributionTag, /*next*/ null); + this(uid, packageName, attributionTag, new Binder()); } /** @hide */ @TestApi public AttributionSource(int uid, @Nullable String packageName, - @Nullable String attributionTag, @Nullable AttributionSource next) { - this(uid, packageName, attributionTag, /*renouncedPermissions*/ null, next); + @Nullable String attributionTag, @NonNull IBinder token) { + this(uid, packageName, attributionTag, token, /*renouncedPermissions*/ null, + /*next*/ null); + } + + /** @hide */ + public AttributionSource(int uid, @Nullable String packageName, + @Nullable String attributionTag, @NonNull IBinder token, + @Nullable AttributionSource next) { + this(uid, packageName, attributionTag, token, /*renouncedPermissions*/ null, next); } /** @hide */ @@ -109,28 +118,32 @@ public final class AttributionSource implements Parcelable { public AttributionSource(int uid, @Nullable String packageName, @Nullable String attributionTag, @Nullable Set<String> renouncedPermissions, @Nullable AttributionSource next) { - this(uid, packageName, attributionTag, /*token*/ null, (renouncedPermissions != null) + this(uid, packageName, attributionTag, (renouncedPermissions != null) ? renouncedPermissions.toArray(new String[0]) : null, next); } /** @hide */ - public AttributionSource(@NonNull AttributionSource current, - @Nullable AttributionSource next) { + public AttributionSource(@NonNull AttributionSource current, @Nullable AttributionSource next) { this(current.getUid(), current.getPackageName(), current.getAttributionTag(), - /*token*/ null, /*renouncedPermissions*/ null, next); + current.getToken(), current.mAttributionSourceState.renouncedPermissions, next); } AttributionSource(int uid, @Nullable String packageName, @Nullable String attributionTag, - @Nullable IBinder token, @Nullable String[] renouncedPermissions, + @Nullable String[] renouncedPermissions, @Nullable AttributionSource next) { + this(uid, packageName, attributionTag, new Binder(), renouncedPermissions, next); + } + + AttributionSource(int uid, @Nullable String packageName, @Nullable String attributionTag, + @NonNull IBinder token, @Nullable String[] renouncedPermissions, @Nullable AttributionSource next) { mAttributionSourceState = new AttributionSourceState(); mAttributionSourceState.uid = uid; + mAttributionSourceState.token = token; mAttributionSourceState.packageName = packageName; mAttributionSourceState.attributionTag = attributionTag; - mAttributionSourceState.token = token; mAttributionSourceState.renouncedPermissions = renouncedPermissions; mAttributionSourceState.next = (next != null) ? new AttributionSourceState[] - {next.mAttributionSourceState} : null; + {next.mAttributionSourceState} : new AttributionSourceState[0]; } AttributionSource(@NonNull Parcel in) { @@ -145,18 +158,12 @@ public final class AttributionSource implements Parcelable { /** @hide */ public AttributionSource withNextAttributionSource(@Nullable AttributionSource next) { return new AttributionSource(getUid(), getPackageName(), getAttributionTag(), - getToken(), mAttributionSourceState.renouncedPermissions, next); - } - - /** @hide */ - public AttributionSource withToken(@Nullable IBinder token) { - return new AttributionSource(getUid(), getPackageName(), getAttributionTag(), - token, mAttributionSourceState.renouncedPermissions, getNext()); + mAttributionSourceState.renouncedPermissions, next); } /** @hide */ public AttributionSource withPackageName(@Nullable String packageName) { - return new AttributionSource(getUid(), packageName, getAttributionTag(), getToken(), + return new AttributionSource(getUid(), packageName, getAttributionTag(), mAttributionSourceState.renouncedPermissions, getNext()); } @@ -165,6 +172,45 @@ public final class AttributionSource implements Parcelable { return mAttributionSourceState; } + /** @hide */ + public @NonNull ScopedParcelState asScopedParcelState() { + return new ScopedParcelState(this); + } + + /** @hide */ + public static AttributionSource myAttributionSource() { + return new AttributionSource(Process.myUid(), ActivityThread.currentOpPackageName(), + /*attributionTag*/ null, (String[]) /*renouncedPermissions*/ null, /*next*/ null); + } + + /** + * This is a scoped object that exposes the content of an attribution source + * as a parcel. This is useful when passing one to native and avoid custom + * conversion logic from Java to native state that needs to be kept in sync + * as attribution source evolves. This way we use the same logic for passing + * to native as the ones for passing in an IPC - in both cases this is the + * same auto generated code. + * + * @hide + */ + public static class ScopedParcelState implements AutoCloseable { + private final Parcel mParcel; + + public @NonNull Parcel getParcel() { + return mParcel; + } + + public ScopedParcelState(AttributionSource attributionSource) { + mParcel = Parcel.obtain(); + attributionSource.writeToParcel(mParcel, 0); + mParcel.setDataPosition(0); + } + + public void close() { + mParcel.recycle(); + } + } + /** * If you are handling an IPC and you don't trust the caller you need to validate * whether the attribution source is one for the calling app to prevent the caller @@ -209,7 +255,8 @@ public final class AttributionSource implements Parcelable { "attributionTag = " + mAttributionSourceState.attributionTag + ", " + "token = " + mAttributionSourceState.token + ", " + "next = " + (mAttributionSourceState.next != null - ? mAttributionSourceState.next[0]: null) + + && mAttributionSourceState.next.length > 0 + ? mAttributionSourceState.next[0] : null) + " }"; } return super.toString(); @@ -221,7 +268,8 @@ public final class AttributionSource implements Parcelable { * @hide */ public int getNextUid() { - if (mAttributionSourceState.next != null) { + if (mAttributionSourceState.next != null + && mAttributionSourceState.next.length > 0) { return mAttributionSourceState.next[0].uid; } return Process.INVALID_UID; @@ -233,26 +281,42 @@ public final class AttributionSource implements Parcelable { * @hide */ public @Nullable String getNextPackageName() { - if (mAttributionSourceState.next != null) { + if (mAttributionSourceState.next != null + && mAttributionSourceState.next.length > 0) { return mAttributionSourceState.next[0].packageName; } return null; } /** - * @return The nexxt package's attribution tag that would receive + * @return The next package's attribution tag that would receive * the permission protected data. * * @hide */ public @Nullable String getNextAttributionTag() { - if (mAttributionSourceState.next != null) { + if (mAttributionSourceState.next != null + && mAttributionSourceState.next.length > 0) { return mAttributionSourceState.next[0].attributionTag; } return null; } /** + * @return The next package's token that would receive + * the permission protected data. + * + * @hide + */ + public @Nullable IBinder getNextToken() { + if (mAttributionSourceState.next != null + && mAttributionSourceState.next.length > 0) { + return mAttributionSourceState.next[0].token; + } + return null; + } + + /** * Checks whether this attribution source can be trusted. That is whether * the app it refers to created it and provided to the attribution chain. * @@ -311,7 +375,7 @@ public final class AttributionSource implements Parcelable { * * @hide */ - public @Nullable IBinder getToken() { + public @NonNull IBinder getToken() { return mAttributionSourceState.token; } @@ -319,7 +383,8 @@ public final class AttributionSource implements Parcelable { * The next app to receive the permission protected data. */ public @Nullable AttributionSource getNext() { - if (mNextCached == null && mAttributionSourceState.next != null) { + if (mNextCached == null && mAttributionSourceState.next != null + && mAttributionSourceState.next.length > 0) { mNextCached = new AttributionSource(mAttributionSourceState.next[0]); } return mNextCached; @@ -442,7 +507,7 @@ public final class AttributionSource implements Parcelable { @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS) public @NonNull Builder setRenouncedPermissions(@Nullable Set<String> value) { checkNotUsed(); - mBuilderFieldsSet |= 0x10; + mBuilderFieldsSet |= 0x8; mAttributionSourceState.renouncedPermissions = (value != null) ? value.toArray(new String[0]) : null; return this; @@ -453,9 +518,9 @@ public final class AttributionSource implements Parcelable { */ public @NonNull Builder setNext(@Nullable AttributionSource value) { checkNotUsed(); - mBuilderFieldsSet |= 0x20; + mBuilderFieldsSet |= 0x10; mAttributionSourceState.next = (value != null) ? new AttributionSourceState[] - {value.mAttributionSourceState} : null; + {value.mAttributionSourceState} : mAttributionSourceState.next; return this; } @@ -471,14 +536,16 @@ public final class AttributionSource implements Parcelable { mAttributionSourceState.attributionTag = null; } if ((mBuilderFieldsSet & 0x8) == 0) { - mAttributionSourceState.token = null; - } - if ((mBuilderFieldsSet & 0x10) == 0) { mAttributionSourceState.renouncedPermissions = null; } - if ((mBuilderFieldsSet & 0x20) == 0) { + if ((mBuilderFieldsSet & 0x10) == 0) { mAttributionSourceState.next = null; } + mAttributionSourceState.token = new Binder(); + if (mAttributionSourceState.next == null) { + // The NDK aidl backend doesn't support null parcelable arrays. + mAttributionSourceState.next = new AttributionSourceState[0]; + } return new AttributionSource(mAttributionSourceState); } |
