Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f9f97694 authored by Nate Myren's avatar Nate Myren Committed by Android (Google) Code Review
Browse files

Merge "Register AttributionSource binders in system server" into main

parents fa01c829 bf73792c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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());
    }
+1 −1
Original line number Diff line number Diff line
@@ -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);

+11 −3
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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;
    }

    /**
+7 −0
Original line number Diff line number Diff line
@@ -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"
+23 −6
Original line number Diff line number Diff line
@@ -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;

@@ -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
@@ -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);
@@ -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;
                }