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

Commit 10dbf33e authored by Robin Lee's avatar Robin Lee Committed by Android Git Automerger
Browse files

am 0756e4e4: Merge "Fix privilege escalation for preferred activities"

* commit '0756e4e4':
  Fix privilege escalation for preferred activities
parents 121e1395 0756e4e4
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" );
                }
            }
        }
    }
}