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

Commit 334fb247 authored by Danny Lin's avatar Danny Lin Committed by Nishith Khanna
Browse files

Add support for app signature spoofing

This is needed by microG GmsCore to pretend to be the official Google
Play Services package, because client apps check the package signature
to make sure it matches Google's official certificate.

This was forward-ported from the Android 10 patch by gudenau:
https://github.com/microg/android_packages_apps_GmsCore/pull/957

Changes made for Android 11:
  - Updated PackageInfo calls
  - Added new permission to public API surface, needed for
    PermissionController which is now an updatable APEX on 11
  - Added a dummy permission group to allow users to manage the
    permission through the PermissionController UI
    (by Vachounet <vachounet@live.fr>)
  - Updated location provider comment for conciseness

Changes made for Android 12:
  - Moved mayFakeSignature into lock-free Computer subclass
  - Always get permissions for packages that request signature spoofing
    (otherwise permissions are usually ommitted and thus the permission
    check doesn't work properly)
  - Optimize mayFakeSignature check order to improve performance

Link: https://github.com/microg/GmsCore/pull/1586
Change-Id: Ied7d6ce0b83a2d2345c3abba0429998d86494a88
parent f19ccf53
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -98,6 +98,7 @@ package android {
    field public static final String EXECUTE_APP_ACTION = "android.permission.EXECUTE_APP_ACTION";
    field public static final String EXPAND_STATUS_BAR = "android.permission.EXPAND_STATUS_BAR";
    field public static final String FACTORY_TEST = "android.permission.FACTORY_TEST";
    field public static final String FAKE_PACKAGE_SIGNATURE = "android.permission.FAKE_PACKAGE_SIGNATURE";
    field public static final String FOREGROUND_SERVICE = "android.permission.FOREGROUND_SERVICE";
    field public static final String FOREGROUND_SERVICE_CAMERA = "android.permission.FOREGROUND_SERVICE_CAMERA";
    field public static final String FOREGROUND_SERVICE_CONNECTED_DEVICE = "android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE";
@@ -342,6 +343,7 @@ package android {
    field public static final String CALL_LOG = "android.permission-group.CALL_LOG";
    field public static final String CAMERA = "android.permission-group.CAMERA";
    field public static final String CONTACTS = "android.permission-group.CONTACTS";
    field public static final String FAKE_PACKAGE = "android.permission-group.FAKE_PACKAGE";
    field public static final String LOCATION = "android.permission-group.LOCATION";
    field public static final String MICROPHONE = "android.permission-group.MICROPHONE";
    field public static final String NEARBY_DEVICES = "android.permission-group.NEARBY_DEVICES";
+4 −0
Original line number Diff line number Diff line
@@ -1169,6 +1169,10 @@ UnflaggedApi: android.R.dimen#system_corner_radius_xlarge:
    New API must be flagged with @FlaggedApi: field android.R.dimen.system_corner_radius_xlarge
UnflaggedApi: android.R.dimen#system_corner_radius_xsmall:
    New API must be flagged with @FlaggedApi: field android.R.dimen.system_corner_radius_xsmall
UnflaggedApi: android.Manifest.permission#FAKE_PACKAGE_SIGNATURE:
    New API must be flagged with @FlaggedApi: field android.Manifest.permission.FAKE_PACKAGE_SIGNATURE
UnflaggedApi: android.Manifest.permission_group#FAKE_PACKAGE:
    New API must be flagged with @FlaggedApi: field android.Manifest.permission_group.FAKE_PACKAGE
UnflaggedApi: android.accessibilityservice.AccessibilityService#OVERLAY_RESULT_INTERNAL_ERROR:
    New API must be flagged with @FlaggedApi: field android.accessibilityservice.AccessibilityService.OVERLAY_RESULT_INTERNAL_ERROR
UnflaggedApi: android.accessibilityservice.AccessibilityService#OVERLAY_RESULT_INVALID:
+15 −0
Original line number Diff line number Diff line
@@ -4481,6 +4481,21 @@
        android:description="@string/permdesc_getPackageSize"
        android:protectionLevel="normal" />

    <!-- Dummy user-facing group for faking package signature -->
    <permission-group android:name="android.permission-group.FAKE_PACKAGE"
        android:label="@string/permgrouplab_fake_package_signature"
        android:description="@string/permgroupdesc_fake_package_signature"
        android:request="@string/permgrouprequest_fake_package_signature"
        android:priority="100" />

    <!-- Allows an application to change the package signature as
         seen by applications -->
    <permission android:name="android.permission.FAKE_PACKAGE_SIGNATURE"
        android:permissionGroup="android.permission-group.UNDEFINED"
        android:protectionLevel="signature|privileged"
        android:label="@string/permlab_fakePackageSignature"
        android:description="@string/permdesc_fakePackageSignature" />

    <!-- @deprecated No longer useful, see
         {@link android.content.pm.PackageManager#addPackageToPreferred}
         for details. -->
+12 −0
Original line number Diff line number Diff line
@@ -1015,6 +1015,18 @@

    <!--  Permissions -->

    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
    <string name="permlab_fakePackageSignature">Spoof package signature</string>
    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
    <string name="permdesc_fakePackageSignature">Allows the app to pretend to be a different app. Malicious applications might be able to use this to access private application data. Legitimate uses include an emulator pretending to be what it emulates. Grant this permission with caution only!</string>
    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
    <string name="permgrouplab_fake_package_signature">Spoof package signature</string>
    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
    <string name="permgroupdesc_fake_package_signature">allow to spoof package signature</string>
    <!-- Message shown to the user when the apps requests permission from this group. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
    <string name="permgrouprequest_fake_package_signature">Allow
        &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to spoof package signature?</string>

    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
    <string name="permlab_statusBar">disable or modify status bar</string>
    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+27 −3
Original line number Diff line number Diff line
@@ -1514,6 +1514,29 @@ public class ComputerEngine implements Computer {
        return Optional.of(fakeSignature);
    }

    private boolean requestsFakeSignature(AndroidPackage p) {
        return p.getMetaData() != null &&
                p.getMetaData().getString("fake-signature") != null;
    }

    private PackageInfo mayFakeSignature(AndroidPackage p, PackageInfo pi,
            Set<String> permissions) {
        try {
            if (p.getMetaData() != null &&
                    p.getTargetSdkVersion() > Build.VERSION_CODES.LOLLIPOP_MR1) {
                String sig = p.getMetaData().getString("fake-signature");
                if (sig != null &&
                        permissions.contains("android.permission.FAKE_PACKAGE_SIGNATURE")) {
                    pi.signatures = new Signature[] {new Signature(sig)};
                }
            }
        } catch (Throwable t) {
            // We should never die because of any failures, this is system code!
            Log.w("PackageManagerService.FAKE_PACKAGE_SIGNATURE", t);
        }
        return pi;
    }

    public final PackageInfo generatePackageInfo(PackageStateInternal ps,
            @PackageManager.PackageInfoFlagsBits long flags, int userId) {
        if (!mUserManager.exists(userId)) return null;
@@ -1547,13 +1570,14 @@ public class ComputerEngine implements Computer {
                    || ArrayUtils.isEmpty(p.getPermissions())) ? Collections.emptySet()
                    : mPermissionManager.getInstalledPermissions(ps.getPackageName());
            // Compute granted permissions only if package has requested permissions
            final Set<String> grantedPermissions = ((flags & PackageManager.GET_PERMISSIONS) == 0
            final Set<String> grantedPermissions = (((flags & PackageManager.GET_PERMISSIONS) == 0
                        && !requestsFakeSignature(p))
                    || ArrayUtils.isEmpty(p.getRequestedPermissions())) ? Collections.emptySet()
                    : mPermissionManager.getGrantedPermissions(ps.getPackageName(), userId);

            PackageInfo packageInfo = PackageInfoUtils.generate(p, gids, flags,
            PackageInfo packageInfo = mayFakeSignature(p, PackageInfoUtils.generate(p, gids, flags,
                    state.getFirstInstallTimeMillis(), ps.getLastUpdateTime(), installedPermissions,
                    grantedPermissions, state, userId, ps);
                    grantedPermissions, state, userId, ps), grantedPermissions);

            if (packageInfo == null) {
                return null;