blob: 6c6a19d3a6d99799fdd2fb5826e2ff7a045a1a2e [file] [log] [blame]
Wayne Ma0ea3bdc2022-01-12 01:12:11 +08001/*
2 * Copyright (C) 2022 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
17package com.android.server;
18
Wayne Ma2fde98c2022-01-17 18:04:05 +080019import android.net.INetd;
20import android.os.RemoteException;
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080021import android.os.ServiceSpecificException;
22import android.system.Os;
23import android.util.Log;
24
Ken Chenf5f51332022-01-28 10:08:16 +080025import com.android.modules.utils.build.SdkLevel;
26
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080027/**
28 * BpfNetMaps is responsible for providing traffic controller relevant functionality.
29 *
30 * {@hide}
31 */
32public class BpfNetMaps {
33 private static final String TAG = "BpfNetMaps";
Wayne Ma2fde98c2022-01-17 18:04:05 +080034 private final INetd mNetd;
Ken Chenf5f51332022-01-28 10:08:16 +080035 // Use legacy netd for releases before T.
36 // TODO: change to !SdkLevel.isAtLeastT()
37 private static final boolean USE_NETD = true;
38 private static boolean sInitialized = false;
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080039
Ken Chenf5f51332022-01-28 10:08:16 +080040 /**
41 * Initializes the class if it is not already initialized. This method will open maps but not
42 * cause any other effects. This method may be called multiple times on any thread.
43 */
44 private static synchronized void ensureInitialized() {
45 if (sInitialized) return;
46 if (!USE_NETD) {
47 System.loadLibrary("service-connectivity");
Wayne Ma2fde98c2022-01-17 18:04:05 +080048 native_init();
49 }
Ken Chenf5f51332022-01-28 10:08:16 +080050 sInitialized = true;
Wayne Ma2fde98c2022-01-17 18:04:05 +080051 }
52
53 public BpfNetMaps(INetd netd) {
Ken Chenf5f51332022-01-28 10:08:16 +080054 ensureInitialized();
Wayne Ma2fde98c2022-01-17 18:04:05 +080055 mNetd = netd;
Wayne Ma790c83e2022-01-13 10:35:05 +080056 }
57
Ken Chenf5f51332022-01-28 10:08:16 +080058 private void maybeThrow(final int err, final String msg) {
59 if (err != 0) {
60 throw new ServiceSpecificException(err, msg + ": " + Os.strerror(err));
61 }
62 }
63
64 /**
65 * Add naughty app bandwidth rule for specific app
66 *
67 * @param uid uid of target app
68 * @throws RemoteException when netd has crashed.
69 * @throws ServiceSpecificException in case of failure, with an error code indicating the
70 * cause of the failure.
71 */
72 public void addNaughtyApp(final int uid) throws RemoteException {
73 if (USE_NETD) {
74 mNetd.bandwidthAddNaughtyApp(uid);
Wayne Ma2fde98c2022-01-17 18:04:05 +080075 return;
76 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080077 final int err = native_addNaughtyApp(uid);
Ken Chenf5f51332022-01-28 10:08:16 +080078 maybeThrow(err, "Unable to add naughty app");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080079 }
80
Ken Chenf5f51332022-01-28 10:08:16 +080081 /**
82 * Remove naughty app bandwidth rule for specific app
83 *
84 * @param uid uid of target app
85 * @throws RemoteException when netd has crashed.
86 * @throws ServiceSpecificException in case of failure, with an error code indicating the
87 * cause of the failure.
88 */
89 public void removeNaughtyApp(final int uid) throws RemoteException {
90 if (USE_NETD) {
91 mNetd.bandwidthRemoveNaughtyApp(uid);
Wayne Ma2fde98c2022-01-17 18:04:05 +080092 return;
93 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080094 final int err = native_removeNaughtyApp(uid);
Ken Chenf5f51332022-01-28 10:08:16 +080095 maybeThrow(err, "Unable to remove naughty app");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080096 }
97
Ken Chenf5f51332022-01-28 10:08:16 +080098 /**
99 * Add nice app bandwidth rule for specific app
100 *
101 * @param uid uid of target app
102 * @throws RemoteException when netd has crashed.
103 * @throws ServiceSpecificException in case of failure, with an error code indicating the
104 * cause of the failure.
105 */
106 public void addNiceApp(final int uid) throws RemoteException {
107 if (USE_NETD) {
108 mNetd.bandwidthAddNiceApp(uid);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800109 return;
110 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800111 final int err = native_addNiceApp(uid);
Ken Chenf5f51332022-01-28 10:08:16 +0800112 maybeThrow(err, "Unable to add nice app");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800113 }
114
Ken Chenf5f51332022-01-28 10:08:16 +0800115 /**
116 * Remove nice app bandwidth rule for specific app
117 *
118 * @param uid uid of target app
119 * @throws RemoteException when netd has crashed.
120 * @throws ServiceSpecificException in case of failure, with an error code indicating the
121 * cause of the failure.
122 */
123 public void removeNiceApp(final int uid) throws RemoteException {
124 if (USE_NETD) {
125 mNetd.bandwidthRemoveNiceApp(uid);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800126 return;
127 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800128 final int err = native_removeNiceApp(uid);
Ken Chenf5f51332022-01-28 10:08:16 +0800129 maybeThrow(err, "Unable to remove nice app");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800130 }
131
Ken Chenf5f51332022-01-28 10:08:16 +0800132 /**
133 * Set target firewall child chain
134 *
135 * @param childChain target chain to enable
136 * @param enable whether to enable or disable child chain.
137 * @throws RemoteException when netd has crashed.
138 * @throws ServiceSpecificException in case of failure, with an error code indicating the
139 * cause of the failure.
140 */
141 public void setChildChain(final int childChain, final boolean enable) throws RemoteException {
142 if (USE_NETD) {
143 mNetd.firewallEnableChildChain(childChain, enable);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800144 return;
145 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800146 final int err = native_setChildChain(childChain, enable);
Ken Chenf5f51332022-01-28 10:08:16 +0800147 maybeThrow(err, "Unable to set child chain");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800148 }
149
150 /**
151 * Replaces the contents of the specified UID-based firewall chain.
152 *
153 * The chain may be an allowlist chain or a denylist chain. A denylist chain contains DROP
154 * rules for the specified UIDs and a RETURN rule at the end. An allowlist chain contains RETURN
Ken Chenf5f51332022-01-28 10:08:16 +0800155 * rules for the system UID range (0 to {@code UID_APP} - 1), RETURN rules for the specified
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800156 * UIDs, and a DROP rule at the end. The chain will be created if it does not exist.
157 *
Ken Chenf5f51332022-01-28 10:08:16 +0800158 * @param chainName The name of the chain to replace.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800159 * @param isAllowlist Whether this is an allowlist or denylist chain.
Ken Chenf5f51332022-01-28 10:08:16 +0800160 * @param uids The list of UIDs to allow/deny.
161 * @return 0 if the chain was successfully replaced, errno otherwise.
162 * @throws RemoteException when netd has crashed.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800163 */
164 public int replaceUidChain(final String chainName, final boolean isAllowlist,
Ken Chenf5f51332022-01-28 10:08:16 +0800165 final int[] uids) throws RemoteException {
166 if (USE_NETD) {
167 mNetd.firewallReplaceUidChain(chainName, isAllowlist, uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800168 return 0;
169 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800170 final int err = native_replaceUidChain(chainName, isAllowlist, uids);
171 if (err != 0) {
172 Log.e(TAG, "replaceUidChain failed: " + Os.strerror(-err));
173 }
174 return -err;
175 }
176
Ken Chenf5f51332022-01-28 10:08:16 +0800177 /**
178 * Set firewall rule for uid
179 *
180 * @param childChain target chain
181 * @param uid uid to allow/deny
182 * @param firewallRule either FIREWALL_RULE_ALLOW or FIREWALL_RULE_DENY
183 * @throws RemoteException when netd has crashed.
184 * @throws ServiceSpecificException in case of failure, with an error code indicating the
185 * cause of the failure.
186 */
187 public void setUidRule(final int childChain, final int uid, final int firewallRule)
188 throws RemoteException {
189 if (USE_NETD) {
190 mNetd.firewallSetUidRule(childChain, uid, firewallRule);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800191 return;
192 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800193 final int err = native_setUidRule(childChain, uid, firewallRule);
Ken Chenf5f51332022-01-28 10:08:16 +0800194 maybeThrow(err, "Unable to set uid rule");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800195 }
196
197 /**
198 * Add ingress interface filtering rules to a list of UIDs
199 *
200 * For a given uid, once a filtering rule is added, the kernel will only allow packets from the
201 * allowed interface and loopback to be sent to the list of UIDs.
202 *
203 * Calling this method on one or more UIDs with an existing filtering rule but a different
204 * interface name will result in the filtering rule being updated to allow the new interface
205 * instead. Otherwise calling this method will not affect existing rules set on other UIDs.
206 *
207 * @param ifName the name of the interface on which the filtering rules will allow packets to
Ken Chenf5f51332022-01-28 10:08:16 +0800208 * be received.
209 * @param uids an array of UIDs which the filtering rules will be set
210 * @throws RemoteException when netd has crashed.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800211 * @throws ServiceSpecificException in case of failure, with an error code indicating the
Ken Chenf5f51332022-01-28 10:08:16 +0800212 * cause of the failure.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800213 */
Ken Chenf5f51332022-01-28 10:08:16 +0800214 public void addUidInterfaceRules(final String ifName, final int[] uids) throws RemoteException {
215 if (USE_NETD) {
216 mNetd.firewallAddUidInterfaceRules(ifName, uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800217 return;
218 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800219 final int err = native_addUidInterfaceRules(ifName, uids);
Ken Chenf5f51332022-01-28 10:08:16 +0800220 maybeThrow(err, "Unable to add uid interface rules");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800221 }
222
223 /**
224 * Remove ingress interface filtering rules from a list of UIDs
225 *
226 * Clear the ingress interface filtering rules from the list of UIDs which were previously set
227 * by addUidInterfaceRules(). Ignore any uid which does not have filtering rule.
228 *
229 * @param uids an array of UIDs from which the filtering rules will be removed
Ken Chenf5f51332022-01-28 10:08:16 +0800230 * @throws RemoteException when netd has crashed.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800231 * @throws ServiceSpecificException in case of failure, with an error code indicating the
Ken Chenf5f51332022-01-28 10:08:16 +0800232 * cause of the failure.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800233 */
Ken Chenf5f51332022-01-28 10:08:16 +0800234 public void removeUidInterfaceRules(final int[] uids) throws RemoteException {
235 if (USE_NETD) {
236 mNetd.firewallRemoveUidInterfaceRules(uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800237 return;
238 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800239 final int err = native_removeUidInterfaceRules(uids);
Ken Chenf5f51332022-01-28 10:08:16 +0800240 maybeThrow(err, "Unable to remove uid interface rules");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800241 }
242
Ken Chenf5f51332022-01-28 10:08:16 +0800243 /**
244 * Request netd to change the current active network stats map.
245 *
246 * @throws RemoteException when netd has crashed.
247 * @throws ServiceSpecificException in case of failure, with an error code indicating the
248 * cause of the failure.
249 */
250 public void swapActiveStatsMap() throws RemoteException {
251 if (USE_NETD) {
252 mNetd.trafficSwapActiveStatsMap();
Wayne Ma2fde98c2022-01-17 18:04:05 +0800253 return;
254 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800255 final int err = native_swapActiveStatsMap();
Ken Chenf5f51332022-01-28 10:08:16 +0800256 maybeThrow(err, "Unable to swap active stats map");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800257 }
258
Ken Chenf5f51332022-01-28 10:08:16 +0800259 /**
260 * Assigns android.permission.INTERNET and/or android.permission.UPDATE_DEVICE_STATS to the uids
261 * specified. Or remove all permissions from the uids.
262 *
263 * @param permissions The permission to grant, it could be either PERMISSION_INTERNET and/or
264 * PERMISSION_UPDATE_DEVICE_STATS. If the permission is NO_PERMISSIONS, then
265 * revoke all permissions for the uids.
266 * @param uids uid of users to grant permission
267 * @throws RemoteException when netd has crashed.
268 */
269 public void setNetPermForUids(final int permissions, final int[] uids) throws RemoteException {
270 if (USE_NETD) {
271 mNetd.trafficSetNetPermForUids(permissions, uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800272 return;
273 }
274 native_setPermissionForUids(permissions, uids);
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800275 }
276
277 /**
278 * Set counter set for uid
279 *
280 * @param counterSet either SET_DEFAULT or SET_FOREGROUND
Ken Chenf5f51332022-01-28 10:08:16 +0800281 * @param uid uid to foreground/background
282 * @throws ServiceSpecificException in case of failure, with an error code indicating the
283 * cause of the failure.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800284 */
Ken Chenf5f51332022-01-28 10:08:16 +0800285 public void setCounterSet(final int counterSet, final int uid) {
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800286 final int err = native_setCounterSet(counterSet, uid);
Ken Chenf5f51332022-01-28 10:08:16 +0800287 maybeThrow(err, "setCounterSet failed");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800288 }
289
290 /**
291 * Reset Uid stats
Ken Chenf5f51332022-01-28 10:08:16 +0800292 *
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800293 * @param tag default 0
294 * @param uid given uid to be clear
Ken Chenf5f51332022-01-28 10:08:16 +0800295 * @throws ServiceSpecificException in case of failure, with an error code indicating the
296 * cause of the failure.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800297 */
Ken Chenf5f51332022-01-28 10:08:16 +0800298 public void deleteTagData(final int tag, final int uid) {
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800299 final int err = native_deleteTagData(tag, uid);
Ken Chenf5f51332022-01-28 10:08:16 +0800300 maybeThrow(err, "deleteTagData failed");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800301 }
302
Wayne Ma790c83e2022-01-13 10:35:05 +0800303 private static native void native_init();
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800304 private native int native_addNaughtyApp(int uid);
305 private native int native_removeNaughtyApp(int uid);
306 private native int native_addNiceApp(int uid);
307 private native int native_removeNiceApp(int uid);
308 private native int native_setChildChain(int childChain, boolean enable);
309 private native int native_replaceUidChain(String name, boolean isAllowlist, int[] uids);
310 private native int native_setUidRule(int childChain, int uid, int firewallRule);
311 private native int native_addUidInterfaceRules(String ifName, int[] uids);
312 private native int native_removeUidInterfaceRules(int[] uids);
313 private native int native_swapActiveStatsMap();
Wayne Ma2fde98c2022-01-17 18:04:05 +0800314 private native void native_setPermissionForUids(int permissions, int[] uids);
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800315 private native int native_setCounterSet(int counterSet, int uid);
316 private native int native_deleteTagData(int tag, int uid);
317}