diff --git a/service/native/TrafficController.cpp b/service/native/TrafficController.cpp index 49b23c9a81..81ddd5a3c2 100644 --- a/service/native/TrafficController.cpp +++ b/service/native/TrafficController.cpp @@ -717,21 +717,6 @@ void TrafficController::dump(int fd, bool verbose) { if (!res.ok()) { dw.println("mUidOwnerMap print end with error: %s", res.error().message().c_str()); } - dumpBpfMap("mUidPermissionMap", dw, ""); - const auto printUidPermissionInfo = [&dw](const uint32_t& key, const int& value, - const BpfMap&) { - dw.println("%u %s", key, UidPermissionTypeToString(value).c_str()); - return base::Result(); - }; - res = mUidPermissionMap.iterateWithValue(printUidPermissionInfo); - if (!res.ok()) { - dw.println("mUidPermissionMap print end with error: %s", res.error().message().c_str()); - } - - dumpBpfMap("mPrivilegedUser", dw, ""); - for (uid_t uid : mPrivilegedUser) { - dw.println("%u ALLOW_UPDATE_DEVICE_STATS", (uint32_t)uid); - } } } // namespace net diff --git a/service/native/TrafficControllerTest.cpp b/service/native/TrafficControllerTest.cpp index 8525738c39..a9b45381ab 100644 --- a/service/native/TrafficControllerTest.cpp +++ b/service/native/TrafficControllerTest.cpp @@ -798,11 +798,6 @@ TEST_F(TrafficControllerTest, TestDumpsys) { expectedLines.emplace_back("mUidOwnerMap:"); expectedLines.emplace_back(fmt::format("{} HAPPY_BOX_MATCH", TEST_UID)); - mTc.setPermissionForUids(INetd::PERMISSION_UPDATE_DEVICE_STATS, {TEST_UID2}); - expectedLines.emplace_back("mUidPermissionMap:"); - expectedLines.emplace_back(fmt::format("{} BPF_PERMISSION_UPDATE_DEVICE_STATS", TEST_UID2)); - expectedLines.emplace_back("mPrivilegedUser:"); - expectedLines.emplace_back(fmt::format("{} ALLOW_UPDATE_DEVICE_STATS", TEST_UID2)); EXPECT_TRUE(expectDumpsysContains(expectedLines)); } @@ -821,8 +816,7 @@ TEST_F(TrafficControllerTest, dumpsysInvalidMaps) { fmt::format("mIfaceStatsMap {}", kErrIterate), fmt::format("mConfigurationMap {}", kErrReadRulesConfig), fmt::format("mConfigurationMap {}", kErrReadStatsMapConfig), - fmt::format("mUidOwnerMap {}", kErrIterate), - fmt::format("mUidPermissionMap {}", kErrIterate)}; + fmt::format("mUidOwnerMap {}", kErrIterate)}; EXPECT_TRUE(expectDumpsysContains(expectedLines)); } diff --git a/service/src/com/android/server/BpfNetMaps.java b/service/src/com/android/server/BpfNetMaps.java index dbfc383b72..0015da26b1 100644 --- a/service/src/com/android/server/BpfNetMaps.java +++ b/service/src/com/android/server/BpfNetMaps.java @@ -27,7 +27,9 @@ import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY; import static android.net.ConnectivityManager.FIREWALL_RULE_ALLOW; import static android.net.ConnectivityManager.FIREWALL_RULE_DENY; import static android.net.INetd.PERMISSION_INTERNET; +import static android.net.INetd.PERMISSION_NONE; import static android.net.INetd.PERMISSION_UNINSTALLED; +import static android.net.INetd.PERMISSION_UPDATE_DEVICE_STATS; import static android.system.OsConstants.EINVAL; import static android.system.OsConstants.ENODEV; import static android.system.OsConstants.ENOENT; @@ -44,12 +46,15 @@ import android.provider.DeviceConfig; import android.system.ErrnoException; import android.system.Os; import android.util.ArraySet; +import android.util.IndentingPrintWriter; import android.util.Log; +import android.util.Pair; import android.util.StatsEvent; import com.android.internal.annotations.VisibleForTesting; import com.android.modules.utils.BackgroundThread; import com.android.modules.utils.build.SdkLevel; +import com.android.net.module.util.BpfDump; import com.android.net.module.util.BpfMap; import com.android.net.module.util.DeviceConfigUtils; import com.android.net.module.util.IBpfMap; @@ -62,8 +67,10 @@ import com.android.net.module.util.bpf.CookieTagMapValue; import java.io.FileDescriptor; import java.io.IOException; +import java.util.Arrays; import java.util.List; import java.util.Set; +import java.util.StringJoiner; /** * BpfNetMaps is responsible for providing traffic controller relevant functionality. @@ -134,6 +141,11 @@ public class BpfNetMaps { @VisibleForTesting public static final long OEM_DENY_3_MATCH = (1 << 11); // LINT.ThenChange(packages/modules/Connectivity/bpf_progs/bpf_shared.h) + private static final List> PERMISSION_LIST = Arrays.asList( + Pair.create(PERMISSION_INTERNET, "PERMISSION_INTERNET"), + Pair.create(PERMISSION_UPDATE_DEVICE_STATS, "PERMISSION_UPDATE_DEVICE_STATS") + ); + /** * Set sEnableJavaBpfMap for test. */ @@ -914,14 +926,40 @@ public class BpfNetMaps { return StatsManager.PULL_SUCCESS; } + private String permissionToString(int permissionMask) { + if (permissionMask == PERMISSION_NONE) { + return "PERMISSION_NONE"; + } + if (permissionMask == PERMISSION_UNINSTALLED) { + // PERMISSION_UNINSTALLED should never appear in the map + return "PERMISSION_UNINSTALLED error!"; + } + + final StringJoiner sj = new StringJoiner(" "); + for (Pair permission: PERMISSION_LIST) { + final int permissionFlag = permission.first; + final String permissionName = permission.second; + if ((permissionMask & permissionFlag) != 0) { + sj.add(permissionName); + permissionMask &= ~permissionFlag; + } + } + if (permissionMask != 0) { + sj.add("PERMISSION_UNKNOWN(" + permissionMask + ")"); + } + return sj.toString(); + } + /** * Dump BPF maps * + * @param pw print writer * @param fd file descriptor to output + * @param verbose verbose dump flag, if true dump the BpfMap contents * @throws IOException when file descriptor is invalid. * @throws ServiceSpecificException when the method is called on an unsupported device. */ - public void dump(final FileDescriptor fd, boolean verbose) + public void dump(final IndentingPrintWriter pw, final FileDescriptor fd, boolean verbose) throws IOException, ServiceSpecificException { if (PRE_T) { throw new ServiceSpecificException( @@ -929,6 +967,11 @@ public class BpfNetMaps { + " devices, use dumpsys netd trafficcontroller instead."); } mDeps.nativeDump(fd, verbose); + + if (verbose) { + BpfDump.dumpMap(sUidPermissionMap, pw, "sUidPermissionMap", + (uid, permission) -> uid.val + " " + permissionToString(permission.val)); + } } private static native void native_init(boolean startSkDestroyListener); diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java index 84cf561511..6804bafe4e 100755 --- a/service/src/com/android/server/ConnectivityService.java +++ b/service/src/com/android/server/ConnectivityService.java @@ -3457,7 +3457,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private void dumpTrafficController(IndentingPrintWriter pw, final FileDescriptor fd, boolean verbose) { try { - mBpfNetMaps.dump(fd, verbose); + mBpfNetMaps.dump(pw, fd, verbose); } catch (ServiceSpecificException e) { pw.println(e.getMessage()); } catch (IOException e) { diff --git a/tests/unit/java/com/android/server/BpfNetMapsTest.java b/tests/unit/java/com/android/server/BpfNetMapsTest.java index 4966aed0dd..7c316074aa 100644 --- a/tests/unit/java/com/android/server/BpfNetMapsTest.java +++ b/tests/unit/java/com/android/server/BpfNetMapsTest.java @@ -61,6 +61,7 @@ import android.net.INetd; import android.os.Build; import android.os.ServiceSpecificException; import android.system.ErrnoException; +import android.util.IndentingPrintWriter; import androidx.test.filters.SmallTest; @@ -84,6 +85,8 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.io.FileDescriptor; +import java.io.StringWriter; import java.util.ArrayList; import java.util.List; @@ -927,4 +930,37 @@ public final class BpfNetMapsTest { final int ret = mBpfNetMaps.pullBpfMapInfoAtom(-1 /* atomTag */, new ArrayList<>()); assertEquals(StatsManager.PULL_SKIP, ret); } + + private void assertDumpContains(final String dump, final String message) { + assertTrue(String.format("dump(%s) does not contain '%s'", dump, message), + dump.contains(message)); + } + + private String getDump() throws Exception { + final StringWriter sw = new StringWriter(); + mBpfNetMaps.dump(new IndentingPrintWriter(sw), new FileDescriptor(), true /* verbose */); + return sw.toString(); + } + + private void doTestDumpUidPermissionMap(final int permission, final String permissionString) + throws Exception { + mUidPermissionMap.updateEntry(new S32(TEST_UID), new U8((short) permission)); + assertDumpContains(getDump(), TEST_UID + " " + permissionString); + } + + @Test + @IgnoreUpTo(Build.VERSION_CODES.S_V2) + public void testDumpUidPermissionMap() throws Exception { + doTestDumpUidPermissionMap(PERMISSION_NONE, "PERMISSION_NONE"); + doTestDumpUidPermissionMap(PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS, + "PERMISSION_INTERNET PERMISSION_UPDATE_DEVICE_STATS"); + } + + @Test + @IgnoreUpTo(Build.VERSION_CODES.S_V2) + public void testDumpUidPermissionMapInvalidPermission() throws Exception { + doTestDumpUidPermissionMap(PERMISSION_UNINSTALLED, "PERMISSION_UNINSTALLED error!"); + doTestDumpUidPermissionMap(PERMISSION_INTERNET | 1 << 6, + "PERMISSION_INTERNET PERMISSION_UNKNOWN(64)"); + } }