blob: f2ca18b2cc058deecf046715d0bc61351800df04 [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
Ken Chene6d511f2022-01-25 11:10:42 +080019import static android.system.OsConstants.EOPNOTSUPP;
20
Wayne Ma2fde98c2022-01-17 18:04:05 +080021import android.net.INetd;
22import android.os.RemoteException;
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080023import android.os.ServiceSpecificException;
24import android.system.Os;
25import android.util.Log;
26
Ken Chenf5f51332022-01-28 10:08:16 +080027import com.android.modules.utils.build.SdkLevel;
28
Ken Chene6d511f2022-01-25 11:10:42 +080029import java.io.FileDescriptor;
30import java.io.IOException;
31
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080032/**
33 * BpfNetMaps is responsible for providing traffic controller relevant functionality.
34 *
35 * {@hide}
36 */
37public class BpfNetMaps {
38 private static final String TAG = "BpfNetMaps";
Wayne Ma2fde98c2022-01-17 18:04:05 +080039 private final INetd mNetd;
Ken Chenf5f51332022-01-28 10:08:16 +080040 // Use legacy netd for releases before T.
Patrick Rohr216dfc82022-02-01 16:01:49 +010041 private static final boolean USE_NETD = !SdkLevel.isAtLeastT();
Ken Chenf5f51332022-01-28 10:08:16 +080042 private static boolean sInitialized = false;
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080043
Ken Chenf5f51332022-01-28 10:08:16 +080044 /**
45 * Initializes the class if it is not already initialized. This method will open maps but not
46 * cause any other effects. This method may be called multiple times on any thread.
47 */
48 private static synchronized void ensureInitialized() {
49 if (sInitialized) return;
50 if (!USE_NETD) {
51 System.loadLibrary("service-connectivity");
Wayne Ma2fde98c2022-01-17 18:04:05 +080052 native_init();
53 }
Ken Chenf5f51332022-01-28 10:08:16 +080054 sInitialized = true;
Wayne Ma2fde98c2022-01-17 18:04:05 +080055 }
56
57 public BpfNetMaps(INetd netd) {
Ken Chenf5f51332022-01-28 10:08:16 +080058 ensureInitialized();
Wayne Ma2fde98c2022-01-17 18:04:05 +080059 mNetd = netd;
Wayne Ma790c83e2022-01-13 10:35:05 +080060 }
61
Ken Chenf5f51332022-01-28 10:08:16 +080062 private void maybeThrow(final int err, final String msg) {
63 if (err != 0) {
64 throw new ServiceSpecificException(err, msg + ": " + Os.strerror(err));
65 }
66 }
67
68 /**
69 * Add naughty app bandwidth rule for specific app
70 *
71 * @param uid uid of target app
72 * @throws RemoteException when netd has crashed.
73 * @throws ServiceSpecificException in case of failure, with an error code indicating the
74 * cause of the failure.
75 */
76 public void addNaughtyApp(final int uid) throws RemoteException {
77 if (USE_NETD) {
78 mNetd.bandwidthAddNaughtyApp(uid);
Wayne Ma2fde98c2022-01-17 18:04:05 +080079 return;
80 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080081 final int err = native_addNaughtyApp(uid);
Ken Chenf5f51332022-01-28 10:08:16 +080082 maybeThrow(err, "Unable to add naughty app");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080083 }
84
Ken Chenf5f51332022-01-28 10:08:16 +080085 /**
86 * Remove naughty app bandwidth rule for specific app
87 *
88 * @param uid uid of target app
89 * @throws RemoteException when netd has crashed.
90 * @throws ServiceSpecificException in case of failure, with an error code indicating the
91 * cause of the failure.
92 */
93 public void removeNaughtyApp(final int uid) throws RemoteException {
94 if (USE_NETD) {
95 mNetd.bandwidthRemoveNaughtyApp(uid);
Wayne Ma2fde98c2022-01-17 18:04:05 +080096 return;
97 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080098 final int err = native_removeNaughtyApp(uid);
Ken Chenf5f51332022-01-28 10:08:16 +080099 maybeThrow(err, "Unable to remove naughty app");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800100 }
101
Ken Chenf5f51332022-01-28 10:08:16 +0800102 /**
103 * Add nice app bandwidth rule for specific app
104 *
105 * @param uid uid of target app
106 * @throws RemoteException when netd has crashed.
107 * @throws ServiceSpecificException in case of failure, with an error code indicating the
108 * cause of the failure.
109 */
110 public void addNiceApp(final int uid) throws RemoteException {
111 if (USE_NETD) {
112 mNetd.bandwidthAddNiceApp(uid);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800113 return;
114 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800115 final int err = native_addNiceApp(uid);
Ken Chenf5f51332022-01-28 10:08:16 +0800116 maybeThrow(err, "Unable to add nice app");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800117 }
118
Ken Chenf5f51332022-01-28 10:08:16 +0800119 /**
120 * Remove nice app bandwidth rule for specific app
121 *
122 * @param uid uid of target app
123 * @throws RemoteException when netd has crashed.
124 * @throws ServiceSpecificException in case of failure, with an error code indicating the
125 * cause of the failure.
126 */
127 public void removeNiceApp(final int uid) throws RemoteException {
128 if (USE_NETD) {
129 mNetd.bandwidthRemoveNiceApp(uid);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800130 return;
131 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800132 final int err = native_removeNiceApp(uid);
Ken Chenf5f51332022-01-28 10:08:16 +0800133 maybeThrow(err, "Unable to remove nice app");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800134 }
135
Ken Chenf5f51332022-01-28 10:08:16 +0800136 /**
137 * Set target firewall child chain
138 *
139 * @param childChain target chain to enable
140 * @param enable whether to enable or disable child chain.
141 * @throws RemoteException when netd has crashed.
142 * @throws ServiceSpecificException in case of failure, with an error code indicating the
143 * cause of the failure.
144 */
145 public void setChildChain(final int childChain, final boolean enable) throws RemoteException {
146 if (USE_NETD) {
147 mNetd.firewallEnableChildChain(childChain, enable);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800148 return;
149 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800150 final int err = native_setChildChain(childChain, enable);
Ken Chenf5f51332022-01-28 10:08:16 +0800151 maybeThrow(err, "Unable to set child chain");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800152 }
153
154 /**
155 * Replaces the contents of the specified UID-based firewall chain.
156 *
157 * The chain may be an allowlist chain or a denylist chain. A denylist chain contains DROP
158 * rules for the specified UIDs and a RETURN rule at the end. An allowlist chain contains RETURN
Ken Chenf5f51332022-01-28 10:08:16 +0800159 * rules for the system UID range (0 to {@code UID_APP} - 1), RETURN rules for the specified
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800160 * UIDs, and a DROP rule at the end. The chain will be created if it does not exist.
161 *
Ken Chenf5f51332022-01-28 10:08:16 +0800162 * @param chainName The name of the chain to replace.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800163 * @param isAllowlist Whether this is an allowlist or denylist chain.
Ken Chenf5f51332022-01-28 10:08:16 +0800164 * @param uids The list of UIDs to allow/deny.
165 * @return 0 if the chain was successfully replaced, errno otherwise.
166 * @throws RemoteException when netd has crashed.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800167 */
168 public int replaceUidChain(final String chainName, final boolean isAllowlist,
Ken Chenf5f51332022-01-28 10:08:16 +0800169 final int[] uids) throws RemoteException {
170 if (USE_NETD) {
171 mNetd.firewallReplaceUidChain(chainName, isAllowlist, uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800172 return 0;
173 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800174 final int err = native_replaceUidChain(chainName, isAllowlist, uids);
175 if (err != 0) {
176 Log.e(TAG, "replaceUidChain failed: " + Os.strerror(-err));
177 }
178 return -err;
179 }
180
Ken Chenf5f51332022-01-28 10:08:16 +0800181 /**
182 * Set firewall rule for uid
183 *
184 * @param childChain target chain
185 * @param uid uid to allow/deny
186 * @param firewallRule either FIREWALL_RULE_ALLOW or FIREWALL_RULE_DENY
187 * @throws RemoteException when netd has crashed.
188 * @throws ServiceSpecificException in case of failure, with an error code indicating the
189 * cause of the failure.
190 */
191 public void setUidRule(final int childChain, final int uid, final int firewallRule)
192 throws RemoteException {
193 if (USE_NETD) {
194 mNetd.firewallSetUidRule(childChain, uid, firewallRule);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800195 return;
196 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800197 final int err = native_setUidRule(childChain, uid, firewallRule);
Ken Chenf5f51332022-01-28 10:08:16 +0800198 maybeThrow(err, "Unable to set uid rule");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800199 }
200
201 /**
202 * Add ingress interface filtering rules to a list of UIDs
203 *
204 * For a given uid, once a filtering rule is added, the kernel will only allow packets from the
205 * allowed interface and loopback to be sent to the list of UIDs.
206 *
207 * Calling this method on one or more UIDs with an existing filtering rule but a different
208 * interface name will result in the filtering rule being updated to allow the new interface
209 * instead. Otherwise calling this method will not affect existing rules set on other UIDs.
210 *
211 * @param ifName the name of the interface on which the filtering rules will allow packets to
Ken Chenf5f51332022-01-28 10:08:16 +0800212 * be received.
213 * @param uids an array of UIDs which the filtering rules will be set
214 * @throws RemoteException when netd has crashed.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800215 * @throws ServiceSpecificException in case of failure, with an error code indicating the
Ken Chenf5f51332022-01-28 10:08:16 +0800216 * cause of the failure.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800217 */
Ken Chenf5f51332022-01-28 10:08:16 +0800218 public void addUidInterfaceRules(final String ifName, final int[] uids) throws RemoteException {
219 if (USE_NETD) {
220 mNetd.firewallAddUidInterfaceRules(ifName, uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800221 return;
222 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800223 final int err = native_addUidInterfaceRules(ifName, uids);
Ken Chenf5f51332022-01-28 10:08:16 +0800224 maybeThrow(err, "Unable to add uid interface rules");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800225 }
226
227 /**
228 * Remove ingress interface filtering rules from a list of UIDs
229 *
230 * Clear the ingress interface filtering rules from the list of UIDs which were previously set
231 * by addUidInterfaceRules(). Ignore any uid which does not have filtering rule.
232 *
233 * @param uids an array of UIDs from which the filtering rules will be removed
Ken Chenf5f51332022-01-28 10:08:16 +0800234 * @throws RemoteException when netd has crashed.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800235 * @throws ServiceSpecificException in case of failure, with an error code indicating the
Ken Chenf5f51332022-01-28 10:08:16 +0800236 * cause of the failure.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800237 */
Ken Chenf5f51332022-01-28 10:08:16 +0800238 public void removeUidInterfaceRules(final int[] uids) throws RemoteException {
239 if (USE_NETD) {
240 mNetd.firewallRemoveUidInterfaceRules(uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800241 return;
242 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800243 final int err = native_removeUidInterfaceRules(uids);
Ken Chenf5f51332022-01-28 10:08:16 +0800244 maybeThrow(err, "Unable to remove uid interface rules");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800245 }
246
Ken Chenf5f51332022-01-28 10:08:16 +0800247 /**
248 * Request netd to change the current active network stats map.
249 *
250 * @throws RemoteException when netd has crashed.
251 * @throws ServiceSpecificException in case of failure, with an error code indicating the
252 * cause of the failure.
253 */
254 public void swapActiveStatsMap() throws RemoteException {
255 if (USE_NETD) {
256 mNetd.trafficSwapActiveStatsMap();
Wayne Ma2fde98c2022-01-17 18:04:05 +0800257 return;
258 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800259 final int err = native_swapActiveStatsMap();
Ken Chenf5f51332022-01-28 10:08:16 +0800260 maybeThrow(err, "Unable to swap active stats map");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800261 }
262
Ken Chenf5f51332022-01-28 10:08:16 +0800263 /**
264 * Assigns android.permission.INTERNET and/or android.permission.UPDATE_DEVICE_STATS to the uids
265 * specified. Or remove all permissions from the uids.
266 *
267 * @param permissions The permission to grant, it could be either PERMISSION_INTERNET and/or
268 * PERMISSION_UPDATE_DEVICE_STATS. If the permission is NO_PERMISSIONS, then
269 * revoke all permissions for the uids.
270 * @param uids uid of users to grant permission
271 * @throws RemoteException when netd has crashed.
272 */
273 public void setNetPermForUids(final int permissions, final int[] uids) throws RemoteException {
274 if (USE_NETD) {
275 mNetd.trafficSetNetPermForUids(permissions, uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800276 return;
277 }
278 native_setPermissionForUids(permissions, uids);
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800279 }
280
Ken Chene6d511f2022-01-25 11:10:42 +0800281 /**
282 * Dump BPF maps
283 *
284 * @param fd file descriptor to output
285 * @throws IOException when file descriptor is invalid.
286 * @throws ServiceSpecificException when the method is called on an unsupported device.
287 */
288 public void dump(final FileDescriptor fd, boolean verbose)
289 throws IOException, ServiceSpecificException {
290 if (USE_NETD) {
291 throw new ServiceSpecificException(
292 EOPNOTSUPP, "dumpsys connectivity trafficcontroller dump not available on pre-T"
293 + " devices, use dumpsys netd trafficcontroller instead.");
294 }
295 native_dump(fd, verbose);
296 }
297
Wayne Ma790c83e2022-01-13 10:35:05 +0800298 private static native void native_init();
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800299 private native int native_addNaughtyApp(int uid);
300 private native int native_removeNaughtyApp(int uid);
301 private native int native_addNiceApp(int uid);
302 private native int native_removeNiceApp(int uid);
303 private native int native_setChildChain(int childChain, boolean enable);
304 private native int native_replaceUidChain(String name, boolean isAllowlist, int[] uids);
305 private native int native_setUidRule(int childChain, int uid, int firewallRule);
306 private native int native_addUidInterfaceRules(String ifName, int[] uids);
307 private native int native_removeUidInterfaceRules(int[] uids);
308 private native int native_swapActiveStatsMap();
Wayne Ma2fde98c2022-01-17 18:04:05 +0800309 private native void native_setPermissionForUids(int permissions, int[] uids);
Ken Chene6d511f2022-01-25 11:10:42 +0800310 private native void native_dump(FileDescriptor fd, boolean verbose);
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800311}