blob: f20159ca0b6b95d368441fceaa37de96ab160b4e [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
Junyu Lai29b7b632023-08-23 17:35:17 +080019import static android.net.BpfNetMapsConstants.CONFIGURATION_MAP_PATH;
20import static android.net.BpfNetMapsConstants.COOKIE_TAG_MAP_PATH;
21import static android.net.BpfNetMapsConstants.CURRENT_STATS_MAP_CONFIGURATION_KEY;
Ken Chen24330172023-10-20 13:02:14 +080022import static android.net.BpfNetMapsConstants.DATA_SAVER_DISABLED;
23import static android.net.BpfNetMapsConstants.DATA_SAVER_ENABLED;
24import static android.net.BpfNetMapsConstants.DATA_SAVER_ENABLED_KEY;
25import static android.net.BpfNetMapsConstants.DATA_SAVER_ENABLED_MAP_PATH;
Junyu Lai29b7b632023-08-23 17:35:17 +080026import static android.net.BpfNetMapsConstants.HAPPY_BOX_MATCH;
27import static android.net.BpfNetMapsConstants.IIF_MATCH;
Motomu Utsumi77b49992023-10-23 17:06:12 +090028import static android.net.BpfNetMapsConstants.INGRESS_DISCARD_MAP_PATH;
Junyu Lai29b7b632023-08-23 17:35:17 +080029import static android.net.BpfNetMapsConstants.LOCKDOWN_VPN_MATCH;
30import static android.net.BpfNetMapsConstants.PENALTY_BOX_MATCH;
31import static android.net.BpfNetMapsConstants.UID_OWNER_MAP_PATH;
32import static android.net.BpfNetMapsConstants.UID_PERMISSION_MAP_PATH;
33import static android.net.BpfNetMapsConstants.UID_RULES_CONFIGURATION_KEY;
Junyu Lai626045a2023-08-28 18:49:44 +080034import static android.net.BpfNetMapsUtils.PRE_T;
Junyu Lai29b7b632023-08-23 17:35:17 +080035import static android.net.BpfNetMapsUtils.getMatchByFirewallChain;
Junyu Laie0031522023-08-29 18:32:57 +080036import static android.net.BpfNetMapsUtils.isFirewallAllowList;
Junyu Lai29b7b632023-08-23 17:35:17 +080037import static android.net.BpfNetMapsUtils.matchToString;
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +000038import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
39import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
40import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_1;
41import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_2;
42import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_3;
43import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE;
44import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED;
45import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY;
Motomu Utsumi40230be2022-07-05 03:27:35 +000046import static android.net.ConnectivityManager.FIREWALL_RULE_ALLOW;
47import static android.net.ConnectivityManager.FIREWALL_RULE_DENY;
Motomu Utsumi65271202022-07-05 08:21:41 +000048import static android.net.INetd.PERMISSION_INTERNET;
Motomu Utsumi310850f2022-09-02 12:48:20 +090049import static android.net.INetd.PERMISSION_NONE;
Motomu Utsumi65271202022-07-05 08:21:41 +000050import static android.net.INetd.PERMISSION_UNINSTALLED;
Motomu Utsumi310850f2022-09-02 12:48:20 +090051import static android.net.INetd.PERMISSION_UPDATE_DEVICE_STATS;
Motomu Utsumi18b287d2022-06-19 10:45:30 +000052import static android.system.OsConstants.EINVAL;
Motomu Utsumi5f52f4f2022-06-30 03:31:09 +000053import static android.system.OsConstants.ENODEV;
Motomu Utsumi60ed3be2022-06-24 10:38:57 +000054import static android.system.OsConstants.ENOENT;
Ken Chene6d511f2022-01-25 11:10:42 +080055import static android.system.OsConstants.EOPNOTSUPP;
56
Motomu Utsumi166f9662022-09-01 10:35:29 +090057import static com.android.server.ConnectivityStatsLog.NETWORK_BPF_MAP_INFO;
58
59import android.app.StatsManager;
Motomu Utsumif688eeb2022-07-22 03:47:35 +000060import android.content.Context;
Junyu Lai626045a2023-08-28 18:49:44 +080061import android.net.BpfNetMapsReader;
Wayne Ma2fde98c2022-01-17 18:04:05 +080062import android.net.INetd;
Junyu Lai626045a2023-08-28 18:49:44 +080063import android.net.UidOwnerValue;
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +000064import android.os.Build;
Wayne Ma2fde98c2022-01-17 18:04:05 +080065import android.os.RemoteException;
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080066import android.os.ServiceSpecificException;
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +000067import android.system.ErrnoException;
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080068import android.system.Os;
Motomu Utsumi1a477b02022-08-23 15:14:56 +090069import android.util.ArraySet;
Motomu Utsumi310850f2022-09-02 12:48:20 +090070import android.util.IndentingPrintWriter;
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080071import android.util.Log;
Motomu Utsumi310850f2022-09-02 12:48:20 +090072import android.util.Pair;
Motomu Utsumi166f9662022-09-01 10:35:29 +090073import android.util.StatsEvent;
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080074
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +000075import androidx.annotation.RequiresApi;
76
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +000077import com.android.internal.annotations.VisibleForTesting;
Motomu Utsumi166f9662022-09-01 10:35:29 +090078import com.android.modules.utils.BackgroundThread;
Ken Chenf5f51332022-01-28 10:08:16 +080079import com.android.modules.utils.build.SdkLevel;
Motomu Utsumi310850f2022-09-02 12:48:20 +090080import com.android.net.module.util.BpfDump;
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +000081import com.android.net.module.util.BpfMap;
Motomu Utsumif688eeb2022-07-22 03:47:35 +000082import com.android.net.module.util.DeviceConfigUtils;
Motomu Utsumi73599a52022-08-24 11:59:21 +090083import com.android.net.module.util.IBpfMap;
Motomu Utsumi166f9662022-09-01 10:35:29 +090084import com.android.net.module.util.Struct;
Maciej Żenczykowski785793f2022-09-17 02:35:20 +000085import com.android.net.module.util.Struct.S32;
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +000086import com.android.net.module.util.Struct.U32;
Motomu Utsumi65271202022-07-05 08:21:41 +000087import com.android.net.module.util.Struct.U8;
Motomu Utsumib9548862022-09-06 16:30:05 +090088import com.android.net.module.util.bpf.CookieTagMapKey;
89import com.android.net.module.util.bpf.CookieTagMapValue;
Motomu Utsumi77b49992023-10-23 17:06:12 +090090import com.android.net.module.util.bpf.IngressDiscardKey;
91import com.android.net.module.util.bpf.IngressDiscardValue;
Ken Chenf5f51332022-01-28 10:08:16 +080092
Ken Chene6d511f2022-01-25 11:10:42 +080093import java.io.FileDescriptor;
94import java.io.IOException;
Motomu Utsumi77b49992023-10-23 17:06:12 +090095import java.net.InetAddress;
Motomu Utsumi310850f2022-09-02 12:48:20 +090096import java.util.Arrays;
Motomu Utsumi166f9662022-09-01 10:35:29 +090097import java.util.List;
Motomu Utsumi9be2ea02022-07-05 06:14:59 +000098import java.util.Set;
Motomu Utsumi310850f2022-09-02 12:48:20 +090099import java.util.StringJoiner;
Ken Chene6d511f2022-01-25 11:10:42 +0800100
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800101/**
102 * BpfNetMaps is responsible for providing traffic controller relevant functionality.
103 *
104 * {@hide}
105 */
106public class BpfNetMaps {
Motomu Utsumi305975f2022-06-27 09:24:32 +0000107 static {
108 if (!PRE_T) {
109 System.loadLibrary("service-connectivity");
110 }
111 }
112
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800113 private static final String TAG = "BpfNetMaps";
Wayne Ma2fde98c2022-01-17 18:04:05 +0800114 private final INetd mNetd;
Motomu Utsumi5f52f4f2022-06-30 03:31:09 +0000115 private final Dependencies mDeps;
Ken Chenf5f51332022-01-28 10:08:16 +0800116 // Use legacy netd for releases before T.
Ken Chenf5f51332022-01-28 10:08:16 +0800117 private static boolean sInitialized = false;
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800118
Motomu Utsumif688eeb2022-07-22 03:47:35 +0000119 private static Boolean sEnableJavaBpfMap = null;
Motomu Utsumi7628ea32023-08-14 11:09:02 +0900120 private static final String BPF_NET_MAPS_FORCE_DISABLE_JAVA_BPF_MAP =
121 "bpf_net_maps_force_disable_java_bpf_map";
Motomu Utsumif688eeb2022-07-22 03:47:35 +0000122
Motomu Utsumi18b287d2022-06-19 10:45:30 +0000123 // Lock for sConfigurationMap entry for UID_RULES_CONFIGURATION_KEY.
124 // This entry is not accessed by others.
125 // BpfNetMaps acquires this lock while sequence of read, modify, and write.
126 private static final Object sUidRulesConfigBpfMapLock = new Object();
127
Motomu Utsumi7abeaa42022-07-20 07:54:18 +0000128 // Lock for sConfigurationMap entry for CURRENT_STATS_MAP_CONFIGURATION_KEY.
129 // BpfNetMaps acquires this lock while sequence of read, modify, and write.
130 // BpfNetMaps is an only writer of this entry.
131 private static final Object sCurrentStatsMapConfigLock = new Object();
132
Motomu Utsumiba2fa152022-07-25 01:57:23 +0000133 private static final long UID_RULES_DEFAULT_CONFIGURATION = 0;
134 private static final long STATS_SELECT_MAP_A = 0;
135 private static final long STATS_SELECT_MAP_B = 1;
136
Maciej Żenczykowskidc886222022-09-17 06:09:22 +0000137 private static IBpfMap<S32, U32> sConfigurationMap = null;
Motomu Utsumi5a68a212022-06-24 10:14:31 +0000138 // BpfMap for UID_OWNER_MAP_PATH. This map is not accessed by others.
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000139 private static IBpfMap<S32, UidOwnerValue> sUidOwnerMap = null;
140 private static IBpfMap<S32, U8> sUidPermissionMap = null;
Motomu Utsumib9548862022-09-06 16:30:05 +0900141 private static IBpfMap<CookieTagMapKey, CookieTagMapValue> sCookieTagMap = null;
Ken Chen24330172023-10-20 13:02:14 +0800142 // TODO: Add BOOL class and replace U8?
143 private static IBpfMap<S32, U8> sDataSaverEnabledMap = null;
Motomu Utsumi77b49992023-10-23 17:06:12 +0900144 private static IBpfMap<IngressDiscardKey, IngressDiscardValue> sIngressDiscardMap = null;
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +0000145
Motomu Utsumi310850f2022-09-02 12:48:20 +0900146 private static final List<Pair<Integer, String>> PERMISSION_LIST = Arrays.asList(
147 Pair.create(PERMISSION_INTERNET, "PERMISSION_INTERNET"),
148 Pair.create(PERMISSION_UPDATE_DEVICE_STATS, "PERMISSION_UPDATE_DEVICE_STATS")
149 );
150
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +0000151 /**
Motomu Utsumif688eeb2022-07-22 03:47:35 +0000152 * Set sEnableJavaBpfMap for test.
153 */
154 @VisibleForTesting
155 public static void setEnableJavaBpfMapForTest(boolean enable) {
156 sEnableJavaBpfMap = enable;
157 }
158
159 /**
Motomu Utsumi305975f2022-06-27 09:24:32 +0000160 * Set configurationMap for test.
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +0000161 */
162 @VisibleForTesting
Maciej Żenczykowskidc886222022-09-17 06:09:22 +0000163 public static void setConfigurationMapForTest(IBpfMap<S32, U32> configurationMap) {
Motomu Utsumi305975f2022-06-27 09:24:32 +0000164 sConfigurationMap = configurationMap;
165 }
166
Motomu Utsumi5a68a212022-06-24 10:14:31 +0000167 /**
168 * Set uidOwnerMap for test.
169 */
170 @VisibleForTesting
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000171 public static void setUidOwnerMapForTest(IBpfMap<S32, UidOwnerValue> uidOwnerMap) {
Motomu Utsumi5a68a212022-06-24 10:14:31 +0000172 sUidOwnerMap = uidOwnerMap;
173 }
174
Motomu Utsumi65271202022-07-05 08:21:41 +0000175 /**
176 * Set uidPermissionMap for test.
177 */
178 @VisibleForTesting
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000179 public static void setUidPermissionMapForTest(IBpfMap<S32, U8> uidPermissionMap) {
Motomu Utsumi65271202022-07-05 08:21:41 +0000180 sUidPermissionMap = uidPermissionMap;
181 }
182
Motomu Utsumib9548862022-09-06 16:30:05 +0900183 /**
184 * Set cookieTagMap for test.
185 */
186 @VisibleForTesting
187 public static void setCookieTagMapForTest(
188 IBpfMap<CookieTagMapKey, CookieTagMapValue> cookieTagMap) {
189 sCookieTagMap = cookieTagMap;
190 }
191
Ken Chen24330172023-10-20 13:02:14 +0800192 /**
193 * Set dataSaverEnabledMap for test.
194 */
195 @VisibleForTesting
196 public static void setDataSaverEnabledMapForTest(IBpfMap<S32, U8> dataSaverEnabledMap) {
197 sDataSaverEnabledMap = dataSaverEnabledMap;
198 }
199
Motomu Utsumi77b49992023-10-23 17:06:12 +0900200 /**
201 * Set ingressDiscardMap for test.
202 */
203 @VisibleForTesting
204 public static void setIngressDiscardMapForTest(
205 IBpfMap<IngressDiscardKey, IngressDiscardValue> ingressDiscardMap) {
206 sIngressDiscardMap = ingressDiscardMap;
207 }
208
Maciej Żenczykowskidc886222022-09-17 06:09:22 +0000209 private static IBpfMap<S32, U32> getConfigurationMap() {
Motomu Utsumi305975f2022-06-27 09:24:32 +0000210 try {
211 return new BpfMap<>(
Maciej Żenczykowskidc886222022-09-17 06:09:22 +0000212 CONFIGURATION_MAP_PATH, BpfMap.BPF_F_RDWR, S32.class, U32.class);
Motomu Utsumi305975f2022-06-27 09:24:32 +0000213 } catch (ErrnoException e) {
214 throw new IllegalStateException("Cannot open netd configuration map", e);
215 }
216 }
217
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000218 private static IBpfMap<S32, UidOwnerValue> getUidOwnerMap() {
Motomu Utsumi5a68a212022-06-24 10:14:31 +0000219 try {
220 return new BpfMap<>(
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000221 UID_OWNER_MAP_PATH, BpfMap.BPF_F_RDWR, S32.class, UidOwnerValue.class);
Motomu Utsumi5a68a212022-06-24 10:14:31 +0000222 } catch (ErrnoException e) {
223 throw new IllegalStateException("Cannot open uid owner map", e);
224 }
225 }
226
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000227 private static IBpfMap<S32, U8> getUidPermissionMap() {
Motomu Utsumi65271202022-07-05 08:21:41 +0000228 try {
229 return new BpfMap<>(
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000230 UID_PERMISSION_MAP_PATH, BpfMap.BPF_F_RDWR, S32.class, U8.class);
Motomu Utsumi65271202022-07-05 08:21:41 +0000231 } catch (ErrnoException e) {
232 throw new IllegalStateException("Cannot open uid permission map", e);
233 }
234 }
235
Motomu Utsumib9548862022-09-06 16:30:05 +0900236 private static IBpfMap<CookieTagMapKey, CookieTagMapValue> getCookieTagMap() {
237 try {
238 return new BpfMap<>(COOKIE_TAG_MAP_PATH, BpfMap.BPF_F_RDWR,
239 CookieTagMapKey.class, CookieTagMapValue.class);
240 } catch (ErrnoException e) {
241 throw new IllegalStateException("Cannot open cookie tag map", e);
242 }
243 }
244
Ken Chen24330172023-10-20 13:02:14 +0800245 private static IBpfMap<S32, U8> getDataSaverEnabledMap() {
246 try {
247 return new BpfMap<>(
248 DATA_SAVER_ENABLED_MAP_PATH, BpfMap.BPF_F_RDWR, S32.class, U8.class);
249 } catch (ErrnoException e) {
250 throw new IllegalStateException("Cannot open data saver enabled map", e);
251 }
252 }
253
Motomu Utsumi77b49992023-10-23 17:06:12 +0900254 private static IBpfMap<IngressDiscardKey, IngressDiscardValue> getIngressDiscardMap() {
255 try {
256 return new BpfMap<>(INGRESS_DISCARD_MAP_PATH, BpfMap.BPF_F_RDWR,
257 IngressDiscardKey.class, IngressDiscardValue.class);
258 } catch (ErrnoException e) {
259 throw new IllegalStateException("Cannot open ingress discard map", e);
260 }
261 }
262
Motomu Utsumiba2fa152022-07-25 01:57:23 +0000263 private static void initBpfMaps() {
Motomu Utsumi305975f2022-06-27 09:24:32 +0000264 if (sConfigurationMap == null) {
265 sConfigurationMap = getConfigurationMap();
266 }
Motomu Utsumiba2fa152022-07-25 01:57:23 +0000267 try {
268 sConfigurationMap.updateEntry(UID_RULES_CONFIGURATION_KEY,
269 new U32(UID_RULES_DEFAULT_CONFIGURATION));
270 } catch (ErrnoException e) {
271 throw new IllegalStateException("Failed to initialize uid rules configuration", e);
272 }
273 try {
274 sConfigurationMap.updateEntry(CURRENT_STATS_MAP_CONFIGURATION_KEY,
275 new U32(STATS_SELECT_MAP_A));
276 } catch (ErrnoException e) {
277 throw new IllegalStateException("Failed to initialize current stats configuration", e);
278 }
279
Motomu Utsumi5a68a212022-06-24 10:14:31 +0000280 if (sUidOwnerMap == null) {
281 sUidOwnerMap = getUidOwnerMap();
282 }
Motomu Utsumiba2fa152022-07-25 01:57:23 +0000283 try {
284 sUidOwnerMap.clear();
285 } catch (ErrnoException e) {
286 throw new IllegalStateException("Failed to initialize uid owner map", e);
287 }
Motomu Utsumi65271202022-07-05 08:21:41 +0000288
289 if (sUidPermissionMap == null) {
290 sUidPermissionMap = getUidPermissionMap();
291 }
Motomu Utsumib9548862022-09-06 16:30:05 +0900292
293 if (sCookieTagMap == null) {
294 sCookieTagMap = getCookieTagMap();
295 }
Ken Chen24330172023-10-20 13:02:14 +0800296
297 if (sDataSaverEnabledMap == null) {
298 sDataSaverEnabledMap = getDataSaverEnabledMap();
299 }
300 try {
301 sDataSaverEnabledMap.updateEntry(DATA_SAVER_ENABLED_KEY, new U8(DATA_SAVER_DISABLED));
302 } catch (ErrnoException e) {
303 throw new IllegalStateException("Failed to initialize data saver configuration", e);
304 }
Motomu Utsumi77b49992023-10-23 17:06:12 +0900305
306 if (sIngressDiscardMap == null) {
307 sIngressDiscardMap = getIngressDiscardMap();
308 }
309 try {
310 sIngressDiscardMap.clear();
311 } catch (ErrnoException e) {
312 throw new IllegalStateException("Failed to initialize ingress discard map", e);
313 }
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +0000314 }
315
Ken Chenf5f51332022-01-28 10:08:16 +0800316 /**
317 * Initializes the class if it is not already initialized. This method will open maps but not
318 * cause any other effects. This method may be called multiple times on any thread.
319 */
Motomu Utsumif688eeb2022-07-22 03:47:35 +0000320 private static synchronized void ensureInitialized(final Context context) {
Ken Chenf5f51332022-01-28 10:08:16 +0800321 if (sInitialized) return;
Motomu Utsumif688eeb2022-07-22 03:47:35 +0000322 if (sEnableJavaBpfMap == null) {
Maciej Żenczykowskie7ebb152022-12-27 10:57:38 +0000323 sEnableJavaBpfMap = SdkLevel.isAtLeastU() ||
Motomu Utsumied4e7ec2023-09-13 14:58:32 +0900324 DeviceConfigUtils.isTetheringFeatureNotChickenedOut(context,
Motomu Utsumi7628ea32023-08-14 11:09:02 +0900325 BPF_NET_MAPS_FORCE_DISABLE_JAVA_BPF_MAP);
Motomu Utsumif688eeb2022-07-22 03:47:35 +0000326 }
327 Log.d(TAG, "BpfNetMaps is initialized with sEnableJavaBpfMap=" + sEnableJavaBpfMap);
328
Motomu Utsumiba2fa152022-07-25 01:57:23 +0000329 initBpfMaps();
Motomu Utsumid95a0da2022-09-03 00:40:30 +0900330 native_init(!sEnableJavaBpfMap /* startSkDestroyListener */);
Ken Chenf5f51332022-01-28 10:08:16 +0800331 sInitialized = true;
Wayne Ma2fde98c2022-01-17 18:04:05 +0800332 }
333
Motomu Utsumid95a0da2022-09-03 00:40:30 +0900334 public boolean isSkDestroyListenerRunning() {
335 return !sEnableJavaBpfMap;
336 }
337
Motomu Utsumi5f52f4f2022-06-30 03:31:09 +0000338 /**
339 * Dependencies of BpfNetMaps, for injection in tests.
340 */
341 @VisibleForTesting
342 public static class Dependencies {
343 /**
344 * Get interface index.
345 */
346 public int getIfIndex(final String ifName) {
347 return Os.if_nametoindex(ifName);
348 }
Motomu Utsumi7abeaa42022-07-20 07:54:18 +0000349
350 /**
Motomu Utsumi77b49992023-10-23 17:06:12 +0900351 * Get interface name
352 */
353 public String getIfName(final int ifIndex) {
354 return Os.if_indextoname(ifIndex);
355 }
356
357 /**
Motomu Utsumi7abeaa42022-07-20 07:54:18 +0000358 * Call synchronize_rcu()
359 */
360 public int synchronizeKernelRCU() {
361 return native_synchronizeKernelRCU();
362 }
Motomu Utsumi166f9662022-09-01 10:35:29 +0900363
364 /**
365 * Build Stats Event for NETWORK_BPF_MAP_INFO atom
366 */
367 public StatsEvent buildStatsEvent(final int cookieTagMapSize, final int uidOwnerMapSize,
368 final int uidPermissionMapSize) {
369 return ConnectivityStatsLog.buildStatsEvent(NETWORK_BPF_MAP_INFO, cookieTagMapSize,
370 uidOwnerMapSize, uidPermissionMapSize);
371 }
Motomu Utsumi5f52f4f2022-06-30 03:31:09 +0000372 }
373
markchien49e944c2022-03-01 15:22:20 +0800374 /** Constructor used after T that doesn't need to use netd anymore. */
Junyu Lai626045a2023-08-28 18:49:44 +0800375 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Motomu Utsumif688eeb2022-07-22 03:47:35 +0000376 public BpfNetMaps(final Context context) {
377 this(context, null);
markchien49e944c2022-03-01 15:22:20 +0800378
Motomu Utsumi25cf86f2022-06-27 08:50:19 +0000379 if (PRE_T) throw new IllegalArgumentException("BpfNetMaps need to use netd before T");
markchien49e944c2022-03-01 15:22:20 +0800380 }
381
Motomu Utsumif688eeb2022-07-22 03:47:35 +0000382 public BpfNetMaps(final Context context, final INetd netd) {
383 this(context, netd, new Dependencies());
Motomu Utsumi5f52f4f2022-06-30 03:31:09 +0000384 }
385
386 @VisibleForTesting
Motomu Utsumif688eeb2022-07-22 03:47:35 +0000387 public BpfNetMaps(final Context context, final INetd netd, final Dependencies deps) {
Motomu Utsumi305975f2022-06-27 09:24:32 +0000388 if (!PRE_T) {
Motomu Utsumif688eeb2022-07-22 03:47:35 +0000389 ensureInitialized(context);
Motomu Utsumi305975f2022-06-27 09:24:32 +0000390 }
Wayne Ma2fde98c2022-01-17 18:04:05 +0800391 mNetd = netd;
Motomu Utsumi5f52f4f2022-06-30 03:31:09 +0000392 mDeps = deps;
Wayne Ma790c83e2022-01-13 10:35:05 +0800393 }
394
Ken Chenf5f51332022-01-28 10:08:16 +0800395 private void maybeThrow(final int err, final String msg) {
396 if (err != 0) {
397 throw new ServiceSpecificException(err, msg + ": " + Os.strerror(err));
398 }
399 }
400
Motomu Utsumi25cf86f2022-06-27 08:50:19 +0000401 private void throwIfPreT(final String msg) {
402 if (PRE_T) {
Motomu Utsumi18b287d2022-06-19 10:45:30 +0000403 throw new UnsupportedOperationException(msg);
404 }
405 }
406
Motomu Utsumi60ed3be2022-06-24 10:38:57 +0000407 private void removeRule(final int uid, final long match, final String caller) {
408 try {
409 synchronized (sUidOwnerMap) {
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000410 final UidOwnerValue oldMatch = sUidOwnerMap.getValue(new S32(uid));
Motomu Utsumi60ed3be2022-06-24 10:38:57 +0000411
412 if (oldMatch == null) {
413 throw new ServiceSpecificException(ENOENT,
414 "sUidOwnerMap does not have entry for uid: " + uid);
415 }
416
417 final UidOwnerValue newMatch = new UidOwnerValue(
418 (match == IIF_MATCH) ? 0 : oldMatch.iif,
419 oldMatch.rule & ~match
420 );
421
422 if (newMatch.rule == 0) {
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000423 sUidOwnerMap.deleteEntry(new S32(uid));
Motomu Utsumi60ed3be2022-06-24 10:38:57 +0000424 } else {
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000425 sUidOwnerMap.updateEntry(new S32(uid), newMatch);
Motomu Utsumi60ed3be2022-06-24 10:38:57 +0000426 }
427 }
428 } catch (ErrnoException e) {
429 throw new ServiceSpecificException(e.errno,
430 caller + " failed to remove rule: " + Os.strerror(e.errno));
431 }
432 }
433
Maciej Żenczykowski6c1c6bb2022-09-16 06:55:33 +0000434 private void addRule(final int uid, final long match, final int iif, final String caller) {
Motomu Utsumi389278e2022-06-28 07:05:05 +0000435 if (match != IIF_MATCH && iif != 0) {
436 throw new ServiceSpecificException(EINVAL,
437 "Non-interface match must have zero interface index");
438 }
439
440 try {
441 synchronized (sUidOwnerMap) {
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000442 final UidOwnerValue oldMatch = sUidOwnerMap.getValue(new S32(uid));
Motomu Utsumi389278e2022-06-28 07:05:05 +0000443
444 final UidOwnerValue newMatch;
445 if (oldMatch != null) {
446 newMatch = new UidOwnerValue(
447 (match == IIF_MATCH) ? iif : oldMatch.iif,
448 oldMatch.rule | match
449 );
450 } else {
451 newMatch = new UidOwnerValue(
452 iif,
453 match
454 );
455 }
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000456 sUidOwnerMap.updateEntry(new S32(uid), newMatch);
Motomu Utsumi389278e2022-06-28 07:05:05 +0000457 }
458 } catch (ErrnoException e) {
459 throw new ServiceSpecificException(e.errno,
460 caller + " failed to add rule: " + Os.strerror(e.errno));
461 }
462 }
463
464 private void addRule(final int uid, final long match, final String caller) {
465 addRule(uid, match, 0 /* iif */, caller);
466 }
467
Ken Chenf5f51332022-01-28 10:08:16 +0800468 /**
469 * Add naughty app bandwidth rule for specific app
470 *
471 * @param uid uid of target app
Ken Chenf5f51332022-01-28 10:08:16 +0800472 * @throws ServiceSpecificException in case of failure, with an error code indicating the
473 * cause of the failure.
474 */
Junyu Lai626045a2023-08-28 18:49:44 +0800475 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Lorenzo Colitti82244fd2022-03-04 23:15:00 +0900476 public void addNaughtyApp(final int uid) {
Motomu Utsumi389278e2022-06-28 07:05:05 +0000477 throwIfPreT("addNaughtyApp is not available on pre-T devices");
Motomu Utsumi55c282e2022-08-03 06:25:33 +0000478
479 if (sEnableJavaBpfMap) {
480 addRule(uid, PENALTY_BOX_MATCH, "addNaughtyApp");
481 } else {
482 final int err = native_addNaughtyApp(uid);
483 maybeThrow(err, "Unable to add naughty app");
484 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800485 }
486
Ken Chenf5f51332022-01-28 10:08:16 +0800487 /**
488 * Remove naughty app bandwidth rule for specific app
489 *
490 * @param uid uid of target app
Ken Chenf5f51332022-01-28 10:08:16 +0800491 * @throws ServiceSpecificException in case of failure, with an error code indicating the
492 * cause of the failure.
493 */
Junyu Lai626045a2023-08-28 18:49:44 +0800494 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Lorenzo Colitti82244fd2022-03-04 23:15:00 +0900495 public void removeNaughtyApp(final int uid) {
Motomu Utsumi60ed3be2022-06-24 10:38:57 +0000496 throwIfPreT("removeNaughtyApp is not available on pre-T devices");
Motomu Utsumi878ce0d2022-08-03 06:22:42 +0000497
498 if (sEnableJavaBpfMap) {
499 removeRule(uid, PENALTY_BOX_MATCH, "removeNaughtyApp");
500 } else {
501 final int err = native_removeNaughtyApp(uid);
502 maybeThrow(err, "Unable to remove naughty app");
503 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800504 }
505
Ken Chenf5f51332022-01-28 10:08:16 +0800506 /**
507 * Add nice app bandwidth rule for specific app
508 *
509 * @param uid uid of target app
Ken Chenf5f51332022-01-28 10:08:16 +0800510 * @throws ServiceSpecificException in case of failure, with an error code indicating the
511 * cause of the failure.
512 */
Junyu Lai626045a2023-08-28 18:49:44 +0800513 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Lorenzo Colitti82244fd2022-03-04 23:15:00 +0900514 public void addNiceApp(final int uid) {
Motomu Utsumi55630d02022-06-29 07:46:52 +0000515 throwIfPreT("addNiceApp is not available on pre-T devices");
Motomu Utsumi7f19df92022-08-03 06:29:59 +0000516
517 if (sEnableJavaBpfMap) {
518 addRule(uid, HAPPY_BOX_MATCH, "addNiceApp");
519 } else {
520 final int err = native_addNiceApp(uid);
521 maybeThrow(err, "Unable to add nice app");
522 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800523 }
524
Ken Chenf5f51332022-01-28 10:08:16 +0800525 /**
526 * Remove nice app bandwidth rule for specific app
527 *
528 * @param uid uid of target app
Ken Chenf5f51332022-01-28 10:08:16 +0800529 * @throws ServiceSpecificException in case of failure, with an error code indicating the
530 * cause of the failure.
531 */
Junyu Lai626045a2023-08-28 18:49:44 +0800532 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Lorenzo Colitti82244fd2022-03-04 23:15:00 +0900533 public void removeNiceApp(final int uid) {
Motomu Utsumi7392eb42022-06-29 03:53:03 +0000534 throwIfPreT("removeNiceApp is not available on pre-T devices");
Motomu Utsumi5f15f752022-08-03 06:27:51 +0000535
536 if (sEnableJavaBpfMap) {
537 removeRule(uid, HAPPY_BOX_MATCH, "removeNiceApp");
538 } else {
539 final int err = native_removeNiceApp(uid);
540 maybeThrow(err, "Unable to remove nice app");
541 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800542 }
543
Ken Chenf5f51332022-01-28 10:08:16 +0800544 /**
545 * Set target firewall child chain
546 *
547 * @param childChain target chain to enable
548 * @param enable whether to enable or disable child chain.
Motomu Utsumi18b287d2022-06-19 10:45:30 +0000549 * @throws UnsupportedOperationException if called on pre-T devices.
Ken Chenf5f51332022-01-28 10:08:16 +0800550 * @throws ServiceSpecificException in case of failure, with an error code indicating the
551 * cause of the failure.
552 */
Junyu Lai626045a2023-08-28 18:49:44 +0800553 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Lorenzo Colitti82244fd2022-03-04 23:15:00 +0900554 public void setChildChain(final int childChain, final boolean enable) {
Motomu Utsumi25cf86f2022-06-27 08:50:19 +0000555 throwIfPreT("setChildChain is not available on pre-T devices");
Motomu Utsumi18b287d2022-06-19 10:45:30 +0000556
Motomu Utsumie057dd42022-08-03 01:23:49 +0000557 if (sEnableJavaBpfMap) {
558 final long match = getMatchByFirewallChain(childChain);
559 try {
560 synchronized (sUidRulesConfigBpfMapLock) {
561 final U32 config = sConfigurationMap.getValue(UID_RULES_CONFIGURATION_KEY);
562 final long newConfig = enable ? (config.val | match) : (config.val & ~match);
563 sConfigurationMap.updateEntry(UID_RULES_CONFIGURATION_KEY, new U32(newConfig));
564 }
565 } catch (ErrnoException e) {
566 throw new ServiceSpecificException(e.errno,
567 "Unable to set child chain: " + Os.strerror(e.errno));
Motomu Utsumi18b287d2022-06-19 10:45:30 +0000568 }
Motomu Utsumie057dd42022-08-03 01:23:49 +0000569 } else {
570 final int err = native_setChildChain(childChain, enable);
571 maybeThrow(err, "Unable to set child chain");
Motomu Utsumi18b287d2022-06-19 10:45:30 +0000572 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800573 }
574
575 /**
Motomu Utsumi25cf86f2022-06-27 08:50:19 +0000576 * Get the specified firewall chain's status.
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +0000577 *
578 * @param childChain target chain
579 * @return {@code true} if chain is enabled, {@code false} if chain is not enabled.
580 * @throws UnsupportedOperationException if called on pre-T devices.
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +0000581 * @throws ServiceSpecificException in case of failure, with an error code indicating the
582 * cause of the failure.
Junyu Lai626045a2023-08-28 18:49:44 +0800583 *
584 * @deprecated Use {@link BpfNetMapsReader#isChainEnabled} instead.
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +0000585 */
Junyu Lai626045a2023-08-28 18:49:44 +0800586 // TODO: Migrate the callers to use {@link BpfNetMapsReader#isChainEnabled} instead.
587 @Deprecated
588 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Motomu Utsumi25cf86f2022-06-27 08:50:19 +0000589 public boolean isChainEnabled(final int childChain) {
Junyu Lai626045a2023-08-28 18:49:44 +0800590 return BpfNetMapsReader.isChainEnabled(sConfigurationMap, childChain);
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +0000591 }
592
Motomu Utsumi1a477b02022-08-23 15:14:56 +0900593 private Set<Integer> asSet(final int[] uids) {
594 final Set<Integer> uidSet = new ArraySet<>();
Motomu Utsumi77b49992023-10-23 17:06:12 +0900595 for (final int uid : uids) {
Motomu Utsumi1a477b02022-08-23 15:14:56 +0900596 uidSet.add(uid);
597 }
598 return uidSet;
599 }
600
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +0000601 /**
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800602 * Replaces the contents of the specified UID-based firewall chain.
Motomu Utsumi9be2ea02022-07-05 06:14:59 +0000603 * Enables the chain for specified uids and disables the chain for non-specified uids.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800604 *
Motomu Utsumi9be2ea02022-07-05 06:14:59 +0000605 * @param chain Target chain.
Ken Chenf5f51332022-01-28 10:08:16 +0800606 * @param uids The list of UIDs to allow/deny.
Motomu Utsumi9be2ea02022-07-05 06:14:59 +0000607 * @throws UnsupportedOperationException if called on pre-T devices.
608 * @throws IllegalArgumentException if {@code chain} is not a valid chain.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800609 */
Junyu Lai626045a2023-08-28 18:49:44 +0800610 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Motomu Utsumi9be2ea02022-07-05 06:14:59 +0000611 public void replaceUidChain(final int chain, final int[] uids) {
612 throwIfPreT("replaceUidChain is not available on pre-T devices");
613
Motomu Utsumic7c16852022-08-03 06:51:41 +0000614 if (sEnableJavaBpfMap) {
615 final long match;
616 try {
617 match = getMatchByFirewallChain(chain);
618 } catch (ServiceSpecificException e) {
619 // Throws IllegalArgumentException to keep the behavior of
620 // ConnectivityManager#replaceFirewallChain API
621 throw new IllegalArgumentException("Invalid firewall chain: " + chain);
Motomu Utsumi5a68a212022-06-24 10:14:31 +0000622 }
Motomu Utsumi1a477b02022-08-23 15:14:56 +0900623 final Set<Integer> uidSet = asSet(uids);
624 final Set<Integer> uidSetToRemoveRule = new ArraySet<>();
Motomu Utsumic7c16852022-08-03 06:51:41 +0000625 try {
626 synchronized (sUidOwnerMap) {
627 sUidOwnerMap.forEach((uid, config) -> {
628 // config could be null if there is a concurrent entry deletion.
Motomu Utsumi8e420ea2022-08-24 18:03:30 +0900629 // http://b/220084230. But sUidOwnerMap update must be done while holding a
630 // lock, so this should not happen.
631 if (config == null) {
632 Log.wtf(TAG, "sUidOwnerMap entry was deleted while holding a lock");
633 } else if (!uidSet.contains((int) uid.val) && (config.rule & match) != 0) {
Motomu Utsumic7c16852022-08-03 06:51:41 +0000634 uidSetToRemoveRule.add((int) uid.val);
635 }
636 });
637
638 for (final int uid : uidSetToRemoveRule) {
639 removeRule(uid, match, "replaceUidChain");
640 }
641 for (final int uid : uids) {
642 addRule(uid, match, "replaceUidChain");
643 }
644 }
645 } catch (ErrnoException | ServiceSpecificException e) {
646 Log.e(TAG, "replaceUidChain failed: " + e);
647 }
648 } else {
649 final int err;
650 switch (chain) {
651 case FIREWALL_CHAIN_DOZABLE:
652 err = native_replaceUidChain("fw_dozable", true /* isAllowList */, uids);
653 break;
654 case FIREWALL_CHAIN_STANDBY:
655 err = native_replaceUidChain("fw_standby", false /* isAllowList */, uids);
656 break;
657 case FIREWALL_CHAIN_POWERSAVE:
658 err = native_replaceUidChain("fw_powersave", true /* isAllowList */, uids);
659 break;
660 case FIREWALL_CHAIN_RESTRICTED:
661 err = native_replaceUidChain("fw_restricted", true /* isAllowList */, uids);
662 break;
663 case FIREWALL_CHAIN_LOW_POWER_STANDBY:
664 err = native_replaceUidChain(
665 "fw_low_power_standby", true /* isAllowList */, uids);
666 break;
667 case FIREWALL_CHAIN_OEM_DENY_1:
668 err = native_replaceUidChain("fw_oem_deny_1", false /* isAllowList */, uids);
669 break;
670 case FIREWALL_CHAIN_OEM_DENY_2:
671 err = native_replaceUidChain("fw_oem_deny_2", false /* isAllowList */, uids);
672 break;
673 case FIREWALL_CHAIN_OEM_DENY_3:
674 err = native_replaceUidChain("fw_oem_deny_3", false /* isAllowList */, uids);
675 break;
676 default:
677 throw new IllegalArgumentException("replaceFirewallChain with invalid chain: "
678 + chain);
679 }
680 if (err != 0) {
681 Log.e(TAG, "replaceUidChain failed: " + Os.strerror(-err));
682 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800683 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800684 }
685
Ken Chenf5f51332022-01-28 10:08:16 +0800686 /**
687 * Set firewall rule for uid
688 *
689 * @param childChain target chain
690 * @param uid uid to allow/deny
691 * @param firewallRule either FIREWALL_RULE_ALLOW or FIREWALL_RULE_DENY
Ken Chenf5f51332022-01-28 10:08:16 +0800692 * @throws ServiceSpecificException in case of failure, with an error code indicating the
693 * cause of the failure.
694 */
Junyu Lai626045a2023-08-28 18:49:44 +0800695 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Lorenzo Colitti82244fd2022-03-04 23:15:00 +0900696 public void setUidRule(final int childChain, final int uid, final int firewallRule) {
Motomu Utsumi40230be2022-07-05 03:27:35 +0000697 throwIfPreT("setUidRule is not available on pre-T devices");
698
Motomu Utsumi381ad9e2022-08-03 06:42:47 +0000699 if (sEnableJavaBpfMap) {
700 final long match = getMatchByFirewallChain(childChain);
701 final boolean isAllowList = isFirewallAllowList(childChain);
702 final boolean add = (firewallRule == FIREWALL_RULE_ALLOW && isAllowList)
703 || (firewallRule == FIREWALL_RULE_DENY && !isAllowList);
Motomu Utsumi40230be2022-07-05 03:27:35 +0000704
Motomu Utsumi381ad9e2022-08-03 06:42:47 +0000705 if (add) {
706 addRule(uid, match, "setUidRule");
707 } else {
708 removeRule(uid, match, "setUidRule");
709 }
Motomu Utsumi40230be2022-07-05 03:27:35 +0000710 } else {
Motomu Utsumi381ad9e2022-08-03 06:42:47 +0000711 final int err = native_setUidRule(childChain, uid, firewallRule);
712 maybeThrow(err, "Unable to set uid rule");
Motomu Utsumi5a68a212022-06-24 10:14:31 +0000713 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800714 }
715
716 /**
Motomu Utsumi56c412a2023-01-19 15:58:39 +0900717 * Get firewall rule of specified firewall chain on specified uid.
718 *
719 * @param childChain target chain
720 * @param uid target uid
721 * @return either FIREWALL_RULE_ALLOW or FIREWALL_RULE_DENY
722 * @throws UnsupportedOperationException if called on pre-T devices.
723 * @throws ServiceSpecificException in case of failure, with an error code indicating the
724 * cause of the failure.
Junyu Lai626045a2023-08-28 18:49:44 +0800725 *
726 * @deprecated use {@link BpfNetMapsReader#getUidRule} instead.
Motomu Utsumi56c412a2023-01-19 15:58:39 +0900727 */
Junyu Lai626045a2023-08-28 18:49:44 +0800728 // TODO: Migrate the callers to use {@link BpfNetMapsReader#getUidRule} instead.
Motomu Utsumi56c412a2023-01-19 15:58:39 +0900729 public int getUidRule(final int childChain, final int uid) {
Junyu Lai626045a2023-08-28 18:49:44 +0800730 return BpfNetMapsReader.getUidRule(sUidOwnerMap, childChain, uid);
Motomu Utsumi56c412a2023-01-19 15:58:39 +0900731 }
732
Motomu Utsumid44a33a2023-03-28 18:08:12 +0900733 private Set<Integer> getUidsMatchEnabled(final int childChain) throws ErrnoException {
734 final long match = getMatchByFirewallChain(childChain);
735 Set<Integer> uids = new ArraySet<>();
736 synchronized (sUidOwnerMap) {
737 sUidOwnerMap.forEach((uid, val) -> {
738 if (val == null) {
739 Log.wtf(TAG, "sUidOwnerMap entry was deleted while holding a lock");
740 } else {
741 if ((val.rule & match) != 0) {
742 uids.add(uid.val);
743 }
744 }
745 });
746 }
747 return uids;
748 }
749
750 /**
751 * Get uids that has FIREWALL_RULE_ALLOW on allowlist chain.
752 * Allowlist means the firewall denies all by default, uids must be explicitly allowed.
753 *
754 * Note that uids that has FIREWALL_RULE_DENY on allowlist chain can not be computed from the
755 * bpf map, since all the uids that does not have explicit FIREWALL_RULE_ALLOW rule in bpf map
756 * are determined to have FIREWALL_RULE_DENY.
757 *
758 * @param childChain target chain
759 * @return Set of uids
760 */
761 public Set<Integer> getUidsWithAllowRuleOnAllowListChain(final int childChain)
762 throws ErrnoException {
763 if (!isFirewallAllowList(childChain)) {
764 throw new IllegalArgumentException("getUidsWithAllowRuleOnAllowListChain is called with"
765 + " denylist chain:" + childChain);
766 }
767 // Corresponding match is enabled for uids that has FIREWALL_RULE_ALLOW on allowlist chain.
768 return getUidsMatchEnabled(childChain);
769 }
770
771 /**
772 * Get uids that has FIREWALL_RULE_DENY on denylist chain.
773 * Denylist means the firewall allows all by default, uids must be explicitly denyed
774 *
775 * Note that uids that has FIREWALL_RULE_ALLOW on denylist chain can not be computed from the
776 * bpf map, since all the uids that does not have explicit FIREWALL_RULE_DENY rule in bpf map
777 * are determined to have the FIREWALL_RULE_ALLOW.
778 *
779 * @param childChain target chain
780 * @return Set of uids
781 */
782 public Set<Integer> getUidsWithDenyRuleOnDenyListChain(final int childChain)
783 throws ErrnoException {
784 if (isFirewallAllowList(childChain)) {
785 throw new IllegalArgumentException("getUidsWithDenyRuleOnDenyListChain is called with"
786 + " allowlist chain:" + childChain);
787 }
788 // Corresponding match is enabled for uids that has FIREWALL_RULE_DENY on denylist chain.
789 return getUidsMatchEnabled(childChain);
790 }
791
Motomu Utsumi56c412a2023-01-19 15:58:39 +0900792 /**
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800793 * Add ingress interface filtering rules to a list of UIDs
794 *
795 * For a given uid, once a filtering rule is added, the kernel will only allow packets from the
796 * allowed interface and loopback to be sent to the list of UIDs.
797 *
798 * Calling this method on one or more UIDs with an existing filtering rule but a different
799 * interface name will result in the filtering rule being updated to allow the new interface
800 * instead. Otherwise calling this method will not affect existing rules set on other UIDs.
801 *
802 * @param ifName the name of the interface on which the filtering rules will allow packets to
Ken Chenf5f51332022-01-28 10:08:16 +0800803 * be received.
804 * @param uids an array of UIDs which the filtering rules will be set
805 * @throws RemoteException when netd has crashed.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800806 * @throws ServiceSpecificException in case of failure, with an error code indicating the
Ken Chenf5f51332022-01-28 10:08:16 +0800807 * cause of the failure.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800808 */
Ken Chenf5f51332022-01-28 10:08:16 +0800809 public void addUidInterfaceRules(final String ifName, final int[] uids) throws RemoteException {
Motomu Utsumi25cf86f2022-06-27 08:50:19 +0000810 if (PRE_T) {
Ken Chenf5f51332022-01-28 10:08:16 +0800811 mNetd.firewallAddUidInterfaceRules(ifName, uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800812 return;
813 }
Motomu Utsumif794e7d2022-08-03 06:38:43 +0000814
815 if (sEnableJavaBpfMap) {
816 // Null ifName is a wildcard to allow apps to receive packets on all interfaces and
817 // ifIndex is set to 0.
818 final int ifIndex;
819 if (ifName == null) {
820 ifIndex = 0;
821 } else {
822 ifIndex = mDeps.getIfIndex(ifName);
823 if (ifIndex == 0) {
824 throw new ServiceSpecificException(ENODEV,
825 "Failed to get index of interface " + ifName);
826 }
827 }
828 for (final int uid : uids) {
829 try {
830 addRule(uid, IIF_MATCH, ifIndex, "addUidInterfaceRules");
831 } catch (ServiceSpecificException e) {
832 Log.e(TAG, "addRule failed uid=" + uid + " ifName=" + ifName + ", " + e);
833 }
834 }
Motomu Utsumi5f52f4f2022-06-30 03:31:09 +0000835 } else {
Motomu Utsumif794e7d2022-08-03 06:38:43 +0000836 final int err = native_addUidInterfaceRules(ifName, uids);
837 maybeThrow(err, "Unable to add uid interface rules");
Motomu Utsumi5a68a212022-06-24 10:14:31 +0000838 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800839 }
840
841 /**
842 * Remove ingress interface filtering rules from a list of UIDs
843 *
844 * Clear the ingress interface filtering rules from the list of UIDs which were previously set
845 * by addUidInterfaceRules(). Ignore any uid which does not have filtering rule.
846 *
847 * @param uids an array of UIDs from which the filtering rules will be removed
Ken Chenf5f51332022-01-28 10:08:16 +0800848 * @throws RemoteException when netd has crashed.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800849 * @throws ServiceSpecificException in case of failure, with an error code indicating the
Ken Chenf5f51332022-01-28 10:08:16 +0800850 * cause of the failure.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800851 */
Ken Chenf5f51332022-01-28 10:08:16 +0800852 public void removeUidInterfaceRules(final int[] uids) throws RemoteException {
Motomu Utsumi25cf86f2022-06-27 08:50:19 +0000853 if (PRE_T) {
Ken Chenf5f51332022-01-28 10:08:16 +0800854 mNetd.firewallRemoveUidInterfaceRules(uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800855 return;
856 }
Motomu Utsumi7dc657d2022-08-03 06:40:46 +0000857
858 if (sEnableJavaBpfMap) {
859 for (final int uid : uids) {
860 try {
861 removeRule(uid, IIF_MATCH, "removeUidInterfaceRules");
862 } catch (ServiceSpecificException e) {
863 Log.e(TAG, "removeRule failed uid=" + uid + ", " + e);
864 }
Motomu Utsumi599c4e52022-06-30 03:37:18 +0000865 }
Motomu Utsumi7dc657d2022-08-03 06:40:46 +0000866 } else {
867 final int err = native_removeUidInterfaceRules(uids);
868 maybeThrow(err, "Unable to remove uid interface rules");
Motomu Utsumi5a68a212022-06-24 10:14:31 +0000869 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800870 }
871
Ken Chenf5f51332022-01-28 10:08:16 +0800872 /**
Motomu Utsumi8b42e6d2022-05-19 06:23:40 +0000873 * Update lockdown rule for uid
874 *
875 * @param uid target uid to add/remove the rule
876 * @param add {@code true} to add the rule, {@code false} to remove the rule.
877 * @throws ServiceSpecificException in case of failure, with an error code indicating the
878 * cause of the failure.
879 */
Junyu Lai626045a2023-08-28 18:49:44 +0800880 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Motomu Utsumi8b42e6d2022-05-19 06:23:40 +0000881 public void updateUidLockdownRule(final int uid, final boolean add) {
Motomu Utsumi697b2992022-06-30 02:25:29 +0000882 throwIfPreT("updateUidLockdownRule is not available on pre-T devices");
Motomu Utsumib2d32b72022-08-03 06:31:58 +0000883
884 if (sEnableJavaBpfMap) {
885 if (add) {
886 addRule(uid, LOCKDOWN_VPN_MATCH, "updateUidLockdownRule");
887 } else {
888 removeRule(uid, LOCKDOWN_VPN_MATCH, "updateUidLockdownRule");
889 }
Motomu Utsumi697b2992022-06-30 02:25:29 +0000890 } else {
Motomu Utsumib2d32b72022-08-03 06:31:58 +0000891 final int err = native_updateUidLockdownRule(uid, add);
892 maybeThrow(err, "Unable to update lockdown rule");
Motomu Utsumi5a68a212022-06-24 10:14:31 +0000893 }
Motomu Utsumi8b42e6d2022-05-19 06:23:40 +0000894 }
895
896 /**
Ken Chenf5f51332022-01-28 10:08:16 +0800897 * Request netd to change the current active network stats map.
898 *
Motomu Utsumi7abeaa42022-07-20 07:54:18 +0000899 * @throws UnsupportedOperationException if called on pre-T devices.
Ken Chenf5f51332022-01-28 10:08:16 +0800900 * @throws ServiceSpecificException in case of failure, with an error code indicating the
901 * cause of the failure.
902 */
Junyu Lai626045a2023-08-28 18:49:44 +0800903 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
markchien49e944c2022-03-01 15:22:20 +0800904 public void swapActiveStatsMap() {
Motomu Utsumi7abeaa42022-07-20 07:54:18 +0000905 throwIfPreT("swapActiveStatsMap is not available on pre-T devices");
906
907 if (sEnableJavaBpfMap) {
908 try {
909 synchronized (sCurrentStatsMapConfigLock) {
910 final long config = sConfigurationMap.getValue(
911 CURRENT_STATS_MAP_CONFIGURATION_KEY).val;
912 final long newConfig = (config == STATS_SELECT_MAP_A)
913 ? STATS_SELECT_MAP_B : STATS_SELECT_MAP_A;
914 sConfigurationMap.updateEntry(CURRENT_STATS_MAP_CONFIGURATION_KEY,
915 new U32(newConfig));
916 }
917 } catch (ErrnoException e) {
918 throw new ServiceSpecificException(e.errno, "Failed to swap active stats map");
919 }
920
921 // After changing the config, it's needed to make sure all the current running eBPF
922 // programs are finished and all the CPUs are aware of this config change before the old
923 // map is modified. So special hack is needed here to wait for the kernel to do a
924 // synchronize_rcu(). Once the kernel called synchronize_rcu(), the updated config will
925 // be available to all cores and the next eBPF programs triggered inside the kernel will
926 // use the new map configuration. So once this function returns it is safe to modify the
927 // old stats map without concerning about race between the kernel and userspace.
928 final int err = mDeps.synchronizeKernelRCU();
929 maybeThrow(err, "synchronizeKernelRCU failed");
930 } else {
931 final int err = native_swapActiveStatsMap();
932 maybeThrow(err, "Unable to swap active stats map");
933 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800934 }
935
Ken Chenf5f51332022-01-28 10:08:16 +0800936 /**
937 * Assigns android.permission.INTERNET and/or android.permission.UPDATE_DEVICE_STATS to the uids
938 * specified. Or remove all permissions from the uids.
939 *
940 * @param permissions The permission to grant, it could be either PERMISSION_INTERNET and/or
941 * PERMISSION_UPDATE_DEVICE_STATS. If the permission is NO_PERMISSIONS, then
942 * revoke all permissions for the uids.
943 * @param uids uid of users to grant permission
944 * @throws RemoteException when netd has crashed.
945 */
946 public void setNetPermForUids(final int permissions, final int[] uids) throws RemoteException {
Motomu Utsumi25cf86f2022-06-27 08:50:19 +0000947 if (PRE_T) {
Ken Chenf5f51332022-01-28 10:08:16 +0800948 mNetd.trafficSetNetPermForUids(permissions, uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800949 return;
950 }
Motomu Utsumi65271202022-07-05 08:21:41 +0000951
952 if (sEnableJavaBpfMap) {
953 // Remove the entry if package is uninstalled or uid has only INTERNET permission.
954 if (permissions == PERMISSION_UNINSTALLED || permissions == PERMISSION_INTERNET) {
955 for (final int uid : uids) {
956 try {
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000957 sUidPermissionMap.deleteEntry(new S32(uid));
Motomu Utsumi65271202022-07-05 08:21:41 +0000958 } catch (ErrnoException e) {
959 Log.e(TAG, "Failed to remove uid " + uid + " from permission map: " + e);
960 }
961 }
962 return;
963 }
964
965 for (final int uid : uids) {
966 try {
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000967 sUidPermissionMap.updateEntry(new S32(uid), new U8((short) permissions));
Motomu Utsumi65271202022-07-05 08:21:41 +0000968 } catch (ErrnoException e) {
969 Log.e(TAG, "Failed to set permission "
970 + permissions + " to uid " + uid + ": " + e);
971 }
972 }
973 } else {
974 native_setPermissionForUids(permissions, uids);
975 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800976 }
977
Ken Chen24330172023-10-20 13:02:14 +0800978 /**
979 * Set Data Saver enabled or disabled
980 *
981 * @param enable whether Data Saver is enabled or disabled.
982 * @throws UnsupportedOperationException if called on pre-T devices.
983 * @throws ServiceSpecificException in case of failure, with an error code indicating the
984 * cause of the failure.
985 */
986 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
987 public void setDataSaverEnabled(boolean enable) {
988 throwIfPreT("setDataSaverEnabled is not available on pre-T devices");
989
990 try {
991 final short config = enable ? DATA_SAVER_ENABLED : DATA_SAVER_DISABLED;
992 sDataSaverEnabledMap.updateEntry(DATA_SAVER_ENABLED_KEY, new U8(config));
993 } catch (ErrnoException e) {
994 throw new ServiceSpecificException(e.errno, "Unable to set data saver: "
995 + Os.strerror(e.errno));
996 }
997 }
998
Motomu Utsumi77b49992023-10-23 17:06:12 +0900999 /**
1000 * Set ingress discard rule
1001 *
1002 * @param address target address to set the ingress discard rule
1003 * @param iface allowed interface
1004 */
1005 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
1006 public void setIngressDiscardRule(final InetAddress address, final String iface) {
1007 throwIfPreT("setIngressDiscardRule is not available on pre-T devices");
1008 final int ifIndex = mDeps.getIfIndex(iface);
1009 if (ifIndex == 0) {
1010 Log.e(TAG, "Failed to get if index, skip setting ingress discard rule for " + address
1011 + "(" + iface + ")");
1012 return;
1013 }
1014 try {
1015 sIngressDiscardMap.updateEntry(new IngressDiscardKey(address),
1016 new IngressDiscardValue(ifIndex, ifIndex));
1017 } catch (ErrnoException e) {
1018 Log.e(TAG, "Failed to set ingress discard rule for " + address + "("
1019 + iface + "), " + e);
1020 }
1021 }
1022
1023 /**
1024 * Remove ingress discard rule
1025 *
1026 * @param address target address to remove the ingress discard rule
1027 */
1028 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
1029 public void removeIngressDiscardRule(final InetAddress address) {
1030 throwIfPreT("removeIngressDiscardRule is not available on pre-T devices");
1031 try {
1032 sIngressDiscardMap.deleteEntry(new IngressDiscardKey(address));
1033 } catch (ErrnoException e) {
1034 Log.e(TAG, "Failed to remove ingress discard rule for " + address + ", " + e);
1035 }
1036 }
1037
Motomu Utsumi166f9662022-09-01 10:35:29 +09001038 /** Register callback for statsd to pull atom. */
Junyu Lai626045a2023-08-28 18:49:44 +08001039 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Motomu Utsumi166f9662022-09-01 10:35:29 +09001040 public void setPullAtomCallback(final Context context) {
1041 throwIfPreT("setPullAtomCallback is not available on pre-T devices");
1042
1043 final StatsManager statsManager = context.getSystemService(StatsManager.class);
1044 statsManager.setPullAtomCallback(NETWORK_BPF_MAP_INFO, null /* metadata */,
1045 BackgroundThread.getExecutor(), this::pullBpfMapInfoAtom);
1046 }
1047
1048 private <K extends Struct, V extends Struct> int getMapSize(IBpfMap<K, V> map)
1049 throws ErrnoException {
1050 // forEach could restart iteration from the beginning if there is a concurrent entry
1051 // deletion. netd and skDestroyListener could delete CookieTagMap entry concurrently.
1052 // So using Set to count the number of entry in the map.
1053 Set<K> keySet = new ArraySet<>();
1054 map.forEach((k, v) -> keySet.add(k));
1055 return keySet.size();
1056 }
1057
1058 /** Callback for StatsManager#setPullAtomCallback */
1059 @VisibleForTesting
1060 public int pullBpfMapInfoAtom(final int atomTag, final List<StatsEvent> data) {
1061 if (atomTag != NETWORK_BPF_MAP_INFO) {
1062 Log.e(TAG, "Unexpected atom tag: " + atomTag);
1063 return StatsManager.PULL_SKIP;
1064 }
1065
1066 try {
1067 data.add(mDeps.buildStatsEvent(getMapSize(sCookieTagMap), getMapSize(sUidOwnerMap),
1068 getMapSize(sUidPermissionMap)));
1069 } catch (ErrnoException e) {
1070 Log.e(TAG, "Failed to pull NETWORK_BPF_MAP_INFO atom: " + e);
1071 return StatsManager.PULL_SKIP;
1072 }
1073 return StatsManager.PULL_SUCCESS;
1074 }
1075
Motomu Utsumi310850f2022-09-02 12:48:20 +09001076 private String permissionToString(int permissionMask) {
1077 if (permissionMask == PERMISSION_NONE) {
1078 return "PERMISSION_NONE";
1079 }
1080 if (permissionMask == PERMISSION_UNINSTALLED) {
1081 // PERMISSION_UNINSTALLED should never appear in the map
1082 return "PERMISSION_UNINSTALLED error!";
1083 }
1084
1085 final StringJoiner sj = new StringJoiner(" ");
1086 for (Pair<Integer, String> permission: PERMISSION_LIST) {
1087 final int permissionFlag = permission.first;
1088 final String permissionName = permission.second;
1089 if ((permissionMask & permissionFlag) != 0) {
1090 sj.add(permissionName);
1091 permissionMask &= ~permissionFlag;
1092 }
1093 }
1094 if (permissionMask != 0) {
1095 sj.add("PERMISSION_UNKNOWN(" + permissionMask + ")");
1096 }
1097 return sj.toString();
1098 }
1099
Motomu Utsumi372c9b42022-09-02 19:02:56 +09001100 private void dumpOwnerMatchConfig(final IndentingPrintWriter pw) {
1101 try {
1102 final long match = sConfigurationMap.getValue(UID_RULES_CONFIGURATION_KEY).val;
1103 pw.println("current ownerMatch configuration: " + match + " " + matchToString(match));
1104 } catch (ErrnoException e) {
1105 pw.println("Failed to read ownerMatch configuration: " + e);
1106 }
1107 }
1108
Motomu Utsumic675d6f2022-09-02 18:15:25 +09001109 private void dumpCurrentStatsMapConfig(final IndentingPrintWriter pw) {
1110 try {
1111 final long config = sConfigurationMap.getValue(CURRENT_STATS_MAP_CONFIGURATION_KEY).val;
1112 final String currentStatsMap =
1113 (config == STATS_SELECT_MAP_A) ? "SELECT_MAP_A" : "SELECT_MAP_B";
1114 pw.println("current statsMap configuration: " + config + " " + currentStatsMap);
1115 } catch (ErrnoException e) {
1116 pw.println("Falied to read current statsMap configuration: " + e);
1117 }
1118 }
1119
Ken Chen24330172023-10-20 13:02:14 +08001120 private void dumpDataSaverConfig(final IndentingPrintWriter pw) {
1121 try {
1122 final short config = sDataSaverEnabledMap.getValue(DATA_SAVER_ENABLED_KEY).val;
1123 // Any non-zero value converted from short to boolean is true by convention.
1124 pw.println("sDataSaverEnabledMap: " + (config != DATA_SAVER_DISABLED));
1125 } catch (ErrnoException e) {
1126 pw.println("Failed to read data saver configuration: " + e);
1127 }
1128 }
Ken Chene6d511f2022-01-25 11:10:42 +08001129 /**
1130 * Dump BPF maps
1131 *
Motomu Utsumi310850f2022-09-02 12:48:20 +09001132 * @param pw print writer
Ken Chene6d511f2022-01-25 11:10:42 +08001133 * @param fd file descriptor to output
Motomu Utsumi310850f2022-09-02 12:48:20 +09001134 * @param verbose verbose dump flag, if true dump the BpfMap contents
Ken Chene6d511f2022-01-25 11:10:42 +08001135 * @throws IOException when file descriptor is invalid.
1136 * @throws ServiceSpecificException when the method is called on an unsupported device.
1137 */
Junyu Lai626045a2023-08-28 18:49:44 +08001138 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Motomu Utsumi310850f2022-09-02 12:48:20 +09001139 public void dump(final IndentingPrintWriter pw, final FileDescriptor fd, boolean verbose)
Ken Chene6d511f2022-01-25 11:10:42 +08001140 throws IOException, ServiceSpecificException {
Motomu Utsumi25cf86f2022-06-27 08:50:19 +00001141 if (PRE_T) {
Ken Chene6d511f2022-01-25 11:10:42 +08001142 throw new ServiceSpecificException(
1143 EOPNOTSUPP, "dumpsys connectivity trafficcontroller dump not available on pre-T"
1144 + " devices, use dumpsys netd trafficcontroller instead.");
1145 }
Maciej Żenczykowskid70a3302023-09-06 16:45:25 +00001146
1147 pw.println("TrafficController"); // required by CTS testDumpBpfNetMaps
Motomu Utsumi310850f2022-09-02 12:48:20 +09001148
Motomu Utsumi316d0572022-09-15 13:24:48 +09001149 pw.println();
1150 pw.println("sEnableJavaBpfMap: " + sEnableJavaBpfMap);
Motomu Utsumi310850f2022-09-02 12:48:20 +09001151 if (verbose) {
Motomu Utsumief546a92022-10-05 16:42:29 +09001152 pw.println();
1153 pw.println("BPF map content:");
1154 pw.increaseIndent();
1155
Motomu Utsumi372c9b42022-09-02 19:02:56 +09001156 dumpOwnerMatchConfig(pw);
Motomu Utsumic675d6f2022-09-02 18:15:25 +09001157 dumpCurrentStatsMapConfig(pw);
1158 pw.println();
1159
Motomu Utsumief546a92022-10-05 16:42:29 +09001160 // TODO: Remove CookieTagMap content dump
1161 // NetworkStatsService also dumps CookieTagMap and NetworkStatsService is a right place
1162 // to dump CookieTagMap. But the TagSocketTest in CTS depends on this dump so the tests
1163 // need to be updated before remove the dump from BpfNetMaps.
1164 BpfDump.dumpMap(sCookieTagMap, pw, "sCookieTagMap",
1165 (key, value) -> "cookie=" + key.socketCookie
1166 + " tag=0x" + Long.toHexString(value.tag)
1167 + " uid=" + value.uid);
Motomu Utsumi956d86c2022-09-02 17:01:25 +09001168 BpfDump.dumpMap(sUidOwnerMap, pw, "sUidOwnerMap",
1169 (uid, match) -> {
1170 if ((match.rule & IIF_MATCH) != 0) {
1171 // TODO: convert interface index to interface name by IfaceIndexNameMap
1172 return uid.val + " " + matchToString(match.rule) + " " + match.iif;
1173 } else {
1174 return uid.val + " " + matchToString(match.rule);
1175 }
1176 });
Motomu Utsumi310850f2022-09-02 12:48:20 +09001177 BpfDump.dumpMap(sUidPermissionMap, pw, "sUidPermissionMap",
1178 (uid, permission) -> uid.val + " " + permissionToString(permission.val));
Motomu Utsumi77b49992023-10-23 17:06:12 +09001179 BpfDump.dumpMap(sIngressDiscardMap, pw, "sIngressDiscardMap",
1180 (key, value) -> "[" + key.dstAddr + "]: "
1181 + value.iif1 + "(" + mDeps.getIfName(value.iif1) + "), "
1182 + value.iif2 + "(" + mDeps.getIfName(value.iif2) + ")");
Ken Chen24330172023-10-20 13:02:14 +08001183 dumpDataSaverConfig(pw);
Motomu Utsumief546a92022-10-05 16:42:29 +09001184 pw.decreaseIndent();
Motomu Utsumi310850f2022-09-02 12:48:20 +09001185 }
Ken Chene6d511f2022-01-25 11:10:42 +08001186 }
1187
Maciej Żenczykowski70fbfa42023-07-18 20:14:38 +00001188 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Motomu Utsumi3af8f0e2022-09-02 23:42:13 +09001189 private static native void native_init(boolean startSkDestroyListener);
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001190
1191 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Wayne Ma0ea3bdc2022-01-12 01:12:11 +08001192 private native int native_addNaughtyApp(int uid);
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001193
1194 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Wayne Ma0ea3bdc2022-01-12 01:12:11 +08001195 private native int native_removeNaughtyApp(int uid);
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001196
1197 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Wayne Ma0ea3bdc2022-01-12 01:12:11 +08001198 private native int native_addNiceApp(int uid);
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001199
1200 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Wayne Ma0ea3bdc2022-01-12 01:12:11 +08001201 private native int native_removeNiceApp(int uid);
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001202
1203 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Motomu Utsumi114cd9c2022-08-01 02:08:35 +00001204 private native int native_setChildChain(int childChain, boolean enable);
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001205
1206 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Wayne Ma0ea3bdc2022-01-12 01:12:11 +08001207 private native int native_replaceUidChain(String name, boolean isAllowlist, int[] uids);
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001208
1209 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Wayne Ma0ea3bdc2022-01-12 01:12:11 +08001210 private native int native_setUidRule(int childChain, int uid, int firewallRule);
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001211
1212 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Wayne Ma0ea3bdc2022-01-12 01:12:11 +08001213 private native int native_addUidInterfaceRules(String ifName, int[] uids);
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001214
1215 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Wayne Ma0ea3bdc2022-01-12 01:12:11 +08001216 private native int native_removeUidInterfaceRules(int[] uids);
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001217
1218 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Motomu Utsumi8b42e6d2022-05-19 06:23:40 +00001219 private native int native_updateUidLockdownRule(int uid, boolean add);
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001220
1221 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Wayne Ma0ea3bdc2022-01-12 01:12:11 +08001222 private native int native_swapActiveStatsMap();
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001223
1224 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Wayne Ma2fde98c2022-01-17 18:04:05 +08001225 private native void native_setPermissionForUids(int permissions, int[] uids);
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001226
1227 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Motomu Utsumi7abeaa42022-07-20 07:54:18 +00001228 private static native int native_synchronizeKernelRCU();
Wayne Ma0ea3bdc2022-01-12 01:12:11 +08001229}