blob: f3ac556218090151d44cf58eff9078f4978e5386 [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
markchien49e944c2022-03-01 15:22:20 +080057 /** Constructor used after T that doesn't need to use netd anymore. */
58 public BpfNetMaps() {
59 this(null);
60
61 if (USE_NETD) throw new IllegalArgumentException("BpfNetMaps need to use netd before T");
62 }
63
Wayne Ma2fde98c2022-01-17 18:04:05 +080064 public BpfNetMaps(INetd netd) {
Ken Chenf5f51332022-01-28 10:08:16 +080065 ensureInitialized();
Wayne Ma2fde98c2022-01-17 18:04:05 +080066 mNetd = netd;
Wayne Ma790c83e2022-01-13 10:35:05 +080067 }
68
Ken Chenf5f51332022-01-28 10:08:16 +080069 private void maybeThrow(final int err, final String msg) {
70 if (err != 0) {
71 throw new ServiceSpecificException(err, msg + ": " + Os.strerror(err));
72 }
73 }
74
75 /**
76 * Add naughty app bandwidth rule for specific app
77 *
78 * @param uid uid of target app
79 * @throws RemoteException when netd has crashed.
80 * @throws ServiceSpecificException in case of failure, with an error code indicating the
81 * cause of the failure.
82 */
83 public void addNaughtyApp(final int uid) throws RemoteException {
84 if (USE_NETD) {
85 mNetd.bandwidthAddNaughtyApp(uid);
Wayne Ma2fde98c2022-01-17 18:04:05 +080086 return;
87 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080088 final int err = native_addNaughtyApp(uid);
Ken Chenf5f51332022-01-28 10:08:16 +080089 maybeThrow(err, "Unable to add naughty app");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080090 }
91
Ken Chenf5f51332022-01-28 10:08:16 +080092 /**
93 * Remove naughty app bandwidth rule for specific app
94 *
95 * @param uid uid of target app
96 * @throws RemoteException when netd has crashed.
97 * @throws ServiceSpecificException in case of failure, with an error code indicating the
98 * cause of the failure.
99 */
100 public void removeNaughtyApp(final int uid) throws RemoteException {
101 if (USE_NETD) {
102 mNetd.bandwidthRemoveNaughtyApp(uid);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800103 return;
104 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800105 final int err = native_removeNaughtyApp(uid);
Ken Chenf5f51332022-01-28 10:08:16 +0800106 maybeThrow(err, "Unable to remove naughty app");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800107 }
108
Ken Chenf5f51332022-01-28 10:08:16 +0800109 /**
110 * Add nice app bandwidth rule for specific app
111 *
112 * @param uid uid of target app
113 * @throws RemoteException when netd has crashed.
114 * @throws ServiceSpecificException in case of failure, with an error code indicating the
115 * cause of the failure.
116 */
117 public void addNiceApp(final int uid) throws RemoteException {
118 if (USE_NETD) {
119 mNetd.bandwidthAddNiceApp(uid);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800120 return;
121 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800122 final int err = native_addNiceApp(uid);
Ken Chenf5f51332022-01-28 10:08:16 +0800123 maybeThrow(err, "Unable to add nice app");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800124 }
125
Ken Chenf5f51332022-01-28 10:08:16 +0800126 /**
127 * Remove nice app bandwidth rule for specific app
128 *
129 * @param uid uid of target app
130 * @throws RemoteException when netd has crashed.
131 * @throws ServiceSpecificException in case of failure, with an error code indicating the
132 * cause of the failure.
133 */
134 public void removeNiceApp(final int uid) throws RemoteException {
135 if (USE_NETD) {
136 mNetd.bandwidthRemoveNiceApp(uid);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800137 return;
138 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800139 final int err = native_removeNiceApp(uid);
Ken Chenf5f51332022-01-28 10:08:16 +0800140 maybeThrow(err, "Unable to remove nice app");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800141 }
142
Ken Chenf5f51332022-01-28 10:08:16 +0800143 /**
144 * Set target firewall child chain
145 *
146 * @param childChain target chain to enable
147 * @param enable whether to enable or disable child chain.
148 * @throws RemoteException when netd has crashed.
149 * @throws ServiceSpecificException in case of failure, with an error code indicating the
150 * cause of the failure.
151 */
152 public void setChildChain(final int childChain, final boolean enable) throws RemoteException {
153 if (USE_NETD) {
154 mNetd.firewallEnableChildChain(childChain, enable);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800155 return;
156 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800157 final int err = native_setChildChain(childChain, enable);
Ken Chenf5f51332022-01-28 10:08:16 +0800158 maybeThrow(err, "Unable to set child chain");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800159 }
160
161 /**
162 * Replaces the contents of the specified UID-based firewall chain.
163 *
164 * The chain may be an allowlist chain or a denylist chain. A denylist chain contains DROP
165 * rules for the specified UIDs and a RETURN rule at the end. An allowlist chain contains RETURN
Ken Chenf5f51332022-01-28 10:08:16 +0800166 * rules for the system UID range (0 to {@code UID_APP} - 1), RETURN rules for the specified
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800167 * UIDs, and a DROP rule at the end. The chain will be created if it does not exist.
168 *
Ken Chenf5f51332022-01-28 10:08:16 +0800169 * @param chainName The name of the chain to replace.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800170 * @param isAllowlist Whether this is an allowlist or denylist chain.
Ken Chenf5f51332022-01-28 10:08:16 +0800171 * @param uids The list of UIDs to allow/deny.
172 * @return 0 if the chain was successfully replaced, errno otherwise.
173 * @throws RemoteException when netd has crashed.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800174 */
175 public int replaceUidChain(final String chainName, final boolean isAllowlist,
Ken Chenf5f51332022-01-28 10:08:16 +0800176 final int[] uids) throws RemoteException {
177 if (USE_NETD) {
178 mNetd.firewallReplaceUidChain(chainName, isAllowlist, uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800179 return 0;
180 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800181 final int err = native_replaceUidChain(chainName, isAllowlist, uids);
182 if (err != 0) {
183 Log.e(TAG, "replaceUidChain failed: " + Os.strerror(-err));
184 }
185 return -err;
186 }
187
Ken Chenf5f51332022-01-28 10:08:16 +0800188 /**
189 * Set firewall rule for uid
190 *
191 * @param childChain target chain
192 * @param uid uid to allow/deny
193 * @param firewallRule either FIREWALL_RULE_ALLOW or FIREWALL_RULE_DENY
194 * @throws RemoteException when netd has crashed.
195 * @throws ServiceSpecificException in case of failure, with an error code indicating the
196 * cause of the failure.
197 */
198 public void setUidRule(final int childChain, final int uid, final int firewallRule)
199 throws RemoteException {
200 if (USE_NETD) {
201 mNetd.firewallSetUidRule(childChain, uid, firewallRule);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800202 return;
203 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800204 final int err = native_setUidRule(childChain, uid, firewallRule);
Ken Chenf5f51332022-01-28 10:08:16 +0800205 maybeThrow(err, "Unable to set uid rule");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800206 }
207
208 /**
209 * Add ingress interface filtering rules to a list of UIDs
210 *
211 * For a given uid, once a filtering rule is added, the kernel will only allow packets from the
212 * allowed interface and loopback to be sent to the list of UIDs.
213 *
214 * Calling this method on one or more UIDs with an existing filtering rule but a different
215 * interface name will result in the filtering rule being updated to allow the new interface
216 * instead. Otherwise calling this method will not affect existing rules set on other UIDs.
217 *
218 * @param ifName the name of the interface on which the filtering rules will allow packets to
Ken Chenf5f51332022-01-28 10:08:16 +0800219 * be received.
220 * @param uids an array of UIDs which the filtering rules will be set
221 * @throws RemoteException when netd has crashed.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800222 * @throws ServiceSpecificException in case of failure, with an error code indicating the
Ken Chenf5f51332022-01-28 10:08:16 +0800223 * cause of the failure.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800224 */
Ken Chenf5f51332022-01-28 10:08:16 +0800225 public void addUidInterfaceRules(final String ifName, final int[] uids) throws RemoteException {
226 if (USE_NETD) {
227 mNetd.firewallAddUidInterfaceRules(ifName, uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800228 return;
229 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800230 final int err = native_addUidInterfaceRules(ifName, uids);
Ken Chenf5f51332022-01-28 10:08:16 +0800231 maybeThrow(err, "Unable to add uid interface rules");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800232 }
233
234 /**
235 * Remove ingress interface filtering rules from a list of UIDs
236 *
237 * Clear the ingress interface filtering rules from the list of UIDs which were previously set
238 * by addUidInterfaceRules(). Ignore any uid which does not have filtering rule.
239 *
240 * @param uids an array of UIDs from which the filtering rules will be removed
Ken Chenf5f51332022-01-28 10:08:16 +0800241 * @throws RemoteException when netd has crashed.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800242 * @throws ServiceSpecificException in case of failure, with an error code indicating the
Ken Chenf5f51332022-01-28 10:08:16 +0800243 * cause of the failure.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800244 */
Ken Chenf5f51332022-01-28 10:08:16 +0800245 public void removeUidInterfaceRules(final int[] uids) throws RemoteException {
246 if (USE_NETD) {
247 mNetd.firewallRemoveUidInterfaceRules(uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800248 return;
249 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800250 final int err = native_removeUidInterfaceRules(uids);
Ken Chenf5f51332022-01-28 10:08:16 +0800251 maybeThrow(err, "Unable to remove uid interface rules");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800252 }
253
Ken Chenf5f51332022-01-28 10:08:16 +0800254 /**
255 * Request netd to change the current active network stats map.
256 *
Ken Chenf5f51332022-01-28 10:08:16 +0800257 * @throws ServiceSpecificException in case of failure, with an error code indicating the
258 * cause of the failure.
259 */
markchien49e944c2022-03-01 15:22:20 +0800260 public void swapActiveStatsMap() {
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800261 final int err = native_swapActiveStatsMap();
Ken Chenf5f51332022-01-28 10:08:16 +0800262 maybeThrow(err, "Unable to swap active stats map");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800263 }
264
Ken Chenf5f51332022-01-28 10:08:16 +0800265 /**
266 * Assigns android.permission.INTERNET and/or android.permission.UPDATE_DEVICE_STATS to the uids
267 * specified. Or remove all permissions from the uids.
268 *
269 * @param permissions The permission to grant, it could be either PERMISSION_INTERNET and/or
270 * PERMISSION_UPDATE_DEVICE_STATS. If the permission is NO_PERMISSIONS, then
271 * revoke all permissions for the uids.
272 * @param uids uid of users to grant permission
273 * @throws RemoteException when netd has crashed.
274 */
275 public void setNetPermForUids(final int permissions, final int[] uids) throws RemoteException {
276 if (USE_NETD) {
277 mNetd.trafficSetNetPermForUids(permissions, uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800278 return;
279 }
280 native_setPermissionForUids(permissions, uids);
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800281 }
282
Ken Chene6d511f2022-01-25 11:10:42 +0800283 /**
284 * Dump BPF maps
285 *
286 * @param fd file descriptor to output
287 * @throws IOException when file descriptor is invalid.
288 * @throws ServiceSpecificException when the method is called on an unsupported device.
289 */
290 public void dump(final FileDescriptor fd, boolean verbose)
291 throws IOException, ServiceSpecificException {
292 if (USE_NETD) {
293 throw new ServiceSpecificException(
294 EOPNOTSUPP, "dumpsys connectivity trafficcontroller dump not available on pre-T"
295 + " devices, use dumpsys netd trafficcontroller instead.");
296 }
297 native_dump(fd, verbose);
298 }
299
Wayne Ma790c83e2022-01-13 10:35:05 +0800300 private static native void native_init();
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800301 private native int native_addNaughtyApp(int uid);
302 private native int native_removeNaughtyApp(int uid);
303 private native int native_addNiceApp(int uid);
304 private native int native_removeNiceApp(int uid);
305 private native int native_setChildChain(int childChain, boolean enable);
306 private native int native_replaceUidChain(String name, boolean isAllowlist, int[] uids);
307 private native int native_setUidRule(int childChain, int uid, int firewallRule);
308 private native int native_addUidInterfaceRules(String ifName, int[] uids);
309 private native int native_removeUidInterfaceRules(int[] uids);
310 private native int native_swapActiveStatsMap();
Wayne Ma2fde98c2022-01-17 18:04:05 +0800311 private native void native_setPermissionForUids(int permissions, int[] uids);
Ken Chene6d511f2022-01-25 11:10:42 +0800312 private native void native_dump(FileDescriptor fd, boolean verbose);
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800313}