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

Commit aacf9455 authored by Rubin Xu's avatar Rubin Xu
Browse files

Set explicit target when constructing PendingIntent

PendingIntent as part of a notification can be intercepted by
a malicious app and re-fired with crafted intent arguments.
System server should set explicit target for these intents
to avoid it being fired to other apps with system privilege.

Bug: 155183624
Test: atest FrameworksServicesTests:DevicePolicyManagerTest
Test: Set a DO/PO with TestDPC, turn on location, verify notification
      works
Test: set a DO with TestDPC, request remote bugreport and verify
      notifcation works
Change-Id: Ib7d0039c3d07a9d1ccf57e944303353ec9e9b66d
parent b8ad491e
Loading
Loading
Loading
Loading
+14 −3
Original line number Diff line number Diff line
@@ -11933,10 +11933,21 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
    }
    private void showLocationSettingsChangedNotification(UserHandle user) {
        Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        // Fill the component explicitly to prevent the PendingIntent from being intercepted
        // and fired with crafted target. b/155183624
        ActivityInfo targetInfo = intent.resolveActivityInfo(
                mInjector.getPackageManager(user.getIdentifier()),
                PackageManager.MATCH_SYSTEM_ONLY);
        if (targetInfo != null) {
            intent.setComponent(targetInfo.getComponentName());
        } else {
            Slog.wtf(LOG_TAG, "Failed to resolve intent for location settings");
        }
        PendingIntent locationSettingsIntent = mInjector.pendingIntentGetActivityAsUser(mContext, 0,
                new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
                        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), PendingIntent.FLAG_UPDATE_CURRENT,
                null, user);
                intent, PendingIntent.FLAG_UPDATE_CURRENT, null, user);
        Notification notification = new Notification.Builder(mContext,
                SystemNotificationChannels.DEVICE_ADMIN)
                .setSmallIcon(R.drawable.ic_info_outline)
+15 −0
Original line number Diff line number Diff line
@@ -22,9 +22,12 @@ import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.format.DateUtils;
import android.util.Slog;

import com.android.internal.R;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
@@ -38,6 +41,7 @@ import java.lang.annotation.RetentionPolicy;
 */
class RemoteBugreportUtils {

    private static final String TAG = "RemoteBugreportUtils";
    static final int NOTIFICATION_ID = SystemMessage.NOTE_REMOTE_BUGREPORT;

    @Retention(RetentionPolicy.SOURCE)
@@ -60,6 +64,17 @@ class RemoteBugreportUtils {
        Intent dialogIntent = new Intent(Settings.ACTION_SHOW_REMOTE_BUGREPORT_DIALOG);
        dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        dialogIntent.putExtra(DevicePolicyManager.EXTRA_BUGREPORT_NOTIFICATION_TYPE, type);

        // Fill the component explicitly to prevent the PendingIntent from being intercepted
        // and fired with crafted target. b/155183624
        ActivityInfo targetInfo = dialogIntent.resolveActivityInfo(
                context.getPackageManager(), PackageManager.MATCH_SYSTEM_ONLY);
        if (targetInfo != null) {
            dialogIntent.setComponent(targetInfo.getComponentName());
        } else {
            Slog.wtf(TAG, "Failed to resolve intent for remote bugreport dialog");
        }

        PendingIntent pendingDialogIntent = PendingIntent.getActivityAsUser(context, type,
                dialogIntent, 0, null, UserHandle.CURRENT);