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

Commit 39b9bf57 authored by Mayank Garg's avatar Mayank Garg Committed by Android (Google) Code Review
Browse files

Merge "Device config is not updated by background user for certain namespaces" into main

parents 6a51fbf5 c5377285
Loading
Loading
Loading
Loading
+39 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.providers.settings;

import android.util.ArraySet;

import java.util.Arrays;
import java.util.Set;

/**
 * Contains the list of prefixes for namespaces in which nothing can be written by background
 * user.
 *
 * <p>
 * The list in enforced is Auto devices only. To add to
 * the list, create a change and tag the OWNER. In the change description, include a
 * description of the flag's functionality, and a justification for why it needs to be
 * denylisted.
 */
final class NonWritableNamespacesForBackgroundUserPrefixes {
    public static final Set<String> DENYLIST =
            new ArraySet<String>(Arrays.asList(
                    "game_overlay"
            ));
}
+42 −1
Original line number Diff line number Diff line
@@ -2392,8 +2392,12 @@ public class SettingsProvider extends ContentProvider {
                == PackageManager.PERMISSION_GRANTED;
        boolean isRoot = Binder.getCallingUid() == Process.ROOT_UID;

        if (isRoot || hasWritePermission) {
        if (isRoot) {
            return;
        }

        if (hasWritePermission) {
            assertCallingUserDenyList(flags);
        } else if (hasAllowlistPermission) {
            for (String flag : flags) {
                boolean namespaceAllowed = false;
@@ -2410,12 +2414,49 @@ public class SettingsProvider extends ContentProvider {
                        + "'; allowlist permission granted, but must add flag to the allowlist.");
                }
            }
            assertCallingUserDenyList(flags);
        } else {
            throw new SecurityException("Permission denial to mutate flag, must have root, "
                + "WRITE_DEVICE_CONFIG, or WRITE_ALLOWLISTED_DEVICE_CONFIG");
        }
    }

    // The check is added mainly for auto devices. On auto devices, it is possible that
    // multiple users are visible simultaneously using visible background users.
    // In such cases, it is desired that Non-current user (ex. visible background users) can
    // only change settings for certain namespaces.
    private void assertCallingUserDenyList(@NonNull Set<String> flags) {
        if (!UserManager.isVisibleBackgroundUsersEnabled()) {
            // enforce the deny list only on devices supporting visible background user.
            return;
        }

        int callingUser = UserHandle.getCallingUserId();
        final long identity = Binder.clearCallingIdentity();
        try {
            int currentUser = ActivityManager.getCurrentUser();
            if (callingUser == currentUser) {
                // enforce the deny list only if the caller is not current user. Currently only auto
                // uses background visible user, and auto doesn't support profiles so profiles of
                // current users is not checked here.
                return;
            }
        } finally {
            Binder.restoreCallingIdentity(identity);
        }

        for (String flag : flags) {
            for (String denylistedPrefix :
                    NonWritableNamespacesForBackgroundUserPrefixes.DENYLIST) {
                if (flag.startsWith(denylistedPrefix)) {
                    throw new SecurityException("Permission denial for flag '" + flag
                            + "' for background user " + callingUser + ". Namespace is added to "
                            + "denylist.");
                }
            }
        }
    }

    private static void warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk(
            int targetSdkVersion, String name) {
        // If the app targets Lollipop MR1 or older SDK we warn, otherwise crash.