BpfHandler: only allow to tag udp/tcp socket
The TrafficController socket destroy listener only monitors
on the group {INET_TCP, INET_UDP, INET6_TCP, INET6_UDP}.
Tagging listener unsupported socket causes that the tag can't
be removed from tag map automatically. Eventually, the tag map
run out of space because of dead tag entries.
See TrafficController::makeSkDestroyListener in
packages/modules/Connectivity/service/native/TrafficController.cpp
Bug: 223094609
Test: atest BpfHandlerTest
Change-Id: Icc19b7c9f37fef498b89f43e44767f6b9e931a5a
diff --git a/netd/BpfHandler.cpp b/netd/BpfHandler.cpp
index 31a180b..1e47ea3 100644
--- a/netd/BpfHandler.cpp
+++ b/netd/BpfHandler.cpp
@@ -143,6 +143,25 @@
return -EPERM;
}
+ // The socket destroy listener only monitors on the group {INET_TCP, INET_UDP, INET6_TCP,
+ // INET6_UDP}. Tagging listener unsupported socket causes that the tag can't be removed from
+ // tag map automatically. Eventually, the tag map may run out of space because of dead tag
+ // entries.
+ // See TrafficController::makeSkDestroyListener in
+ // packages/modules/Connectivity/service/native/TrafficController.cpp
+ // TODO: remove this once the socket destroy listener can detect more types of socket destroy.
+ int socketProto;
+ socklen_t intSize = sizeof(socketProto);
+ if (getsockopt(sockFd, SOL_SOCKET, SO_PROTOCOL, &socketProto, &intSize)) {
+ ALOGE("Failed to getsockopt: %s, fd: %d", strerror(errno), sockFd);
+ return -errno;
+ } else {
+ if (socketProto != IPPROTO_UDP && socketProto != IPPROTO_TCP) {
+ ALOGE("Unsupported protocol: %d", socketProto);
+ return -EPROTONOSUPPORT;
+ }
+ }
+
uint64_t sock_cookie = getSocketCookie(sockFd);
if (sock_cookie == NONEXISTENT_COOKIE) return -errno;
UidTagValue newKey = {.uid = (uint32_t)chargeUid, .tag = tag};
diff --git a/netd/BpfHandlerTest.cpp b/netd/BpfHandlerTest.cpp
index 925a92f..66a2f80 100644
--- a/netd/BpfHandlerTest.cpp
+++ b/netd/BpfHandlerTest.cpp
@@ -188,6 +188,14 @@
expectMapEmpty(mFakeCookieTagMap);
}
+TEST_F(BpfHandlerTest, TestTagSocketWithUnsupportedProtocol) {
+ int rawSocket = socket(AF_INET, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_RAW);
+ EXPECT_LE(0, rawSocket);
+ uint64_t sockCookie = getSocketCookie(rawSocket);
+ EXPECT_NE(NONEXISTENT_COOKIE, sockCookie);
+ EXPECT_EQ(-EPROTONOSUPPORT, mBh.tagSocket(rawSocket, TEST_TAG, TEST_UID, TEST_UID));
+}
+
TEST_F(BpfHandlerTest, TestTagSocketWithoutPermission) {
int sock = socket(AF_INET6, SOCK_STREAM | SOCK_CLOEXEC, 0);
ASSERT_NE(-1, sock);