1 /*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <aidl/android/hardware/net/nlinterceptor/IInterceptor.h>
18 #include <android-base/logging.h>
19 #include <android-base/macros.h>
20 #include <android/binder_manager.h>
21 #include <libnlinterceptor/libnlinterceptor.h>
22 #include <linux/netlink.h>
23
24 #include <mutex>
25
26 namespace android::nlinterceptor {
27 using namespace std::string_literals;
28 using namespace ::aidl::android::hardware::net::nlinterceptor;
29 using base::borrowed_fd;
30 using AidlInterceptedSocket =
31 ::aidl::android::hardware::net::nlinterceptor::InterceptedSocket;
32
33 static const auto kServiceName = IInterceptor::descriptor + "/default"s;
34
InterceptedSocket(::aidl::android::hardware::net::nlinterceptor::InterceptedSocket sock)35 InterceptedSocket::InterceptedSocket(
36 ::aidl::android::hardware::net::nlinterceptor::InterceptedSocket sock)
37 : nlFamily(sock.nlFamily), portId(sock.portId) {}
38
InterceptedSocket(uint32_t nlFamily,uint32_t portId)39 InterceptedSocket::InterceptedSocket(uint32_t nlFamily, uint32_t portId)
40 : nlFamily(nlFamily), portId(portId) {}
41
operator <<(std::ostream & os,const InterceptedSocket & sock)42 std::ostream& operator<<(std::ostream& os, const InterceptedSocket& sock) {
43 return os << "family: " << sock.nlFamily << ", portId: " << sock.portId;
44 }
45
operator <(const InterceptedSocket & other) const46 bool InterceptedSocket::operator<(const InterceptedSocket& other) const {
47 if (nlFamily != other.nlFamily) {
48 return nlFamily < other.nlFamily;
49 }
50 return portId < other.portId;
51 }
52
operator sockaddr_nl() const53 InterceptedSocket::operator sockaddr_nl() const {
54 return {
55 .nl_family = AF_NETLINK,
56 .nl_pad = 0,
57 .nl_pid = portId,
58 .nl_groups = 0,
59 };
60 }
61
operator AidlInterceptedSocket() const62 InterceptedSocket::operator AidlInterceptedSocket() const {
63 return {
64 .nlFamily = static_cast<int32_t>(nlFamily),
65 .portId = static_cast<int32_t>(portId),
66 };
67 }
68
isEnabled()69 bool isEnabled() {
70 static std::mutex supportedMutex;
71 static std::optional<bool> interceptorSupported;
72 // Avoid querying service manager when we can cache the result.
73 if (interceptorSupported.has_value()) return *interceptorSupported;
74 std::lock_guard lock(supportedMutex);
75 if (interceptorSupported.has_value()) return *interceptorSupported;
76
77 if (!AServiceManager_isDeclared(kServiceName.c_str())) {
78 interceptorSupported = false;
79 return false;
80 }
81 interceptorSupported = true;
82 return true;
83 }
84
getInstance()85 static IInterceptor& getInstance() {
86 static std::mutex instanceMutex;
87 static std::shared_ptr<IInterceptor> interceptorInstance;
88 CHECK(isEnabled()) << "Can't getInstance! Interceptor not supported!";
89 // Don't overwrite the pointer once we've acquired it.
90 if (interceptorInstance != nullptr) return *interceptorInstance;
91 std::lock_guard lock(instanceMutex);
92 if (interceptorInstance != nullptr) return *interceptorInstance;
93 interceptorInstance = IInterceptor::fromBinder(
94 ndk::SpAIBinder(AServiceManager_waitForService(kServiceName.c_str())));
95 CHECK(interceptorInstance != nullptr)
96 << "Failed to get Netlink Interceptor service!";
97 return *interceptorInstance;
98 }
99
createSocket(borrowed_fd clientSocket,const std::string & clientName)100 std::optional<InterceptedSocket> createSocket(borrowed_fd clientSocket,
101 const std::string& clientName) {
102 sockaddr_nl nladdr = {};
103 socklen_t nlsize = sizeof(nladdr);
104 if (getsockname(clientSocket.get(), reinterpret_cast<sockaddr*>(&nladdr),
105 &nlsize) < 0) {
106 PLOG(ERROR) << "Failed to get pid of fd passed by " << clientName;
107 return std::nullopt;
108 }
109
110 ::aidl::android::hardware::net::nlinterceptor::InterceptedSocket
111 interceptedSocket;
112 auto aidlStatus = getInstance().createSocket(
113 nladdr.nl_family, nladdr.nl_pid, clientName, &interceptedSocket);
114 if (!aidlStatus.isOk()) {
115 return std::nullopt;
116 }
117
118 return InterceptedSocket{nladdr.nl_family,
119 uint32_t(interceptedSocket.portId)};
120 }
121
closeSocket(const InterceptedSocket & sock)122 void closeSocket(const InterceptedSocket& sock) {
123 auto aidlStatus = getInstance().closeSocket(sock);
124 if (!aidlStatus.isOk()) {
125 LOG(ERROR) << "Failed to close socket with pid = " << sock.portId;
126 }
127 }
128
subscribe(const InterceptedSocket & sock,uint32_t group)129 bool subscribe(const InterceptedSocket& sock, uint32_t group) {
130 auto aidlStatus = getInstance().subscribeGroup(sock, group);
131 return aidlStatus.isOk();
132 }
133
unsubscribe(const InterceptedSocket & sock,uint32_t group)134 bool unsubscribe(const InterceptedSocket& sock, uint32_t group) {
135 auto aidlStatus = getInstance().unsubscribeGroup(sock, group);
136 return aidlStatus.isOk();
137 }
138
android_nlinterceptor_isEnabled()139 extern "C" bool android_nlinterceptor_isEnabled() { return isEnabled(); }
140
android_nlinterceptor_createSocket(int clientSocketFd,const char * clientName,android_nlinterceptor_InterceptedSocket * interceptedSocket)141 extern "C" bool android_nlinterceptor_createSocket(
142 int clientSocketFd, const char* clientName,
143 android_nlinterceptor_InterceptedSocket* interceptedSocket) {
144 if (!clientName || clientSocketFd <= 0) return false;
145 const auto maybeSocket =
146 createSocket(borrowed_fd(clientSocketFd), clientName);
147 if (!maybeSocket) return false;
148 *interceptedSocket = {.nlFamily = maybeSocket->nlFamily,
149 .portId = maybeSocket->portId};
150 return true;
151 }
152
android_nlinterceptor_closeSocket(android_nlinterceptor_InterceptedSocket sock)153 extern "C" void android_nlinterceptor_closeSocket(android_nlinterceptor_InterceptedSocket sock) {
154 closeSocket({sock.nlFamily, sock.portId});
155 }
156
android_nlinterceptor_subscribe(android_nlinterceptor_InterceptedSocket sock,uint32_t group)157 extern "C" bool android_nlinterceptor_subscribe(android_nlinterceptor_InterceptedSocket sock,
158 uint32_t group) {
159 return subscribe({sock.nlFamily, sock.portId}, group);
160 }
161
android_nlinterceptor_unsubscribe(android_nlinterceptor_InterceptedSocket sock,uint32_t group)162 extern "C" bool android_nlinterceptor_unsubscribe(android_nlinterceptor_InterceptedSocket sock,
163 uint32_t group) {
164 return unsubscribe({sock.nlFamily, sock.portId}, group);
165 }
166
167 } // namespace android::nlinterceptor
168