Add unaudited exported flag to exposed runtime receivers

Android T allows apps to declare a runtime receiver as not exported
by invoking registerReceiver with a new RECEIVER_NOT_EXPORTED flag;
receivers registered with this flag will only receive broadcasts from
the platform and the app itself. However to ensure developers can
properly protect their receivers, all apps targeting T or later
registering a receiver for non-system broadcasts must specify either
the exported or not exported flag when invoking #registerReceiver;
if one of these flags is not provided, the platform will throw a
SecurityException. This commit updates all the exposed receivers
with a new RECEIVER_EXPORTED_UNAUDITED flag to maintain the existing
behavior of exporting the receiver while also flagging the receiver
for audit before the T release.

Bug: 161145287
Test: Build
Change-Id: I5faa64ae0d2b22b62390bf13cb2b87fd6926e0c7
This commit is contained in:
Michael Groover 2021-12-30 09:03:25 -08:00
parent 2e6243d900
commit de14599c42
20 changed files with 74 additions and 23 deletions

View File

@ -137,7 +137,8 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
filter.addAction(PLUGIN_CHANGED);
filter.addAction(DISABLE_PLUGIN);
filter.addDataScheme("package");
mContext.registerReceiver(this, filter, PluginActionManager.PLUGIN_PERMISSION, null);
mContext.registerReceiver(this, filter, PluginActionManager.PLUGIN_PERMISSION, null,
Context.RECEIVER_EXPORTED_UNAUDITED);
filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
mContext.registerReceiver(this, filter);
}

View File

@ -91,7 +91,8 @@ class KeyguardEsimArea extends Button implements View.OnClickListener {
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_DISABLE_ESIM),
PERMISSION_SELF, null /* scheduler */);
PERMISSION_SELF, null /* scheduler */,
Context.RECEIVER_EXPORTED_UNAUDITED);
}
public static boolean isEsimLocked(Context context, int subId) {

View File

@ -112,7 +112,8 @@ public class SliceBroadcastRelayHandler extends CoreStartable {
public void register(Context context, ComponentName receiver, IntentFilter filter) {
mReceivers.add(receiver);
context.registerReceiver(this, filter);
context.registerReceiver(this, filter,
Context.RECEIVER_EXPORTED_UNAUDITED);
}
public void unregister(Context context) {

View File

@ -518,7 +518,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
context.registerReceiver(mBroadcastReceiver, filter);
context.registerReceiver(mBroadcastReceiver, filter, Context.RECEIVER_EXPORTED_UNAUDITED);
mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class);
}

View File

@ -539,7 +539,8 @@ public class UdfpsController implements DozeReceiver {
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
context.registerReceiver(mBroadcastReceiver, filter);
context.registerReceiver(mBroadcastReceiver, filter,
Context.RECEIVER_EXPORTED_UNAUDITED);
udfpsHapticsSimulator.setUdfpsController(this);
}

View File

@ -88,7 +88,8 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
filter.addAction(ACTION_GET_FLAGS);
flagManager.setRestartAction(this::restartSystemUI);
flagManager.setClearCacheAction(this::removeFromCache);
context.registerReceiver(mReceiver, filter, null, null);
context.registerReceiver(mReceiver, filter, null, null,
Context.RECEIVER_EXPORTED_UNAUDITED);
dumpManager.registerDumpable(TAG, this);
}

View File

@ -894,7 +894,8 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
delayedActionFilter.addAction(DELAYED_KEYGUARD_ACTION);
delayedActionFilter.addAction(DELAYED_LOCK_PROFILE_ACTION);
mContext.registerReceiver(mDelayedLockBroadcastReceiver, delayedActionFilter,
SYSTEMUI_PERMISSION, null /* scheduler */);
SYSTEMUI_PERMISSION, null /* scheduler */,
Context.RECEIVER_EXPORTED_UNAUDITED);
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);

View File

@ -293,7 +293,8 @@ public class NotificationLockscreenUserManagerImpl implements
IntentFilter internalFilter = new IntentFilter();
internalFilter.addAction(NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION);
mContext.registerReceiver(mBaseBroadcastReceiver, internalFilter, PERMISSION_SELF, null);
mContext.registerReceiver(mBaseBroadcastReceiver, internalFilter, PERMISSION_SELF, null,
Context.RECEIVER_EXPORTED_UNAUDITED);
mCurrentUserId = ActivityManager.getCurrentUser(); // in case we reg'd receiver too late
updateCurrentProfilesCache();

