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

Commit 2d750615 authored by Sally's avatar Sally
Browse files

Restrict proxies for displays owned by the caller

A virtual device should only be allowed to proxy displays it owns. This checks
the available displays and compares the owners to the calling uid used
when registering a proxy.

Test: atest AccessibilityDisplayProxyTest, manual with Exo
Bug: 280661435
Change-Id: I7f7a4d5c1cb5510410e5b8d5348d2ce67b30af4b
parent 66b0e8ad
Loading
Loading
Loading
Loading
+4 −3
Original line number Original line Diff line number Diff line
@@ -4014,9 +4014,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        if (displayId < 0) {
        if (displayId < 0) {
            throw new IllegalArgumentException("The display id " + displayId + " is invalid.");
            throw new IllegalArgumentException("The display id " + displayId + " is invalid.");
        }
        }
        if (displayId == Display.DEFAULT_DISPLAY) {
            throw new IllegalArgumentException("The default display cannot be proxy-ed.");
        }
        if (!isTrackedDisplay(displayId)) {
        if (!isTrackedDisplay(displayId)) {
            throw new IllegalArgumentException("The display " + displayId + " does not exist or is"
            throw new IllegalArgumentException("The display " + displayId + " does not exist or is"
                    + " not tracked by accessibility.");
                    + " not tracked by accessibility.");
@@ -4025,6 +4022,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
            throw new IllegalArgumentException("The display " + displayId + " is already being"
            throw new IllegalArgumentException("The display " + displayId + " is already being"
                    + " proxy-ed");
                    + " proxy-ed");
        }
        }
        if (!mProxyManager.displayBelongsToCaller(Binder.getCallingUid(), displayId)) {
            throw new SecurityException("The display " + displayId + " does not belong to"
                    + " the caller.");
        }


        final long identity = Binder.clearCallingIdentity();
        final long identity = Binder.clearCallingIdentity();
        try {
        try {
+20 −0
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@ import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.AccessibilityTrace;
import android.accessibilityservice.AccessibilityTrace;
import android.accessibilityservice.IAccessibilityServiceClient;
import android.accessibilityservice.IAccessibilityServiceClient;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.companion.virtual.VirtualDevice;
import android.companion.virtual.VirtualDeviceManager;
import android.companion.virtual.VirtualDeviceManager;
import android.content.ComponentName;
import android.content.ComponentName;
import android.content.Context;
import android.content.Context;
@@ -319,6 +320,25 @@ public class ProxyManager {
        return isTrackingDeviceId;
        return isTrackingDeviceId;
    }
    }


    /** Returns true if the display belongs to one of the caller's virtual devices. */
    public boolean displayBelongsToCaller(int callingUid, int proxyDisplayId) {
        final VirtualDeviceManager vdm = mContext.getSystemService(VirtualDeviceManager.class);
        final VirtualDeviceManagerInternal localVdm = getLocalVdm();
        if (vdm == null || localVdm == null) {
            return false;
        }
        final List<VirtualDevice> virtualDevices = vdm.getVirtualDevices();
        for (VirtualDevice device : virtualDevices) {
            if (localVdm.getDisplayIdsForDevice(device.getDeviceId()).contains(proxyDisplayId)) {
                final int ownerUid = localVdm.getDeviceOwnerUid(device.getDeviceId());
                if (callingUid == ownerUid) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
    /**
     * Sends AccessibilityEvents to a proxy given the event's displayId.
     * Sends AccessibilityEvents to a proxy given the event's displayId.
     */
     */
+3 −1
Original line number Original line Diff line number Diff line
@@ -280,6 +280,7 @@ public class AccessibilityManagerServiceTest {
    @SmallTest
    @SmallTest
    @Test
    @Test
    public void testRegisterProxy() throws Exception {
    public void testRegisterProxy() throws Exception {
        when(mProxyManager.displayBelongsToCaller(anyInt(), anyInt())).thenReturn(true);
        mA11yms.registerProxyForDisplay(mMockServiceClient, TEST_DISPLAY);
        mA11yms.registerProxyForDisplay(mMockServiceClient, TEST_DISPLAY);
        verify(mProxyManager).registerProxy(eq(mMockServiceClient), eq(TEST_DISPLAY), anyInt(),
        verify(mProxyManager).registerProxy(eq(mMockServiceClient), eq(TEST_DISPLAY), anyInt(),
                eq(mMockSecurityPolicy),
                eq(mMockSecurityPolicy),
@@ -314,7 +315,7 @@ public class AccessibilityManagerServiceTest {
    @SmallTest
    @SmallTest
    @Test
    @Test
    public void testRegisterProxyForDefaultDisplay() throws Exception {
    public void testRegisterProxyForDefaultDisplay() throws Exception {
        assertThrows(IllegalArgumentException.class,
        assertThrows(SecurityException.class,
                () -> mA11yms.registerProxyForDisplay(mMockServiceClient, Display.DEFAULT_DISPLAY));
                () -> mA11yms.registerProxyForDisplay(mMockServiceClient, Display.DEFAULT_DISPLAY));
        verify(mProxyManager, never()).registerProxy(any(), anyInt(), anyInt(), any(),
        verify(mProxyManager, never()).registerProxy(any(), anyInt(), anyInt(), any(),
                any(), any(), any());
                any(), any(), any());
@@ -332,6 +333,7 @@ public class AccessibilityManagerServiceTest {
    @SmallTest
    @SmallTest
    @Test
    @Test
    public void testUnRegisterProxyWithPermission() throws Exception {
    public void testUnRegisterProxyWithPermission() throws Exception {
        when(mProxyManager.displayBelongsToCaller(anyInt(), anyInt())).thenReturn(true);
        mA11yms.registerProxyForDisplay(mMockServiceClient, TEST_DISPLAY);
        mA11yms.registerProxyForDisplay(mMockServiceClient, TEST_DISPLAY);
        mA11yms.unregisterProxyForDisplay(TEST_DISPLAY);
        mA11yms.unregisterProxyForDisplay(TEST_DISPLAY);