diff --git a/netd/BpfHandler.cpp b/netd/BpfHandler.cpp index 31a180bcb2..1e47ea3e91 100644 --- a/netd/BpfHandler.cpp +++ b/netd/BpfHandler.cpp @@ -143,6 +143,25 @@ int BpfHandler::tagSocket(int sockFd, uint32_t tag, uid_t chargeUid, uid_t realU 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 925a92f301..66a2f803a3 100644 --- a/netd/BpfHandlerTest.cpp +++ b/netd/BpfHandlerTest.cpp @@ -188,6 +188,14 @@ TEST_F(BpfHandlerTest, TestTagInvalidSocket) { 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);