blob: ccff9c99b05b66d77ee8b6a44aa9d10f3990765d [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;
36import static android.net.BpfNetMapsUtils.matchToString;
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +000037import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
38import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
39import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_1;
40import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_2;
41import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_3;
42import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE;
43import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED;
44import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY;
Motomu Utsumi40230be2022-07-05 03:27:35 +000045import static android.net.ConnectivityManager.FIREWALL_RULE_ALLOW;
46import static android.net.ConnectivityManager.FIREWALL_RULE_DENY;
Motomu Utsumi65271202022-07-05 08:21:41 +000047import static android.net.INetd.PERMISSION_INTERNET;
Motomu Utsumi310850f2022-09-02 12:48:20 +090048import static android.net.INetd.PERMISSION_NONE;
Motomu Utsumi65271202022-07-05 08:21:41 +000049import static android.net.INetd.PERMISSION_UNINSTALLED;
Motomu Utsumi310850f2022-09-02 12:48:20 +090050import static android.net.INetd.PERMISSION_UPDATE_DEVICE_STATS;
Motomu Utsumi18b287d2022-06-19 10:45:30 +000051import static android.system.OsConstants.EINVAL;
Motomu Utsumi5f52f4f2022-06-30 03:31:09 +000052import static android.system.OsConstants.ENODEV;
Motomu Utsumi60ed3be2022-06-24 10:38:57 +000053import static android.system.OsConstants.ENOENT;
Ken Chene6d511f2022-01-25 11:10:42 +080054import static android.system.OsConstants.EOPNOTSUPP;
55
Motomu Utsumi166f9662022-09-01 10:35:29 +090056import static com.android.server.ConnectivityStatsLog.NETWORK_BPF_MAP_INFO;
57
58import android.app.StatsManager;
Motomu Utsumif688eeb2022-07-22 03:47:35 +000059import android.content.Context;
Junyu Lai626045a2023-08-28 18:49:44 +080060import android.net.BpfNetMapsReader;
Wayne Ma2fde98c2022-01-17 18:04:05 +080061import android.net.INetd;
Junyu Lai626045a2023-08-28 18:49:44 +080062import android.net.UidOwnerValue;
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +000063import android.os.Build;
Wayne Ma2fde98c2022-01-17 18:04:05 +080064import android.os.RemoteException;
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080065import android.os.ServiceSpecificException;
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +000066import android.system.ErrnoException;
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080067import android.system.Os;
Motomu Utsumi1a477b02022-08-23 15:14:56 +090068import android.util.ArraySet;
Motomu Utsumi310850f2022-09-02 12:48:20 +090069import android.util.IndentingPrintWriter;
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080070import android.util.Log;
Motomu Utsumi310850f2022-09-02 12:48:20 +090071import android.util.Pair;
Motomu Utsumi166f9662022-09-01 10:35:29 +090072import android.util.StatsEvent;
Wayne Ma0ea3bdc2022-01-12 01:12:11 +080073
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +000074import androidx.annotation.RequiresApi;
75
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +000076import com.android.internal.annotations.VisibleForTesting;
Motomu Utsumi166f9662022-09-01 10:35:29 +090077import com.android.modules.utils.BackgroundThread;
Ken Chenf5f51332022-01-28 10:08:16 +080078import com.android.modules.utils.build.SdkLevel;
Motomu Utsumi310850f2022-09-02 12:48:20 +090079import com.android.net.module.util.BpfDump;
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +000080import com.android.net.module.util.BpfMap;
Motomu Utsumif688eeb2022-07-22 03:47:35 +000081import com.android.net.module.util.DeviceConfigUtils;
Motomu Utsumi73599a52022-08-24 11:59:21 +090082import com.android.net.module.util.IBpfMap;
Motomu Utsumi166f9662022-09-01 10:35:29 +090083import com.android.net.module.util.Struct;
Maciej Żenczykowski785793f2022-09-17 02:35:20 +000084import com.android.net.module.util.Struct.S32;
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +000085import com.android.net.module.util.Struct.U32;
Motomu Utsumi65271202022-07-05 08:21:41 +000086import com.android.net.module.util.Struct.U8;
Motomu Utsumib9548862022-09-06 16:30:05 +090087import com.android.net.module.util.bpf.CookieTagMapKey;
88import com.android.net.module.util.bpf.CookieTagMapValue;
Motomu Utsumi77b49992023-10-23 17:06:12 +090089import com.android.net.module.util.bpf.IngressDiscardKey;
90import com.android.net.module.util.bpf.IngressDiscardValue;
Ken Chenf5f51332022-01-28 10:08:16 +080091
Ken Chene6d511f2022-01-25 11:10:42 +080092import java.io.FileDescriptor;
93import java.io.IOException;
Motomu Utsumi77b49992023-10-23 17:06:12 +090094import java.net.InetAddress;
Motomu Utsumi310850f2022-09-02 12:48:20 +090095import java.util.Arrays;
Motomu Utsumi166f9662022-09-01 10:35:29 +090096import java.util.List;
Motomu Utsumi9be2ea02022-07-05 06:14:59 +000097import java.util.Set;
Motomu Utsumi310850f2022-09-02 12:48:20 +090098import java.util.StringJoiner;
Ken Chene6d511f2022-01-25 11:10:42 +080099
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800100/**
101 * BpfNetMaps is responsible for providing traffic controller relevant functionality.
102 *
103 * {@hide}
104 */
105public class BpfNetMaps {
Motomu Utsumi305975f2022-06-27 09:24:32 +0000106 static {
107 if (!PRE_T) {
108 System.loadLibrary("service-connectivity");
109 }
110 }
111
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800112 private static final String TAG = "BpfNetMaps";
Wayne Ma2fde98c2022-01-17 18:04:05 +0800113 private final INetd mNetd;
Motomu Utsumi5f52f4f2022-06-30 03:31:09 +0000114 private final Dependencies mDeps;
Ken Chenf5f51332022-01-28 10:08:16 +0800115 // Use legacy netd for releases before T.
Ken Chenf5f51332022-01-28 10:08:16 +0800116 private static boolean sInitialized = false;
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800117
Motomu Utsumif688eeb2022-07-22 03:47:35 +0000118 private static Boolean sEnableJavaBpfMap = null;
Motomu Utsumi7628ea32023-08-14 11:09:02 +0900119 private static final String BPF_NET_MAPS_FORCE_DISABLE_JAVA_BPF_MAP =
120 "bpf_net_maps_force_disable_java_bpf_map";
Motomu Utsumif688eeb2022-07-22 03:47:35 +0000121
Motomu Utsumi18b287d2022-06-19 10:45:30 +0000122 // Lock for sConfigurationMap entry for UID_RULES_CONFIGURATION_KEY.
123 // This entry is not accessed by others.
124 // BpfNetMaps acquires this lock while sequence of read, modify, and write.
125 private static final Object sUidRulesConfigBpfMapLock = new Object();
126
Motomu Utsumi7abeaa42022-07-20 07:54:18 +0000127 // Lock for sConfigurationMap entry for CURRENT_STATS_MAP_CONFIGURATION_KEY.
128 // BpfNetMaps acquires this lock while sequence of read, modify, and write.
129 // BpfNetMaps is an only writer of this entry.
130 private static final Object sCurrentStatsMapConfigLock = new Object();
131
Motomu Utsumiba2fa152022-07-25 01:57:23 +0000132 private static final long UID_RULES_DEFAULT_CONFIGURATION = 0;
133 private static final long STATS_SELECT_MAP_A = 0;
134 private static final long STATS_SELECT_MAP_B = 1;
135
Maciej Żenczykowskidc886222022-09-17 06:09:22 +0000136 private static IBpfMap<S32, U32> sConfigurationMap = null;
Motomu Utsumi5a68a212022-06-24 10:14:31 +0000137 // BpfMap for UID_OWNER_MAP_PATH. This map is not accessed by others.
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000138 private static IBpfMap<S32, UidOwnerValue> sUidOwnerMap = null;
139 private static IBpfMap<S32, U8> sUidPermissionMap = null;
Motomu Utsumib9548862022-09-06 16:30:05 +0900140 private static IBpfMap<CookieTagMapKey, CookieTagMapValue> sCookieTagMap = null;
Ken Chen24330172023-10-20 13:02:14 +0800141 // TODO: Add BOOL class and replace U8?
142 private static IBpfMap<S32, U8> sDataSaverEnabledMap = null;
Motomu Utsumi77b49992023-10-23 17:06:12 +0900143 private static IBpfMap<IngressDiscardKey, IngressDiscardValue> sIngressDiscardMap = null;
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +0000144
Motomu Utsumi310850f2022-09-02 12:48:20 +0900145 private static final List<Pair<Integer, String>> PERMISSION_LIST = Arrays.asList(
146 Pair.create(PERMISSION_INTERNET, "PERMISSION_INTERNET"),
147 Pair.create(PERMISSION_UPDATE_DEVICE_STATS, "PERMISSION_UPDATE_DEVICE_STATS")
148 );
149
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +0000150 /**
Motomu Utsumif688eeb2022-07-22 03:47:35 +0000151 * Set sEnableJavaBpfMap for test.
152 */
153 @VisibleForTesting
154 public static void setEnableJavaBpfMapForTest(boolean enable) {
155 sEnableJavaBpfMap = enable;
156 }
157
158 /**
Motomu Utsumi305975f2022-06-27 09:24:32 +0000159 * Set configurationMap for test.
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +0000160 */
161 @VisibleForTesting
Maciej Żenczykowskidc886222022-09-17 06:09:22 +0000162 public static void setConfigurationMapForTest(IBpfMap<S32, U32> configurationMap) {
Motomu Utsumi305975f2022-06-27 09:24:32 +0000163 sConfigurationMap = configurationMap;
164 }
165
Motomu Utsumi5a68a212022-06-24 10:14:31 +0000166 /**
167 * Set uidOwnerMap for test.
168 */
169 @VisibleForTesting
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000170 public static void setUidOwnerMapForTest(IBpfMap<S32, UidOwnerValue> uidOwnerMap) {
Motomu Utsumi5a68a212022-06-24 10:14:31 +0000171 sUidOwnerMap = uidOwnerMap;
172 }
173
Motomu Utsumi65271202022-07-05 08:21:41 +0000174 /**
175 * Set uidPermissionMap for test.
176 */
177 @VisibleForTesting
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000178 public static void setUidPermissionMapForTest(IBpfMap<S32, U8> uidPermissionMap) {
Motomu Utsumi65271202022-07-05 08:21:41 +0000179 sUidPermissionMap = uidPermissionMap;
180 }
181
Motomu Utsumib9548862022-09-06 16:30:05 +0900182 /**
183 * Set cookieTagMap for test.
184 */
185 @VisibleForTesting
186 public static void setCookieTagMapForTest(
187 IBpfMap<CookieTagMapKey, CookieTagMapValue> cookieTagMap) {
188 sCookieTagMap = cookieTagMap;
189 }
190
Ken Chen24330172023-10-20 13:02:14 +0800191 /**
192 * Set dataSaverEnabledMap for test.
193 */
194 @VisibleForTesting
195 public static void setDataSaverEnabledMapForTest(IBpfMap<S32, U8> dataSaverEnabledMap) {
196 sDataSaverEnabledMap = dataSaverEnabledMap;
197 }
198
Motomu Utsumi77b49992023-10-23 17:06:12 +0900199 /**
200 * Set ingressDiscardMap for test.
201 */
202 @VisibleForTesting
203 public static void setIngressDiscardMapForTest(
204 IBpfMap<IngressDiscardKey, IngressDiscardValue> ingressDiscardMap) {
205 sIngressDiscardMap = ingressDiscardMap;
206 }
207
Maciej Żenczykowskidc886222022-09-17 06:09:22 +0000208 private static IBpfMap<S32, U32> getConfigurationMap() {
Motomu Utsumi305975f2022-06-27 09:24:32 +0000209 try {
210 return new BpfMap<>(
Maciej Żenczykowskidc886222022-09-17 06:09:22 +0000211 CONFIGURATION_MAP_PATH, BpfMap.BPF_F_RDWR, S32.class, U32.class);
Motomu Utsumi305975f2022-06-27 09:24:32 +0000212 } catch (ErrnoException e) {
213 throw new IllegalStateException("Cannot open netd configuration map", e);
214 }
215 }
216
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000217 private static IBpfMap<S32, UidOwnerValue> getUidOwnerMap() {
Motomu Utsumi5a68a212022-06-24 10:14:31 +0000218 try {
219 return new BpfMap<>(
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000220 UID_OWNER_MAP_PATH, BpfMap.BPF_F_RDWR, S32.class, UidOwnerValue.class);
Motomu Utsumi5a68a212022-06-24 10:14:31 +0000221 } catch (ErrnoException e) {
222 throw new IllegalStateException("Cannot open uid owner map", e);
223 }
224 }
225
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000226 private static IBpfMap<S32, U8> getUidPermissionMap() {
Motomu Utsumi65271202022-07-05 08:21:41 +0000227 try {
228 return new BpfMap<>(
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000229 UID_PERMISSION_MAP_PATH, BpfMap.BPF_F_RDWR, S32.class, U8.class);
Motomu Utsumi65271202022-07-05 08:21:41 +0000230 } catch (ErrnoException e) {
231 throw new IllegalStateException("Cannot open uid permission map", e);
232 }
233 }
234
Motomu Utsumib9548862022-09-06 16:30:05 +0900235 private static IBpfMap<CookieTagMapKey, CookieTagMapValue> getCookieTagMap() {
236 try {
237 return new BpfMap<>(COOKIE_TAG_MAP_PATH, BpfMap.BPF_F_RDWR,
238 CookieTagMapKey.class, CookieTagMapValue.class);
239 } catch (ErrnoException e) {
240 throw new IllegalStateException("Cannot open cookie tag map", e);
241 }
242 }
243
Ken Chen24330172023-10-20 13:02:14 +0800244 private static IBpfMap<S32, U8> getDataSaverEnabledMap() {
245 try {
246 return new BpfMap<>(
247 DATA_SAVER_ENABLED_MAP_PATH, BpfMap.BPF_F_RDWR, S32.class, U8.class);
248 } catch (ErrnoException e) {
249 throw new IllegalStateException("Cannot open data saver enabled map", e);
250 }
251 }
252
Motomu Utsumi77b49992023-10-23 17:06:12 +0900253 private static IBpfMap<IngressDiscardKey, IngressDiscardValue> getIngressDiscardMap() {
254 try {
255 return new BpfMap<>(INGRESS_DISCARD_MAP_PATH, BpfMap.BPF_F_RDWR,
256 IngressDiscardKey.class, IngressDiscardValue.class);
257 } catch (ErrnoException e) {
258 throw new IllegalStateException("Cannot open ingress discard map", e);
259 }
260 }
261
Motomu Utsumiba2fa152022-07-25 01:57:23 +0000262 private static void initBpfMaps() {
Motomu Utsumi305975f2022-06-27 09:24:32 +0000263 if (sConfigurationMap == null) {
264 sConfigurationMap = getConfigurationMap();
265 }
Motomu Utsumiba2fa152022-07-25 01:57:23 +0000266 try {
267 sConfigurationMap.updateEntry(UID_RULES_CONFIGURATION_KEY,
268 new U32(UID_RULES_DEFAULT_CONFIGURATION));
269 } catch (ErrnoException e) {
270 throw new IllegalStateException("Failed to initialize uid rules configuration", e);
271 }
272 try {
273 sConfigurationMap.updateEntry(CURRENT_STATS_MAP_CONFIGURATION_KEY,
274 new U32(STATS_SELECT_MAP_A));
275 } catch (ErrnoException e) {
276 throw new IllegalStateException("Failed to initialize current stats configuration", e);
277 }
278
Motomu Utsumi5a68a212022-06-24 10:14:31 +0000279 if (sUidOwnerMap == null) {
280 sUidOwnerMap = getUidOwnerMap();
281 }
Motomu Utsumiba2fa152022-07-25 01:57:23 +0000282 try {
283 sUidOwnerMap.clear();
284 } catch (ErrnoException e) {
285 throw new IllegalStateException("Failed to initialize uid owner map", e);
286 }
Motomu Utsumi65271202022-07-05 08:21:41 +0000287
288 if (sUidPermissionMap == null) {
289 sUidPermissionMap = getUidPermissionMap();
290 }
Motomu Utsumib9548862022-09-06 16:30:05 +0900291
292 if (sCookieTagMap == null) {
293 sCookieTagMap = getCookieTagMap();
294 }
Ken Chen24330172023-10-20 13:02:14 +0800295
296 if (sDataSaverEnabledMap == null) {
297 sDataSaverEnabledMap = getDataSaverEnabledMap();
298 }
299 try {
300 sDataSaverEnabledMap.updateEntry(DATA_SAVER_ENABLED_KEY, new U8(DATA_SAVER_DISABLED));
301 } catch (ErrnoException e) {
302 throw new IllegalStateException("Failed to initialize data saver configuration", e);
303 }
Motomu Utsumi77b49992023-10-23 17:06:12 +0900304
305 if (sIngressDiscardMap == null) {
306 sIngressDiscardMap = getIngressDiscardMap();
307 }
308 try {
309 sIngressDiscardMap.clear();
310 } catch (ErrnoException e) {
311 throw new IllegalStateException("Failed to initialize ingress discard map", e);
312 }
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +0000313 }
314
Ken Chenf5f51332022-01-28 10:08:16 +0800315 /**
316 * Initializes the class if it is not already initialized. This method will open maps but not
317 * cause any other effects. This method may be called multiple times on any thread.
318 */
Motomu Utsumif688eeb2022-07-22 03:47:35 +0000319 private static synchronized void ensureInitialized(final Context context) {
Ken Chenf5f51332022-01-28 10:08:16 +0800320 if (sInitialized) return;
Motomu Utsumif688eeb2022-07-22 03:47:35 +0000321 if (sEnableJavaBpfMap == null) {
Maciej Żenczykowskie7ebb152022-12-27 10:57:38 +0000322 sEnableJavaBpfMap = SdkLevel.isAtLeastU() ||
Motomu Utsumied4e7ec2023-09-13 14:58:32 +0900323 DeviceConfigUtils.isTetheringFeatureNotChickenedOut(context,
Motomu Utsumi7628ea32023-08-14 11:09:02 +0900324 BPF_NET_MAPS_FORCE_DISABLE_JAVA_BPF_MAP);
Motomu Utsumif688eeb2022-07-22 03:47:35 +0000325 }
326 Log.d(TAG, "BpfNetMaps is initialized with sEnableJavaBpfMap=" + sEnableJavaBpfMap);
327
Motomu Utsumiba2fa152022-07-25 01:57:23 +0000328 initBpfMaps();
Motomu Utsumid95a0da2022-09-03 00:40:30 +0900329 native_init(!sEnableJavaBpfMap /* startSkDestroyListener */);
Ken Chenf5f51332022-01-28 10:08:16 +0800330 sInitialized = true;
Wayne Ma2fde98c2022-01-17 18:04:05 +0800331 }
332
Motomu Utsumid95a0da2022-09-03 00:40:30 +0900333 public boolean isSkDestroyListenerRunning() {
334 return !sEnableJavaBpfMap;
335 }
336
Motomu Utsumi5f52f4f2022-06-30 03:31:09 +0000337 /**
338 * Dependencies of BpfNetMaps, for injection in tests.
339 */
340 @VisibleForTesting
341 public static class Dependencies {
342 /**
343 * Get interface index.
344 */
345 public int getIfIndex(final String ifName) {
346 return Os.if_nametoindex(ifName);
347 }
Motomu Utsumi7abeaa42022-07-20 07:54:18 +0000348
349 /**
Motomu Utsumi77b49992023-10-23 17:06:12 +0900350 * Get interface name
351 */
352 public String getIfName(final int ifIndex) {
353 return Os.if_indextoname(ifIndex);
354 }
355
356 /**
Motomu Utsumi7abeaa42022-07-20 07:54:18 +0000357 * Call synchronize_rcu()
358 */
359 public int synchronizeKernelRCU() {
360 return native_synchronizeKernelRCU();
361 }
Motomu Utsumi166f9662022-09-01 10:35:29 +0900362
363 /**
364 * Build Stats Event for NETWORK_BPF_MAP_INFO atom
365 */
366 public StatsEvent buildStatsEvent(final int cookieTagMapSize, final int uidOwnerMapSize,
367 final int uidPermissionMapSize) {
368 return ConnectivityStatsLog.buildStatsEvent(NETWORK_BPF_MAP_INFO, cookieTagMapSize,
369 uidOwnerMapSize, uidPermissionMapSize);
370 }
Motomu Utsumi5f52f4f2022-06-30 03:31:09 +0000371 }
372
markchien49e944c2022-03-01 15:22:20 +0800373 /** Constructor used after T that doesn't need to use netd anymore. */
Junyu Lai626045a2023-08-28 18:49:44 +0800374 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Motomu Utsumif688eeb2022-07-22 03:47:35 +0000375 public BpfNetMaps(final Context context) {
376 this(context, null);
markchien49e944c2022-03-01 15:22:20 +0800377
Motomu Utsumi25cf86f2022-06-27 08:50:19 +0000378 if (PRE_T) throw new IllegalArgumentException("BpfNetMaps need to use netd before T");
markchien49e944c2022-03-01 15:22:20 +0800379 }
380
Motomu Utsumif688eeb2022-07-22 03:47:35 +0000381 public BpfNetMaps(final Context context, final INetd netd) {
382 this(context, netd, new Dependencies());
Motomu Utsumi5f52f4f2022-06-30 03:31:09 +0000383 }
384
385 @VisibleForTesting
Motomu Utsumif688eeb2022-07-22 03:47:35 +0000386 public BpfNetMaps(final Context context, final INetd netd, final Dependencies deps) {
Motomu Utsumi305975f2022-06-27 09:24:32 +0000387 if (!PRE_T) {
Motomu Utsumif688eeb2022-07-22 03:47:35 +0000388 ensureInitialized(context);
Motomu Utsumi305975f2022-06-27 09:24:32 +0000389 }
Wayne Ma2fde98c2022-01-17 18:04:05 +0800390 mNetd = netd;
Motomu Utsumi5f52f4f2022-06-30 03:31:09 +0000391 mDeps = deps;
Wayne Ma790c83e2022-01-13 10:35:05 +0800392 }
393
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +0000394 /**
Motomu Utsumi40230be2022-07-05 03:27:35 +0000395 * Get if the chain is allow list or not.
396 *
397 * ALLOWLIST means the firewall denies all by default, uids must be explicitly allowed
398 * DENYLIST means the firewall allows all by default, uids must be explicitly denyed
399 */
Motomu Utsumi40230be2022-07-05 03:27:35 +0000400 public boolean isFirewallAllowList(final int chain) {
401 switch (chain) {
402 case FIREWALL_CHAIN_DOZABLE:
403 case FIREWALL_CHAIN_POWERSAVE:
404 case FIREWALL_CHAIN_RESTRICTED:
405 case FIREWALL_CHAIN_LOW_POWER_STANDBY:
406 return true;
407 case FIREWALL_CHAIN_STANDBY:
408 case FIREWALL_CHAIN_OEM_DENY_1:
409 case FIREWALL_CHAIN_OEM_DENY_2:
410 case FIREWALL_CHAIN_OEM_DENY_3:
411 return false;
412 default:
413 throw new ServiceSpecificException(EINVAL, "Invalid firewall chain: " + chain);
414 }
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +0000415 }
416
Ken Chenf5f51332022-01-28 10:08:16 +0800417 private void maybeThrow(final int err, final String msg) {
418 if (err != 0) {
419 throw new ServiceSpecificException(err, msg + ": " + Os.strerror(err));
420 }
421 }
422
Motomu Utsumi25cf86f2022-06-27 08:50:19 +0000423 private void throwIfPreT(final String msg) {
424 if (PRE_T) {
Motomu Utsumi18b287d2022-06-19 10:45:30 +0000425 throw new UnsupportedOperationException(msg);
426 }
427 }
428
Motomu Utsumi60ed3be2022-06-24 10:38:57 +0000429 private void removeRule(final int uid, final long match, final String caller) {
430 try {
431 synchronized (sUidOwnerMap) {
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000432 final UidOwnerValue oldMatch = sUidOwnerMap.getValue(new S32(uid));
Motomu Utsumi60ed3be2022-06-24 10:38:57 +0000433
434 if (oldMatch == null) {
435 throw new ServiceSpecificException(ENOENT,
436 "sUidOwnerMap does not have entry for uid: " + uid);
437 }
438
439 final UidOwnerValue newMatch = new UidOwnerValue(
440 (match == IIF_MATCH) ? 0 : oldMatch.iif,
441 oldMatch.rule & ~match
442 );
443
444 if (newMatch.rule == 0) {
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000445 sUidOwnerMap.deleteEntry(new S32(uid));
Motomu Utsumi60ed3be2022-06-24 10:38:57 +0000446 } else {
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000447 sUidOwnerMap.updateEntry(new S32(uid), newMatch);
Motomu Utsumi60ed3be2022-06-24 10:38:57 +0000448 }
449 }
450 } catch (ErrnoException e) {
451 throw new ServiceSpecificException(e.errno,
452 caller + " failed to remove rule: " + Os.strerror(e.errno));
453 }
454 }
455
Maciej Żenczykowski6c1c6bb2022-09-16 06:55:33 +0000456 private void addRule(final int uid, final long match, final int iif, final String caller) {
Motomu Utsumi389278e2022-06-28 07:05:05 +0000457 if (match != IIF_MATCH && iif != 0) {
458 throw new ServiceSpecificException(EINVAL,
459 "Non-interface match must have zero interface index");
460 }
461
462 try {
463 synchronized (sUidOwnerMap) {
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000464 final UidOwnerValue oldMatch = sUidOwnerMap.getValue(new S32(uid));
Motomu Utsumi389278e2022-06-28 07:05:05 +0000465
466 final UidOwnerValue newMatch;
467 if (oldMatch != null) {
468 newMatch = new UidOwnerValue(
469 (match == IIF_MATCH) ? iif : oldMatch.iif,
470 oldMatch.rule | match
471 );
472 } else {
473 newMatch = new UidOwnerValue(
474 iif,
475 match
476 );
477 }
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000478 sUidOwnerMap.updateEntry(new S32(uid), newMatch);
Motomu Utsumi389278e2022-06-28 07:05:05 +0000479 }
480 } catch (ErrnoException e) {
481 throw new ServiceSpecificException(e.errno,
482 caller + " failed to add rule: " + Os.strerror(e.errno));
483 }
484 }
485
486 private void addRule(final int uid, final long match, final String caller) {
487 addRule(uid, match, 0 /* iif */, caller);
488 }
489
Ken Chenf5f51332022-01-28 10:08:16 +0800490 /**
491 * Add naughty app bandwidth rule for specific app
492 *
493 * @param uid uid of target app
Ken Chenf5f51332022-01-28 10:08:16 +0800494 * @throws ServiceSpecificException in case of failure, with an error code indicating the
495 * cause of the failure.
496 */
Junyu Lai626045a2023-08-28 18:49:44 +0800497 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Lorenzo Colitti82244fd2022-03-04 23:15:00 +0900498 public void addNaughtyApp(final int uid) {
Motomu Utsumi389278e2022-06-28 07:05:05 +0000499 throwIfPreT("addNaughtyApp is not available on pre-T devices");
Motomu Utsumi55c282e2022-08-03 06:25:33 +0000500
501 if (sEnableJavaBpfMap) {
502 addRule(uid, PENALTY_BOX_MATCH, "addNaughtyApp");
503 } else {
504 final int err = native_addNaughtyApp(uid);
505 maybeThrow(err, "Unable to add naughty app");
506 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800507 }
508
Ken Chenf5f51332022-01-28 10:08:16 +0800509 /**
510 * Remove naughty app bandwidth rule for specific app
511 *
512 * @param uid uid of target app
Ken Chenf5f51332022-01-28 10:08:16 +0800513 * @throws ServiceSpecificException in case of failure, with an error code indicating the
514 * cause of the failure.
515 */
Junyu Lai626045a2023-08-28 18:49:44 +0800516 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Lorenzo Colitti82244fd2022-03-04 23:15:00 +0900517 public void removeNaughtyApp(final int uid) {
Motomu Utsumi60ed3be2022-06-24 10:38:57 +0000518 throwIfPreT("removeNaughtyApp is not available on pre-T devices");
Motomu Utsumi878ce0d2022-08-03 06:22:42 +0000519
520 if (sEnableJavaBpfMap) {
521 removeRule(uid, PENALTY_BOX_MATCH, "removeNaughtyApp");
522 } else {
523 final int err = native_removeNaughtyApp(uid);
524 maybeThrow(err, "Unable to remove naughty app");
525 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800526 }
527
Ken Chenf5f51332022-01-28 10:08:16 +0800528 /**
529 * Add nice app bandwidth rule for specific app
530 *
531 * @param uid uid of target app
Ken Chenf5f51332022-01-28 10:08:16 +0800532 * @throws ServiceSpecificException in case of failure, with an error code indicating the
533 * cause of the failure.
534 */
Junyu Lai626045a2023-08-28 18:49:44 +0800535 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Lorenzo Colitti82244fd2022-03-04 23:15:00 +0900536 public void addNiceApp(final int uid) {
Motomu Utsumi55630d02022-06-29 07:46:52 +0000537 throwIfPreT("addNiceApp is not available on pre-T devices");
Motomu Utsumi7f19df92022-08-03 06:29:59 +0000538
539 if (sEnableJavaBpfMap) {
540 addRule(uid, HAPPY_BOX_MATCH, "addNiceApp");
541 } else {
542 final int err = native_addNiceApp(uid);
543 maybeThrow(err, "Unable to add nice app");
544 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800545 }
546
Ken Chenf5f51332022-01-28 10:08:16 +0800547 /**
548 * Remove nice app bandwidth rule for specific app
549 *
550 * @param uid uid of target app
Ken Chenf5f51332022-01-28 10:08:16 +0800551 * @throws ServiceSpecificException in case of failure, with an error code indicating the
552 * cause of the failure.
553 */
Junyu Lai626045a2023-08-28 18:49:44 +0800554 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Lorenzo Colitti82244fd2022-03-04 23:15:00 +0900555 public void removeNiceApp(final int uid) {
Motomu Utsumi7392eb42022-06-29 03:53:03 +0000556 throwIfPreT("removeNiceApp is not available on pre-T devices");
Motomu Utsumi5f15f752022-08-03 06:27:51 +0000557
558 if (sEnableJavaBpfMap) {
559 removeRule(uid, HAPPY_BOX_MATCH, "removeNiceApp");
560 } else {
561 final int err = native_removeNiceApp(uid);
562 maybeThrow(err, "Unable to remove nice app");
563 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800564 }
565
Ken Chenf5f51332022-01-28 10:08:16 +0800566 /**
567 * Set target firewall child chain
568 *
569 * @param childChain target chain to enable
570 * @param enable whether to enable or disable child chain.
Motomu Utsumi18b287d2022-06-19 10:45:30 +0000571 * @throws UnsupportedOperationException if called on pre-T devices.
Ken Chenf5f51332022-01-28 10:08:16 +0800572 * @throws ServiceSpecificException in case of failure, with an error code indicating the
573 * cause of the failure.
574 */
Junyu Lai626045a2023-08-28 18:49:44 +0800575 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Lorenzo Colitti82244fd2022-03-04 23:15:00 +0900576 public void setChildChain(final int childChain, final boolean enable) {
Motomu Utsumi25cf86f2022-06-27 08:50:19 +0000577 throwIfPreT("setChildChain is not available on pre-T devices");
Motomu Utsumi18b287d2022-06-19 10:45:30 +0000578
Motomu Utsumie057dd42022-08-03 01:23:49 +0000579 if (sEnableJavaBpfMap) {
580 final long match = getMatchByFirewallChain(childChain);
581 try {
582 synchronized (sUidRulesConfigBpfMapLock) {
583 final U32 config = sConfigurationMap.getValue(UID_RULES_CONFIGURATION_KEY);
584 final long newConfig = enable ? (config.val | match) : (config.val & ~match);
585 sConfigurationMap.updateEntry(UID_RULES_CONFIGURATION_KEY, new U32(newConfig));
586 }
587 } catch (ErrnoException e) {
588 throw new ServiceSpecificException(e.errno,
589 "Unable to set child chain: " + Os.strerror(e.errno));
Motomu Utsumi18b287d2022-06-19 10:45:30 +0000590 }
Motomu Utsumie057dd42022-08-03 01:23:49 +0000591 } else {
592 final int err = native_setChildChain(childChain, enable);
593 maybeThrow(err, "Unable to set child chain");
Motomu Utsumi18b287d2022-06-19 10:45:30 +0000594 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800595 }
596
597 /**
Motomu Utsumi25cf86f2022-06-27 08:50:19 +0000598 * Get the specified firewall chain's status.
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +0000599 *
600 * @param childChain target chain
601 * @return {@code true} if chain is enabled, {@code false} if chain is not enabled.
602 * @throws UnsupportedOperationException if called on pre-T devices.
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +0000603 * @throws ServiceSpecificException in case of failure, with an error code indicating the
604 * cause of the failure.
Junyu Lai626045a2023-08-28 18:49:44 +0800605 *
606 * @deprecated Use {@link BpfNetMapsReader#isChainEnabled} instead.
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +0000607 */
Junyu Lai626045a2023-08-28 18:49:44 +0800608 // TODO: Migrate the callers to use {@link BpfNetMapsReader#isChainEnabled} instead.
609 @Deprecated
610 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Motomu Utsumi25cf86f2022-06-27 08:50:19 +0000611 public boolean isChainEnabled(final int childChain) {
Junyu Lai626045a2023-08-28 18:49:44 +0800612 return BpfNetMapsReader.isChainEnabled(sConfigurationMap, childChain);
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +0000613 }
614
Motomu Utsumi1a477b02022-08-23 15:14:56 +0900615 private Set<Integer> asSet(final int[] uids) {
616 final Set<Integer> uidSet = new ArraySet<>();
Motomu Utsumi77b49992023-10-23 17:06:12 +0900617 for (final int uid : uids) {
Motomu Utsumi1a477b02022-08-23 15:14:56 +0900618 uidSet.add(uid);
619 }
620 return uidSet;
621 }
622
Motomu Utsumibe3ff1e2022-06-08 10:05:07 +0000623 /**
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800624 * Replaces the contents of the specified UID-based firewall chain.
Motomu Utsumi9be2ea02022-07-05 06:14:59 +0000625 * Enables the chain for specified uids and disables the chain for non-specified uids.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800626 *
Motomu Utsumi9be2ea02022-07-05 06:14:59 +0000627 * @param chain Target chain.
Ken Chenf5f51332022-01-28 10:08:16 +0800628 * @param uids The list of UIDs to allow/deny.
Motomu Utsumi9be2ea02022-07-05 06:14:59 +0000629 * @throws UnsupportedOperationException if called on pre-T devices.
630 * @throws IllegalArgumentException if {@code chain} is not a valid chain.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800631 */
Junyu Lai626045a2023-08-28 18:49:44 +0800632 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Motomu Utsumi9be2ea02022-07-05 06:14:59 +0000633 public void replaceUidChain(final int chain, final int[] uids) {
634 throwIfPreT("replaceUidChain is not available on pre-T devices");
635
Motomu Utsumic7c16852022-08-03 06:51:41 +0000636 if (sEnableJavaBpfMap) {
637 final long match;
638 try {
639 match = getMatchByFirewallChain(chain);
640 } catch (ServiceSpecificException e) {
641 // Throws IllegalArgumentException to keep the behavior of
642 // ConnectivityManager#replaceFirewallChain API
643 throw new IllegalArgumentException("Invalid firewall chain: " + chain);
Motomu Utsumi5a68a212022-06-24 10:14:31 +0000644 }
Motomu Utsumi1a477b02022-08-23 15:14:56 +0900645 final Set<Integer> uidSet = asSet(uids);
646 final Set<Integer> uidSetToRemoveRule = new ArraySet<>();
Motomu Utsumic7c16852022-08-03 06:51:41 +0000647 try {
648 synchronized (sUidOwnerMap) {
649 sUidOwnerMap.forEach((uid, config) -> {
650 // config could be null if there is a concurrent entry deletion.
Motomu Utsumi8e420ea2022-08-24 18:03:30 +0900651 // http://b/220084230. But sUidOwnerMap update must be done while holding a
652 // lock, so this should not happen.
653 if (config == null) {
654 Log.wtf(TAG, "sUidOwnerMap entry was deleted while holding a lock");
655 } else if (!uidSet.contains((int) uid.val) && (config.rule & match) != 0) {
Motomu Utsumic7c16852022-08-03 06:51:41 +0000656 uidSetToRemoveRule.add((int) uid.val);
657 }
658 });
659
660 for (final int uid : uidSetToRemoveRule) {
661 removeRule(uid, match, "replaceUidChain");
662 }
663 for (final int uid : uids) {
664 addRule(uid, match, "replaceUidChain");
665 }
666 }
667 } catch (ErrnoException | ServiceSpecificException e) {
668 Log.e(TAG, "replaceUidChain failed: " + e);
669 }
670 } else {
671 final int err;
672 switch (chain) {
673 case FIREWALL_CHAIN_DOZABLE:
674 err = native_replaceUidChain("fw_dozable", true /* isAllowList */, uids);
675 break;
676 case FIREWALL_CHAIN_STANDBY:
677 err = native_replaceUidChain("fw_standby", false /* isAllowList */, uids);
678 break;
679 case FIREWALL_CHAIN_POWERSAVE:
680 err = native_replaceUidChain("fw_powersave", true /* isAllowList */, uids);
681 break;
682 case FIREWALL_CHAIN_RESTRICTED:
683 err = native_replaceUidChain("fw_restricted", true /* isAllowList */, uids);
684 break;
685 case FIREWALL_CHAIN_LOW_POWER_STANDBY:
686 err = native_replaceUidChain(
687 "fw_low_power_standby", true /* isAllowList */, uids);
688 break;
689 case FIREWALL_CHAIN_OEM_DENY_1:
690 err = native_replaceUidChain("fw_oem_deny_1", false /* isAllowList */, uids);
691 break;
692 case FIREWALL_CHAIN_OEM_DENY_2:
693 err = native_replaceUidChain("fw_oem_deny_2", false /* isAllowList */, uids);
694 break;
695 case FIREWALL_CHAIN_OEM_DENY_3:
696 err = native_replaceUidChain("fw_oem_deny_3", false /* isAllowList */, uids);
697 break;
698 default:
699 throw new IllegalArgumentException("replaceFirewallChain with invalid chain: "
700 + chain);
701 }
702 if (err != 0) {
703 Log.e(TAG, "replaceUidChain failed: " + Os.strerror(-err));
704 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800705 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800706 }
707
Ken Chenf5f51332022-01-28 10:08:16 +0800708 /**
709 * Set firewall rule for uid
710 *
711 * @param childChain target chain
712 * @param uid uid to allow/deny
713 * @param firewallRule either FIREWALL_RULE_ALLOW or FIREWALL_RULE_DENY
Ken Chenf5f51332022-01-28 10:08:16 +0800714 * @throws ServiceSpecificException in case of failure, with an error code indicating the
715 * cause of the failure.
716 */
Junyu Lai626045a2023-08-28 18:49:44 +0800717 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Lorenzo Colitti82244fd2022-03-04 23:15:00 +0900718 public void setUidRule(final int childChain, final int uid, final int firewallRule) {
Motomu Utsumi40230be2022-07-05 03:27:35 +0000719 throwIfPreT("setUidRule is not available on pre-T devices");
720
Motomu Utsumi381ad9e2022-08-03 06:42:47 +0000721 if (sEnableJavaBpfMap) {
722 final long match = getMatchByFirewallChain(childChain);
723 final boolean isAllowList = isFirewallAllowList(childChain);
724 final boolean add = (firewallRule == FIREWALL_RULE_ALLOW && isAllowList)
725 || (firewallRule == FIREWALL_RULE_DENY && !isAllowList);
Motomu Utsumi40230be2022-07-05 03:27:35 +0000726
Motomu Utsumi381ad9e2022-08-03 06:42:47 +0000727 if (add) {
728 addRule(uid, match, "setUidRule");
729 } else {
730 removeRule(uid, match, "setUidRule");
731 }
Motomu Utsumi40230be2022-07-05 03:27:35 +0000732 } else {
Motomu Utsumi381ad9e2022-08-03 06:42:47 +0000733 final int err = native_setUidRule(childChain, uid, firewallRule);
734 maybeThrow(err, "Unable to set uid rule");
Motomu Utsumi5a68a212022-06-24 10:14:31 +0000735 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800736 }
737
738 /**
Motomu Utsumi56c412a2023-01-19 15:58:39 +0900739 * Get firewall rule of specified firewall chain on specified uid.
740 *
741 * @param childChain target chain
742 * @param uid target uid
743 * @return either FIREWALL_RULE_ALLOW or FIREWALL_RULE_DENY
744 * @throws UnsupportedOperationException if called on pre-T devices.
745 * @throws ServiceSpecificException in case of failure, with an error code indicating the
746 * cause of the failure.
Junyu Lai626045a2023-08-28 18:49:44 +0800747 *
748 * @deprecated use {@link BpfNetMapsReader#getUidRule} instead.
Motomu Utsumi56c412a2023-01-19 15:58:39 +0900749 */
Junyu Lai626045a2023-08-28 18:49:44 +0800750 // TODO: Migrate the callers to use {@link BpfNetMapsReader#getUidRule} instead.
Motomu Utsumi56c412a2023-01-19 15:58:39 +0900751 public int getUidRule(final int childChain, final int uid) {
Junyu Lai626045a2023-08-28 18:49:44 +0800752 return BpfNetMapsReader.getUidRule(sUidOwnerMap, childChain, uid);
Motomu Utsumi56c412a2023-01-19 15:58:39 +0900753 }
754
Motomu Utsumid44a33a2023-03-28 18:08:12 +0900755 private Set<Integer> getUidsMatchEnabled(final int childChain) throws ErrnoException {
756 final long match = getMatchByFirewallChain(childChain);
757 Set<Integer> uids = new ArraySet<>();
758 synchronized (sUidOwnerMap) {
759 sUidOwnerMap.forEach((uid, val) -> {
760 if (val == null) {
761 Log.wtf(TAG, "sUidOwnerMap entry was deleted while holding a lock");
762 } else {
763 if ((val.rule & match) != 0) {
764 uids.add(uid.val);
765 }
766 }
767 });
768 }
769 return uids;
770 }
771
772 /**
773 * Get uids that has FIREWALL_RULE_ALLOW on allowlist chain.
774 * Allowlist means the firewall denies all by default, uids must be explicitly allowed.
775 *
776 * Note that uids that has FIREWALL_RULE_DENY on allowlist chain can not be computed from the
777 * bpf map, since all the uids that does not have explicit FIREWALL_RULE_ALLOW rule in bpf map
778 * are determined to have FIREWALL_RULE_DENY.
779 *
780 * @param childChain target chain
781 * @return Set of uids
782 */
783 public Set<Integer> getUidsWithAllowRuleOnAllowListChain(final int childChain)
784 throws ErrnoException {
785 if (!isFirewallAllowList(childChain)) {
786 throw new IllegalArgumentException("getUidsWithAllowRuleOnAllowListChain is called with"
787 + " denylist chain:" + childChain);
788 }
789 // Corresponding match is enabled for uids that has FIREWALL_RULE_ALLOW on allowlist chain.
790 return getUidsMatchEnabled(childChain);
791 }
792
793 /**
794 * Get uids that has FIREWALL_RULE_DENY on denylist chain.
795 * Denylist means the firewall allows all by default, uids must be explicitly denyed
796 *
797 * Note that uids that has FIREWALL_RULE_ALLOW on denylist chain can not be computed from the
798 * bpf map, since all the uids that does not have explicit FIREWALL_RULE_DENY rule in bpf map
799 * are determined to have the FIREWALL_RULE_ALLOW.
800 *
801 * @param childChain target chain
802 * @return Set of uids
803 */
804 public Set<Integer> getUidsWithDenyRuleOnDenyListChain(final int childChain)
805 throws ErrnoException {
806 if (isFirewallAllowList(childChain)) {
807 throw new IllegalArgumentException("getUidsWithDenyRuleOnDenyListChain is called with"
808 + " allowlist chain:" + childChain);
809 }
810 // Corresponding match is enabled for uids that has FIREWALL_RULE_DENY on denylist chain.
811 return getUidsMatchEnabled(childChain);
812 }
813
Motomu Utsumi56c412a2023-01-19 15:58:39 +0900814 /**
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800815 * Add ingress interface filtering rules to a list of UIDs
816 *
817 * For a given uid, once a filtering rule is added, the kernel will only allow packets from the
818 * allowed interface and loopback to be sent to the list of UIDs.
819 *
820 * Calling this method on one or more UIDs with an existing filtering rule but a different
821 * interface name will result in the filtering rule being updated to allow the new interface
822 * instead. Otherwise calling this method will not affect existing rules set on other UIDs.
823 *
824 * @param ifName the name of the interface on which the filtering rules will allow packets to
Ken Chenf5f51332022-01-28 10:08:16 +0800825 * be received.
826 * @param uids an array of UIDs which the filtering rules will be set
827 * @throws RemoteException when netd has crashed.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800828 * @throws ServiceSpecificException in case of failure, with an error code indicating the
Ken Chenf5f51332022-01-28 10:08:16 +0800829 * cause of the failure.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800830 */
Ken Chenf5f51332022-01-28 10:08:16 +0800831 public void addUidInterfaceRules(final String ifName, final int[] uids) throws RemoteException {
Motomu Utsumi25cf86f2022-06-27 08:50:19 +0000832 if (PRE_T) {
Ken Chenf5f51332022-01-28 10:08:16 +0800833 mNetd.firewallAddUidInterfaceRules(ifName, uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800834 return;
835 }
Motomu Utsumif794e7d2022-08-03 06:38:43 +0000836
837 if (sEnableJavaBpfMap) {
838 // Null ifName is a wildcard to allow apps to receive packets on all interfaces and
839 // ifIndex is set to 0.
840 final int ifIndex;
841 if (ifName == null) {
842 ifIndex = 0;
843 } else {
844 ifIndex = mDeps.getIfIndex(ifName);
845 if (ifIndex == 0) {
846 throw new ServiceSpecificException(ENODEV,
847 "Failed to get index of interface " + ifName);
848 }
849 }
850 for (final int uid : uids) {
851 try {
852 addRule(uid, IIF_MATCH, ifIndex, "addUidInterfaceRules");
853 } catch (ServiceSpecificException e) {
854 Log.e(TAG, "addRule failed uid=" + uid + " ifName=" + ifName + ", " + e);
855 }
856 }
Motomu Utsumi5f52f4f2022-06-30 03:31:09 +0000857 } else {
Motomu Utsumif794e7d2022-08-03 06:38:43 +0000858 final int err = native_addUidInterfaceRules(ifName, uids);
859 maybeThrow(err, "Unable to add uid interface rules");
Motomu Utsumi5a68a212022-06-24 10:14:31 +0000860 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800861 }
862
863 /**
864 * Remove ingress interface filtering rules from a list of UIDs
865 *
866 * Clear the ingress interface filtering rules from the list of UIDs which were previously set
867 * by addUidInterfaceRules(). Ignore any uid which does not have filtering rule.
868 *
869 * @param uids an array of UIDs from which the filtering rules will be removed
Ken Chenf5f51332022-01-28 10:08:16 +0800870 * @throws RemoteException when netd has crashed.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800871 * @throws ServiceSpecificException in case of failure, with an error code indicating the
Ken Chenf5f51332022-01-28 10:08:16 +0800872 * cause of the failure.
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800873 */
Ken Chenf5f51332022-01-28 10:08:16 +0800874 public void removeUidInterfaceRules(final int[] uids) throws RemoteException {
Motomu Utsumi25cf86f2022-06-27 08:50:19 +0000875 if (PRE_T) {
Ken Chenf5f51332022-01-28 10:08:16 +0800876 mNetd.firewallRemoveUidInterfaceRules(uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800877 return;
878 }
Motomu Utsumi7dc657d2022-08-03 06:40:46 +0000879
880 if (sEnableJavaBpfMap) {
881 for (final int uid : uids) {
882 try {
883 removeRule(uid, IIF_MATCH, "removeUidInterfaceRules");
884 } catch (ServiceSpecificException e) {
885 Log.e(TAG, "removeRule failed uid=" + uid + ", " + e);
886 }
Motomu Utsumi599c4e52022-06-30 03:37:18 +0000887 }
Motomu Utsumi7dc657d2022-08-03 06:40:46 +0000888 } else {
889 final int err = native_removeUidInterfaceRules(uids);
890 maybeThrow(err, "Unable to remove uid interface rules");
Motomu Utsumi5a68a212022-06-24 10:14:31 +0000891 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800892 }
893
Ken Chenf5f51332022-01-28 10:08:16 +0800894 /**
Motomu Utsumi8b42e6d2022-05-19 06:23:40 +0000895 * Update lockdown rule for uid
896 *
897 * @param uid target uid to add/remove the rule
898 * @param add {@code true} to add the rule, {@code false} to remove the rule.
899 * @throws ServiceSpecificException in case of failure, with an error code indicating the
900 * cause of the failure.
901 */
Junyu Lai626045a2023-08-28 18:49:44 +0800902 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Motomu Utsumi8b42e6d2022-05-19 06:23:40 +0000903 public void updateUidLockdownRule(final int uid, final boolean add) {
Motomu Utsumi697b2992022-06-30 02:25:29 +0000904 throwIfPreT("updateUidLockdownRule is not available on pre-T devices");
Motomu Utsumib2d32b72022-08-03 06:31:58 +0000905
906 if (sEnableJavaBpfMap) {
907 if (add) {
908 addRule(uid, LOCKDOWN_VPN_MATCH, "updateUidLockdownRule");
909 } else {
910 removeRule(uid, LOCKDOWN_VPN_MATCH, "updateUidLockdownRule");
911 }
Motomu Utsumi697b2992022-06-30 02:25:29 +0000912 } else {
Motomu Utsumib2d32b72022-08-03 06:31:58 +0000913 final int err = native_updateUidLockdownRule(uid, add);
914 maybeThrow(err, "Unable to update lockdown rule");
Motomu Utsumi5a68a212022-06-24 10:14:31 +0000915 }
Motomu Utsumi8b42e6d2022-05-19 06:23:40 +0000916 }
917
918 /**
Ken Chenf5f51332022-01-28 10:08:16 +0800919 * Request netd to change the current active network stats map.
920 *
Motomu Utsumi7abeaa42022-07-20 07:54:18 +0000921 * @throws UnsupportedOperationException if called on pre-T devices.
Ken Chenf5f51332022-01-28 10:08:16 +0800922 * @throws ServiceSpecificException in case of failure, with an error code indicating the
923 * cause of the failure.
924 */
Junyu Lai626045a2023-08-28 18:49:44 +0800925 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
markchien49e944c2022-03-01 15:22:20 +0800926 public void swapActiveStatsMap() {
Motomu Utsumi7abeaa42022-07-20 07:54:18 +0000927 throwIfPreT("swapActiveStatsMap is not available on pre-T devices");
928
929 if (sEnableJavaBpfMap) {
930 try {
931 synchronized (sCurrentStatsMapConfigLock) {
932 final long config = sConfigurationMap.getValue(
933 CURRENT_STATS_MAP_CONFIGURATION_KEY).val;
934 final long newConfig = (config == STATS_SELECT_MAP_A)
935 ? STATS_SELECT_MAP_B : STATS_SELECT_MAP_A;
936 sConfigurationMap.updateEntry(CURRENT_STATS_MAP_CONFIGURATION_KEY,
937 new U32(newConfig));
938 }
939 } catch (ErrnoException e) {
940 throw new ServiceSpecificException(e.errno, "Failed to swap active stats map");
941 }
942
943 // After changing the config, it's needed to make sure all the current running eBPF
944 // programs are finished and all the CPUs are aware of this config change before the old
945 // map is modified. So special hack is needed here to wait for the kernel to do a
946 // synchronize_rcu(). Once the kernel called synchronize_rcu(), the updated config will
947 // be available to all cores and the next eBPF programs triggered inside the kernel will
948 // use the new map configuration. So once this function returns it is safe to modify the
949 // old stats map without concerning about race between the kernel and userspace.
950 final int err = mDeps.synchronizeKernelRCU();
951 maybeThrow(err, "synchronizeKernelRCU failed");
952 } else {
953 final int err = native_swapActiveStatsMap();
954 maybeThrow(err, "Unable to swap active stats map");
955 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800956 }
957
Ken Chenf5f51332022-01-28 10:08:16 +0800958 /**
959 * Assigns android.permission.INTERNET and/or android.permission.UPDATE_DEVICE_STATS to the uids
960 * specified. Or remove all permissions from the uids.
961 *
962 * @param permissions The permission to grant, it could be either PERMISSION_INTERNET and/or
963 * PERMISSION_UPDATE_DEVICE_STATS. If the permission is NO_PERMISSIONS, then
964 * revoke all permissions for the uids.
965 * @param uids uid of users to grant permission
966 * @throws RemoteException when netd has crashed.
967 */
968 public void setNetPermForUids(final int permissions, final int[] uids) throws RemoteException {
Motomu Utsumi25cf86f2022-06-27 08:50:19 +0000969 if (PRE_T) {
Ken Chenf5f51332022-01-28 10:08:16 +0800970 mNetd.trafficSetNetPermForUids(permissions, uids);
Wayne Ma2fde98c2022-01-17 18:04:05 +0800971 return;
972 }
Motomu Utsumi65271202022-07-05 08:21:41 +0000973
974 if (sEnableJavaBpfMap) {
975 // Remove the entry if package is uninstalled or uid has only INTERNET permission.
976 if (permissions == PERMISSION_UNINSTALLED || permissions == PERMISSION_INTERNET) {
977 for (final int uid : uids) {
978 try {
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000979 sUidPermissionMap.deleteEntry(new S32(uid));
Motomu Utsumi65271202022-07-05 08:21:41 +0000980 } catch (ErrnoException e) {
981 Log.e(TAG, "Failed to remove uid " + uid + " from permission map: " + e);
982 }
983 }
984 return;
985 }
986
987 for (final int uid : uids) {
988 try {
Maciej Żenczykowski785793f2022-09-17 02:35:20 +0000989 sUidPermissionMap.updateEntry(new S32(uid), new U8((short) permissions));
Motomu Utsumi65271202022-07-05 08:21:41 +0000990 } catch (ErrnoException e) {
991 Log.e(TAG, "Failed to set permission "
992 + permissions + " to uid " + uid + ": " + e);
993 }
994 }
995 } else {
996 native_setPermissionForUids(permissions, uids);
997 }
Wayne Ma0ea3bdc2022-01-12 01:12:11 +0800998 }
999
Ken Chen24330172023-10-20 13:02:14 +08001000 /**
1001 * Set Data Saver enabled or disabled
1002 *
1003 * @param enable whether Data Saver is enabled or disabled.
1004 * @throws UnsupportedOperationException if called on pre-T devices.
1005 * @throws ServiceSpecificException in case of failure, with an error code indicating the
1006 * cause of the failure.
1007 */
1008 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
1009 public void setDataSaverEnabled(boolean enable) {
1010 throwIfPreT("setDataSaverEnabled is not available on pre-T devices");
1011
1012 try {
1013 final short config = enable ? DATA_SAVER_ENABLED : DATA_SAVER_DISABLED;
1014 sDataSaverEnabledMap.updateEntry(DATA_SAVER_ENABLED_KEY, new U8(config));
1015 } catch (ErrnoException e) {
1016 throw new ServiceSpecificException(e.errno, "Unable to set data saver: "
1017 + Os.strerror(e.errno));
1018 }
1019 }
1020
Motomu Utsumi77b49992023-10-23 17:06:12 +09001021 /**
1022 * Set ingress discard rule
1023 *
1024 * @param address target address to set the ingress discard rule
1025 * @param iface allowed interface
1026 */
1027 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
1028 public void setIngressDiscardRule(final InetAddress address, final String iface) {
1029 throwIfPreT("setIngressDiscardRule is not available on pre-T devices");
1030 final int ifIndex = mDeps.getIfIndex(iface);
1031 if (ifIndex == 0) {
1032 Log.e(TAG, "Failed to get if index, skip setting ingress discard rule for " + address
1033 + "(" + iface + ")");
1034 return;
1035 }
1036 try {
1037 sIngressDiscardMap.updateEntry(new IngressDiscardKey(address),
1038 new IngressDiscardValue(ifIndex, ifIndex));
1039 } catch (ErrnoException e) {
1040 Log.e(TAG, "Failed to set ingress discard rule for " + address + "("
1041 + iface + "), " + e);
1042 }
1043 }
1044
1045 /**
1046 * Remove ingress discard rule
1047 *
1048 * @param address target address to remove the ingress discard rule
1049 */
1050 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
1051 public void removeIngressDiscardRule(final InetAddress address) {
1052 throwIfPreT("removeIngressDiscardRule is not available on pre-T devices");
1053 try {
1054 sIngressDiscardMap.deleteEntry(new IngressDiscardKey(address));
1055 } catch (ErrnoException e) {
1056 Log.e(TAG, "Failed to remove ingress discard rule for " + address + ", " + e);
1057 }
1058 }
1059
Motomu Utsumi166f9662022-09-01 10:35:29 +09001060 /** Register callback for statsd to pull atom. */
Junyu Lai626045a2023-08-28 18:49:44 +08001061 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Motomu Utsumi166f9662022-09-01 10:35:29 +09001062 public void setPullAtomCallback(final Context context) {
1063 throwIfPreT("setPullAtomCallback is not available on pre-T devices");
1064
1065 final StatsManager statsManager = context.getSystemService(StatsManager.class);
1066 statsManager.setPullAtomCallback(NETWORK_BPF_MAP_INFO, null /* metadata */,
1067 BackgroundThread.getExecutor(), this::pullBpfMapInfoAtom);
1068 }
1069
1070 private <K extends Struct, V extends Struct> int getMapSize(IBpfMap<K, V> map)
1071 throws ErrnoException {
1072 // forEach could restart iteration from the beginning if there is a concurrent entry
1073 // deletion. netd and skDestroyListener could delete CookieTagMap entry concurrently.
1074 // So using Set to count the number of entry in the map.
1075 Set<K> keySet = new ArraySet<>();
1076 map.forEach((k, v) -> keySet.add(k));
1077 return keySet.size();
1078 }
1079
1080 /** Callback for StatsManager#setPullAtomCallback */
1081 @VisibleForTesting
1082 public int pullBpfMapInfoAtom(final int atomTag, final List<StatsEvent> data) {
1083 if (atomTag != NETWORK_BPF_MAP_INFO) {
1084 Log.e(TAG, "Unexpected atom tag: " + atomTag);
1085 return StatsManager.PULL_SKIP;
1086 }
1087
1088 try {
1089 data.add(mDeps.buildStatsEvent(getMapSize(sCookieTagMap), getMapSize(sUidOwnerMap),
1090 getMapSize(sUidPermissionMap)));
1091 } catch (ErrnoException e) {
1092 Log.e(TAG, "Failed to pull NETWORK_BPF_MAP_INFO atom: " + e);
1093 return StatsManager.PULL_SKIP;
1094 }
1095 return StatsManager.PULL_SUCCESS;
1096 }
1097
Motomu Utsumi310850f2022-09-02 12:48:20 +09001098 private String permissionToString(int permissionMask) {
1099 if (permissionMask == PERMISSION_NONE) {
1100 return "PERMISSION_NONE";
1101 }
1102 if (permissionMask == PERMISSION_UNINSTALLED) {
1103 // PERMISSION_UNINSTALLED should never appear in the map
1104 return "PERMISSION_UNINSTALLED error!";
1105 }
1106
1107 final StringJoiner sj = new StringJoiner(" ");
1108 for (Pair<Integer, String> permission: PERMISSION_LIST) {
1109 final int permissionFlag = permission.first;
1110 final String permissionName = permission.second;
1111 if ((permissionMask & permissionFlag) != 0) {
1112 sj.add(permissionName);
1113 permissionMask &= ~permissionFlag;
1114 }
1115 }
1116 if (permissionMask != 0) {
1117 sj.add("PERMISSION_UNKNOWN(" + permissionMask + ")");
1118 }
1119 return sj.toString();
1120 }
1121
Motomu Utsumi372c9b42022-09-02 19:02:56 +09001122 private void dumpOwnerMatchConfig(final IndentingPrintWriter pw) {
1123 try {
1124 final long match = sConfigurationMap.getValue(UID_RULES_CONFIGURATION_KEY).val;
1125 pw.println("current ownerMatch configuration: " + match + " " + matchToString(match));
1126 } catch (ErrnoException e) {
1127 pw.println("Failed to read ownerMatch configuration: " + e);
1128 }
1129 }
1130
Motomu Utsumic675d6f2022-09-02 18:15:25 +09001131 private void dumpCurrentStatsMapConfig(final IndentingPrintWriter pw) {
1132 try {
1133 final long config = sConfigurationMap.getValue(CURRENT_STATS_MAP_CONFIGURATION_KEY).val;
1134 final String currentStatsMap =
1135 (config == STATS_SELECT_MAP_A) ? "SELECT_MAP_A" : "SELECT_MAP_B";
1136 pw.println("current statsMap configuration: " + config + " " + currentStatsMap);
1137 } catch (ErrnoException e) {
1138 pw.println("Falied to read current statsMap configuration: " + e);
1139 }
1140 }
1141
Ken Chen24330172023-10-20 13:02:14 +08001142 private void dumpDataSaverConfig(final IndentingPrintWriter pw) {
1143 try {
1144 final short config = sDataSaverEnabledMap.getValue(DATA_SAVER_ENABLED_KEY).val;
1145 // Any non-zero value converted from short to boolean is true by convention.
1146 pw.println("sDataSaverEnabledMap: " + (config != DATA_SAVER_DISABLED));
1147 } catch (ErrnoException e) {
1148 pw.println("Failed to read data saver configuration: " + e);
1149 }
1150 }
Ken Chene6d511f2022-01-25 11:10:42 +08001151 /**
1152 * Dump BPF maps
1153 *
Motomu Utsumi310850f2022-09-02 12:48:20 +09001154 * @param pw print writer
Ken Chene6d511f2022-01-25 11:10:42 +08001155 * @param fd file descriptor to output
Motomu Utsumi310850f2022-09-02 12:48:20 +09001156 * @param verbose verbose dump flag, if true dump the BpfMap contents
Ken Chene6d511f2022-01-25 11:10:42 +08001157 * @throws IOException when file descriptor is invalid.
1158 * @throws ServiceSpecificException when the method is called on an unsupported device.
1159 */
Junyu Lai626045a2023-08-28 18:49:44 +08001160 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Motomu Utsumi310850f2022-09-02 12:48:20 +09001161 public void dump(final IndentingPrintWriter pw, final FileDescriptor fd, boolean verbose)
Ken Chene6d511f2022-01-25 11:10:42 +08001162 throws IOException, ServiceSpecificException {
Motomu Utsumi25cf86f2022-06-27 08:50:19 +00001163 if (PRE_T) {
Ken Chene6d511f2022-01-25 11:10:42 +08001164 throw new ServiceSpecificException(
1165 EOPNOTSUPP, "dumpsys connectivity trafficcontroller dump not available on pre-T"
1166 + " devices, use dumpsys netd trafficcontroller instead.");
1167 }
Maciej Żenczykowskid70a3302023-09-06 16:45:25 +00001168
1169 pw.println("TrafficController"); // required by CTS testDumpBpfNetMaps
Motomu Utsumi310850f2022-09-02 12:48:20 +09001170
Motomu Utsumi316d0572022-09-15 13:24:48 +09001171 pw.println();
1172 pw.println("sEnableJavaBpfMap: " + sEnableJavaBpfMap);
Motomu Utsumi310850f2022-09-02 12:48:20 +09001173 if (verbose) {
Motomu Utsumief546a92022-10-05 16:42:29 +09001174 pw.println();
1175 pw.println("BPF map content:");
1176 pw.increaseIndent();
1177
Motomu Utsumi372c9b42022-09-02 19:02:56 +09001178 dumpOwnerMatchConfig(pw);
Motomu Utsumic675d6f2022-09-02 18:15:25 +09001179 dumpCurrentStatsMapConfig(pw);
1180 pw.println();
1181
Motomu Utsumief546a92022-10-05 16:42:29 +09001182 // TODO: Remove CookieTagMap content dump
1183 // NetworkStatsService also dumps CookieTagMap and NetworkStatsService is a right place
1184 // to dump CookieTagMap. But the TagSocketTest in CTS depends on this dump so the tests
1185 // need to be updated before remove the dump from BpfNetMaps.
1186 BpfDump.dumpMap(sCookieTagMap, pw, "sCookieTagMap",
1187 (key, value) -> "cookie=" + key.socketCookie
1188 + " tag=0x" + Long.toHexString(value.tag)
1189 + " uid=" + value.uid);
Motomu Utsumi956d86c2022-09-02 17:01:25 +09001190 BpfDump.dumpMap(sUidOwnerMap, pw, "sUidOwnerMap",
1191 (uid, match) -> {
1192 if ((match.rule & IIF_MATCH) != 0) {
1193 // TODO: convert interface index to interface name by IfaceIndexNameMap
1194 return uid.val + " " + matchToString(match.rule) + " " + match.iif;
1195 } else {
1196 return uid.val + " " + matchToString(match.rule);
1197 }
1198 });
Motomu Utsumi310850f2022-09-02 12:48:20 +09001199 BpfDump.dumpMap(sUidPermissionMap, pw, "sUidPermissionMap",
1200 (uid, permission) -> uid.val + " " + permissionToString(permission.val));
Motomu Utsumi77b49992023-10-23 17:06:12 +09001201 BpfDump.dumpMap(sIngressDiscardMap, pw, "sIngressDiscardMap",
1202 (key, value) -> "[" + key.dstAddr + "]: "
1203 + value.iif1 + "(" + mDeps.getIfName(value.iif1) + "), "
1204 + value.iif2 + "(" + mDeps.getIfName(value.iif2) + ")");
Ken Chen24330172023-10-20 13:02:14 +08001205 dumpDataSaverConfig(pw);
Motomu Utsumief546a92022-10-05 16:42:29 +09001206 pw.decreaseIndent();
Motomu Utsumi310850f2022-09-02 12:48:20 +09001207 }
Ken Chene6d511f2022-01-25 11:10:42 +08001208 }
1209
Maciej Żenczykowski70fbfa42023-07-18 20:14:38 +00001210 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Motomu Utsumi3af8f0e2022-09-02 23:42:13 +09001211 private static native void native_init(boolean startSkDestroyListener);
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001212
1213 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Wayne Ma0ea3bdc2022-01-12 01:12:11 +08001214 private native int native_addNaughtyApp(int uid);
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001215
1216 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Wayne Ma0ea3bdc2022-01-12 01:12:11 +08001217 private native int native_removeNaughtyApp(int uid);
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001218
1219 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Wayne Ma0ea3bdc2022-01-12 01:12:11 +08001220 private native int native_addNiceApp(int uid);
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001221
1222 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Wayne Ma0ea3bdc2022-01-12 01:12:11 +08001223 private native int native_removeNiceApp(int uid);
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001224
1225 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Motomu Utsumi114cd9c2022-08-01 02:08:35 +00001226 private native int native_setChildChain(int childChain, boolean enable);
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001227
1228 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Wayne Ma0ea3bdc2022-01-12 01:12:11 +08001229 private native int native_replaceUidChain(String name, boolean isAllowlist, int[] uids);
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001230
1231 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Wayne Ma0ea3bdc2022-01-12 01:12:11 +08001232 private native int native_setUidRule(int childChain, int uid, int firewallRule);
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001233
1234 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Wayne Ma0ea3bdc2022-01-12 01:12:11 +08001235 private native int native_addUidInterfaceRules(String ifName, int[] uids);
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001236
1237 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Wayne Ma0ea3bdc2022-01-12 01:12:11 +08001238 private native int native_removeUidInterfaceRules(int[] uids);
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001239
1240 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Motomu Utsumi8b42e6d2022-05-19 06:23:40 +00001241 private native int native_updateUidLockdownRule(int uid, boolean add);
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001242
1243 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Wayne Ma0ea3bdc2022-01-12 01:12:11 +08001244 private native int native_swapActiveStatsMap();
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001245
1246 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Wayne Ma2fde98c2022-01-17 18:04:05 +08001247 private native void native_setPermissionForUids(int permissions, int[] uids);
Maciej Żenczykowskie7da6fd2023-07-18 14:19:19 +00001248
1249 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
Motomu Utsumi7abeaa42022-07-20 07:54:18 +00001250 private static native int native_synchronizeKernelRCU();
Wayne Ma0ea3bdc2022-01-12 01:12:11 +08001251}