bpf: allow tagging non-tcp/udp sockets on T+ & 5.10+
Possible since inet_sock_release hook is now enabled on T+ 5.10+
and that will perform map cleanup for us without reliance on
netlink notifications (which aren't available for other types).
Test: atest netd_updatable_unit_test TagSocketTest, adbz_cookies
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: I141b1f98ae8e4ce80813194a66a26755925b6683
diff --git a/bpf/netd/BpfHandler.cpp b/bpf/netd/BpfHandler.cpp
index e3e508b..d41aa81 100644
--- a/bpf/netd/BpfHandler.cpp
+++ b/bpf/netd/BpfHandler.cpp
@@ -341,8 +341,8 @@
if (chargeUid == AID_CLAT) 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
+ // INET6_UDP}. Tagging listener unsupported sockets (on <5.10) means the tag cannot be
+ // removed from tag map automatically. Eventually, it may run out of space due to dead tag
// entries. Note that although tagSocket() of net client has already denied the family which
// is neither AF_INET nor AF_INET6, the family validation is still added here just in case.
// See tagSocket in system/netd/client/NetdClient.cpp and
@@ -360,15 +360,19 @@
return -EAFNOSUPPORT;
}
- int socketProto;
- socklen_t protoLen = sizeof(socketProto);
- if (getsockopt(sockFd, SOL_SOCKET, SO_PROTOCOL, &socketProto, &protoLen)) {
- ALOGE("Failed to getsockopt SO_PROTOCOL: %s, fd: %d", strerror(errno), sockFd);
- return -errno;
- }
- if (socketProto != IPPROTO_UDP && socketProto != IPPROTO_TCP) {
- ALOGV("Unsupported protocol: %d", socketProto);
- return -EPROTONOSUPPORT;
+ // On 5.10+ the BPF_CGROUP_INET_SOCK_RELEASE hook takes care of cookie tag map cleanup
+ // during socket destruction. As such the socket destroy listener is superfluous.
+ if (!isAtLeastKernelVersion(5, 10, 0)) {
+ int socketProto;
+ socklen_t protoLen = sizeof(socketProto);
+ if (getsockopt(sockFd, SOL_SOCKET, SO_PROTOCOL, &socketProto, &protoLen)) {
+ ALOGE("Failed to getsockopt SO_PROTOCOL: %s, fd: %d", strerror(errno), sockFd);
+ return -errno;
+ }
+ if (socketProto != IPPROTO_UDP && socketProto != IPPROTO_TCP) {
+ ALOGV("Unsupported protocol: %d", socketProto);
+ return -EPROTONOSUPPORT;
+ }
}
uint64_t sock_cookie = getSocketCookie(sockFd);
diff --git a/bpf/netd/BpfHandlerTest.cpp b/bpf/netd/BpfHandlerTest.cpp
index b38fa16..4002b4c 100644
--- a/bpf/netd/BpfHandlerTest.cpp
+++ b/bpf/netd/BpfHandlerTest.cpp
@@ -191,7 +191,11 @@
int rawSocket = socket(AF_INET, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_RAW);
EXPECT_LE(0, rawSocket);
EXPECT_NE(NONEXISTENT_COOKIE, getSocketCookie(rawSocket));
- EXPECT_EQ(-EPROTONOSUPPORT, mBh.tagSocket(rawSocket, TEST_TAG, TEST_UID, TEST_UID));
+ if (isAtLeastKernelVersion(5, 10, 0)) {
+ EXPECT_EQ(0, mBh.tagSocket(rawSocket, TEST_TAG, TEST_UID, TEST_UID));
+ } else {
+ EXPECT_EQ(-EPROTONOSUPPORT, mBh.tagSocket(rawSocket, TEST_TAG, TEST_UID, TEST_UID));
+ }
}
TEST_F(BpfHandlerTest, TestTagSocketWithoutPermission) {