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

Commit fd0d0536 authored by Sergey Nikolaienkov's avatar Sergey Nikolaienkov
Browse files

Validate device profiles in CdmService

Make sure the device profiles CdmService receives from a companion
application in an AssociationRequest are supported: null or
android.app.role.COMPANION_DEVICE_WATCH.

Bug: 201618687
Test: make
Change-Id: I3139c8717b3e3ffe13492d2796a6093ad1146088
parent 5e92df00
Loading
Loading
Loading
Loading
+34 −23
Original line number Original line Diff line number Diff line
@@ -145,6 +145,7 @@ import java.util.Collections;
import java.util.Date;
import java.util.Date;
import java.util.HashSet;
import java.util.HashSet;
import java.util.List;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Objects;
import java.util.Set;
import java.util.Set;
import java.util.TimeZone;
import java.util.TimeZone;
@@ -156,6 +157,15 @@ import java.util.function.Function;
@SuppressLint("LongLogTag")
@SuppressLint("LongLogTag")
public class CompanionDeviceManagerService extends SystemService implements Binder.DeathRecipient {
public class CompanionDeviceManagerService extends SystemService implements Binder.DeathRecipient {


    private static final Map<String, String> DEVICE_PROFILE_TO_PERMISSION;
    static {
        final Map<String, String> map = new ArrayMap<>();
        map.put(AssociationRequest.DEVICE_PROFILE_WATCH,
                Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH);

        DEVICE_PROFILE_TO_PERMISSION = Collections.unmodifiableMap(map);
    }

    private static final ComponentName SERVICE_TO_BIND_TO = ComponentName.createRelative(
    private static final ComponentName SERVICE_TO_BIND_TO = ComponentName.createRelative(
            CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME,
            CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME,
            ".CompanionDeviceDiscoveryService");
            ".CompanionDeviceDiscoveryService");
@@ -429,7 +439,8 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
            checkCallerIsSystemOr(callingPackage);
            checkCallerIsSystemOr(callingPackage);
            int userId = getCallingUserId();
            int userId = getCallingUserId();
            checkUsesFeature(callingPackage, userId);
            checkUsesFeature(callingPackage, userId);
            checkProfilePermissions(request);
            final String deviceProfile = request.getDeviceProfile();
            validateDeviceProfileAndCheckPermission(deviceProfile);


            mFindDeviceCallback = callback;
            mFindDeviceCallback = callback;
            mRequest = request;
            mRequest = request;
@@ -442,13 +453,8 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
            }
            }
            callback.asBinder().linkToDeath(CompanionDeviceManagerService.this /* recipient */, 0);
            callback.asBinder().linkToDeath(CompanionDeviceManagerService.this /* recipient */, 0);


            AndroidFuture<String> fetchProfileDescription =
            mOngoingDeviceDiscovery = getDeviceProfilePermissionDescription(deviceProfile)
                    request.getDeviceProfile() == null
                    .thenComposeAsync(description -> {
                            ? AndroidFuture.completedFuture(null)
                            : getDeviceProfilePermissionDescription(
                                    request.getDeviceProfile());

            mOngoingDeviceDiscovery = fetchProfileDescription.thenComposeAsync(description -> {
                Slog.d(LOG_TAG, "fetchProfileDescription done: " + description);
                Slog.d(LOG_TAG, "fetchProfileDescription done: " + description);


                request.setDeviceProfilePrivilegesDescription(description);
                request.setDeviceProfilePrivilegesDescription(description);
@@ -464,8 +470,7 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
            }, FgThread.getExecutor()).whenComplete(uncheckExceptions((deviceAddress, err) -> {
            }, FgThread.getExecutor()).whenComplete(uncheckExceptions((deviceAddress, err) -> {
                if (err == null) {
                if (err == null) {
                    Association association = new Association(userId, deviceAddress, callingPackage,
                    Association association = new Association(userId, deviceAddress, callingPackage,
                            mRequest.getDeviceProfile(), false,
                            deviceProfile, false, System.currentTimeMillis());
                            System.currentTimeMillis());
                    addAssociation(association, userId);
                    addAssociation(association, userId);
                } else {
                } else {
                    Slog.e(LOG_TAG, "Failed to discover device(s)", err);
                    Slog.e(LOG_TAG, "Failed to discover device(s)", err);
@@ -542,18 +547,18 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
            }
            }
        }
        }


        private void checkProfilePermissions(AssociationRequest request) {
        private void validateDeviceProfileAndCheckPermission(@Nullable String deviceProfile) {
            checkProfilePermission(request,
            // Device profile can be null.
                    AssociationRequest.DEVICE_PROFILE_WATCH,
            if (deviceProfile == null) return;
                    Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH);

            if (!DEVICE_PROFILE_TO_PERMISSION.containsKey(deviceProfile)) {
                throw new IllegalArgumentException("Unsupported device profile: " + deviceProfile);
            }
            }


        private void checkProfilePermission(
            final String permission = DEVICE_PROFILE_TO_PERMISSION.get(deviceProfile);
                AssociationRequest request, String profile, String permission) {
            if (getContext().checkCallingOrSelfPermission(permission) != PERMISSION_GRANTED) {
            if (profile.equals(request.getDeviceProfile())
                throw new SecurityException("Application must hold " + permission + " to associate "
                    && getContext().checkCallingOrSelfPermission(permission)
                        + "with a device with " + deviceProfile + " profile.");
                            != PackageManager.PERMISSION_GRANTED) {
                throw new SecurityException("Using " + profile + " requires " + permission);
            }
            }
        }
        }


@@ -1517,8 +1522,14 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
        return result;
        return result;
    }
    }


    private AndroidFuture<String> getDeviceProfilePermissionDescription(String deviceProfile) {
    @NonNull
        AndroidFuture<String> result = new AndroidFuture<>();
    private AndroidFuture<String> getDeviceProfilePermissionDescription(
            @Nullable String deviceProfile) {
        if (deviceProfile == null) {
            return AndroidFuture.completedFuture(null);
        }

        final AndroidFuture<String> result = new AndroidFuture<>();
        mPermissionControllerManager.getPrivilegesDescriptionStringForProfile(
        mPermissionControllerManager.getPrivilegesDescriptionStringForProfile(
                deviceProfile, FgThread.getExecutor(), desc -> {
                deviceProfile, FgThread.getExecutor(), desc -> {
                        try {
                        try {