blob: 7a3bab37192707458fce7fa05b549e504ff5bbb0 [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.
Patrick Rohr216dfc82022-02-01 16:01:49 +010036 private static final boolean USE_NETD = !SdkLevel.isAtLeastT();
Ken Chenf5f51332022-01-28 10:08:16 +080037 private static boolean sInitialized = false;
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080038
Ken Chenf5f51332022-01-28 10:08:16 +080039 /**
40 * Initializes the class if it is not already initialized. This method will open maps but not
41 * cause any other effects. This method may be called multiple times on any thread.
42 */
43 private static synchronized void ensureInitialized() {
44 if (sInitialized) return;
45 if (!USE_NETD) {
46 System.loadLibrary("service-connectivity");
Wayne Ma2fde98c2022-01-17 18:04:05 +080047 native_init();
48 }
Ken Chenf5f51332022-01-28 10:08:16 +080049 sInitialized = true;
Wayne Ma2fde98c2022-01-17 18:04:05 +080050 }
51
52 public BpfNetMaps(INetd netd) {
Ken Chenf5f51332022-01-28 10:08:16 +080053 ensureInitialized();
Wayne Ma2fde98c2022-01-17 18:04:05 +080054 mNetd = netd;
Wayne Ma790c83e2022-01-13 10:35:05 +080055 }
56
Ken Chenf5f51332022-01-28 10:08:16 +080057 private void maybeThrow(final int err, final String msg) {
58 if (err != 0) {
59 throw new ServiceSpecificException(err, msg + ": " + Os.strerror(err));
60 }
61 }
62
63 /**
64 * Add naughty app bandwidth rule for specific app
65 *
66 * @param uid uid of target app
67 * @throws RemoteException when netd has crashed.
68 * @throws ServiceSpecificException in case of failure, with an error code indicating the
69 * cause of the failure.
70 */
71 public void addNaughtyApp(final int uid) throws RemoteException {
72 if (USE_NETD) {
73 mNetd.bandwidthAddNaughtyApp(uid);
Wayne Ma2fde98c2022-01-17 18:04:05 +080074 return;
75 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080076 final int err = native_addNaughtyApp(uid);
Ken Chenf5f51332022-01-28 10:08:16 +080077 maybeThrow(err, "Unable to add naughty app");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080078 }
79
Ken Chenf5f51332022-01-28 10:08:16 +080080 /**
81 * Remove naughty app bandwidth rule for specific app
82 *
83 * @param uid uid of target app
84 * @throws RemoteException when netd has crashed.
85 * @throws ServiceSpecificException in case of failure, with an error code indicating the
86 * cause of the failure.
87 */
88 public void removeNaughtyApp(final int uid) throws RemoteException {
89 if (USE_NETD) {
90 mNetd.bandwidthRemoveNaughtyApp(uid);
Wayne Ma2fde98c2022-01-17 18:04:05 +080091 return;
92 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080093 final int err = native_removeNaughtyApp(uid);
Ken Chenf5f51332022-01-28 10:08:16 +080094 maybeThrow(err, "Unable to remove naughty app");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080095 }
96
Ken Chenf5f51332022-01-28 10:08:16 +080097 /**
98 * Add nice app bandwidth rule for specific app
99 *
100 * @param uid uid of target app
101 * @throws RemoteException when netd has crashed.
102 * @throws ServiceSpecificException in case of failure, with an error code indicating the
103 * cause of the failure.
104 */
105 public void addNiceApp(final int uid) throws RemoteException {
106 if (USE_NETD) {
107 mNetd.bandwidthAddNiceApp(uid);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800108 return;
109 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800110 final int err = native_addNiceApp(uid);
Ken Chenf5f51332022-01-28 10:08:16 +0800111 maybeThrow(err, "Unable to add nice app");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800112 }
113
Ken Chenf5f51332022-01-28 10:08:16 +0800114 /**
115 * Remove nice app bandwidth rule for specific app
116 *
117 * @param uid uid of target app
118 * @throws RemoteException when netd has crashed.
119 * @throws ServiceSpecificException in case of failure, with an error code indicating the
120 * cause of the failure.
121 */
122 public void removeNiceApp(final int uid) throws RemoteException {
123 if (USE_NETD) {
124 mNetd.bandwidthRemoveNiceApp(uid);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800125 return;
126 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800127 final int err = native_removeNiceApp(uid);
Ken Chenf5f51332022-01-28 10:08:16 +0800128 maybeThrow(err, "Unable to remove nice app");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800129 }
130
Ken Chenf5f51332022-01-28 10:08:16 +0800131 /**
132 * Set target firewall child chain
133 *
134 * @param childChain target chain to enable
135 * @param enable whether to enable or disable child chain.
136 * @throws RemoteException when netd has crashed.
137 * @throws ServiceSpecificException in case of failure, with an error code indicating the
138 * cause of the failure.
139 */
140 public void setChildChain(final int childChain, final boolean enable) throws RemoteException {
141 if (USE_NETD) {
142 mNetd.firewallEnableChildChain(childChain, enable);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800143 return;
144 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800145 final int err = native_setChildChain(childChain, enable);
Ken Chenf5f51332022-01-28 10:08:16 +0800146 maybeThrow(err, "Unable to set child chain");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800147 }
148
149 /**
150 * Replaces the contents of the specified UID-based firewall chain.
151 *
152 * The chain may be an allowlist chain or a denylist chain. A denylist chain contains DROP
153 * rules for the specified UIDs and a RETURN rule at the end. An allowlist chain contains RETURN
Ken Chenf5f51332022-01-28 10:08:16 +0800154 * rules for the system UID range (0 to {@code UID_APP} - 1), RETURN rules for the specified
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800155 * UIDs, and a DROP rule at the end. The chain will be created if it does not exist.
156 *
Ken Chenf5f51332022-01-28 10:08:16 +0800157 * @param chainName The name of the chain to replace.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800158 * @param isAllowlist Whether this is an allowlist or denylist chain.
Ken Chenf5f51332022-01-28 10:08:16 +0800159 * @param uids The list of UIDs to allow/deny.
160 * @return 0 if the chain was successfully replaced, errno otherwise.
161 * @throws RemoteException when netd has crashed.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800162 */
163 public int replaceUidChain(final String chainName, final boolean isAllowlist,
Ken Chenf5f51332022-01-28 10:08:16 +0800164 final int[] uids) throws RemoteException {
165 if (USE_NETD) {
166 mNetd.firewallReplaceUidChain(chainName, isAllowlist, uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800167 return 0;
168 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800169 final int err = native_replaceUidChain(chainName, isAllowlist, uids);
170 if (err != 0) {
171 Log.e(TAG, "replaceUidChain failed: " + Os.strerror(-err));
172 }
173 return -err;
174 }
175
Ken Chenf5f51332022-01-28 10:08:16 +0800176 /**
177 * Set firewall rule for uid
178 *
179 * @param childChain target chain
180 * @param uid uid to allow/deny
181 * @param firewallRule either FIREWALL_RULE_ALLOW or FIREWALL_RULE_DENY
182 * @throws RemoteException when netd has crashed.
183 * @throws ServiceSpecificException in case of failure, with an error code indicating the
184 * cause of the failure.
185 */
186 public void setUidRule(final int childChain, final int uid, final int firewallRule)
187 throws RemoteException {
188 if (USE_NETD) {
189 mNetd.firewallSetUidRule(childChain, uid, firewallRule);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800190 return;
191 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800192 final int err = native_setUidRule(childChain, uid, firewallRule);
Ken Chenf5f51332022-01-28 10:08:16 +0800193 maybeThrow(err, "Unable to set uid rule");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800194 }
195
196 /**
197 * Add ingress interface filtering rules to a list of UIDs
198 *
199 * For a given uid, once a filtering rule is added, the kernel will only allow packets from the
200 * allowed interface and loopback to be sent to the list of UIDs.
201 *
202 * Calling this method on one or more UIDs with an existing filtering rule but a different
203 * interface name will result in the filtering rule being updated to allow the new interface
204 * instead. Otherwise calling this method will not affect existing rules set on other UIDs.
205 *
206 * @param ifName the name of the interface on which the filtering rules will allow packets to
Ken Chenf5f51332022-01-28 10:08:16 +0800207 * be received.
208 * @param uids an array of UIDs which the filtering rules will be set
209 * @throws RemoteException when netd has crashed.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800210 * @throws ServiceSpecificException in case of failure, with an error code indicating the
Ken Chenf5f51332022-01-28 10:08:16 +0800211 * cause of the failure.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800212 */
Ken Chenf5f51332022-01-28 10:08:16 +0800213 public void addUidInterfaceRules(final String ifName, final int[] uids) throws RemoteException {
214 if (USE_NETD) {
215 mNetd.firewallAddUidInterfaceRules(ifName, uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800216 return;
217 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800218 final int err = native_addUidInterfaceRules(ifName, uids);
Ken Chenf5f51332022-01-28 10:08:16 +0800219 maybeThrow(err, "Unable to add uid interface rules");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800220 }
221
222 /**
223 * Remove ingress interface filtering rules from a list of UIDs
224 *
225 * Clear the ingress interface filtering rules from the list of UIDs which were previously set
226 * by addUidInterfaceRules(). Ignore any uid which does not have filtering rule.
227 *
228 * @param uids an array of UIDs from which the filtering rules will be removed
Ken Chenf5f51332022-01-28 10:08:16 +0800229 * @throws RemoteException when netd has crashed.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800230 * @throws ServiceSpecificException in case of failure, with an error code indicating the
Ken Chenf5f51332022-01-28 10:08:16 +0800231 * cause of the failure.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800232 */
Ken Chenf5f51332022-01-28 10:08:16 +0800233 public void removeUidInterfaceRules(final int[] uids) throws RemoteException {
234 if (USE_NETD) {
235 mNetd.firewallRemoveUidInterfaceRules(uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800236 return;
237 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800238 final int err = native_removeUidInterfaceRules(uids);
Ken Chenf5f51332022-01-28 10:08:16 +0800239 maybeThrow(err, "Unable to remove uid interface rules");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800240 }
241
Ken Chenf5f51332022-01-28 10:08:16 +0800242 /**
243 * Request netd to change the current active network stats map.
244 *
245 * @throws RemoteException when netd has crashed.
246 * @throws ServiceSpecificException in case of failure, with an error code indicating the
247 * cause of the failure.
248 */
249 public void swapActiveStatsMap() throws RemoteException {
250 if (USE_NETD) {
251 mNetd.trafficSwapActiveStatsMap();
Wayne Ma2fde98c2022-01-17 18:04:05 +0800252 return;
253 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800254 final int err = native_swapActiveStatsMap();
Ken Chenf5f51332022-01-28 10:08:16 +0800255 maybeThrow(err, "Unable to swap active stats map");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800256 }
257
Ken Chenf5f51332022-01-28 10:08:16 +0800258 /**
259 * Assigns android.permission.INTERNET and/or android.permission.UPDATE_DEVICE_STATS to the uids
260 * specified. Or remove all permissions from the uids.
261 *
262 * @param permissions The permission to grant, it could be either PERMISSION_INTERNET and/or
263 * PERMISSION_UPDATE_DEVICE_STATS. If the permission is NO_PERMISSIONS, then
264 * revoke all permissions for the uids.
265 * @param uids uid of users to grant permission
266 * @throws RemoteException when netd has crashed.
267 */
268 public void setNetPermForUids(final int permissions, final int[] uids) throws RemoteException {
269 if (USE_NETD) {
270 mNetd.trafficSetNetPermForUids(permissions, uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800271 return;
272 }
273 native_setPermissionForUids(permissions, uids);
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800274 }
275
276 /**
277 * Set counter set for uid
278 *
279 * @param counterSet either SET_DEFAULT or SET_FOREGROUND
Ken Chenf5f51332022-01-28 10:08:16 +0800280 * @param uid uid to foreground/background
281 * @throws ServiceSpecificException in case of failure, with an error code indicating the
282 * cause of the failure.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800283 */
Ken Chenf5f51332022-01-28 10:08:16 +0800284 public void setCounterSet(final int counterSet, final int uid) {
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800285 final int err = native_setCounterSet(counterSet, uid);
Ken Chenf5f51332022-01-28 10:08:16 +0800286 maybeThrow(err, "setCounterSet failed");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800287 }
288
289 /**
290 * Reset Uid stats
Ken Chenf5f51332022-01-28 10:08:16 +0800291 *
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800292 * @param tag default 0
293 * @param uid given uid to be clear
Ken Chenf5f51332022-01-28 10:08:16 +0800294 * @throws ServiceSpecificException in case of failure, with an error code indicating the
295 * cause of the failure.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800296 */
Ken Chenf5f51332022-01-28 10:08:16 +0800297 public void deleteTagData(final int tag, final int uid) {
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800298 final int err = native_deleteTagData(tag, uid);
Ken Chenf5f51332022-01-28 10:08:16 +0800299 maybeThrow(err, "deleteTagData failed");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800300 }
301
Wayne Ma790c83e2022-01-13 10:35:05 +0800302 private static native void native_init();
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800303 private native int native_addNaughtyApp(int uid);
304 private native int native_removeNaughtyApp(int uid);
305 private native int native_addNiceApp(int uid);
306 private native int native_removeNiceApp(int uid);
307 private native int native_setChildChain(int childChain, boolean enable);
308 private native int native_replaceUidChain(String name, boolean isAllowlist, int[] uids);
309 private native int native_setUidRule(int childChain, int uid, int firewallRule);
310 private native int native_addUidInterfaceRules(String ifName, int[] uids);
311 private native int native_removeUidInterfaceRules(int[] uids);
312 private native int native_swapActiveStatsMap();
Wayne Ma2fde98c2022-01-17 18:04:05 +0800313 private native void native_setPermissionForUids(int permissions, int[] uids);
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800314 private native int native_setCounterSet(int counterSet, int uid);
315 private native int native_deleteTagData(int tag, int uid);
316}