blob: c006bc605ffd63c8c624e01cacfdedfa00c31b5f [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
Ken Chenf5f51332022-01-28 10:08:16 +080079 * @throws ServiceSpecificException in case of failure, with an error code indicating the
80 * cause of the failure.
81 */
Lorenzo Colitti82244fd2022-03-04 23:15:00 +090082 public void addNaughtyApp(final int uid) {
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080083 final int err = native_addNaughtyApp(uid);
Ken Chenf5f51332022-01-28 10:08:16 +080084 maybeThrow(err, "Unable to add naughty app");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080085 }
86
Ken Chenf5f51332022-01-28 10:08:16 +080087 /**
88 * Remove naughty app bandwidth rule for specific app
89 *
90 * @param uid uid of target app
Ken Chenf5f51332022-01-28 10:08:16 +080091 * @throws ServiceSpecificException in case of failure, with an error code indicating the
92 * cause of the failure.
93 */
Lorenzo Colitti82244fd2022-03-04 23:15:00 +090094 public void removeNaughtyApp(final int uid) {
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080095 final int err = native_removeNaughtyApp(uid);
Ken Chenf5f51332022-01-28 10:08:16 +080096 maybeThrow(err, "Unable to remove naughty app");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080097 }
98
Ken Chenf5f51332022-01-28 10:08:16 +080099 /**
100 * Add nice app bandwidth rule for specific app
101 *
102 * @param uid uid of target app
Ken Chenf5f51332022-01-28 10:08:16 +0800103 * @throws ServiceSpecificException in case of failure, with an error code indicating the
104 * cause of the failure.
105 */
Lorenzo Colitti82244fd2022-03-04 23:15:00 +0900106 public void addNiceApp(final int uid) {
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800107 final int err = native_addNiceApp(uid);
Ken Chenf5f51332022-01-28 10:08:16 +0800108 maybeThrow(err, "Unable to add nice app");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800109 }
110
Ken Chenf5f51332022-01-28 10:08:16 +0800111 /**
112 * Remove nice app bandwidth rule for specific app
113 *
114 * @param uid uid of target app
Ken Chenf5f51332022-01-28 10:08:16 +0800115 * @throws ServiceSpecificException in case of failure, with an error code indicating the
116 * cause of the failure.
117 */
Lorenzo Colitti82244fd2022-03-04 23:15:00 +0900118 public void removeNiceApp(final int uid) {
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800119 final int err = native_removeNiceApp(uid);
Ken Chenf5f51332022-01-28 10:08:16 +0800120 maybeThrow(err, "Unable to remove nice app");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800121 }
122
Ken Chenf5f51332022-01-28 10:08:16 +0800123 /**
124 * Set target firewall child chain
125 *
126 * @param childChain target chain to enable
127 * @param enable whether to enable or disable child chain.
Ken Chenf5f51332022-01-28 10:08:16 +0800128 * @throws ServiceSpecificException in case of failure, with an error code indicating the
129 * cause of the failure.
130 */
Lorenzo Colitti82244fd2022-03-04 23:15:00 +0900131 public void setChildChain(final int childChain, final boolean enable) {
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800132 final int err = native_setChildChain(childChain, enable);
Ken Chenf5f51332022-01-28 10:08:16 +0800133 maybeThrow(err, "Unable to set child chain");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800134 }
135
136 /**
137 * Replaces the contents of the specified UID-based firewall chain.
138 *
139 * The chain may be an allowlist chain or a denylist chain. A denylist chain contains DROP
140 * rules for the specified UIDs and a RETURN rule at the end. An allowlist chain contains RETURN
Ken Chenf5f51332022-01-28 10:08:16 +0800141 * rules for the system UID range (0 to {@code UID_APP} - 1), RETURN rules for the specified
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800142 * UIDs, and a DROP rule at the end. The chain will be created if it does not exist.
143 *
Ken Chenf5f51332022-01-28 10:08:16 +0800144 * @param chainName The name of the chain to replace.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800145 * @param isAllowlist Whether this is an allowlist or denylist chain.
Ken Chenf5f51332022-01-28 10:08:16 +0800146 * @param uids The list of UIDs to allow/deny.
147 * @return 0 if the chain was successfully replaced, errno otherwise.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800148 */
149 public int replaceUidChain(final String chainName, final boolean isAllowlist,
Lorenzo Colitti82244fd2022-03-04 23:15:00 +0900150 final int[] uids) {
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800151 final int err = native_replaceUidChain(chainName, isAllowlist, uids);
152 if (err != 0) {
153 Log.e(TAG, "replaceUidChain failed: " + Os.strerror(-err));
154 }
155 return -err;
156 }
157
Ken Chenf5f51332022-01-28 10:08:16 +0800158 /**
159 * Set firewall rule for uid
160 *
161 * @param childChain target chain
162 * @param uid uid to allow/deny
163 * @param firewallRule either FIREWALL_RULE_ALLOW or FIREWALL_RULE_DENY
Ken Chenf5f51332022-01-28 10:08:16 +0800164 * @throws ServiceSpecificException in case of failure, with an error code indicating the
165 * cause of the failure.
166 */
Lorenzo Colitti82244fd2022-03-04 23:15:00 +0900167 public void setUidRule(final int childChain, final int uid, final int firewallRule) {
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800168 final int err = native_setUidRule(childChain, uid, firewallRule);
Ken Chenf5f51332022-01-28 10:08:16 +0800169 maybeThrow(err, "Unable to set uid rule");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800170 }
171
172 /**
173 * Add ingress interface filtering rules to a list of UIDs
174 *
175 * For a given uid, once a filtering rule is added, the kernel will only allow packets from the
176 * allowed interface and loopback to be sent to the list of UIDs.
177 *
178 * Calling this method on one or more UIDs with an existing filtering rule but a different
179 * interface name will result in the filtering rule being updated to allow the new interface
180 * instead. Otherwise calling this method will not affect existing rules set on other UIDs.
181 *
182 * @param ifName the name of the interface on which the filtering rules will allow packets to
Ken Chenf5f51332022-01-28 10:08:16 +0800183 * be received.
184 * @param uids an array of UIDs which the filtering rules will be set
185 * @throws RemoteException when netd has crashed.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800186 * @throws ServiceSpecificException in case of failure, with an error code indicating the
Ken Chenf5f51332022-01-28 10:08:16 +0800187 * cause of the failure.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800188 */
Ken Chenf5f51332022-01-28 10:08:16 +0800189 public void addUidInterfaceRules(final String ifName, final int[] uids) throws RemoteException {
190 if (USE_NETD) {
191 mNetd.firewallAddUidInterfaceRules(ifName, uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800192 return;
193 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800194 final int err = native_addUidInterfaceRules(ifName, uids);
Ken Chenf5f51332022-01-28 10:08:16 +0800195 maybeThrow(err, "Unable to add uid interface rules");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800196 }
197
198 /**
199 * Remove ingress interface filtering rules from a list of UIDs
200 *
201 * Clear the ingress interface filtering rules from the list of UIDs which were previously set
202 * by addUidInterfaceRules(). Ignore any uid which does not have filtering rule.
203 *
204 * @param uids an array of UIDs from which the filtering rules will be removed
Ken Chenf5f51332022-01-28 10:08:16 +0800205 * @throws RemoteException when netd has crashed.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800206 * @throws ServiceSpecificException in case of failure, with an error code indicating the
Ken Chenf5f51332022-01-28 10:08:16 +0800207 * cause of the failure.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800208 */
Ken Chenf5f51332022-01-28 10:08:16 +0800209 public void removeUidInterfaceRules(final int[] uids) throws RemoteException {
210 if (USE_NETD) {
211 mNetd.firewallRemoveUidInterfaceRules(uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800212 return;
213 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800214 final int err = native_removeUidInterfaceRules(uids);
Ken Chenf5f51332022-01-28 10:08:16 +0800215 maybeThrow(err, "Unable to remove uid interface rules");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800216 }
217
Ken Chenf5f51332022-01-28 10:08:16 +0800218 /**
219 * Request netd to change the current active network stats map.
220 *
Ken Chenf5f51332022-01-28 10:08:16 +0800221 * @throws ServiceSpecificException in case of failure, with an error code indicating the
222 * cause of the failure.
223 */
markchien49e944c2022-03-01 15:22:20 +0800224 public void swapActiveStatsMap() {
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800225 final int err = native_swapActiveStatsMap();
Ken Chenf5f51332022-01-28 10:08:16 +0800226 maybeThrow(err, "Unable to swap active stats map");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800227 }
228
Ken Chenf5f51332022-01-28 10:08:16 +0800229 /**
230 * Assigns android.permission.INTERNET and/or android.permission.UPDATE_DEVICE_STATS to the uids
231 * specified. Or remove all permissions from the uids.
232 *
233 * @param permissions The permission to grant, it could be either PERMISSION_INTERNET and/or
234 * PERMISSION_UPDATE_DEVICE_STATS. If the permission is NO_PERMISSIONS, then
235 * revoke all permissions for the uids.
236 * @param uids uid of users to grant permission
237 * @throws RemoteException when netd has crashed.
238 */
239 public void setNetPermForUids(final int permissions, final int[] uids) throws RemoteException {
240 if (USE_NETD) {
241 mNetd.trafficSetNetPermForUids(permissions, uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800242 return;
243 }
244 native_setPermissionForUids(permissions, uids);
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800245 }
246
Ken Chene6d511f2022-01-25 11:10:42 +0800247 /**
248 * Dump BPF maps
249 *
250 * @param fd file descriptor to output
251 * @throws IOException when file descriptor is invalid.
252 * @throws ServiceSpecificException when the method is called on an unsupported device.
253 */
254 public void dump(final FileDescriptor fd, boolean verbose)
255 throws IOException, ServiceSpecificException {
256 if (USE_NETD) {
257 throw new ServiceSpecificException(
258 EOPNOTSUPP, "dumpsys connectivity trafficcontroller dump not available on pre-T"
259 + " devices, use dumpsys netd trafficcontroller instead.");
260 }
261 native_dump(fd, verbose);
262 }
263
Wayne Ma790c83e2022-01-13 10:35:05 +0800264 private static native void native_init();
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800265 private native int native_addNaughtyApp(int uid);
266 private native int native_removeNaughtyApp(int uid);
267 private native int native_addNiceApp(int uid);
268 private native int native_removeNiceApp(int uid);
269 private native int native_setChildChain(int childChain, boolean enable);
270 private native int native_replaceUidChain(String name, boolean isAllowlist, int[] uids);
271 private native int native_setUidRule(int childChain, int uid, int firewallRule);
272 private native int native_addUidInterfaceRules(String ifName, int[] uids);
273 private native int native_removeUidInterfaceRules(int[] uids);
274 private native int native_swapActiveStatsMap();
Wayne Ma2fde98c2022-01-17 18:04:05 +0800275 private native void native_setPermissionForUids(int permissions, int[] uids);
Ken Chene6d511f2022-01-25 11:10:42 +0800276 private native void native_dump(FileDescriptor fd, boolean verbose);
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800277}