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

Commit c5377285 authored by Mayank Garg's avatar Mayank Garg
Browse files

Device config is not updated by background user for certain namespaces

Bug: 328686115
Test: atest AndroidCarApiTest:android.car.apitest.DeviceConfigTest
Test: atest --user-type secondary_user_on_secondary_display AndroidCarApiTest:android.car.apitest.DeviceConfigTest
Change-Id: Iaba61179584c4e1dc6e0290c290b9c7b538011e3
parent 04665456
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
@@ -2389,8 +2389,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;
@@ -2407,12 +2411,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.