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);