1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.util;
18 
19 import static android.os.Binder.getCallingPid;
20 import static android.os.Binder.getCallingUid;
21 
22 import android.os.Process;
23 import android.os.UserHandle;
24 
25 import java.util.concurrent.atomic.AtomicInteger;
26 
27 /**
28  * Utility class to check calling permissions on the network stack.
29  */
30 public final class PermissionUtil {
31     private static final AtomicInteger sSystemPid = new AtomicInteger(-1);
32 
33     /**
34      * Check that the caller is allowed to communicate with the network stack.
35      * @throws SecurityException The caller is not allowed to communicate with the network stack.
36      */
enforceNetworkStackCallingPermission()37     public static void enforceNetworkStackCallingPermission() {
38         final int caller = getCallingUid();
39         if (caller == Process.SYSTEM_UID) {
40             checkConsistentSystemPid();
41             return;
42         }
43 
44         if (caller != Process.myUid() && // apps with NETWORK_STACK_UID
45                 UserHandle.getAppId(caller) != Process.BLUETOOTH_UID) {
46             throw new SecurityException("Invalid caller: " + caller);
47         }
48     }
49 
checkConsistentSystemPid()50     private static void checkConsistentSystemPid() {
51         // Apart from the system server process, no process with a system UID should try to
52         // communicate with the network stack. This is to ensure that the network stack does not
53         // need to maintain behavior for clients it was not designed to work with.
54         // Checking that all calls from a system UID originate from the same PID loosely enforces
55         // this restriction as if another system process calls the network stack first, the system
56         // server would lose access to the network stack and cause obvious failures. If the system
57         // server calls the network stack first, other clients would lose access as expected.
58         final int systemPid = getCallingPid();
59         if (sSystemPid.compareAndSet(-1, systemPid)) {
60             // sSystemPid was unset (-1): this was the first call
61             return;
62         }
63 
64         if (sSystemPid.get() != systemPid) {
65             throw new SecurityException("Invalid PID for the system server, expected "
66                     + sSystemPid.get() + " but was called from " + systemPid);
67         }
68     }
69 
70     /**
71      * Check that the caller is allowed to dump the network stack, e.g. dumpsys.
72      * @throws SecurityException The caller is not allowed to dump the network stack.
73      */
checkDumpPermission()74     public static void checkDumpPermission() {
75         final int caller = getCallingUid();
76         if (caller != Process.myUid() && caller != Process.SYSTEM_UID && caller != Process.ROOT_UID
77                 && caller != Process.SHELL_UID) {
78             throw new SecurityException("No dump permissions for caller: " + caller);
79         }
80     }
81 
PermissionUtil()82     private PermissionUtil() {
83         throw new UnsupportedOperationException("This class is not to be instantiated");
84     }
85 }
86