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

Commit 88d3cceb authored by Roman Birg's avatar Roman Birg Committed by Steve Kondik
Browse files

PackageManager: make protected-broadcasts permission aware



This extends the <protected-broadcast> mechanism to allow protecting
actions based on a permission for system apps.

For instance:

   <protected-broadcast android:name="ACTION_A"
                        android:permission="PERMISSION_X" />

will restrict intents with action "ACTION_A" to be only sent with
apps holding the "PERMISSION_X" permission. Note that system UIDs will
bypass the permission check and always be allowed, just like the normal
protected-broadcast mechanism.

You must still be a system application to delcare a protected broadcast.

Change-Id: Id25cffd233d400800dcb5249c5f487134e1b4152
Signed-off-by: default avatarRoman Birg <roman@cyngn.com>
parent ad00cb08
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -581,4 +581,7 @@ interface IPackageManager {
    /** Protected Apps */
    boolean isComponentProtected(in String callingPackage, in int callingUid,
    in ComponentName componentName, int userId);

    /** protected broadcast ext */
    boolean isProtectedBroadcastAllowed(in String actionName, in int callingUid);
}
+11 −4
Original line number Diff line number Diff line
@@ -2061,14 +2061,18 @@ public class PackageParser {
                String name = sa.getNonResourceString(
                        com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);

                String permission = sa.getNonResourceString(
                        com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_permission);

                sa.recycle();

                if (name != null && (flags&PARSE_IS_SYSTEM) != 0) {
                    if (pkg.protectedBroadcasts == null) {
                        pkg.protectedBroadcasts = new ArrayList<String>();
                        pkg.protectedBroadcasts = new ArrayMap<>();
                    }
                    if (!pkg.protectedBroadcasts.contains(name)) {
                        pkg.protectedBroadcasts.add(name.intern());
                    if (!pkg.protectedBroadcasts.containsKey(name)) {
                        pkg.protectedBroadcasts.put(name.intern(),
                                permission != null ? permission.intern() : null);
                    }
                }

@@ -4811,7 +4815,10 @@ public class PackageParser {

        public final ArrayList<String> requestedPermissions = new ArrayList<String>();

        public ArrayList<String> protectedBroadcasts;
        /**
         * Maps from package -> permission, null for system (default behavior)
         */
        public ArrayMap<String,String> protectedBroadcasts;

        public Package parentPackage;
        public ArrayList<Package> childPackages;
+1 −0
Original line number Diff line number Diff line
@@ -1647,6 +1647,7 @@
         {@link #AndroidManifest manifest} tag. -->
    <declare-styleable name="AndroidManifestProtectedBroadcast" parent="AndroidManifest">
        <attr name="name" />
        <attr name="permission" />
    </declare-styleable>

    <!-- Private tag to declare the original package name that this package is
+15 −6
Original line number Diff line number Diff line
@@ -17974,8 +17974,9 @@ public final class ActivityManagerService extends ActivityManagerNative
        // and that system code is only sending protected broadcasts.
        final String action = intent.getAction();
        final boolean isProtectedBroadcast;
        final IPackageManager pm = AppGlobals.getPackageManager();
        try {
            isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);
            isProtectedBroadcast = pm.isProtectedBroadcast(action);
        } catch (RemoteException e) {
            Slog.w(TAG, "Remote exception", e);
            return ActivityManager.BROADCAST_SUCCESS;
@@ -18027,11 +18028,19 @@ public final class ActivityManagerService extends ActivityManagerNative
        } else {
            if (isProtectedBroadcast) {
                boolean allowed = false;
                try {
                    allowed = pm.isProtectedBroadcastAllowed(action, callingUid);
                } catch (RemoteException e) {
                    Log.wtf(TAG, e.getMessage(), e);
                }
                if (!allowed) {
                    String msg = "Permission Denial: not allowed to send broadcast "
                            + action + " from pid="
                            + callingPid + ", uid=" + callingUid;
                    Slog.w(TAG, msg);
                    throw new SecurityException(msg);
                }
            } else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)
                    || AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
                // Special case for compatibility: we don't want apps to send this,
+16 −3
Original line number Diff line number Diff line
@@ -698,7 +698,7 @@ public class PackageManagerService extends IPackageManager.Stub {
    final ArraySet<String> mTransferedPackages = new ArraySet<String>();
    // Broadcast actions that are only available to the system.
    final ArraySet<String> mProtectedBroadcasts = new ArraySet<String>();
    final ArrayMap<String, String> mProtectedBroadcasts = new ArrayMap<>();
    /** List of packages waiting for verification. */
    final SparseArray<PackageVerificationState> mPendingVerification
@@ -4654,7 +4654,7 @@ public class PackageManagerService extends IPackageManager.Stub {
    @Override
    public boolean isProtectedBroadcast(String actionName) {
        synchronized (mPackages) {
            if (mProtectedBroadcasts.contains(actionName)) {
            if (mProtectedBroadcasts.containsKey(actionName)) {
                return true;
            } else if (actionName != null) {
                // TODO: remove these terrible hacks
@@ -4669,6 +4669,18 @@ public class PackageManagerService extends IPackageManager.Stub {
        return false;
    }
    @Override
    public boolean isProtectedBroadcastAllowed(String actionName, int callingUid) {
        synchronized (mPackages) {
            if (mProtectedBroadcasts.containsKey(actionName)) {
               final int result = checkUidPermission(mProtectedBroadcasts.get(actionName),
                        callingUid);
                return result == PackageManager.PERMISSION_GRANTED;
            }
        }
        return false;
    }
    @Override
    public int checkSignatures(String pkg1, String pkg2) {
        synchronized (mPackages) {
@@ -9126,7 +9138,8 @@ public class PackageManagerService extends IPackageManager.Stub {
            if (pkg.protectedBroadcasts != null) {
                N = pkg.protectedBroadcasts.size();
                for (i=0; i<N; i++) {
                    mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
                    mProtectedBroadcasts.put(pkg.protectedBroadcasts.keyAt(i),
                            pkg.protectedBroadcasts.valueAt(i));
                }
            }