diff options
| author | 2023-04-24 23:57:57 +0000 | |
|---|---|---|
| committer | 2023-05-11 19:37:48 +0000 | |
| commit | 6af25e465a8069989dfb7c71dccdaaea5ecd7b2d (patch) | |
| tree | ba695c04aa2832ea5e14381069a6da11d4d2a28a | |
| parent | f3192865a3508ecb46959d93685f6087e182eaab (diff) | |
Make sure stickies get resent from the same UID.
Make sure that sticky broadcasts that get resent don't just get resent
from a random UID, that they get resent from the original UID.
Test: atest ContextText
Test: atest ActivityManagerServiceTest
Bug: 244351792
Change-Id: I0dc465f3c953438ee14cc03e92c048a9a75668bb
4 files changed, 63 insertions, 15 deletions
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 5d3bb31bc31f..75ecbfc92656 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1175,17 +1175,21 @@ public class ActivityManagerService extends IActivityManager.Stub static final class StickyBroadcast { public Intent intent; public boolean deferUntilActive; + public int originalCallingUid; - public static StickyBroadcast create(Intent intent, boolean deferUntilActive) { + public static StickyBroadcast create(Intent intent, boolean deferUntilActive, + int originalCallingUid) { final StickyBroadcast b = new StickyBroadcast(); b.intent = intent; b.deferUntilActive = deferUntilActive; + b.originalCallingUid = originalCallingUid; return b; } @Override public String toString() { - return "{intent=" + intent + ", defer=" + deferUntilActive + "}"; + return "{intent=" + intent + ", defer=" + deferUntilActive + ", originalCallingUid=" + + originalCallingUid + "}"; } } @@ -11110,6 +11114,9 @@ public class ActivityManagerService extends IActivityManager.Stub pw.print(" [D]"); } pw.println(); + pw.print(" originalCallingUid: "); + pw.println(broadcasts.get(i).originalCallingUid); + pw.println(); Bundle bundle = intent.getExtras(); if (bundle != null) { pw.print(" extras: "); @@ -13999,16 +14006,25 @@ public class ActivityManagerService extends IActivityManager.Stub if (allSticky != null) { ArrayList receivers = new ArrayList(); receivers.add(bf); + sticky = null; final int stickyCount = allSticky.size(); for (int i = 0; i < stickyCount; i++) { final StickyBroadcast broadcast = allSticky.get(i); + final int originalStickyCallingUid = allSticky.get(i).originalCallingUid; + // TODO(b/281889567): consider using checkComponentPermission instead of + // canAccessUnexportedComponents + if (sticky == null && (exported || originalStickyCallingUid == callingUid + || ActivityManager.canAccessUnexportedComponents( + originalStickyCallingUid))) { + sticky = broadcast.intent; + } BroadcastQueue queue = broadcastQueueForIntent(broadcast.intent); BroadcastRecord r = new BroadcastRecord(queue, broadcast.intent, null, null, null, -1, -1, false, null, null, null, null, OP_NONE, BroadcastOptions.makeWithDeferUntilActive(broadcast.deferUntilActive), receivers, null, null, 0, null, null, false, true, true, -1, - BackgroundStartPrivileges.NONE, + originalStickyCallingUid, BackgroundStartPrivileges.NONE, false /* only PRE_BOOT_COMPLETED should be exempt, no stickies */, null /* filterExtrasForReceiver */); queue.enqueueBroadcastLocked(r); @@ -14886,12 +14902,13 @@ public class ActivityManagerService extends IActivityManager.Stub for (i = 0; i < stickiesCount; i++) { if (intent.filterEquals(list.get(i).intent)) { // This sticky already exists, replace it. - list.set(i, StickyBroadcast.create(new Intent(intent), deferUntilActive)); + list.set(i, StickyBroadcast.create(new Intent(intent), deferUntilActive, + callingUid)); break; } } if (i >= stickiesCount) { - list.add(StickyBroadcast.create(new Intent(intent), deferUntilActive)); + list.add(StickyBroadcast.create(new Intent(intent), deferUntilActive, callingUid)); } } diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java index 64fe39314f0e..8f859f0f5f53 100644 --- a/services/core/java/com/android/server/am/BroadcastRecord.java +++ b/services/core/java/com/android/server/am/BroadcastRecord.java @@ -79,6 +79,9 @@ final class BroadcastRecord extends Binder { final @Nullable String callerFeatureId; // which feature in the package sent this final int callingPid; // the pid of who sent this final int callingUid; // the uid of who sent this + + final int originalStickyCallingUid; + // if this is a sticky broadcast, the Uid of the original sender final boolean callerInstantApp; // caller is an Instant App? final boolean callerInstrumented; // caller is being instrumented? final boolean ordered; // serialize the send to receivers? @@ -322,7 +325,8 @@ final class BroadcastRecord extends Binder { pw.print(prefix); pw.print("resultAbort="); pw.print(resultAbort); pw.print(" ordered="); pw.print(ordered); pw.print(" sticky="); pw.print(sticky); - pw.print(" initialSticky="); pw.println(initialSticky); + pw.print(" initialSticky="); pw.print(initialSticky); + pw.print(" originalStickyCallingUid="); pw.println(originalStickyCallingUid); } if (nextReceiver != 0) { pw.print(prefix); pw.print("nextReceiver="); pw.println(nextReceiver); @@ -391,6 +395,27 @@ final class BroadcastRecord extends Binder { } } + BroadcastRecord(BroadcastQueue queue, + Intent intent, ProcessRecord callerApp, String callerPackage, + @Nullable String callerFeatureId, int callingPid, int callingUid, + boolean callerInstantApp, String resolvedType, + String[] requiredPermissions, String[] excludedPermissions, + String[] excludedPackages, int appOp, + BroadcastOptions options, List receivers, + ProcessRecord resultToApp, IIntentReceiver resultTo, int resultCode, + String resultData, Bundle resultExtras, boolean serialized, boolean sticky, + boolean initialSticky, int userId, + @NonNull BackgroundStartPrivileges backgroundStartPrivileges, + boolean timeoutExempt, + @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver) { + this(queue, intent, callerApp, callerPackage, callerFeatureId, callingPid, + callingUid, callerInstantApp, resolvedType, requiredPermissions, + excludedPermissions, excludedPackages, appOp, options, receivers, resultToApp, + resultTo, resultCode, resultData, resultExtras, serialized, sticky, + initialSticky, userId, -1, backgroundStartPrivileges, timeoutExempt, + filterExtrasForReceiver); + } + BroadcastRecord(BroadcastQueue _queue, Intent _intent, ProcessRecord _callerApp, String _callerPackage, @Nullable String _callerFeatureId, int _callingPid, int _callingUid, @@ -400,7 +425,7 @@ final class BroadcastRecord extends Binder { BroadcastOptions _options, List _receivers, ProcessRecord _resultToApp, IIntentReceiver _resultTo, int _resultCode, String _resultData, Bundle _resultExtras, boolean _serialized, boolean _sticky, - boolean _initialSticky, int _userId, + boolean _initialSticky, int _userId, int originalStickyCallingUid, @NonNull BackgroundStartPrivileges backgroundStartPrivileges, boolean timeoutExempt, @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver) { @@ -452,6 +477,7 @@ final class BroadcastRecord extends Binder { interactive = options != null && options.isInteractive(); shareIdentity = options != null && options.isShareIdentityEnabled(); this.filterExtrasForReceiver = filterExtrasForReceiver; + this.originalStickyCallingUid = originalStickyCallingUid; } /** @@ -516,6 +542,7 @@ final class BroadcastRecord extends Binder { shareIdentity = from.shareIdentity; urgent = from.urgent; filterExtrasForReceiver = from.filterExtrasForReceiver; + originalStickyCallingUid = from.originalStickyCallingUid; } /** diff --git a/services/core/java/com/android/server/am/BroadcastSkipPolicy.java b/services/core/java/com/android/server/am/BroadcastSkipPolicy.java index 6718319c7ac6..5f918cfa3478 100644 --- a/services/core/java/com/android/server/am/BroadcastSkipPolicy.java +++ b/services/core/java/com/android/server/am/BroadcastSkipPolicy.java @@ -563,14 +563,15 @@ public class BroadcastSkipPolicy { // Ensure that broadcasts are only sent to other apps if they are explicitly marked as // exported, or are System level broadcasts + final int originalCallingUid = r.sticky ? r.originalStickyCallingUid : r.callingUid; if (!filter.exported && checkComponentPermission(null, r.callingPid, - r.callingUid, filter.receiverList.uid, filter.exported) + originalCallingUid, filter.receiverList.uid, filter.exported) != PackageManager.PERMISSION_GRANTED) { return "Exported Denial: sending " + r.intent.toString() + ", action: " + r.intent.getAction() + " from " + r.callerPackage - + " (uid=" + r.callingUid + ")" + + " (uid=" + originalCallingUid + ")" + " due to receiver " + filter.receiverList.app + " (uid " + filter.receiverList.uid + ")" + " not specifying RECEIVER_EXPORTED"; diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java index f82d246d68bd..bfe7d7fd201c 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java @@ -648,24 +648,24 @@ public class ActivityManagerServiceTest { broadcastIntent(intent1, null, true); assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION1, TEST_USER), - StickyBroadcast.create(intent1, false)); + StickyBroadcast.create(intent1, false, Process.myUid())); assertNull(mAms.getStickyBroadcasts(TEST_ACTION2, TEST_USER)); assertNull(mAms.getStickyBroadcasts(TEST_ACTION3, TEST_USER)); broadcastIntent(intent2, options.toBundle(), true); assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION1, TEST_USER), - StickyBroadcast.create(intent1, false)); + StickyBroadcast.create(intent1, false, Process.myUid())); assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION2, TEST_USER), - StickyBroadcast.create(intent2, true)); + StickyBroadcast.create(intent2, true, Process.myUid())); assertNull(mAms.getStickyBroadcasts(TEST_ACTION3, TEST_USER)); broadcastIntent(intent3, null, true); assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION1, TEST_USER), - StickyBroadcast.create(intent1, false)); + StickyBroadcast.create(intent1, false, Process.myUid())); assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION2, TEST_USER), - StickyBroadcast.create(intent2, true)); + StickyBroadcast.create(intent2, true, Process.myUid())); assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION3, TEST_USER), - StickyBroadcast.create(intent3, false)); + StickyBroadcast.create(intent3, false, Process.myUid())); } @SuppressWarnings("GuardedBy") @@ -698,6 +698,9 @@ public class ActivityManagerServiceTest { if (a.deferUntilActive != b.deferUntilActive) { return false; } + if (a.originalCallingUid != b.originalCallingUid) { + return false; + } return true; } |