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
This commit is contained in:
Sally
2023-05-25 15:20:51 +00:00
parent 66b0e8ad1e
commit 2d75061519
3 changed files with 27 additions and 4 deletions

View File

@@ -4014,9 +4014,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
if (displayId < 0) {
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)) {
throw new IllegalArgumentException("The display " + displayId + " does not exist or is"
+ " not tracked by accessibility.");
@@ -4025,6 +4022,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
throw new IllegalArgumentException("The display " + displayId + " is already being"
+ " 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();
try {

View File

@@ -24,6 +24,7 @@ import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.AccessibilityTrace;
import android.accessibilityservice.IAccessibilityServiceClient;
import android.annotation.NonNull;
import android.companion.virtual.VirtualDevice;
import android.companion.virtual.VirtualDeviceManager;
import android.content.ComponentName;
import android.content.Context;
@@ -319,6 +320,25 @@ public class ProxyManager {
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.
*/

View File

@@ -280,6 +280,7 @@ public class AccessibilityManagerServiceTest {
@SmallTest
@Test
public void testRegisterProxy() throws Exception {
when(mProxyManager.displayBelongsToCaller(anyInt(), anyInt())).thenReturn(true);
mA11yms.registerProxyForDisplay(mMockServiceClient, TEST_DISPLAY);
verify(mProxyManager).registerProxy(eq(mMockServiceClient), eq(TEST_DISPLAY), anyInt(),
eq(mMockSecurityPolicy),
@@ -314,7 +315,7 @@ public class AccessibilityManagerServiceTest {
@SmallTest
@Test
public void testRegisterProxyForDefaultDisplay() throws Exception {
assertThrows(IllegalArgumentException.class,
assertThrows(SecurityException.class,
() -> mA11yms.registerProxyForDisplay(mMockServiceClient, Display.DEFAULT_DISPLAY));
verify(mProxyManager, never()).registerProxy(any(), anyInt(), anyInt(), any(),
any(), any(), any());
@@ -332,6 +333,7 @@ public class AccessibilityManagerServiceTest {
@SmallTest
@Test
public void testUnRegisterProxyWithPermission() throws Exception {
when(mProxyManager.displayBelongsToCaller(anyInt(), anyInt())).thenReturn(true);
mA11yms.registerProxyForDisplay(mMockServiceClient, TEST_DISPLAY);
mA11yms.unregisterProxyForDisplay(TEST_DISPLAY);