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

Commit f46a2128 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Merge cherrypicks of ['googleplex-android-review.googlesource.com/28885593',...

Merge cherrypicks of ['googleplex-android-review.googlesource.com/28885593', 'googleplex-android-review.googlesource.com/29596646', 'googleplex-android-review.googlesource.com/29596586', 'googleplex-android-review.googlesource.com/29706438', 'googleplex-android-review.googlesource.com/29119723', 'googleplex-android-review.googlesource.com/29814087', 'googleplex-android-review.googlesource.com/30024116', 'googleplex-android-review.googlesource.com/30021456'] into security-aosp-24Q3-release.

Change-Id: Ibb90b21c0e110138267561d4d5e25860dd5e1330
parents f009ecdc 3b2be226
Loading
Loading
Loading
Loading
+19 −34
Original line number Diff line number Diff line
@@ -2678,16 +2678,11 @@ public class Notification implements Parcelable
        if (mAllowlistToken == null) {
            mAllowlistToken = processAllowlistToken;
        }
        if (Flags.secureAllowlistToken()) {
        // Propagate this token to all pending intents that are unmarshalled from the parcel,
        // or keep the one we're already propagating, if that's the case.
        if (!parcel.hasClassCookie(PendingIntent.class)) {
            parcel.setClassCookie(PendingIntent.class, mAllowlistToken);
        }
        } else {
            // Propagate this token to all pending intents that are unmarshalled from the parcel.
            parcel.setClassCookie(PendingIntent.class, mAllowlistToken);
        }
        when = parcel.readLong();
        creationTime = parcel.readLong();
@@ -3301,7 +3296,6 @@ public class Notification implements Parcelable
            PendingIntent.addOnMarshaledListener(addedListener);
        }
        try {
            if (Flags.secureAllowlistToken()) {
            boolean mustClearCookie = false;
            if (!parcel.hasClassCookie(Notification.class)) {
                // This is the "root" notification, and not an "inner" notification (including
@@ -3319,11 +3313,6 @@ public class Notification implements Parcelable
                    parcel.removeClassCookie(Notification.class, mAllowlistToken);
                }
            }
            } else {
                // IMPORTANT: Add marshaling code in writeToParcelImpl as we
                // want to intercept all pending events written to the parcel.
                writeToParcelImpl(parcel, flags);
            }
            synchronized (this) {
                // Must be written last!
@@ -3339,13 +3328,9 @@ public class Notification implements Parcelable
    private void writeToParcelImpl(Parcel parcel, int flags) {
        parcel.writeInt(1);
        if (Flags.secureAllowlistToken()) {
        // Always use the same token as the root notification (might be null).
        IBinder rootNotificationToken = (IBinder) parcel.getClassCookie(Notification.class);
        parcel.writeStrongBinder(rootNotificationToken);
        } else {
            parcel.writeStrongBinder(mAllowlistToken);
        }
        parcel.writeLong(when);
        parcel.writeLong(creationTime);
+23 −9
Original line number Diff line number Diff line
@@ -138,11 +138,13 @@ public class ServiceListing {
        }

        final PackageManager pmWrapper = mContext.getPackageManager();
        // Add requesting apps, with full validation
        List<ResolveInfo> installedServices = pmWrapper.queryIntentServicesAsUser(
                new Intent(mIntentAction), flags, user);
        for (ResolveInfo resolveInfo : installedServices) {
            ServiceInfo info = resolveInfo.serviceInfo;

            if (!mEnabledServices.contains(info.getComponentName())) {
                if (!mPermission.equals(info.permission)) {
                    Slog.w(mTag, "Skipping " + mNoun + " service "
                            + info.packageName + "/" + info.name
@@ -155,6 +157,18 @@ public class ServiceListing {
                }
                mServices.add(info);
            }
        }

        // Add all apps with access, in case prior approval was granted without full validation
        for (ComponentName cn : mEnabledServices) {
            List<ResolveInfo> enabledServices = pmWrapper.queryIntentServicesAsUser(
                    new Intent().setComponent(cn), flags, user);
            for (ResolveInfo resolveInfo : enabledServices) {
                ServiceInfo info = resolveInfo.serviceInfo;
                mServices.add(info);
            }
        }

        for (Callback callback : mCallbacks) {
            callback.onServicesReloaded(mServices);
        }
+65 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -29,6 +30,7 @@ import static org.mockito.Mockito.when;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
@@ -42,6 +44,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;

@@ -72,19 +75,26 @@ public class ServiceListingTest {
                .build();
    }

    private ArgumentMatcher<Intent> filterEquals(Intent intent) {
        return (test) -> {
            return intent.filterEquals(test);
        };
    }

    @Test
    public void testValidator() {
        ServiceInfo s1 = new ServiceInfo();
        s1.permission = "testPermission";
        s1.packageName = "pkg";
        s1.name = "Service1";
        ServiceInfo s2 = new ServiceInfo();
        s2.permission = "testPermission";
        s2.packageName = "pkg2";
        s2.name = "service2";
        ResolveInfo r1 = new ResolveInfo();
        r1.serviceInfo = s1;
        ResolveInfo r2 = new ResolveInfo();
        r2.serviceInfo = s2;

        when(mPm.queryIntentServicesAsUser(any(), anyInt(), anyInt())).thenReturn(
                ImmutableList.of(r1, r2));

@@ -118,9 +128,11 @@ public class ServiceListingTest {
        ServiceInfo s1 = new ServiceInfo();
        s1.permission = "testPermission";
        s1.packageName = "pkg";
        s1.name = "Service1";
        ServiceInfo s2 = new ServiceInfo();
        s2.permission = "testPermission";
        s2.packageName = "pkg2";
        s2.name = "service2";
        ResolveInfo r1 = new ResolveInfo();
        r1.serviceInfo = s1;
        ResolveInfo r2 = new ResolveInfo();
@@ -193,4 +205,56 @@ public class ServiceListingTest {
        assertThat(Settings.Secure.getString(RuntimeEnvironment.application.getContentResolver(),
                TEST_SETTING)).contains(testComponent2.flattenToString());
    }

    @Test
    public void testHasPermissionWithoutMeetingCurrentRegs() {
        ServiceInfo s1 = new ServiceInfo();
        s1.permission = "testPermission";
        s1.packageName = "pkg";
        s1.name = "Service1";
        ServiceInfo s2 = new ServiceInfo();
        s2.permission = "testPermission";
        s2.packageName = "pkg2";
        s2.name = "service2";
        ResolveInfo r1 = new ResolveInfo();
        r1.serviceInfo = s1;
        ResolveInfo r2 = new ResolveInfo();
        r2.serviceInfo = s2;

        ComponentName approvedComponent = new ComponentName(s2.packageName, s2.name);

        Settings.Secure.putString(
                mContext.getContentResolver(), TEST_SETTING, approvedComponent.flattenToString());

        when(mPm.queryIntentServicesAsUser(argThat(
                filterEquals(new Intent(TEST_INTENT))), anyInt(), anyInt()))
                .thenReturn(ImmutableList.of(r1));
        when(mPm.queryIntentServicesAsUser(argThat(
                filterEquals(new Intent().setComponent(approvedComponent))),
                anyInt(), anyInt()))
                .thenReturn(ImmutableList.of(r2));

        mServiceListing = new ServiceListing.Builder(mContext)
                .setTag("testTag")
                .setSetting(TEST_SETTING)
                .setNoun("testNoun")
                .setIntentAction(TEST_INTENT)
                .setValidator(info -> {
                    if (info.packageName.equals("pkg")) {
                        return true;
                    }
                    return false;
                })
                .setPermission("testPermission")
                .build();
        ServiceListing.Callback callback = mock(ServiceListing.Callback.class);
        mServiceListing.addCallback(callback);
        mServiceListing.reload();

        verify(mPm, times(2)).queryIntentServicesAsUser(any(), anyInt(), anyInt());
        ArgumentCaptor<List<ServiceInfo>> captor = ArgumentCaptor.forClass(List.class);
        verify(callback, times(1)).onServicesReloaded(captor.capture());

        assertThat(captor.getValue()).containsExactlyElementsIn(ImmutableList.of(s2, s1));
    }
}
+49 −1
Original line number Diff line number Diff line
@@ -205,6 +205,15 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku

    private static final String PENDING_DELETED_IDS_ATTR = "pending_deleted_ids";

    // Hard limit of number of hosts an app can create, note that the app that hosts the widgets
    // can have multiple instances of {@link AppWidgetHost}, typically in respect to different
    // surfaces in the host app.
    // @see AppWidgetHost
    // @see AppWidgetHost#mHostId
    private static final int MAX_NUMBER_OF_HOSTS_PER_PACKAGE = 20;
    // Hard limit of number of widgets can be pinned by a host.
    private static final int MAX_NUMBER_OF_WIDGETS_PER_HOST = 200;

    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
@@ -2048,7 +2057,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
        if (host != null) {
            return host;
        }

        ensureHostCountBeforeAddLocked(id);
        host = new Host();
        host.id = id;
        mHosts.add(host);
@@ -2056,6 +2065,24 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
        return host;
    }

    /**
     * Ensures that the number of hosts for a package is less than the maximum number of hosts per
     * package. If the number of hosts is greater than the maximum number of hosts per package, then
     * removes the oldest host.
     */
    private void ensureHostCountBeforeAddLocked(@NonNull final HostId hostId) {
        final List<Host> hosts = new ArrayList<>();
        for (Host host : mHosts) {
            if (host.id.uid == hostId.uid
                    && host.id.packageName.equals(hostId.packageName)) {
                hosts.add(host);
            }
        }
        while (hosts.size() >= MAX_NUMBER_OF_HOSTS_PER_PACKAGE) {
            deleteHostLocked(hosts.remove(0));
        }
    }

    private void deleteHostLocked(Host host) {
        if (DEBUG) {
            Slog.i(TAG, "deleteHostLocked() " + host);
@@ -3356,11 +3383,32 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
        if (DEBUG) {
            Slog.i(TAG, "addWidgetLocked() " + widget);
        }
        ensureWidgetCountBeforeAddLocked(widget);
        mWidgets.add(widget);

        onWidgetProviderAddedOrChangedLocked(widget);
    }

    /**
     * Ensures that the widget count for the widget's host is not greater than the maximum
     * number of widgets per host. If the count is greater than the maximum, removes oldest widgets
     * from the host until the count is less than or equal to the maximum.
     */
    private void ensureWidgetCountBeforeAddLocked(@NonNull final Widget widget) {
        if (widget.host == null || widget.host.id == null) {
            return;
        }
        final List<Widget> widgetsInSameHost = new ArrayList<>();
        for (Widget w : mWidgets) {
            if (w.host != null && widget.host.id.equals(w.host.id)) {
                widgetsInSameHost.add(w);
            }
        }
        while (widgetsInSameHost.size() >= MAX_NUMBER_OF_WIDGETS_PER_HOST) {
            removeWidgetLocked(widgetsInSameHost.remove(0));
        }
    }

    /**
     * Checks if the provider is assigned and updates the mWidgetPackages to track packages
     * that have bound widgets.
+9 −0
Original line number Diff line number Diff line
@@ -628,16 +628,25 @@ public class CompanionDeviceManagerService extends SystemService {

        @Override
        public void enablePermissionsSync(int associationId) {
            if (getCallingUid() != SYSTEM_UID) {
                throw new SecurityException("Caller must be system UID");
            }
            mSystemDataTransferProcessor.enablePermissionsSync(associationId);
        }

        @Override
        public void disablePermissionsSync(int associationId) {
            if (getCallingUid() != SYSTEM_UID) {
                throw new SecurityException("Caller must be system UID");
            }
            mSystemDataTransferProcessor.disablePermissionsSync(associationId);
        }

        @Override
        public PermissionSyncRequest getPermissionSyncRequest(int associationId) {
            if (getCallingUid() != SYSTEM_UID) {
                throw new SecurityException("Caller must be system UID");
            }
            return mSystemDataTransferProcessor.getPermissionSyncRequest(associationId);
        }

Loading