Verify the access to the mdnsd socket is blocked from Android U
The untrusted apps should not directly access /dev/socket/mdnsd since
Android U(SDK 34). For untrusted apps built with target SDK 33 or less,
it should still be able to access the mdnsd socket. Fix the mts test
suits from mts-networking to mts-tethering. If the test suits is marked
as mts-networking, it would run in NetworkStack MTS, which isn't really
what is tested in the tests.
Test: atest CtsNetTestCases CtsNetTestCasesMaxTargetSdk33
Bug: 267102290
Change-Id: I851c181fa7489115fb1f335a369830078f5a5c14
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 34646e2..4d3ecdf 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -58,6 +58,17 @@
]
},
{
+ "name": "CtsNetTestCasesMaxTargetSdk33",
+ "options": [
+ {
+ "exclude-annotation": "com.android.testutils.SkipPresubmit"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.RequiresDevice"
+ }
+ ]
+ },
+ {
"name": "bpf_existence_test"
},
{
@@ -143,6 +154,17 @@
}
]
},
+ {
+ "name": "CtsNetTestCasesMaxTargetSdk33[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex]",
+ "options": [
+ {
+ "exclude-annotation": "com.android.testutils.SkipPresubmit"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.RequiresDevice"
+ }
+ ]
+ },
// Test with APK modules only, in cases where APEX is not supported, or the other modules
// were simply not updated
{
diff --git a/tests/cts/net/Android.bp b/tests/cts/net/Android.bp
index 23cb15c..f9fe5b0 100644
--- a/tests/cts/net/Android.bp
+++ b/tests/cts/net/Android.bp
@@ -114,34 +114,39 @@
],
}
-android_test {
- name: "CtsNetTestCasesMaxTargetSdk31", // Must match CtsNetTestCasesMaxTargetSdk31 annotation.
+java_defaults {
+ name: "CtsNetTestCasesMaxTargetSdkDefaults",
defaults: [
"CtsNetTestCasesDefaults",
"CtsNetTestCasesApiStableDefaults",
],
- target_sdk_version: "31",
- package_name: "android.net.cts.maxtargetsdk31", // CTS package names must be unique.
- instrumentation_target_package: "android.net.cts.maxtargetsdk31",
test_suites: [
"cts",
"general-tests",
- "mts-networking",
+ "mts-tethering",
],
}
android_test {
+ name: "CtsNetTestCasesMaxTargetSdk33", // Must match CtsNetTestCasesMaxTargetSdk33 annotation.
+ defaults: ["CtsNetTestCasesMaxTargetSdkDefaults"],
+ target_sdk_version: "33",
+ package_name: "android.net.cts.maxtargetsdk33",
+ instrumentation_target_package: "android.net.cts.maxtargetsdk33",
+}
+
+android_test {
+ name: "CtsNetTestCasesMaxTargetSdk31", // Must match CtsNetTestCasesMaxTargetSdk31 annotation.
+ defaults: ["CtsNetTestCasesMaxTargetSdkDefaults"],
+ target_sdk_version: "31",
+ package_name: "android.net.cts.maxtargetsdk31", // CTS package names must be unique.
+ instrumentation_target_package: "android.net.cts.maxtargetsdk31",
+}
+
+android_test {
name: "CtsNetTestCasesMaxTargetSdk30", // Must match CtsNetTestCasesMaxTargetSdk30 annotation.
- defaults: [
- "CtsNetTestCasesDefaults",
- "CtsNetTestCasesApiStableDefaults",
- ],
+ defaults: ["CtsNetTestCasesMaxTargetSdkDefaults"],
target_sdk_version: "30",
package_name: "android.net.cts.maxtargetsdk30", // CTS package names must be unique.
instrumentation_target_package: "android.net.cts.maxtargetsdk30",
- test_suites: [
- "cts",
- "general-tests",
- "mts-networking",
- ],
}
diff --git a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
index 093c7f8..de5e46f 100644
--- a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
+++ b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
@@ -20,6 +20,8 @@
import android.net.ConnectivityManager
import android.net.ConnectivityManager.NetworkCallback
import android.net.LinkProperties
+import android.net.LocalSocket
+import android.net.LocalSocketAddress
import android.net.Network
import android.net.NetworkAgentConfig
import android.net.NetworkCapabilities
@@ -63,6 +65,8 @@
import android.util.Log
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.runner.AndroidJUnit4
+import com.android.compatibility.common.util.PollingCheck
+import com.android.compatibility.common.util.PropertyUtil
import com.android.net.module.util.ArrayTrackRecord
import com.android.net.module.util.TrackRecord
import com.android.networkstack.apishim.NsdShimImpl
@@ -72,14 +76,17 @@
import com.android.testutils.TestableNetworkAgent
import com.android.testutils.TestableNetworkCallback
import com.android.testutils.filters.CtsNetTestCasesMaxTargetSdk30
+import com.android.testutils.filters.CtsNetTestCasesMaxTargetSdk33
import com.android.testutils.runAsShell
import com.android.testutils.tryTest
import com.android.testutils.waitForIdle
import java.io.File
+import java.io.IOException
import java.net.ServerSocket
import java.nio.charset.StandardCharsets
import java.util.Random
import java.util.concurrent.Executor
+import kotlin.math.min
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertNotNull
@@ -763,6 +770,69 @@
}
}
+ private fun checkConnectSocketToMdnsd(shouldFail: Boolean) {
+ val discoveryRecord = NsdDiscoveryRecord()
+ val localSocket = LocalSocket()
+ tryTest {
+ // Discover any service from NsdManager to enforce NsdService to start the mdnsd.
+ nsdManager.discoverServices(serviceType, NsdManager.PROTOCOL_DNS_SD, discoveryRecord)
+ discoveryRecord.expectCallback<DiscoveryStarted>()
+
+ // Checks the /dev/socket/mdnsd is created.
+ val socket = File("/dev/socket/mdnsd")
+ val doesSocketExist = PollingCheck.waitFor(
+ TIMEOUT_MS,
+ {
+ socket.exists()
+ },
+ { doesSocketExist ->
+ doesSocketExist
+ },
+ )
+
+ // If the socket is not created, then no need to check the access.
+ if (doesSocketExist) {
+ // Create a LocalSocket and try to connect to mdnsd.
+ assertFalse("LocalSocket is connected.", localSocket.isConnected)
+ val address = LocalSocketAddress("mdnsd", LocalSocketAddress.Namespace.RESERVED)
+ if (shouldFail) {
+ assertFailsWith<IOException>("Expect fail but socket connected") {
+ localSocket.connect(address)
+ }
+ } else {
+ localSocket.connect(address)
+ assertTrue("LocalSocket is not connected.", localSocket.isConnected)
+ }
+ }
+ } cleanup {
+ localSocket.close()
+ nsdManager.stopServiceDiscovery(discoveryRecord)
+ discoveryRecord.expectCallback<DiscoveryStopped>()
+ }
+ }
+
+ /**
+ * Starting from Android U, the access to the /dev/socket/mdnsd is blocked by the
+ * sepolicy(b/265364111).
+ */
+ @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @Test
+ fun testCannotConnectSocketToMdnsd() {
+ val targetSdkVersion = context.packageManager
+ .getTargetSdkVersion(context.applicationInfo.packageName)
+ assumeTrue(targetSdkVersion > Build.VERSION_CODES.TIRAMISU)
+ val firstApiLevel = min(PropertyUtil.getFirstApiLevel(), PropertyUtil.getVendorApiLevel())
+ // The sepolicy is implemented in the vendor image, so the access may not be blocked if
+ // the vendor image is not update to date.
+ assumeTrue(firstApiLevel > Build.VERSION_CODES.TIRAMISU)
+ checkConnectSocketToMdnsd(shouldFail = true)
+ }
+
+ @Test @CtsNetTestCasesMaxTargetSdk33("mdnsd socket is accessible up to target SDK 33")
+ fun testCanConnectSocketToMdnsd() {
+ checkConnectSocketToMdnsd(shouldFail = false)
+ }
+
@Test @CtsNetTestCasesMaxTargetSdk30("Socket is started with the service up to target SDK 30")
fun testManagerCreatesLegacySocket() {
nsdManager // Ensure the lazy-init member is initialized, so NsdManager is created