Loading core/java/android/content/AttributionSource.java +1 −1 Original line number Diff line number Diff line Loading @@ -231,7 +231,7 @@ public final class AttributionSource implements Parcelable { } /** @hide */ public AttributionSource withToken(@NonNull Binder token) { public AttributionSource withToken(@NonNull IBinder token) { return new AttributionSource(getUid(), getPid(), getPackageName(), getAttributionTag(), token, mAttributionSourceState.renouncedPermissions, getDeviceId(), getNext()); } Loading core/java/android/permission/IPermissionManager.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -92,7 +92,7 @@ interface IPermissionManager { boolean isAutoRevokeExempted(String packageName, int userId); void registerAttributionSource(in AttributionSourceState source); IBinder registerAttributionSource(in AttributionSourceState source); boolean isRegisteredAttributionSource(in AttributionSourceState source); Loading core/java/android/permission/PermissionManager.java +11 −3 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED; import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET; import static android.os.Build.VERSION_CODES.S; import static android.permission.flags.Flags.serverSideAttributionRegistration; import android.Manifest; import android.annotation.CheckResult; Loading Loading @@ -59,6 +60,7 @@ import android.media.AudioManager; import android.os.Binder; import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.Process; Loading Loading @@ -1464,13 +1466,19 @@ public final class PermissionManager { // We use a shared static token for sources that are not registered since the token's // only used for process death detection. If we are about to use the source for security // enforcement we need to replace the binder with a unique one. final AttributionSource registeredSource = source.withToken(new Binder()); try { if (serverSideAttributionRegistration()) { IBinder newToken = mPermissionManager.registerAttributionSource(source.asState()); return source.withToken(newToken); } else { AttributionSource registeredSource = source.withToken(new Binder()); mPermissionManager.registerAttributionSource(registeredSource.asState()); return registeredSource; } } catch (RemoteException e) { e.rethrowFromSystemServer(); } return registeredSource; return source; } /** Loading core/java/android/permission/flags.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,13 @@ flag { bug: "274132354" } flag { name: "server_side_attribution_registration" namespace: "permissions" description: "controls whether the binder representing an AttributionSource is created in the system server, or client process" bug: "310953959" } flag { name: "wallet_role_enabled" namespace: "wallet_integration" Loading services/core/java/com/android/server/pm/permission/PermissionManagerService.java +23 −6 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import static android.app.AppOpsManager.MODE_IGNORED; import static android.app.AppOpsManager.OP_BLUETOOTH_CONNECT; import static android.content.pm.ApplicationInfo.AUTO_REVOKE_DISALLOWED; import static android.content.pm.ApplicationInfo.AUTO_REVOKE_DISCOURAGED; import static android.permission.flags.Flags.serverSideAttributionRegistration; import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME; Loading Loading @@ -439,10 +440,27 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } /** * Reference propagation over binder is affected by the ownership of the object. So if * the token is owned by client, references to the token on client side won't be * propagated to the server and the token may still be garbage collected on server side. * But if the token is owned by server, references to the token on client side will now * be propagated to the server since it's a foreign object to the client, and that will * keep the token referenced on the server side as long as the client is alive and * holding it. */ @Override public void registerAttributionSource(@NonNull AttributionSourceState source) { public IBinder registerAttributionSource(@NonNull AttributionSourceState source) { if (serverSideAttributionRegistration()) { Binder token = new Binder(); mAttributionSourceRegistry .registerAttributionSource(new AttributionSource(source).withToken(token)); return token; } else { mAttributionSourceRegistry .registerAttributionSource(new AttributionSource(source)); return source.token; } } @Override Loading Loading @@ -1218,7 +1236,6 @@ public class PermissionManagerService extends IPermissionManager.Stub { @Nullable String message, boolean forDataDelivery, boolean startDataDelivery, boolean fromDatasource, int attributedOp) { PermissionInfo permissionInfo = sPlatformPermissions.get(permission); if (permissionInfo == null) { try { permissionInfo = context.getPackageManager().getPermissionInfo(permission, 0); Loading Loading @@ -1346,8 +1363,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { // If the call is from a datasource we need to vet only the chain before it. This // way we can avoid the datasource creating an attribution context for every call. if (!(fromDatasource && current.equals(attributionSource)) && next != null && !current.isTrusted(context)) { boolean isDatasource = fromDatasource && current.equals(attributionSource); if (!isDatasource && next != null && !current.isTrusted(context)) { return PermissionChecker.PERMISSION_HARD_DENIED; } Loading Loading
core/java/android/content/AttributionSource.java +1 −1 Original line number Diff line number Diff line Loading @@ -231,7 +231,7 @@ public final class AttributionSource implements Parcelable { } /** @hide */ public AttributionSource withToken(@NonNull Binder token) { public AttributionSource withToken(@NonNull IBinder token) { return new AttributionSource(getUid(), getPid(), getPackageName(), getAttributionTag(), token, mAttributionSourceState.renouncedPermissions, getDeviceId(), getNext()); } Loading
core/java/android/permission/IPermissionManager.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -92,7 +92,7 @@ interface IPermissionManager { boolean isAutoRevokeExempted(String packageName, int userId); void registerAttributionSource(in AttributionSourceState source); IBinder registerAttributionSource(in AttributionSourceState source); boolean isRegisteredAttributionSource(in AttributionSourceState source); Loading
core/java/android/permission/PermissionManager.java +11 −3 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED; import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET; import static android.os.Build.VERSION_CODES.S; import static android.permission.flags.Flags.serverSideAttributionRegistration; import android.Manifest; import android.annotation.CheckResult; Loading Loading @@ -59,6 +60,7 @@ import android.media.AudioManager; import android.os.Binder; import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.Process; Loading Loading @@ -1464,13 +1466,19 @@ public final class PermissionManager { // We use a shared static token for sources that are not registered since the token's // only used for process death detection. If we are about to use the source for security // enforcement we need to replace the binder with a unique one. final AttributionSource registeredSource = source.withToken(new Binder()); try { if (serverSideAttributionRegistration()) { IBinder newToken = mPermissionManager.registerAttributionSource(source.asState()); return source.withToken(newToken); } else { AttributionSource registeredSource = source.withToken(new Binder()); mPermissionManager.registerAttributionSource(registeredSource.asState()); return registeredSource; } } catch (RemoteException e) { e.rethrowFromSystemServer(); } return registeredSource; return source; } /** Loading
core/java/android/permission/flags.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,13 @@ flag { bug: "274132354" } flag { name: "server_side_attribution_registration" namespace: "permissions" description: "controls whether the binder representing an AttributionSource is created in the system server, or client process" bug: "310953959" } flag { name: "wallet_role_enabled" namespace: "wallet_integration" Loading
services/core/java/com/android/server/pm/permission/PermissionManagerService.java +23 −6 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import static android.app.AppOpsManager.MODE_IGNORED; import static android.app.AppOpsManager.OP_BLUETOOTH_CONNECT; import static android.content.pm.ApplicationInfo.AUTO_REVOKE_DISALLOWED; import static android.content.pm.ApplicationInfo.AUTO_REVOKE_DISCOURAGED; import static android.permission.flags.Flags.serverSideAttributionRegistration; import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME; Loading Loading @@ -439,10 +440,27 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } /** * Reference propagation over binder is affected by the ownership of the object. So if * the token is owned by client, references to the token on client side won't be * propagated to the server and the token may still be garbage collected on server side. * But if the token is owned by server, references to the token on client side will now * be propagated to the server since it's a foreign object to the client, and that will * keep the token referenced on the server side as long as the client is alive and * holding it. */ @Override public void registerAttributionSource(@NonNull AttributionSourceState source) { public IBinder registerAttributionSource(@NonNull AttributionSourceState source) { if (serverSideAttributionRegistration()) { Binder token = new Binder(); mAttributionSourceRegistry .registerAttributionSource(new AttributionSource(source).withToken(token)); return token; } else { mAttributionSourceRegistry .registerAttributionSource(new AttributionSource(source)); return source.token; } } @Override Loading Loading @@ -1218,7 +1236,6 @@ public class PermissionManagerService extends IPermissionManager.Stub { @Nullable String message, boolean forDataDelivery, boolean startDataDelivery, boolean fromDatasource, int attributedOp) { PermissionInfo permissionInfo = sPlatformPermissions.get(permission); if (permissionInfo == null) { try { permissionInfo = context.getPackageManager().getPermissionInfo(permission, 0); Loading Loading @@ -1346,8 +1363,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { // If the call is from a datasource we need to vet only the chain before it. This // way we can avoid the datasource creating an attribution context for every call. if (!(fromDatasource && current.equals(attributionSource)) && next != null && !current.isTrusted(context)) { boolean isDatasource = fromDatasource && current.equals(attributionSource); if (!isDatasource && next != null && !current.isTrusted(context)) { return PermissionChecker.PERMISSION_HARD_DENIED; } Loading