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

Commit 0756e4e4 authored by Robin Lee's avatar Robin Lee Committed by Android (Google) Code Review
Browse files

Merge "Fix privilege escalation for preferred activities"

parents ecc5c8a4 5c921daa
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -51,6 +51,22 @@ import java.util.HashMap;
public final class DeviceAdminInfo implements Parcelable {
    static final String TAG = "DeviceAdminInfo";

    /**
     * A type of policy that this device admin can use: device owner meta-policy
     * for an admin that is designated as owner of the device.
     *
     * @hide
     */
    public static final int USES_POLICY_DEVICE_OWNER = -2;

    /**
     * A type of policy that this device admin can use: profile owner meta-policy
     * for admins that have been installed as owner of some user profile.
     *
     * @hide
     */
    public static final int USES_POLICY_PROFILE_OWNER = -1;

    /**
     * A type of policy that this device admin can use: limit the passwords
     * that the user can select, via {@link DevicePolicyManager#setPasswordQuality}
+65 −63
Original line number Diff line number Diff line
@@ -170,7 +170,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        int mActivePasswordNonLetter = 0;
        int mFailedPasswordAttempts = 0;

        int mUserHandle;;
        int mUserHandle;
        int mPasswordOwner = -1;
        long mLastMaximumTimeToLock = -1;

@@ -722,6 +722,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        final int callingUid = Binder.getCallingUid();
        final int userHandle = UserHandle.getUserId(callingUid);
        final DevicePolicyData policy = getUserData(userHandle);

        List<ActiveAdmin> candidates = new ArrayList<ActiveAdmin>();

        // Build a list of admins for this uid matching the given ComponentName
        if (who != null) {
            ActiveAdmin admin = policy.mAdminMap.get(who);
            if (admin == null) {
@@ -731,22 +735,43 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                throw new SecurityException("Admin " + who + " is not owned by uid "
                        + Binder.getCallingUid());
            }
            if (!admin.info.usesPolicy(reqPolicy)) {
                throw new SecurityException("Admin " + admin.info.getComponent()
                        + " did not specify uses-policy for: "
                        + admin.info.getTagForPolicy(reqPolicy));
            candidates.add(admin);
        } else {
            for (ActiveAdmin admin : policy.mAdminList) {
                if (admin.getUid() == callingUid) {
                    candidates.add(admin);
                }
            }
        }

        // Try to find an admin which can use reqPolicy
        for (ActiveAdmin admin : candidates) {
            boolean ownsDevice = isDeviceOwner(admin.info.getPackageName());
            boolean ownsProfile = (getProfileOwner(userHandle) != null
                    && getProfileOwner(userHandle).equals(admin.info.getPackageName()));

            if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) {
                if (ownsDevice) {
                    return admin;
                }
            } else if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) {
                if (ownsDevice || ownsProfile) {
                    return admin;
                }
            } else {
            final int N = policy.mAdminList.size();
            for (int i=0; i<N; i++) {
                ActiveAdmin admin = policy.mAdminList.get(i);
                if (admin.getUid() == callingUid && admin.info.usesPolicy(reqPolicy)) {
                if (admin.info.usesPolicy(reqPolicy)) {
                    return admin;
                }
            }
        }

        if (who != null) {
            throw new SecurityException("Admin " + candidates.get(0).info.getComponent()
                    + " did not specify uses-policy for: "
                    + candidates.get(0).info.getTagForPolicy(reqPolicy));
        } else {
            throw new SecurityException("No active admin owned by uid "
                    + Binder.getCallingUid() + " for policy #" + reqPolicy);
                    + Binder.getCallingUid() + " for policy:" + reqPolicy);
        }
    }

@@ -2966,65 +2991,42 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
    }

    private boolean isProfileOwner(String packageName, int userId) {
        String profileOwnerPackage = getProfileOwner(userId);
        // TODO: make public and connect with isProfileOwnerApp in DPM
        return profileOwnerPackage != null && profileOwnerPackage.equals(packageName);
    }

    public void addPersistentPreferredActivity(ComponentName admin, IntentFilter filter,
    public void addPersistentPreferredActivity(ComponentName who, IntentFilter filter,
            ComponentName activity) {
        int callingUserId = UserHandle.getCallingUserId();
        Slog.d(LOG_TAG,"called by user " + callingUserId);
        synchronized (this) {
            ActiveAdmin aa = getActiveAdminUncheckedLocked(admin, callingUserId);
            if (aa == null) {
                throw new SecurityException("No active admin " + admin);
            } else {
                if (isProfileOwner(admin.getPackageName(), callingUserId)
                        || isDeviceOwner(admin.getPackageName())) {
            if (who == null) {
                throw new NullPointerException("ComponentName is null");
            }
            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);

            IPackageManager pm = AppGlobals.getPackageManager();
            long id = Binder.clearCallingIdentity();
            try {
                        pm.addPersistentPreferredActivity(filter, activity, callingUserId);
                pm.addPersistentPreferredActivity(filter, activity, UserHandle.getCallingUserId());
            } catch (RemoteException re) {
                // Shouldn't happen
            } finally {
                restoreCallingIdentity(id);
            }
                } else {
                    throw new SecurityException("Admin " + admin +
                            "is not device owner or profile owner" );
                }
            }
        }
    }

    public void clearPackagePersistentPreferredActivities(ComponentName admin,
            String packageName) {
        int callingUserId = UserHandle.getCallingUserId();
        Slog.d(LOG_TAG,"called by user " + callingUserId);
    public void clearPackagePersistentPreferredActivities(ComponentName who, String packageName) {
        synchronized (this) {
            ActiveAdmin aa = getActiveAdminUncheckedLocked(admin, callingUserId);
            if (aa == null) {
                throw new SecurityException("No active admin " + admin);
            } else {
                if (isProfileOwner(admin.getPackageName(), callingUserId)
                        || isDeviceOwner(admin.getPackageName())) {
            if (who == null) {
                throw new NullPointerException("ComponentName is null");
            }
            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);

            IPackageManager pm = AppGlobals.getPackageManager();
            long id = Binder.clearCallingIdentity();
            try {
                        pm.clearPackagePersistentPreferredActivities(packageName, callingUserId);
                pm.clearPackagePersistentPreferredActivities(packageName, UserHandle.getCallingUserId());
            } catch (RemoteException re) {
                // Shouldn't happen
            } finally {
                restoreCallingIdentity(id);
            }
                } else {
                    throw new SecurityException("Admin " + admin +
                            "is not device owner or profile owner" );
                }
            }
        }
    }
}