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

Commit 002fdbdb authored by Jiyong Park's avatar Jiyong Park
Browse files

Support privileged vendor apps

Privileged apps can now be located in the vendor partition. This is
mainly to move SoC-dependent apks to the vendor partition so that the
system partition becomes more generic.

Like existing privileged apps in the system partition, the list of
privileged apps in the vendor partition and the permissions they are
using must be white-listed. The whitelist can be specified via
<privapp-permissions> tags in one of /vendor/etc/permissions/*.xml
files. Note: vendors can only white-list the apps in vendor partition,
but not the apps in system partition.

This change also introduces a new flag 'vendor-privileged' to the
permission protection level. It is used to expose platform-defined
permissions to the privileged vendor apps. If a platform permission does
not have this flag, it is not granted to vendor apps even when the app
is privileged and white-listed.

Bug: 35301609
Test: `mm` under frameworks/base/tests/privapp-permissions
adb sync && adb reboot
adb shell cmd package \
com.android.framework.permission.privapp.tests.vendor
shows that the app is installed.
android.permission.BIND_IMS_SERVICE is in the installed permissions list
android.permission.MANAGE_USE is not in the installed permissions list,
but is in the requested permissions list.

Change-Id: I196375aaaa9ea3a2ba15686ef08cf3f70ade7046
parent 304494b6
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -638,8 +638,7 @@ public final class LoadedApk {
        final String defaultSearchPaths = System.getProperty("java.library.path");
        final boolean treatVendorApkAsUnbundled = !defaultSearchPaths.contains("/vendor/lib");
        if (mApplicationInfo.getCodePath() != null
                && mApplicationInfo.getCodePath().startsWith("/vendor/")
                && treatVendorApkAsUnbundled) {
                && mApplicationInfo.isVendor() && treatVendorApkAsUnbundled) {
            isBundledApp = false;
        }

+13 −0
Original line number Diff line number Diff line
@@ -594,6 +594,13 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
     */
    public static final int PRIVATE_FLAG_OEM = 1 << 17;

    /**
     * Value for {@linl #privateFlags}: whether this app is pre-installed on the
     * vendor partition of the system image.
     * @hide
     */
    public static final int PRIVATE_FLAG_VENDOR = 1 << 18;

    /** @hide */
    @IntDef(flag = true, prefix = { "PRIVATE_FLAG_" }, value = {
            PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE,
@@ -613,6 +620,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
            PRIVATE_FLAG_PRIVILEGED,
            PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER,
            PRIVATE_FLAG_STATIC_SHARED_LIBRARY,
            PRIVATE_FLAG_VENDOR,
            PRIVATE_FLAG_VIRTUAL_PRELOAD,
    })
    @Retention(RetentionPolicy.SOURCE)
@@ -1569,6 +1577,11 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
        return (flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
    }

    /** @hide */
    public boolean isVendor() {
        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
    }

    /**
     * Returns whether or not this application was installed as a virtual preload.
     */
+5 −0
Original line number Diff line number Diff line
@@ -6266,6 +6266,11 @@ public class PackageParser {
            return applicationInfo.isOem();
        }

        /** @hide */
        public boolean isVendor() {
            return applicationInfo.isVendor();
        }

        /** @hide */
        public boolean isPrivileged() {
            return applicationInfo.isPrivilegedApp();
+18 −0
Original line number Diff line number Diff line
@@ -143,6 +143,15 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
    @SystemApi
    public static final int PROTECTION_FLAG_OEM = 0x4000;

    /**
     * Additional flag for {${link #protectionLevel}, corresponding
     * to the <code>vendorPrivileged</code> value of
     * {@link android.R.attr#protectionLevel}.
     *
     * @hide
     */
    public static final int PROTECTION_FLAG_VENDOR_PRIVILEGED = 0x8000;

    /**
     * Mask for {@link #protectionLevel}: the basic protection type.
     */
@@ -231,6 +240,12 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
        if (level == PROTECTION_SIGNATURE_OR_SYSTEM) {
            level = PROTECTION_SIGNATURE | PROTECTION_FLAG_PRIVILEGED;
        }
        if ((level & PROTECTION_FLAG_VENDOR_PRIVILEGED) != 0
                && (level & PROTECTION_FLAG_PRIVILEGED) == 0) {
            // 'vendorPrivileged' must be 'privileged'. If not,
            // drop the vendorPrivileged.
            level = level & ~PROTECTION_FLAG_VENDOR_PRIVILEGED;
        }
        return level;
    }

@@ -284,6 +299,9 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
        if ((level & PermissionInfo.PROTECTION_FLAG_OEM) != 0) {
            protLevel += "|oem";
        }
        if ((level & PermissionInfo.PROTECTION_FLAG_VENDOR_PRIVILEGED) != 0) {
            protLevel += "|vendorPrivileged";
        }
        return protLevel;
    }

+33 −7
Original line number Diff line number Diff line
@@ -146,6 +146,9 @@ public class SystemConfig {
    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, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>();

    public static SystemConfig getInstance() {
@@ -229,6 +232,14 @@ public class SystemConfig {
        return mPrivAppDenyPermissions.get(packageName);
    }

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

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

    public Map<String, Boolean> getOemPermissions(String packageName) {
        final Map<String, Boolean> oemPermissions = mOemPermissions.get(packageName);
        if (oemPermissions != null) {
@@ -248,7 +259,7 @@ public class SystemConfig {

        // Allow Vendor to customize system configs around libs, features, permissions and apps
        int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
                ALLOW_APP_CONFIGS;
                ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS;
        readPermissions(Environment.buildPath(
                Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
        readPermissions(Environment.buildPath(
@@ -587,7 +598,19 @@ public class SystemConfig {
                    }
                    XmlUtils.skipCurrentTag(parser);
                } else if ("privapp-permissions".equals(name) && allowPrivappPermissions) {
                    readPrivAppPermissions(parser);
                    // privapp permissions from system and vendor partitions are stored
                    // separately. This is to prevent xml files in the vendor partition from
                    // granting permissions to priv apps in the system partition and vice
                    // versa.
                    boolean vendor = permFile.toPath().startsWith(
                            Environment.getVendorDirectory().toPath());
                    if (vendor) {
                        readPrivAppPermissions(parser, mVendorPrivAppPermissions,
                                mVendorPrivAppDenyPermissions);
                    } else {
                        readPrivAppPermissions(parser, mPrivAppPermissions,
                                mPrivAppDenyPermissions);
                    }
                } else if ("oem-permissions".equals(name) && allowOemPermissions) {
                    readOemPermissions(parser);
                } else {
@@ -674,7 +697,10 @@ public class SystemConfig {
        }
    }

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

        ArraySet<String> permissions = mPrivAppPermissions.get(packageName);
        ArraySet<String> permissions = grantMap.get(packageName);
        if (permissions == null) {
            permissions = new ArraySet<>();
        }
        ArraySet<String> denyPermissions = mPrivAppDenyPermissions.get(packageName);
        ArraySet<String> denyPermissions = denyMap.get(packageName);
        int depth = parser.getDepth();
        while (XmlUtils.nextElementWithin(parser, depth)) {
            String name = parser.getName();
@@ -711,9 +737,9 @@ public class SystemConfig {
                denyPermissions.add(permName);
            }
        }
        mPrivAppPermissions.put(packageName, permissions);
        grantMap.put(packageName, permissions);
        if (denyPermissions != null) {
            mPrivAppDenyPermissions.put(packageName, denyPermissions);
            denyMap.put(packageName, denyPermissions);
        }
    }

Loading