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

Commit 8cd28b57 authored by Amith Yamasani's avatar Amith Yamasani
Browse files

Apply cross-user restrictions to Shell

Even though Shell user is allowed to perform cross-user actions,
lock that path down if the target user has restrictions imposed by
the profile owner device admin that prevents access via adb.

If the profile owner has imposed DISALLOW_DEBUGGING_FEATURES, don't
allow the shell user to make the following types of calls:
start activities, make service calls, access content providers,
send broadcasts, block/unblock packages, clear user data, etc.

Bug: 15086577
Change-Id: I9669fc165953076f786ed51cbc17d20d6fa995c3
parent da6e6c88
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -846,7 +846,7 @@ public class Am extends BaseCommand {
    }

    private void sendBroadcast() throws Exception {
        Intent intent = makeIntent(UserHandle.USER_ALL);
        Intent intent = makeIntent(UserHandle.USER_CURRENT);
        IntentReceiver receiver = new IntentReceiver();
        System.out.println("Broadcasting: " + intent);
        mAm.broadcastIntent(null, intent, null, receiver, 0, null, null, mReceiverPermission,
+1 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ interface IUserManager {
    int getUserSerialNumber(int userHandle);
    int getUserHandle(int userSerialNumber);
    Bundle getUserRestrictions(int userHandle);
    boolean hasUserRestriction(in String restrictionKey, int userHandle);
    void setUserRestrictions(in Bundle restrictions, int userHandle);
    void setApplicationRestrictions(in String packageName, in Bundle restrictions,
            int userHandle);
+7 −1
Original line number Diff line number Diff line
@@ -630,7 +630,13 @@ public class UserManager {
     * @param userHandle the UserHandle of the user for whom to retrieve the restrictions.
     */
    public boolean hasUserRestriction(String restrictionKey, UserHandle userHandle) {
        return getUserRestrictions(userHandle).getBoolean(restrictionKey, false);
        try {
            return mService.hasUserRestriction(restrictionKey,
                    userHandle.getIdentifier());
        } catch (RemoteException re) {
            Log.w(TAG, "Could not check user restrictions", re);
            return false;
        }
    }

    /**
+52 −6
Original line number Diff line number Diff line
@@ -180,6 +180,7 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UpdateLock;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.text.format.DateUtils;
import android.text.format.Time;
@@ -3364,6 +3365,16 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
    }
    void enforceShellRestriction(String restriction, int userHandle) {
        if (Binder.getCallingUid() == Process.SHELL_UID) {
            if (userHandle < 0
                    || mUserManager.hasUserRestriction(restriction, userHandle)) {
                throw new SecurityException("Shell does not have permission to access user "
                        + userHandle);
            }
        }
    }
    @Override
    public int getFrontActivityScreenCompatMode() {
        enforceNotIsolatedCaller("getFrontActivityScreenCompatMode");
@@ -14548,6 +14559,14 @@ public final class ActivityManagerService extends ActivityManagerNative
            throw new IllegalArgumentException(
                    "Call does not support special user #" + targetUserId);
        }
        // Check shell permission
        if (callingUid == Process.SHELL_UID && targetUserId >= UserHandle.USER_OWNER) {
            if (mUserManager.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES,
                    targetUserId)) {
                throw new SecurityException("Shell does not have permission to access user "
                        + targetUserId + "\n " + Debug.getCallers(3));
            }
        }
        return targetUserId;
    }
@@ -14606,6 +14625,7 @@ public final class ActivityManagerService extends ActivityManagerNative
            Intent service, String resolvedType,
            IServiceConnection connection, int flags, int userId) {
        enforceNotIsolatedCaller("bindService");
        // Refuse possible leaked file descriptors
        if (service != null && service.hasFileDescriptors() == true) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
@@ -15040,12 +15060,18 @@ public final class ActivityManagerService extends ActivityManagerNative
    }
    private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType,
            int[] users) {
            int callingUid, int[] users) {
        List<ResolveInfo> receivers = null;
        try {
            HashSet<ComponentName> singleUserReceivers = null;
            boolean scannedFirstReceivers = false;
            for (int user : users) {
                // Skip users that have Shell restrictions
                if (callingUid == Process.SHELL_UID
                        && getUserManagerLocked().hasUserRestriction(
                                UserManager.DISALLOW_DEBUGGING_FEATURES, user)) {
                    continue;
                }
                List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
                        .queryIntentReceivers(intent, resolvedType, STOCK_PM_FLAGS, user);
                if (user != 0 && newReceivers != null) {
@@ -15134,7 +15160,6 @@ public final class ActivityManagerService extends ActivityManagerNative
        // Make sure that the user who is receiving this broadcast is started.
        // If not, we will just skip it.
        if (userId != UserHandle.USER_ALL && mStartedUsers.get(userId) == null) {
            if (callingUid != Process.SYSTEM_UID || (intent.getFlags()
                    & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
@@ -15399,12 +15424,31 @@ public final class ActivityManagerService extends ActivityManagerNative
        // Need to resolve the intent to interested receivers...
        if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
                 == 0) {
            receivers = collectReceiverComponents(intent, resolvedType, users);
            receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
        }
        if (intent.getComponent() == null) {
            if (userId == UserHandle.USER_ALL && callingUid == Process.SHELL_UID) {
                // Query one target user at a time, excluding shell-restricted users
                UserManagerService ums = getUserManagerLocked();
                for (int i = 0; i < users.length; i++) {
                    if (ums.hasUserRestriction(
                            UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {
                        continue;
                    }
                    List<BroadcastFilter> registeredReceiversForUser =
                            mReceiverResolver.queryIntent(intent,
                                    resolvedType, false, users[i]);
                    if (registeredReceivers == null) {
                        registeredReceivers = registeredReceiversForUser;
                    } else if (registeredReceiversForUser != null) {
                        registeredReceivers.addAll(registeredReceiversForUser);
                    }
                }
            } else {
                registeredReceivers = mReceiverResolver.queryIntent(intent,
                        resolvedType, false, userId);
            }
        }
        final boolean replacePending =
                (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
@@ -17973,6 +18017,7 @@ public final class ActivityManagerService extends ActivityManagerNative
    @Override
    public boolean switchUser(final int userId) {
        enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, userId);
        String userName;
        synchronized (this) {
            UserInfo userInfo = getUserManagerLocked().getUserInfo(userId);
@@ -18414,6 +18459,7 @@ public final class ActivityManagerService extends ActivityManagerNative
        if (userId <= 0) {
            throw new IllegalArgumentException("Can't stop primary user " + userId);
        }
        enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, userId);
        synchronized (this) {
            return stopUserLocked(userId, callback);
        }
+5 −5
Original line number Diff line number Diff line
@@ -446,7 +446,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
    private int createSessionInternal(SessionParams params, String installerPackageName, int userId)
            throws IOException {
        final int callingUid = Binder.getCallingUid();
        mPm.enforceCrossUserPermission(callingUid, userId, true, "createSession");
        mPm.enforceCrossUserPermission(callingUid, userId, true, false, "createSession");

        if (mPm.isUserRestricted(UserHandle.getUserId(callingUid),
                UserManager.DISALLOW_INSTALL_APPS)) {
@@ -654,7 +654,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub {

    @Override
    public List<SessionInfo> getAllSessions(int userId) {
        mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "getAllSessions");
        mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "getAllSessions");

        final List<SessionInfo> result = new ArrayList<>();
        synchronized (mSessions) {
@@ -670,7 +670,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub {

    @Override
    public List<SessionInfo> getMySessions(String installerPackageName, int userId) {
        mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "getMySessions");
        mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "getMySessions");
        mAppOps.checkPackage(Binder.getCallingUid(), installerPackageName);

        final List<SessionInfo> result = new ArrayList<>();
@@ -688,7 +688,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub {

    @Override
    public void uninstall(String packageName, int flags, IntentSender statusReceiver, int userId) {
        mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "uninstall");
        mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "uninstall");

        final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext,
                statusReceiver, packageName);
@@ -717,7 +717,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub {

    @Override
    public void registerCallback(IPackageInstallerCallback callback, int userId) {
        mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "registerCallback");
        mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "registerCallback");
        mCallbacks.register(callback, userId);
    }

Loading