[CLATJ#32] ClatCoordinator: untag clat raw socket
Untag clat raw socket while stopping clatd.
Bug: 218407445
Test: atest FrameworksNetTests
Test: connect and disconnect to/from IPv6 only network
Check dumpsys tag map and logging for tagging/untagging socket
03-04 16:29:17.247 1330 1714 I jniClatCoordinator: tag uid AID_CLAT to socket fd 420, cookie 16524
03-04 16:29:31.343 1330 1714 I jniClatCoordinator: untag socket cookie 16524
Change-Id: Id5f5bdfc97a15abfa1a49b06dcb3c2c25743c74f
diff --git a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
index 5be8307..4517b5c 100644
--- a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
+++ b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
@@ -514,6 +514,36 @@
return static_cast<jlong>(sock_cookie);
}
+static void com_android_server_connectivity_ClatCoordinator_untagSocket(JNIEnv* env, jobject clazz,
+ jlong cookie) {
+ uint64_t sock_cookie = static_cast<uint64_t>(cookie);
+ if (sock_cookie == bpf::NONEXISTENT_COOKIE) {
+ jniThrowExceptionFmt(env, "java/io/IOException", "Invalid socket cookie");
+ return;
+ }
+
+ // The reason that deleting entry from cookie tag map directly is that the tag socket destroy
+ // listener only monitors on group INET_TCP, INET_UDP, INET6_TCP, INET6_UDP. The other socket
+ // types, ex: raw, are not able to be removed automatically by the listener.
+ // See TrafficController::makeSkDestroyListener.
+ bpf::BpfMap<uint64_t, UidTagValue> cookieTagMap;
+ auto res = cookieTagMap.init(COOKIE_TAG_MAP_PATH);
+ if (!res.ok()) {
+ throwIOException(env, "failed to init the cookieTagMap", res.error().code());
+ return;
+ }
+
+ res = cookieTagMap.deleteValue(sock_cookie);
+ if (!res.ok()) {
+ jniThrowExceptionFmt(env, "java/io/IOException", "Failed to untag the socket: %s",
+ strerror(res.error().code()));
+ return;
+ }
+
+ ALOGI("untag socket cookie %" PRIu64 "", sock_cookie);
+ return;
+}
+
/*
* JNI registration.
*/
@@ -545,6 +575,8 @@
(void*)com_android_server_connectivity_ClatCoordinator_stopClatd},
{"native_tagSocketAsClat", "(Ljava/io/FileDescriptor;)J",
(void*)com_android_server_connectivity_ClatCoordinator_tagSocketAsClat},
+ {"native_untagSocket", "(J)V",
+ (void*)com_android_server_connectivity_ClatCoordinator_untagSocket},
};
int register_com_android_server_connectivity_ClatCoordinator(JNIEnv* env) {
diff --git a/service/src/com/android/server/connectivity/ClatCoordinator.java b/service/src/com/android/server/connectivity/ClatCoordinator.java
index f8d5a28..c1a8195 100644
--- a/service/src/com/android/server/connectivity/ClatCoordinator.java
+++ b/service/src/com/android/server/connectivity/ClatCoordinator.java
@@ -194,6 +194,13 @@
public long tagSocketAsClat(@NonNull FileDescriptor sock) throws IOException {
return native_tagSocketAsClat(sock);
}
+
+ /**
+ * Untag socket.
+ */
+ public void untagSocket(long cookie) throws IOException {
+ native_untagSocket(cookie);
+ }
}
@VisibleForTesting
@@ -375,7 +382,7 @@
mXlatLocalAddress6 = v6;
mCookie = cookie;
} catch (IOException e) {
- // TODO: untag socket.
+ mDeps.untagSocket(cookie);
throw new IOException("Error start clatd on " + iface + ": " + e);
} finally {
tunFd.close();
@@ -396,7 +403,7 @@
Log.i(TAG, "Stopping clatd pid=" + mPid + " on " + mIface);
mDeps.stopClatd(mIface, mNat64Prefix, mXlatLocalAddress4, mXlatLocalAddress6, mPid);
- // TODO: remove setIptablesDropRule
+ mDeps.untagSocket(mCookie);
Log.i(TAG, "clatd on " + mIface + " stopped");
@@ -405,6 +412,7 @@
mXlatLocalAddress4 = null;
mXlatLocalAddress6 = null;
mPid = INVALID_PID;
+ mCookie = INVALID_COOKIE;
}
private static native String native_selectIpv4Address(String v4addr, int prefixlen)
@@ -426,4 +434,5 @@
private static native void native_stopClatd(String iface, String pfx96, String v4, String v6,
int pid) throws IOException;
private static native long native_tagSocketAsClat(FileDescriptor sock) throws IOException;
+ private static native void native_untagSocket(long cookie) throws IOException;
}
diff --git a/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java b/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java
index 63050a3..8a2cfc2 100644
--- a/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java
+++ b/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java
@@ -26,13 +26,10 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.argThat;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.inOrder;
-import static org.mockito.Mockito.never;
import android.annotation.NonNull;
import android.net.INetd;
@@ -278,6 +275,16 @@
fail("unsupported arg: " + sock);
return 0;
}
+
+ /**
+ * Untag socket.
+ */
+ @Override
+ public void untagSocket(long cookie) throws IOException {
+ if (cookie != RAW_SOCK_COOKIE) {
+ fail("unsupported arg: " + cookie);
+ }
+ }
};
@NonNull
@@ -364,13 +371,12 @@
coordinator.clatStop();
inOrder.verify(mDeps).stopClatd(eq(BASE_IFACE), eq(NAT64_PREFIX_STRING),
eq(XLAT_LOCAL_IPV4ADDR_STRING), eq(XLAT_LOCAL_IPV6ADDR_STRING), eq(CLATD_PID));
+ inOrder.verify(mDeps).untagSocket(eq(RAW_SOCK_COOKIE));
inOrder.verifyNoMoreInteractions();
// [4] Expect an IO exception while stopping a clatd that doesn't exist.
assertThrows("java.io.IOException: Clatd has not started", IOException.class,
() -> coordinator.clatStop());
- inOrder.verify(mDeps, never()).stopClatd(anyString(), anyString(), anyString(),
- anyString(), anyInt());
inOrder.verifyNoMoreInteractions();
}