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

Commit bebc4ec8 authored by Hai Zhang's avatar Hai Zhang Committed by Android (Google) Code Review
Browse files

Merge "Consolidate OEM and different privileged permission allowlists into one."

parents a1cd85a6 182e2439
Loading
Loading
Loading
Loading
+38 −150
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import android.util.Xml;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.XmlUtils;
import com.android.modules.utils.build.UnboundedSdkLevel;
import com.android.server.pm.permission.PermissionAllowlist;

import libcore.io.IoUtils;
import libcore.util.EmptyArray;
@@ -304,24 +305,7 @@ public class SystemConfig {
    final ArrayMap<String, List<CarrierAssociatedAppEntry>>
            mDisabledUntilUsedPreinstalledCarrierAssociatedApps = new ArrayMap<>();

    final ArrayMap<String, ArraySet<String>> mPrivAppPermissions = new ArrayMap<>();
    final ArrayMap<String, ArraySet<String>> mPrivAppDenyPermissions = new ArrayMap<>();

    final ArrayMap<String, ArraySet<String>> mVendorPrivAppPermissions = new ArrayMap<>();
    final ArrayMap<String, ArraySet<String>> mVendorPrivAppDenyPermissions = new ArrayMap<>();

    final ArrayMap<String, ArraySet<String>> mProductPrivAppPermissions = new ArrayMap<>();
    final ArrayMap<String, ArraySet<String>> mProductPrivAppDenyPermissions = new ArrayMap<>();

    final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppPermissions = new ArrayMap<>();
    final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppDenyPermissions = new ArrayMap<>();

    final ArrayMap<String, ArrayMap<String, ArraySet<String>>> mApexPrivAppPermissions =
            new ArrayMap<>();
    final ArrayMap<String, ArrayMap<String, ArraySet<String>>> mApexPrivAppDenyPermissions =
            new ArrayMap<>();

    final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>();
    private final PermissionAllowlist mPermissionAllowlist = new PermissionAllowlist();

    // Allowed associations between applications.  If there are any entries
    // for an app, those are the only associations allowed; otherwise, all associations
@@ -459,64 +443,8 @@ public class SystemConfig {
        return mDisabledUntilUsedPreinstalledCarrierAssociatedApps;
    }

    public ArraySet<String> getPrivAppPermissions(String packageName) {
        return mPrivAppPermissions.get(packageName);
    }

    public ArraySet<String> getPrivAppDenyPermissions(String packageName) {
        return mPrivAppDenyPermissions.get(packageName);
    }

    /** Get privapp permission allowlist for an apk-in-apex. */
    public ArraySet<String> getApexPrivAppPermissions(String apexName, String apkPackageName) {
        return mApexPrivAppPermissions.getOrDefault(apexName, EMPTY_PERMISSIONS)
                .get(apkPackageName);
    }

    /** Get privapp permissions denylist for an apk-in-apex. */
    public ArraySet<String> getApexPrivAppDenyPermissions(String apexName, String apkPackageName) {
        return mApexPrivAppDenyPermissions.getOrDefault(apexName, EMPTY_PERMISSIONS)
                .get(apkPackageName);
    }

    public ArraySet<String> getVendorPrivAppPermissions(String packageName) {
        return mVendorPrivAppPermissions.get(packageName);
    }

    public ArraySet<String> getVendorPrivAppDenyPermissions(String packageName) {
        return mVendorPrivAppDenyPermissions.get(packageName);
    }

    public ArraySet<String> getProductPrivAppPermissions(String packageName) {
        return mProductPrivAppPermissions.get(packageName);
    }

    public ArraySet<String> getProductPrivAppDenyPermissions(String packageName) {
        return mProductPrivAppDenyPermissions.get(packageName);
    }

    /**
     * Read from "permission" tags in /system_ext/etc/permissions/*.xml
     * @return Set of privileged permissions that are explicitly granted.
     */
    public ArraySet<String> getSystemExtPrivAppPermissions(String packageName) {
        return mSystemExtPrivAppPermissions.get(packageName);
    }

    /**
     * Read from "deny-permission" tags in /system_ext/etc/permissions/*.xml
     * @return Set of privileged permissions that are explicitly denied.
     */
    public ArraySet<String> getSystemExtPrivAppDenyPermissions(String packageName) {
        return mSystemExtPrivAppDenyPermissions.get(packageName);
    }

    public Map<String, Boolean> getOemPermissions(String packageName) {
        final Map<String, Boolean> oemPermissions = mOemPermissions.get(packageName);
        if (oemPermissions != null) {
            return oemPermissions;
        }
        return Collections.emptyMap();
    public PermissionAllowlist getPermissionAllowlist() {
        return mPermissionAllowlist;
    }

    public ArrayMap<String, ArraySet<String>> getAllowedAssociations() {
@@ -1253,20 +1181,20 @@ public class SystemConfig {
                                    Environment.getApexDirectory().toPath() + "/")
                                    && ApexProperties.updatable().orElse(false);
                            if (vendor) {
                                readPrivAppPermissions(parser, mVendorPrivAppPermissions,
                                        mVendorPrivAppDenyPermissions);
                                readPrivAppPermissions(parser,
                                        mPermissionAllowlist.getVendorPrivilegedAppAllowlist());
                            } else if (product) {
                                readPrivAppPermissions(parser, mProductPrivAppPermissions,
                                        mProductPrivAppDenyPermissions);
                                readPrivAppPermissions(parser,
                                        mPermissionAllowlist.getProductPrivilegedAppAllowlist());
                            } else if (systemExt) {
                                readPrivAppPermissions(parser, mSystemExtPrivAppPermissions,
                                        mSystemExtPrivAppDenyPermissions);
                                readPrivAppPermissions(parser,
                                        mPermissionAllowlist.getSystemExtPrivilegedAppAllowlist());
                            } else if (apex) {
                                readApexPrivAppPermissions(parser, permFile,
                                        Environment.getApexDirectory().toPath());
                            } else {
                                readPrivAppPermissions(parser, mPrivAppPermissions,
                                        mPrivAppDenyPermissions);
                                readPrivAppPermissions(parser,
                                        mPermissionAllowlist.getPrivilegedAppAllowlist());
                            }
                        } else {
                            logNotAllowedInPartition(name, permFile, parser);
@@ -1589,50 +1517,10 @@ public class SystemConfig {
        }
    }

    private void readPrivAppPermissions(XmlPullParser parser,
            ArrayMap<String, ArraySet<String>> grantMap,
            ArrayMap<String, ArraySet<String>> denyMap)
    private void readPrivAppPermissions(@NonNull XmlPullParser parser,
            @NonNull ArrayMap<String, ArrayMap<String, Boolean>> allowlist)
            throws IOException, XmlPullParserException {
        String packageName = parser.getAttributeValue(null, "package");
        if (TextUtils.isEmpty(packageName)) {
            Slog.w(TAG, "package is required for <privapp-permissions> in "
                    + parser.getPositionDescription());
            return;
        }

        ArraySet<String> permissions = grantMap.get(packageName);
        if (permissions == null) {
            permissions = new ArraySet<>();
        }
        ArraySet<String> denyPermissions = denyMap.get(packageName);
        int depth = parser.getDepth();
        while (XmlUtils.nextElementWithin(parser, depth)) {
            String name = parser.getName();
            if ("permission".equals(name)) {
                String permName = parser.getAttributeValue(null, "name");
                if (TextUtils.isEmpty(permName)) {
                    Slog.w(TAG, "name is required for <permission> in "
                            + parser.getPositionDescription());
                    continue;
                }
                permissions.add(permName);
            } else if ("deny-permission".equals(name)) {
                String permName = parser.getAttributeValue(null, "name");
                if (TextUtils.isEmpty(permName)) {
                    Slog.w(TAG, "name is required for <deny-permission> in "
                            + parser.getPositionDescription());
                    continue;
                }
                if (denyPermissions == null) {
                    denyPermissions = new ArraySet<>();
                }
                denyPermissions.add(permName);
            }
        }
        grantMap.put(packageName, permissions);
        if (denyPermissions != null) {
            denyMap.put(packageName, denyPermissions);
        }
        readPermissionAllowlist(parser, allowlist, "privapp-permissions");
    }

    private void readInstallInUserType(XmlPullParser parser,
@@ -1683,14 +1571,21 @@ public class SystemConfig {
    }

    void readOemPermissions(XmlPullParser parser) throws IOException, XmlPullParserException {
        readPermissionAllowlist(parser, mPermissionAllowlist.getOemAppAllowlist(),
                "oem-permissions");
    }

    private static void readPermissionAllowlist(@NonNull XmlPullParser parser,
            @NonNull ArrayMap<String, ArrayMap<String, Boolean>> allowlist, @NonNull String tagName)
            throws IOException, XmlPullParserException {
        final String packageName = parser.getAttributeValue(null, "package");
        if (TextUtils.isEmpty(packageName)) {
            Slog.w(TAG, "package is required for <oem-permissions> in "
            Slog.w(TAG, "package is required for <" + tagName + "> in "
                    + parser.getPositionDescription());
            return;
        }

        ArrayMap<String, Boolean> permissions = mOemPermissions.get(packageName);
        ArrayMap<String, Boolean> permissions = allowlist.get(packageName);
        if (permissions == null) {
            permissions = new ArrayMap<>();
        }
@@ -1698,24 +1593,24 @@ public class SystemConfig {
        while (XmlUtils.nextElementWithin(parser, depth)) {
            final String name = parser.getName();
            if ("permission".equals(name)) {
                final String permName = parser.getAttributeValue(null, "name");
                if (TextUtils.isEmpty(permName)) {
                final String permissionName = parser.getAttributeValue(null, "name");
                if (TextUtils.isEmpty(permissionName)) {
                    Slog.w(TAG, "name is required for <permission> in "
                            + parser.getPositionDescription());
                    continue;
                }
                permissions.put(permName, Boolean.TRUE);
                permissions.put(permissionName, Boolean.TRUE);
            } else if ("deny-permission".equals(name)) {
                String permName = parser.getAttributeValue(null, "name");
                if (TextUtils.isEmpty(permName)) {
                String permissionName = parser.getAttributeValue(null, "name");
                if (TextUtils.isEmpty(permissionName)) {
                    Slog.w(TAG, "name is required for <deny-permission> in "
                            + parser.getPositionDescription());
                    continue;
                }
                permissions.put(permName, Boolean.FALSE);
                permissions.put(permissionName, Boolean.FALSE);
            }
        }
        mOemPermissions.put(packageName, permissions);
        allowlist.put(packageName, permissions);
    }

    private void readSplitPermission(XmlPullParser parser, File permFile)
@@ -1865,21 +1760,14 @@ public class SystemConfig {
            Path apexDirectoryPath) throws IOException, XmlPullParserException {
        final String moduleName =
                getApexModuleNameFromFilePath(permFile.toPath(), apexDirectoryPath);
        final ArrayMap<String, ArraySet<String>> privAppPermissions;
        if (mApexPrivAppPermissions.containsKey(moduleName)) {
            privAppPermissions = mApexPrivAppPermissions.get(moduleName);
        } else {
            privAppPermissions = new ArrayMap<>();
            mApexPrivAppPermissions.put(moduleName, privAppPermissions);
        }
        final ArrayMap<String, ArraySet<String>> privAppDenyPermissions;
        if (mApexPrivAppDenyPermissions.containsKey(moduleName)) {
            privAppDenyPermissions = mApexPrivAppDenyPermissions.get(moduleName);
        } else {
            privAppDenyPermissions = new ArrayMap<>();
            mApexPrivAppDenyPermissions.put(moduleName, privAppDenyPermissions);
        }
        readPrivAppPermissions(parser, privAppPermissions, privAppDenyPermissions);
        final ArrayMap<String, ArrayMap<String, ArrayMap<String, Boolean>>> allowlists =
                mPermissionAllowlist.getApexPrivilegedAppAllowlists();
        ArrayMap<String, ArrayMap<String, Boolean>> allowlist = allowlists.get(moduleName);
        if (allowlist == null) {
            allowlist = new ArrayMap<>();
            allowlists.put(moduleName, allowlist);
        }
        readPrivAppPermissions(parser, allowlist);
    }

    private static boolean isSystemProcess() {
+46 −40
Original line number Diff line number Diff line
@@ -99,7 +99,6 @@ import android.system.Os;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.IntArray;
import android.util.PrintWriterPrinter;
import android.util.Slog;
@@ -116,6 +115,7 @@ import com.android.server.SystemConfig;
import com.android.server.art.ArtManagerLocal;
import com.android.server.pm.PackageManagerShellCommandDataLoader.Metadata;
import com.android.server.pm.permission.LegacyPermissionManagerInternal;
import com.android.server.pm.permission.PermissionAllowlist;
import com.android.server.pm.verify.domain.DomainVerificationShell;

import dalvik.system.DexFile;
@@ -2684,26 +2684,7 @@ class PackageManagerShellCommand extends ShellCommand {
            getErrPrintWriter().println("Error: no package specified.");
            return 1;
        }

        ArraySet<String> privAppPermissions = null;
        if (isVendorApp(pkg)) {
            privAppPermissions = SystemConfig.getInstance().getVendorPrivAppPermissions(pkg);
        } else if (isProductApp(pkg)) {
            privAppPermissions = SystemConfig.getInstance().getProductPrivAppPermissions(pkg);
        } else if (isSystemExtApp(pkg)) {
            privAppPermissions = SystemConfig.getInstance()
                    .getSystemExtPrivAppPermissions(pkg);
        } else if (isApexApp(pkg)) {
            final String apexName = ApexManager.getInstance().getApexModuleNameForPackageName(
                    getApexPackageNameContainingPackage(pkg));
            privAppPermissions = SystemConfig.getInstance()
                    .getApexPrivAppPermissions(apexName, pkg);
        } else {
            privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
        }

        getOutPrintWriter().println(privAppPermissions == null
                ? "{}" : privAppPermissions.toString());
        getOutPrintWriter().println(getPrivAppPermissionsString(pkg, true));
        return 0;
    }

@@ -2713,27 +2694,52 @@ class PackageManagerShellCommand extends ShellCommand {
            getErrPrintWriter().println("Error: no package specified.");
            return 1;
        }
        getOutPrintWriter().println(getPrivAppPermissionsString(pkg, false));
        return 0;
    }

        ArraySet<String> privAppPermissions = null;
        if (isVendorApp(pkg)) {
            privAppPermissions = SystemConfig.getInstance().getVendorPrivAppDenyPermissions(pkg);
        } else if (isProductApp(pkg)) {
            privAppPermissions = SystemConfig.getInstance().getProductPrivAppDenyPermissions(pkg);
        } else if (isSystemExtApp(pkg)) {
            privAppPermissions = SystemConfig.getInstance()
                    .getSystemExtPrivAppDenyPermissions(pkg);
        } else if (isApexApp(pkg)) {
            final String apexName = ApexManager.getInstance().getApexModuleNameForPackageName(
                    getApexPackageNameContainingPackage(pkg));
            privAppPermissions = SystemConfig.getInstance()
                    .getApexPrivAppDenyPermissions(apexName, pkg);
    @NonNull
    private String getPrivAppPermissionsString(@NonNull String packageName, boolean allowed) {
        final PermissionAllowlist permissionAllowlist =
                SystemConfig.getInstance().getPermissionAllowlist();
        final ArrayMap<String, ArrayMap<String, Boolean>> privAppPermissions;
        if (isVendorApp(packageName)) {
            privAppPermissions = permissionAllowlist.getVendorPrivilegedAppAllowlist();
        } else if (isProductApp(packageName)) {
            privAppPermissions = permissionAllowlist.getProductPrivilegedAppAllowlist();
        } else if (isSystemExtApp(packageName)) {
            privAppPermissions = permissionAllowlist.getSystemExtPrivilegedAppAllowlist();
        } else if (isApexApp(packageName)) {
            final String moduleName = ApexManager.getInstance().getApexModuleNameForPackageName(
                    getApexPackageNameContainingPackage(packageName));
            privAppPermissions = permissionAllowlist.getApexPrivilegedAppAllowlists()
                    .get(moduleName);
        } else {
            privAppPermissions = SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
            privAppPermissions = permissionAllowlist.getPrivilegedAppAllowlist();
        }
        final ArrayMap<String, Boolean> permissions = privAppPermissions != null
                ? privAppPermissions.get(packageName) : null;
        if (permissions == null) {
            return "{}";
        }
        final StringBuilder result = new StringBuilder("{");
        boolean isFirstPermission = true;
        final int permissionsSize = permissions.size();
        for (int i = 0; i < permissionsSize; i++) {
            boolean permissionAllowed = permissions.valueAt(i);
            if (permissionAllowed != allowed) {
                continue;
            }

        getOutPrintWriter().println(privAppPermissions == null
                ? "{}" : privAppPermissions.toString());
        return 0;
            if (isFirstPermission) {
                isFirstPermission = false;
            } else {
                result.append(", ");
            }
            String permissionName = permissions.keyAt(i);
            result.append(permissionName);
        }
        result.append("}");
        return result.toString();
    }

    private int runGetOemPermissions() {
@@ -2743,7 +2749,7 @@ class PackageManagerShellCommand extends ShellCommand {
            return 1;
        }
        final Map<String, Boolean> oemPermissions = SystemConfig.getInstance()
                .getOemPermissions(pkg);
                .getPermissionAllowlist().getOemAppAllowlist().get(pkg);
        if (oemPermissions == null || oemPermissions.isEmpty()) {
            getOutPrintWriter().println("{}");
        } else {
+140 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.pm.permission;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.util.ArrayMap;

/**
 * Data class for OEM and privileged app permission allowlist state.
 */
public final class PermissionAllowlist {
    @NonNull
    private final ArrayMap<String, ArrayMap<String, Boolean>> mOemAppAllowlist = new ArrayMap<>();
    @NonNull
    private final ArrayMap<String, ArrayMap<String, Boolean>> mPrivilegedAppAllowlist =
            new ArrayMap<>();
    @NonNull
    private final ArrayMap<String, ArrayMap<String, Boolean>> mVendorPrivilegedAppAllowlist =
            new ArrayMap<>();
    @NonNull
    private final ArrayMap<String, ArrayMap<String, Boolean>> mProductPrivilegedAppAllowlist =
            new ArrayMap<>();
    @NonNull
    private final ArrayMap<String, ArrayMap<String, Boolean>> mSystemExtPrivilegedAppAllowlist =
            new ArrayMap<>();
    @NonNull
    private final ArrayMap<String, ArrayMap<String, ArrayMap<String, Boolean>>>
            mApexPrivilegedAppAllowlists = new ArrayMap<>();

    @NonNull
    public ArrayMap<String, ArrayMap<String, Boolean>> getOemAppAllowlist() {
        return mOemAppAllowlist;
    }

    @NonNull
    public ArrayMap<String, ArrayMap<String, Boolean>> getPrivilegedAppAllowlist() {
        return mPrivilegedAppAllowlist;
    }

    @NonNull
    public ArrayMap<String, ArrayMap<String, Boolean>> getVendorPrivilegedAppAllowlist() {
        return mVendorPrivilegedAppAllowlist;
    }

    @NonNull
    public ArrayMap<String, ArrayMap<String, Boolean>> getProductPrivilegedAppAllowlist() {
        return mProductPrivilegedAppAllowlist;
    }

    @NonNull
    public ArrayMap<String, ArrayMap<String, Boolean>> getSystemExtPrivilegedAppAllowlist() {
        return mSystemExtPrivilegedAppAllowlist;
    }

    @NonNull
    public ArrayMap<String, ArrayMap<String, ArrayMap<String, Boolean>>>
            getApexPrivilegedAppAllowlists() {
        return mApexPrivilegedAppAllowlists;
    }

    @Nullable
    public Boolean getOemAppAllowlistState(@NonNull String packageName,
            @NonNull String permissionName) {
        ArrayMap<String, Boolean> permissions = mOemAppAllowlist.get(packageName);
        if (permissions == null) {
            return null;
        }
        return permissions.get(permissionName);
    }

    @Nullable
    public Boolean getPrivilegedAppAllowlistState(@NonNull String packageName,
            @NonNull String permissionName) {
        ArrayMap<String, Boolean> permissions = mPrivilegedAppAllowlist.get(packageName);
        if (permissions == null) {
            return null;
        }
        return permissions.get(permissionName);
    }

    @Nullable
    public Boolean getVendorPrivilegedAppAllowlistState(@NonNull String packageName,
            @NonNull String permissionName) {
        ArrayMap<String, Boolean> permissions = mVendorPrivilegedAppAllowlist.get(packageName);
        if (permissions == null) {
            return null;
        }
        return permissions.get(permissionName);
    }

    @Nullable
    public Boolean getProductPrivilegedAppAllowlistState(@NonNull String packageName,
            @NonNull String permissionName) {
        ArrayMap<String, Boolean> permissions = mProductPrivilegedAppAllowlist.get(packageName);
        if (permissions == null) {
            return null;
        }
        return permissions.get(permissionName);
    }

    @Nullable
    public Boolean getSystemExtPrivilegedAppAllowlistState(@NonNull String packageName,
            @NonNull String permissionName) {
        ArrayMap<String, Boolean> permissions = mSystemExtPrivilegedAppAllowlist.get(packageName);
        if (permissions == null) {
            return null;
        }
        return permissions.get(permissionName);
    }

    @Nullable
    public Boolean getApexPrivilegedAppAllowlistState(@NonNull String moduleName,
            @NonNull String packageName, @NonNull String permissionName) {
        ArrayMap<String, ArrayMap<String, Boolean>> allowlist =
                mApexPrivilegedAppAllowlists.get(moduleName);
        if (allowlist == null) {
            return null;
        }
        ArrayMap<String, Boolean> permissions = allowlist.get(packageName);
        if (permissions == null) {
            return null;
        }
        return permissions.get(permissionName);
    }
}
+31 −52

File changed.

Preview size limit exceeded, changes collapsed.

+5 −6
Original line number Diff line number Diff line
@@ -405,12 +405,11 @@ public class SystemConfigTest {

        mSysConfig.readApexPrivAppPermissions(parser, permissionFile, apexDir.toPath());

        assertThat(mSysConfig.getApexPrivAppPermissions("com.android.my_module",
                "com.android.apk_in_apex"))
            .containsExactly("android.permission.FOO");
        assertThat(mSysConfig.getApexPrivAppDenyPermissions("com.android.my_module",
                "com.android.apk_in_apex"))
            .containsExactly("android.permission.BAR");
        ArrayMap<String, Boolean> permissions = mSysConfig.getPermissionAllowlist()
                .getApexPrivilegedAppAllowlists().get("com.android.my_module")
                .get("com.android.apk_in_apex");
        assertThat(permissions)
            .containsExactly("android.permission.FOO", true, "android.permission.BAR", false);
    }

    /**