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

Commit b3c3362b authored by yutingfang's avatar yutingfang
Browse files

Prevent setting app op mode for device provisioning app through shell

command

For security reasons, device provisioning package should be restricted
from setting app op mode through shell command.

Bug: 330507809
Test: Manual through adb shell command
Flag: EXEMPT bug fix
Change-Id: Ifa2ea860054c90a69834e95c24307d2cc2d28a45
parent b86c4a61
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
@@ -182,6 +182,7 @@ import com.android.server.SystemServiceManager;
import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
import com.android.server.pm.PackageList;
import com.android.server.pm.PackageManagerLocal;
import com.android.server.pm.ProtectedPackages;
import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageState;
@@ -311,6 +312,8 @@ public class AppOpsService extends IAppOpsService.Stub {
    private final IPlatformCompat mPlatformCompat = IPlatformCompat.Stub.asInterface(
            ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));

    private ProtectedPackages mProtectedPackages;

    /**
     * Registered callbacks, called from {@link #collectAsyncNotedOp}.
     *
@@ -2121,6 +2124,12 @@ public class AppOpsService extends IAppOpsService.Stub {

        enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid);
        verifyIncomingOp(code);

        if (isDeviceProvisioningPackage(uid, null)) {
            Slog.w(TAG, "Cannot set uid mode for device provisioning app by Shell");
            return;
        }

        code = AppOpsManager.opToSwitch(code);

        if (permissionPolicyCallback == null) {
@@ -2431,6 +2440,11 @@ public class AppOpsService extends IAppOpsService.Stub {
            return;
        }

        if (isDeviceProvisioningPackage(uid, packageName)) {
            Slog.w(TAG, "Cannot set op mode for device provisioning app by Shell");
            return;
        }

        code = AppOpsManager.opToSwitch(code);

        PackageVerificationResult pvr;
@@ -2461,6 +2475,36 @@ public class AppOpsService extends IAppOpsService.Stub {
        notifyStorageManagerOpModeChangedSync(code, uid, packageName, mode, previousMode);
    }

    // Device provisioning package is restricted from setting app op mode through shell command
    private boolean isDeviceProvisioningPackage(int uid,
            @Nullable String packageName) {
        if (UserHandle.getAppId(Binder.getCallingUid()) == Process.SHELL_UID) {
            ProtectedPackages protectedPackages = getProtectedPackages();

            if (packageName != null && protectedPackages.isDeviceProvisioningPackage(packageName)) {
                return true;
            }

            String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
            if (packageNames != null) {
                for (String pkg : packageNames) {
                    if (protectedPackages.isDeviceProvisioningPackage(pkg)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    // Race condition is allowed here for better performance
    private ProtectedPackages getProtectedPackages() {
        if (mProtectedPackages == null) {
            mProtectedPackages = new ProtectedPackages(mContext);
        }
        return mProtectedPackages;
    }

    private void notifyOpChanged(ArraySet<OnOpModeChangedListener> callbacks, int code,
            int uid, String packageName, String persistentDeviceId) {
        for (int i = 0; i < callbacks.size(); i++) {
+11 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.Context;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.SparseArray;

@@ -27,6 +28,7 @@ import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;

import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
@@ -164,4 +166,13 @@ public class ProtectedPackages {
        return hasDeviceOwnerOrProfileOwner(userId, packageName)
                || isProtectedPackage(userId, packageName);
    }

    /**
     * Returns {@code true} if a given package is the device provisioning package. Otherwise,
     * returns {@code false}.
     */
    public synchronized boolean isDeviceProvisioningPackage(String packageName) {
        return !TextUtils.isEmpty(mDeviceProvisioningPackage) && Objects.equals(
                mDeviceProvisioningPackage, packageName);
    }
}