View File

@ -1003,7 +1003,7 @@ public class StatusBar extends CoreStartable implements
internalFilter.addAction(BANNER_ACTION_CANCEL);
internalFilter.addAction(BANNER_ACTION_SETUP);
mContext.registerReceiver(mBannerActionBroadcastReceiver, internalFilter, PERMISSION_SELF,
null);
null, Context.RECEIVER_EXPORTED_UNAUDITED);
if (mWallpaperSupported) {
IWallpaperManager wallpaperManager = IWallpaperManager.Stub.asInterface(
@ -1332,7 +1332,8 @@ public class StatusBar extends CoreStartable implements
demoFilter.addAction(ACTION_FAKE_ARTWORK);
}
mContext.registerReceiverAsUser(mDemoReceiver, UserHandle.ALL, demoFilter,
android.Manifest.permission.DUMP, null);
android.Manifest.permission.DUMP, null,
Context.RECEIVER_EXPORTED_UNAUDITED);
// listen for USER_SETUP_COMPLETE setting (per-user)
mDeviceProvisionedController.addCallback(mUserSetupObserver);

View File

@ -128,7 +128,7 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum
update(true /* updateAlways */);
}
}
}, filter, null, null);
}, filter, null, null, Context.RECEIVER_EXPORTED_UNAUDITED);
}
}

View File

@ -74,7 +74,7 @@ public class UserInfoControllerImpl implements UserInfoController {
profileFilter.addAction(ContactsContract.Intents.ACTION_PROFILE_CHANGED);
profileFilter.addAction(Intent.ACTION_USER_INFO_CHANGED);
mContext.registerReceiverAsUser(mProfileReceiver, UserHandle.ALL, profileFilter,
null, null);
null, null, Context.RECEIVER_EXPORTED_UNAUDITED);
}
@Override

View File

@ -229,7 +229,8 @@ public class UserSwitcherController implements Dumpable {
filter = new IntentFilter();
mContext.registerReceiverAsUser(mReceiver, UserHandle.SYSTEM, filter,
PERMISSION_SELF, null /* scheduler */);
PERMISSION_SELF, null /* scheduler */,
Context.RECEIVER_EXPORTED_UNAUDITED);
mSettingsObserver = new ContentObserver(mHandler) {
@Override

View File

@ -167,9 +167,11 @@ public class StorageNotification extends CoreStartable {
mStorageManager.registerListener(mListener);
mContext.registerReceiver(mSnoozeReceiver, new IntentFilter(ACTION_SNOOZE_VOLUME),
android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS, null);
android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS, null,
Context.RECEIVER_EXPORTED_UNAUDITED);
mContext.registerReceiver(mFinishReceiver, new IntentFilter(ACTION_FINISH_WIZARD),
android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS, null);
android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS, null,
Context.RECEIVER_EXPORTED_UNAUDITED);
// Kick current state into place
final List<DiskInfo> disks = mStorageManager.getDisks();

View File

@ -63,7 +63,8 @@ abstract public class SafetyWarningDialog extends SystemUIDialog
setOnDismissListener(this);
final IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
context.registerReceiver(mReceiver, filter);
context.registerReceiver(mReceiver, filter,
Context.RECEIVER_EXPORTED_UNAUDITED);
}
abstract protected void cleanUp();

View File

