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

Commit 1472faf7 authored by Cintia Martins's avatar Cintia Martins
Browse files

Ensure setSupervisionEnabledForUser caller is SystemUid

Bug: 395630828
Flag: android.app.supervision.flags.supervision_manager_apis
Test: SupervisionServiceTest
Change-Id: Id1ee536f5be643232bb41503f771aebb645ca192
parent 5f8a9b4a
Loading
Loading
Loading
Loading
+20 −1
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.IInterface;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
@@ -77,6 +78,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/** Service for handling system supervision. */
public class SupervisionService extends ISupervisionManager.Stub {
@@ -136,7 +138,7 @@ public class SupervisionService extends ISupervisionManager.Stub {

    @Override
    public void setSupervisionEnabledForUser(@UserIdInt int userId, boolean enabled) {
        // TODO(b/395630828): Ensure that this method can only be called by the system.
        enforceSystemCaller();
        if (UserHandle.getUserId(Binder.getCallingUid()) != userId) {
            enforcePermission(INTERACT_ACROSS_USERS);
        }
@@ -556,6 +558,13 @@ public class SupervisionService extends ISupervisionManager.Stub {
        checkCallAuthorization(authorized);
    }

    /** Enforces that the caller is the system. */
    private void enforceSystemCaller() {
        int callingUid = mInjector.getCallingUid();
        checkCallAuthorization(UserHandle.isSameApp(callingUid, Process.SYSTEM_UID),
              "Caller with UID %s is not authorized.", callingUid);
    }

    /** Provides local services in a lazy manner. */
    static class Injector {
        public Context context;
@@ -565,6 +574,7 @@ public class SupervisionService extends ISupervisionManager.Stub {
        private KeyguardManager mKeyguardManager;
        private PackageManager mPackageManager;
        private UserManagerInternal mUserManagerInternal;
        private Integer mCallingUid;

        Injector(Context context) {
            this.context = context;
@@ -606,6 +616,15 @@ public class SupervisionService extends ISupervisionManager.Stub {
            }
            return mUserManagerInternal;
        }

        int getCallingUid() {
            return Objects.requireNonNullElseGet(mCallingUid, Binder::getCallingUid);
        }

        @VisibleForTesting
        public void setCallingUid(int Uid) {
            mCallingUid = Uid;
        }
    }

    /** Publishes local and binder services and allows the service to act during initialization. */
+17 −2
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@ import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.content.IntentFilter
import android.os.IBinder
import android.content.pm.PackageManager
import android.content.pm.UserInfo
import android.content.pm.UserInfo.FLAG_FOR_TESTING
@@ -38,7 +37,9 @@ import android.content.pm.UserInfo.FLAG_FULL
import android.content.pm.UserInfo.FLAG_MAIN
import android.content.pm.UserInfo.FLAG_SYSTEM
import android.os.Handler
import android.os.IBinder
import android.os.PersistableBundle
import android.os.Process
import android.os.UserHandle
import android.os.UserHandle.MIN_SECONDARY_USER_ID
import android.os.UserHandle.USER_SYSTEM
@@ -56,6 +57,7 @@ import com.android.server.LocalServices
import com.android.server.SystemService.TargetUser
import com.android.server.pm.UserManagerInternal
import com.android.server.supervision.SupervisionService.ACTION_CONFIRM_SUPERVISION_CREDENTIALS
import com.android.server.supervision.SupervisionService.Injector
import com.google.common.truth.Truth.assertThat
import java.nio.file.Files
import org.junit.Before
@@ -73,6 +75,7 @@ import org.mockito.kotlin.mock
import org.mockito.kotlin.never
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
import org.testng.Assert.assertThrows

/**
 * Unit tests for [SupervisionService].
@@ -94,6 +97,7 @@ class SupervisionServiceTest {
    private lateinit var context: Context
    private lateinit var lifecycle: SupervisionService.Lifecycle
    private lateinit var service: SupervisionService
    private lateinit var injector: Injector

    @Before
    fun setUp() {
@@ -110,10 +114,12 @@ class SupervisionServiceTest {
        SupervisionSettings.getInstance()
            .changeDirForTesting(Files.createTempDirectory("tempSupervisionFolder").toFile())

        service = SupervisionService(context)
        injector = Injector(context.createAttributionContext(SupervisionLog.TAG));
        service = SupervisionService(injector)
        lifecycle = SupervisionService.Lifecycle(context, service)
        lifecycle.registerProfileOwnerListener()

        injector.callingUid = Process.SYSTEM_UID
        assertThat(service.isSupervisionEnabledForUser(USER_ID)).isFalse()
    }

@@ -270,6 +276,15 @@ class SupervisionServiceTest {
        assertThat(getSecureSetting(SEARCH_CONTENT_FILTERS_ENABLED)).isEqualTo(-1)
    }

    @Test
    fun setSupervisionEnabledForUser_callerIsNotSystemUid_throwsException() {
        injector.callingUid = Process.NOBODY_UID

        assertThrows(SecurityException::class.java) {
            service.setSupervisionEnabledForUser(USER_ID, true);
        }
    }

    @Test
    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_REMOVE_POLICIES_ON_SUPERVISION_DISABLE)
    fun setSupervisionEnabledForUser_removesPoliciesWhenDisabling() {