blob: c9773911434df1a9dba50626110d370c568f3193 [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
Ken Chenf5f51332022-01-28 10:08:16 +080072 * @throws ServiceSpecificException in case of failure, with an error code indicating the
73 * cause of the failure.
74 */
Lorenzo Colitti82244fd2022-03-04 23:15:00 +090075 public void addNaughtyApp(final int uid) {
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
Ken Chenf5f51332022-01-28 10:08:16 +080084 * @throws ServiceSpecificException in case of failure, with an error code indicating the
85 * cause of the failure.
86 */
Lorenzo Colitti82244fd2022-03-04 23:15:00 +090087 public void removeNaughtyApp(final int uid) {
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080088 final int err = native_removeNaughtyApp(uid);
Ken Chenf5f51332022-01-28 10:08:16 +080089 maybeThrow(err, "Unable to remove naughty app");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080090 }
91
Ken Chenf5f51332022-01-28 10:08:16 +080092 /**
93 * Add nice app bandwidth rule for specific app
94 *
95 * @param uid uid of target app
Ken Chenf5f51332022-01-28 10:08:16 +080096 * @throws ServiceSpecificException in case of failure, with an error code indicating the
97 * cause of the failure.
98 */
Lorenzo Colitti82244fd2022-03-04 23:15:00 +090099 public void addNiceApp(final int uid) {
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800100 final int err = native_addNiceApp(uid);
Ken Chenf5f51332022-01-28 10:08:16 +0800101 maybeThrow(err, "Unable to add nice app");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800102 }
103
Ken Chenf5f51332022-01-28 10:08:16 +0800104 /**
105 * Remove nice app bandwidth rule for specific app
106 *
107 * @param uid uid of target app
Ken Chenf5f51332022-01-28 10:08:16 +0800108 * @throws ServiceSpecificException in case of failure, with an error code indicating the
109 * cause of the failure.
110 */
Lorenzo Colitti82244fd2022-03-04 23:15:00 +0900111 public void removeNiceApp(final int uid) {
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800112 final int err = native_removeNiceApp(uid);
Ken Chenf5f51332022-01-28 10:08:16 +0800113 maybeThrow(err, "Unable to remove nice app");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800114 }
115
Ken Chenf5f51332022-01-28 10:08:16 +0800116 /**
117 * Set target firewall child chain
118 *
119 * @param childChain target chain to enable
120 * @param enable whether to enable or disable child chain.
Ken Chenf5f51332022-01-28 10:08:16 +0800121 * @throws ServiceSpecificException in case of failure, with an error code indicating the
122 * cause of the failure.
123 */
Lorenzo Colitti82244fd2022-03-04 23:15:00 +0900124 public void setChildChain(final int childChain, final boolean enable) {
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800125 final int err = native_setChildChain(childChain, enable);
Ken Chenf5f51332022-01-28 10:08:16 +0800126 maybeThrow(err, "Unable to set child chain");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800127 }
128
129 /**
130 * Replaces the contents of the specified UID-based firewall chain.
131 *
132 * The chain may be an allowlist chain or a denylist chain. A denylist chain contains DROP
133 * rules for the specified UIDs and a RETURN rule at the end. An allowlist chain contains RETURN
Ken Chenf5f51332022-01-28 10:08:16 +0800134 * rules for the system UID range (0 to {@code UID_APP} - 1), RETURN rules for the specified
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800135 * UIDs, and a DROP rule at the end. The chain will be created if it does not exist.
136 *
Ken Chenf5f51332022-01-28 10:08:16 +0800137 * @param chainName The name of the chain to replace.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800138 * @param isAllowlist Whether this is an allowlist or denylist chain.
Ken Chenf5f51332022-01-28 10:08:16 +0800139 * @param uids The list of UIDs to allow/deny.
140 * @return 0 if the chain was successfully replaced, errno otherwise.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800141 */
142 public int replaceUidChain(final String chainName, final boolean isAllowlist,
Lorenzo Colitti82244fd2022-03-04 23:15:00 +0900143 final int[] uids) {
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800144 final int err = native_replaceUidChain(chainName, isAllowlist, uids);
145 if (err != 0) {
146 Log.e(TAG, "replaceUidChain failed: " + Os.strerror(-err));
147 }
148 return -err;
149 }
150
Ken Chenf5f51332022-01-28 10:08:16 +0800151 /**
152 * Set firewall rule for uid
153 *
154 * @param childChain target chain
155 * @param uid uid to allow/deny
156 * @param firewallRule either FIREWALL_RULE_ALLOW or FIREWALL_RULE_DENY
Ken Chenf5f51332022-01-28 10:08:16 +0800157 * @throws ServiceSpecificException in case of failure, with an error code indicating the
158 * cause of the failure.
159 */
Lorenzo Colitti82244fd2022-03-04 23:15:00 +0900160 public void setUidRule(final int childChain, final int uid, final int firewallRule) {
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800161 final int err = native_setUidRule(childChain, uid, firewallRule);
Ken Chenf5f51332022-01-28 10:08:16 +0800162 maybeThrow(err, "Unable to set uid rule");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800163 }
164
165 /**
166 * Add ingress interface filtering rules to a list of UIDs
167 *
168 * For a given uid, once a filtering rule is added, the kernel will only allow packets from the
169 * allowed interface and loopback to be sent to the list of UIDs.
170 *
171 * Calling this method on one or more UIDs with an existing filtering rule but a different
172 * interface name will result in the filtering rule being updated to allow the new interface
173 * instead. Otherwise calling this method will not affect existing rules set on other UIDs.
174 *
175 * @param ifName the name of the interface on which the filtering rules will allow packets to
Ken Chenf5f51332022-01-28 10:08:16 +0800176 * be received.
177 * @param uids an array of UIDs which the filtering rules will be set
178 * @throws RemoteException when netd has crashed.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800179 * @throws ServiceSpecificException in case of failure, with an error code indicating the
Ken Chenf5f51332022-01-28 10:08:16 +0800180 * cause of the failure.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800181 */
Ken Chenf5f51332022-01-28 10:08:16 +0800182 public void addUidInterfaceRules(final String ifName, final int[] uids) throws RemoteException {
183 if (USE_NETD) {
184 mNetd.firewallAddUidInterfaceRules(ifName, uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800185 return;
186 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800187 final int err = native_addUidInterfaceRules(ifName, uids);
Ken Chenf5f51332022-01-28 10:08:16 +0800188 maybeThrow(err, "Unable to add uid interface rules");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800189 }
190
191 /**
192 * Remove ingress interface filtering rules from a list of UIDs
193 *
194 * Clear the ingress interface filtering rules from the list of UIDs which were previously set
195 * by addUidInterfaceRules(). Ignore any uid which does not have filtering rule.
196 *
197 * @param uids an array of UIDs from which the filtering rules will be removed
Ken Chenf5f51332022-01-28 10:08:16 +0800198 * @throws RemoteException when netd has crashed.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800199 * @throws ServiceSpecificException in case of failure, with an error code indicating the
Ken Chenf5f51332022-01-28 10:08:16 +0800200 * cause of the failure.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800201 */
Ken Chenf5f51332022-01-28 10:08:16 +0800202 public void removeUidInterfaceRules(final int[] uids) throws RemoteException {
203 if (USE_NETD) {
204 mNetd.firewallRemoveUidInterfaceRules(uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800205 return;
206 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800207 final int err = native_removeUidInterfaceRules(uids);
Ken Chenf5f51332022-01-28 10:08:16 +0800208 maybeThrow(err, "Unable to remove uid interface rules");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800209 }
210
Ken Chenf5f51332022-01-28 10:08:16 +0800211 /**
212 * Request netd to change the current active network stats map.
213 *
214 * @throws RemoteException when netd has crashed.
215 * @throws ServiceSpecificException in case of failure, with an error code indicating the
216 * cause of the failure.
217 */
218 public void swapActiveStatsMap() throws RemoteException {
219 if (USE_NETD) {
220 mNetd.trafficSwapActiveStatsMap();
Wayne Ma2fde98c2022-01-17 18:04:05 +0800221 return;
222 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800223 final int err = native_swapActiveStatsMap();
Ken Chenf5f51332022-01-28 10:08:16 +0800224 maybeThrow(err, "Unable to swap active stats map");
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800225 }
226
Ken Chenf5f51332022-01-28 10:08:16 +0800227 /**
228 * Assigns android.permission.INTERNET and/or android.permission.UPDATE_DEVICE_STATS to the uids
229 * specified. Or remove all permissions from the uids.
230 *
231 * @param permissions The permission to grant, it could be either PERMISSION_INTERNET and/or
232 * PERMISSION_UPDATE_DEVICE_STATS. If the permission is NO_PERMISSIONS, then
233 * revoke all permissions for the uids.
234 * @param uids uid of users to grant permission
235 * @throws RemoteException when netd has crashed.
236 */
237 public void setNetPermForUids(final int permissions, final int[] uids) throws RemoteException {
238 if (USE_NETD) {
239 mNetd.trafficSetNetPermForUids(permissions, uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800240 return;
241 }
242 native_setPermissionForUids(permissions, uids);
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800243 }
244
Ken Chene6d511f2022-01-25 11:10:42 +0800245 /**
246 * Dump BPF maps
247 *
248 * @param fd file descriptor to output
249 * @throws IOException when file descriptor is invalid.
250 * @throws ServiceSpecificException when the method is called on an unsupported device.
251 */
252 public void dump(final FileDescriptor fd, boolean verbose)
253 throws IOException, ServiceSpecificException {
254 if (USE_NETD) {
255 throw new ServiceSpecificException(
256 EOPNOTSUPP, "dumpsys connectivity trafficcontroller dump not available on pre-T"
257 + " devices, use dumpsys netd trafficcontroller instead.");
258 }
259 native_dump(fd, verbose);
260 }
261
Wayne Ma790c83e2022-01-13 10:35:05 +0800262 private static native void native_init();
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800263 private native int native_addNaughtyApp(int uid);
264 private native int native_removeNaughtyApp(int uid);
265 private native int native_addNiceApp(int uid);
266 private native int native_removeNiceApp(int uid);
267 private native int native_setChildChain(int childChain, boolean enable);
268 private native int native_replaceUidChain(String name, boolean isAllowlist, int[] uids);
269 private native int native_setUidRule(int childChain, int uid, int firewallRule);
270 private native int native_addUidInterfaceRules(String ifName, int[] uids);
271 private native int native_removeUidInterfaceRules(int[] uids);
272 private native int native_swapActiveStatsMap();
Wayne Ma2fde98c2022-01-17 18:04:05 +0800273 private native void native_setPermissionForUids(int permissions, int[] uids);
Ken Chene6d511f2022-01-25 11:10:42 +0800274 private native void native_dump(FileDescriptor fd, boolean verbose);
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800275}