@ -15,6 +15,7 @@
package com.android.systemui;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@ -79,7 +80,7 @@ public class SliceBroadcastRelayHandlerTest extends SysuiTestCase {
intent.putExtra(SliceBroadcastRelay.EXTRA_URI, testUri);
mRelayHandler.handleIntent(intent);
verify(mSpyContext).registerReceiver(any(), eq(value));
verify(mSpyContext).registerReceiver(any(), eq(value), anyInt());
}
@Test
@ -99,7 +100,7 @@ public class SliceBroadcastRelayHandlerTest extends SysuiTestCase {
mRelayHandler.handleIntent(intent);
ArgumentCaptor<BroadcastReceiver> relay = ArgumentCaptor.forClass(BroadcastReceiver.class);
verify(mSpyContext).registerReceiver(relay.capture(), eq(value));
verify(mSpyContext).registerReceiver(relay.capture(), eq(value), anyInt());
intent = new Intent(SliceBroadcastRelay.ACTION_UNREGISTER);
intent.putExtra(SliceBroadcastRelay.EXTRA_URI, ContentProvider.maybeAddUserId(testUri, 0));
@ -138,7 +139,7 @@ public class SliceBroadcastRelayHandlerTest extends SysuiTestCase {
mRelayHandler.handleIntent(intent);
ArgumentCaptor<BroadcastReceiver> relay = ArgumentCaptor.forClass(BroadcastReceiver.class);
verify(mSpyContext).registerReceiver(relay.capture(), eq(value));
verify(mSpyContext).registerReceiver(relay.capture(), eq(value), anyInt());
relay.getValue().onReceive(mSpyContext, new Intent(TEST_ACTION));
verify(Receiver.sReceiver, timeout(2000)).onReceive(any(), any());

View File

@ -82,6 +82,16 @@ public class SysuiTestableContext extends TestableContext {
return super.registerReceiver(receiver, filter);
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, int flags) {
if (receiver != null) {
synchronized (mRegisteredReceivers) {
mRegisteredReceivers.add(receiver);
}
}
return super.registerReceiver(receiver, filter, flags);
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
@ -93,6 +103,17 @@ public class SysuiTestableContext extends TestableContext {
return super.registerReceiver(receiver, filter, broadcastPermission, scheduler);
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler, int flags) {
if (receiver != null) {
synchronized (mRegisteredReceivers) {
mRegisteredReceivers.add(receiver);
}
}
return super.registerReceiver(receiver, filter, broadcastPermission, scheduler, flags);
}
@Override
public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
IntentFilter filter, String broadcastPermission, Handler scheduler) {
@ -104,6 +125,18 @@ public class SysuiTestableContext extends TestableContext {
return super.registerReceiverAsUser(receiver, user, filter, broadcastPermission, scheduler);
}
@Override
public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
IntentFilter filter, String broadcastPermission, Handler scheduler, int flags) {
if (receiver != null) {
synchronized (mRegisteredReceivers) {
mRegisteredReceivers.add(receiver);
}
}
return super.registerReceiverAsUser(receiver, user, filter, broadcastPermission, scheduler,
flags);
}
@Override
public void unregisterReceiver(BroadcastReceiver receiver) {
if (receiver != null) {

View File

@ -76,7 +76,8 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
)
verify(mFlagManager).restartAction = any()
mBroadcastReceiver = withArgCaptor {
verify(mMockContext).registerReceiver(capture(), any(), nullable(), nullable())
verify(mMockContext).registerReceiver(capture(), any(), nullable(), nullable(),
any())
}
mClearCacheAction = withArgCaptor {
verify(mFlagManager).clearCacheAction = capture()

View File

@ -102,7 +102,8 @@ public class RemoteInputViewTest extends SysuiTestCase {
mReceiver = new BlockingQueueIntentReceiver();
mContext.registerReceiver(mReceiver, new IntentFilter(TEST_ACTION), null,
Handler.createAsync(Dependency.get(Dependency.BG_LOOPER)));
Handler.createAsync(Dependency.get(Dependency.BG_LOOPER)),
Context.RECEIVER_EXPORTED_UNAUDITED);
// Avoid SecurityException RemoteInputView#sendRemoteInput().
mContext.addMockSystemService(ShortcutManager.class, mShortcutManager);

View File

@ -30,6 +30,7 @@ import static org.mockito.Mockito.when;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
@ -119,7 +120,8 @@ public class SmartReplyViewTest extends SysuiTestCase {
public void setUp() {
MockitoAnnotations.initMocks(this);
mReceiver = new BlockingQueueIntentReceiver();
mContext.registerReceiver(mReceiver, new IntentFilter(TEST_ACTION));
mContext.registerReceiver(mReceiver, new IntentFilter(TEST_ACTION),
Context.RECEIVER_EXPORTED_UNAUDITED);
mKeyguardDismissUtil.setDismissHandler((action, unused, afterKgGone) -> action.onDismiss());
mDependency.injectMockDependency(KeyguardUpdateMonitor.class);
mDependency.injectMockDependency(ShadeController.class);

View File

@ -81,7 +81,8 @@ public class DozeTestDream extends DreamService {
intent.setPackage(getPackageName());
IntentFilter filter = new IntentFilter();
filter.addAction(intent.getAction());
registerReceiver(mAlarmReceiver, filter);
registerReceiver(mAlarmReceiver, filter,
Context.RECEIVER_EXPORTED_UNAUDITED);
mAlarmIntent = PendingIntent.getBroadcast(this, 0, intent,
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);