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

Commit 494dd981 authored by Lokesh Kumar Goel's avatar Lokesh Kumar Goel
Browse files

Revert "Check sound Uri permission when creating a notification channel"

This reverts commit 94fc92cf.

Reason for revert: CVE-2025-22420 A-337775777 is being removed from ASB#2025-04 due to an possible app compatibility regression. Partners are recommended to remove this fix and should not reference it in any public documentation. An updated fix will be required as part of a future Android Security Bulletin.

Pixel Impact: Internal testing found WhatsApp java crashes with this fix. Detected on Dogfood builds. We recommend Pixel removal if possible. Crash report here b/390020418

Change-Id: Iaf59e34577bed2eba8da30037a77d15e4f4bd690
parent b8a3ba91
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -2809,7 +2809,6 @@ public class NotificationManagerService extends SystemService {
                mNotificationChannelLogger,
                mAppOps,
                mUserProfiles,
                mUgmInternal,
                mShowReviewPermissionsNotification,
                Clock.systemUTC());
        mRankingHelper = new RankingHelper(getContext(), mRankingHandler, mPreferencesHelper,
@@ -7210,7 +7209,13 @@ public class NotificationManagerService extends SystemService {
            final Uri originalSoundUri =
                    (originalChannel != null) ? originalChannel.getSound() : null;
            if (soundUri != null && !Objects.equals(originalSoundUri, soundUri)) {
                PermissionHelper.grantUriPermission(mUgmInternal, soundUri, sourceUid);
                Binder.withCleanCallingIdentity(() -> {
                    mUgmInternal.checkGrantUriPermission(sourceUid, null,
                            ContentProvider.getUriWithoutUserId(soundUri),
                            Intent.FLAG_GRANT_READ_URI_PERMISSION,
                            ContentProvider.getUserIdFromUri(soundUri,
                            UserHandle.getUserId(sourceUid)));
                });
            }
        }
+4 −52
Original line number Diff line number Diff line
@@ -1513,23 +1513,14 @@ public final class NotificationRecord {

            final Notification notification = getNotification();
            notification.visitUris((uri) -> {
                if (com.android.server.notification.Flags.notificationVerifyChannelSoundUri()) {
                visitGrantableUri(uri, false, false);
                } else {
                    oldVisitGrantableUri(uri, false, false);
                }
            });

            if (notification.getChannelId() != null) {
                NotificationChannel channel = getChannel();
                if (channel != null) {
                    if (com.android.server.notification.Flags.notificationVerifyChannelSoundUri()) {
                    visitGrantableUri(channel.getSound(), (channel.getUserLockedFields()
                            & NotificationChannel.USER_LOCKED_SOUND) != 0, true);
                    } else {
                        oldVisitGrantableUri(channel.getSound(), (channel.getUserLockedFields()
                                & NotificationChannel.USER_LOCKED_SOUND) != 0, true);
                    }
                }
            }
        } finally {
@@ -1545,7 +1536,7 @@ public final class NotificationRecord {
     * {@link #mGrantableUris}. Otherwise, this will either log or throw
     * {@link SecurityException} depending on target SDK of enqueuing app.
     */
    private void oldVisitGrantableUri(Uri uri, boolean userOverriddenUri, boolean isSound) {
    private void visitGrantableUri(Uri uri, boolean userOverriddenUri, boolean isSound) {
        if (uri == null || !ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) return;

        if (mGrantableUris != null && mGrantableUris.contains(uri)) {
@@ -1584,45 +1575,6 @@ public final class NotificationRecord {
        }
    }

    /**
     * Note the presence of a {@link Uri} that should have permission granted to
     * whoever will be rendering it.
     * <p>
     * If the enqueuing app has the ability to grant access, it will be added to
     * {@link #mGrantableUris}. Otherwise, this will either log or throw
     * {@link SecurityException} depending on target SDK of enqueuing app.
     */
    private void visitGrantableUri(Uri uri, boolean userOverriddenUri,
            boolean isSound) {
        if (mGrantableUris != null && mGrantableUris.contains(uri)) {
            return; // already verified this URI
        }

        final int sourceUid = getSbn().getUid();
        try {
            PermissionHelper.grantUriPermission(mUgmInternal, uri, sourceUid);

            if (mGrantableUris == null) {
                mGrantableUris = new ArraySet<>();
            }
            mGrantableUris.add(uri);
        } catch (SecurityException e) {
            if (!userOverriddenUri) {
                if (isSound) {
                    mSound = Settings.System.DEFAULT_NOTIFICATION_URI;
                    Log.w(TAG, "Replacing " + uri + " from " + sourceUid + ": " + e.getMessage());
                } else {
                    if (mTargetSdkVersion >= Build.VERSION_CODES.P) {
                        throw e;
                    } else {
                        Log.w(TAG,
                                "Ignoring " + uri + " from " + sourceUid + ": " + e.getMessage());
                    }
                }
            }
        }
    }

    public LogMaker getLogMaker(long now) {
        LogMaker lm = getSbn().getLogMaker()
                .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_IMPORTANCE, mImportance)
+1 −20
Original line number Diff line number Diff line
@@ -25,25 +25,19 @@ import android.Manifest;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.companion.virtual.VirtualDeviceManager;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.net.Uri;
import android.os.Binder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.permission.IPermissionManager;
import android.util.ArrayMap;
import android.util.Pair;
import android.util.Slog;

import com.android.internal.util.ArrayUtils;
import com.android.server.uri.UriGrantsManagerInternal;

import java.util.Collections;
import java.util.HashSet;
@@ -304,19 +298,6 @@ public final class PermissionHelper {
        return false;
    }

    static void grantUriPermission(final UriGrantsManagerInternal ugmInternal, Uri uri,
            int sourceUid) {
        if (uri == null || !ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) return;

        Binder.withCleanCallingIdentity(() -> {
            // This will throw a SecurityException if the caller can't grant.
            ugmInternal.checkGrantUriPermission(sourceUid, null,
                    ContentProvider.getUriWithoutUserId(uri),
                    Intent.FLAG_GRANT_READ_URI_PERMISSION,
                    ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(sourceUid)));
        });
    }

    public static class PackagePermission {
        public final String packageName;
        public final @UserIdInt int userId;
+0 −11
Original line number Diff line number Diff line
@@ -100,7 +100,6 @@ import com.android.internal.util.XmlUtils;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
import com.android.server.notification.PermissionHelper.PackagePermission;
import com.android.server.uri.UriGrantsManagerInternal;

import org.json.JSONArray;
import org.json.JSONException;
@@ -228,7 +227,6 @@ public class PreferencesHelper implements RankingConfig {
    private final NotificationChannelLogger mNotificationChannelLogger;
    private final AppOpsManager mAppOps;
    private final ManagedServices.UserProfiles mUserProfiles;
    private final UriGrantsManagerInternal mUgmInternal;

    private SparseBooleanArray mBadgingEnabled;
    private SparseBooleanArray mBubblesEnabled;
@@ -247,7 +245,6 @@ public class PreferencesHelper implements RankingConfig {
            ZenModeHelper zenHelper, PermissionHelper permHelper, PermissionManager permManager,
            NotificationChannelLogger notificationChannelLogger,
            AppOpsManager appOpsManager, ManagedServices.UserProfiles userProfiles,
            UriGrantsManagerInternal ugmInternal,
            boolean showReviewPermissionsNotification, Clock clock) {
        mContext = context;
        mZenModeHelper = zenHelper;
@@ -258,7 +255,6 @@ public class PreferencesHelper implements RankingConfig {
        mNotificationChannelLogger = notificationChannelLogger;
        mAppOps = appOpsManager;
        mUserProfiles = userProfiles;
        mUgmInternal = ugmInternal;
        mShowReviewPermissionsNotification = showReviewPermissionsNotification;
        mIsMediaNotificationFilteringEnabled = context.getResources()
                .getBoolean(R.bool.config_quickSettingsShowMediaPlayer);
@@ -1195,13 +1191,6 @@ public class PreferencesHelper implements RankingConfig {
                }
                clearLockedFieldsLocked(channel);

                // Verify that the app has permission to read the sound Uri
                // Only check for new channels, as regular apps can only set sound
                // before creating. See: {@link NotificationChannel#setSound}
                if (Flags.notificationVerifyChannelSoundUri()) {
                    PermissionHelper.grantUriPermission(mUgmInternal, channel.getSound(), uid);
                }

                channel.setImportanceLockedByCriticalDeviceFunction(
                        r.defaultAppLockedImportance || r.fixedImportance);

+0 −10
Original line number Diff line number Diff line
@@ -164,16 +164,6 @@ flag {
  bug: "358524009"
}

flag {
  name: "notification_verify_channel_sound_uri"
  namespace: "systemui"
  description: "Verify Uri permission for sound when creating a notification channel"
  bug: "337775777"
  metadata {
    purpose: PURPOSE_BUGFIX
  }
}

flag {
  name: "notification_vibration_in_sound_uri_for_channel"
  namespace: "systemui"
Loading