blob: 49ca8d71dd3f4f823e627844d4e3d9d885a999d0 [file] [log] [blame]
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +09001/*
2 * Copyright (C) 2016 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
Bernie Innocenti196f1b82019-05-20 16:34:16 +090017#define LOG_TAG "Netd"
18
19#include "SockDiag.h"
20
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +090021#include <errno.h>
Bernie Innocenti196f1b82019-05-20 16:34:16 +090022#include <linux/inet_diag.h>
23#include <linux/netlink.h>
24#include <linux/sock_diag.h>
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +090025#include <netdb.h>
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +090026#include <netinet/in.h>
27#include <netinet/tcp.h>
Bernie Innocenti196f1b82019-05-20 16:34:16 +090028#include <string.h>
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +090029#include <sys/socket.h>
30#include <sys/uio.h>
31
Bernie Innocenti196f1b82019-05-20 16:34:16 +090032#include <cinttypes>
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +090033
steven_fannf3cfb3a2021-01-20 14:43:00 +080034#include <android-base/properties.h>
Lorenzo Colitticaccab42021-06-17 12:16:37 +090035#include <android-base/stringprintf.h>
Lorenzo Colittifff4bd32016-04-14 00:56:01 +090036#include <android-base/strings.h>
Logan Chien3f461482018-04-23 14:31:32 +080037#include <log/log.h>
Luke Huang25599322019-06-14 00:34:05 +080038#include <netdutils/InternetAddresses.h>
Mike Yue7e332f2019-03-13 17:15:48 +080039#include <netdutils/Stopwatch.h>
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +090040
Lorenzo Colittifbe76b92016-09-14 02:25:05 +090041#include "Permission.h"
Lorenzo Colittif32fc592016-02-15 01:09:14 +090042
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +090043#ifndef SOCK_DESTROY
44#define SOCK_DESTROY 21
45#endif
46
Lorenzo Colittifbe76b92016-09-14 02:25:05 +090047#define INET_DIAG_BC_MARK_COND 10
48
Lorenzo Colitti7035f222017-02-13 18:29:00 +090049namespace android {
Lorenzo Colitti7035f222017-02-13 18:29:00 +090050
Lorenzo Colitticaccab42021-06-17 12:16:37 +090051using android::base::StringPrintf;
Luke Huang25599322019-06-14 00:34:05 +080052using netdutils::ScopedAddrinfo;
Mike Yue7e332f2019-03-13 17:15:48 +080053using netdutils::Stopwatch;
54
55namespace net {
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +090056namespace {
57
steven_fannf3cfb3a2021-01-20 14:43:00 +080058int getAdbPort() {
59 return android::base::GetIntProperty("service.adb.tcp.port", 0);
60}
61
62bool isAdbSocket(const inet_diag_msg *msg, int adbPort) {
63 return adbPort > 0 && msg->id.idiag_sport == htons(adbPort) &&
64 (msg->idiag_uid == AID_ROOT || msg->idiag_uid == AID_SHELL);
65}
66
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +090067int checkError(int fd) {
68 struct {
69 nlmsghdr h;
70 nlmsgerr err;
71 } __attribute__((__packed__)) ack;
72 ssize_t bytesread = recv(fd, &ack, sizeof(ack), MSG_DONTWAIT | MSG_PEEK);
73 if (bytesread == -1) {
74 // Read failed (error), or nothing to read (good).
75 return (errno == EAGAIN) ? 0 : -errno;
76 } else if (bytesread == (ssize_t) sizeof(ack) && ack.h.nlmsg_type == NLMSG_ERROR) {
77 // We got an error. Consume it.
78 recv(fd, &ack, sizeof(ack), 0);
79 return ack.err.error;
80 } else {
81 // The kernel replied with something. Leave it to the caller.
82 return 0;
83 }
84}
85
86} // namespace
87
88bool SockDiag::open() {
89 if (hasSocks()) {
90 return false;
91 }
92
Nick Kralevichaf02b552016-12-20 08:40:35 -080093 mSock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_INET_DIAG);
94 mWriteSock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_INET_DIAG);
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +090095 if (!hasSocks()) {
96 closeSocks();
97 return false;
98 }
99
100 sockaddr_nl nl = { .nl_family = AF_NETLINK };
101 if ((connect(mSock, reinterpret_cast<sockaddr *>(&nl), sizeof(nl)) == -1) ||
102 (connect(mWriteSock, reinterpret_cast<sockaddr *>(&nl), sizeof(nl)) == -1)) {
103 closeSocks();
104 return false;
105 }
106
107 return true;
108}
109
Hugo Benichidee94812018-01-12 14:47:00 +0900110int SockDiag::sendDumpRequest(uint8_t proto, uint8_t family, uint8_t extensions, uint32_t states,
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900111 iovec *iov, int iovcnt) {
112 struct {
113 nlmsghdr nlh;
114 inet_diag_req_v2 req;
115 } __attribute__((__packed__)) request = {
116 .nlh = {
117 .nlmsg_type = SOCK_DIAG_BY_FAMILY,
118 .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
119 },
120 .req = {
121 .sdiag_family = family,
122 .sdiag_protocol = proto,
Hugo Benichidee94812018-01-12 14:47:00 +0900123 .idiag_ext = extensions,
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900124 .idiag_states = states,
125 },
126 };
127
128 size_t len = 0;
129 iov[0].iov_base = &request;
130 iov[0].iov_len = sizeof(request);
131 for (int i = 0; i < iovcnt; i++) {
132 len += iov[i].iov_len;
133 }
134 request.nlh.nlmsg_len = len;
135
George Burgess IVbda08aa2021-12-06 23:50:24 -0800136 ssize_t writevRet = writev(mSock, iov, iovcnt);
137 // Don't let pointers to the stack escape.
138 iov[0] = {nullptr, 0};
139 if (writevRet != (ssize_t)len) {
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900140 return -errno;
141 }
142
143 return checkError(mSock);
144}
145
146int SockDiag::sendDumpRequest(uint8_t proto, uint8_t family, uint32_t states) {
147 iovec iov[] = {
148 { nullptr, 0 },
149 };
Hugo Benichidee94812018-01-12 14:47:00 +0900150 return sendDumpRequest(proto, family, 0, states, iov, ARRAY_SIZE(iov));
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900151}
152
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900153int SockDiag::sendDumpRequest(uint8_t proto, uint8_t family, const char *addrstr) {
154 addrinfo hints = { .ai_flags = AI_NUMERICHOST };
155 addrinfo *res;
156 in6_addr mapped = { .s6_addr32 = { 0, 0, htonl(0xffff), 0 } };
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900157
158 // TODO: refactor the netlink parsing code out of system/core, bring it into netd, and stop
159 // doing string conversions when they're not necessary.
Maciej Żenczykowski84b59d92020-04-30 16:30:55 -0700160 int ret = getaddrinfo(addrstr, nullptr, &hints, &res);
161 if (ret != 0) return -EINVAL;
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900162
163 // So we don't have to call freeaddrinfo on every failure path.
164 ScopedAddrinfo resP(res);
165
166 void *addr;
167 uint8_t addrlen;
168 if (res->ai_family == AF_INET && family == AF_INET) {
169 in_addr& ina = reinterpret_cast<sockaddr_in*>(res->ai_addr)->sin_addr;
170 addr = &ina;
171 addrlen = sizeof(ina);
172 } else if (res->ai_family == AF_INET && family == AF_INET6) {
173 in_addr& ina = reinterpret_cast<sockaddr_in*>(res->ai_addr)->sin_addr;
174 mapped.s6_addr32[3] = ina.s_addr;
175 addr = &mapped;
176 addrlen = sizeof(mapped);
177 } else if (res->ai_family == AF_INET6 && family == AF_INET6) {
178 in6_addr& in6a = reinterpret_cast<sockaddr_in6*>(res->ai_addr)->sin6_addr;
179 addr = &in6a;
180 addrlen = sizeof(in6a);
181 } else {
182 return -EAFNOSUPPORT;
183 }
184
185 uint8_t prefixlen = addrlen * 8;
186 uint8_t yesjump = sizeof(inet_diag_bc_op) + sizeof(inet_diag_hostcond) + addrlen;
187 uint8_t nojump = yesjump + 4;
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900188
189 struct {
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900190 nlattr nla;
191 inet_diag_bc_op op;
192 inet_diag_hostcond cond;
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900193 } __attribute__((__packed__)) attrs = {
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900194 .nla = {
195 .nla_type = INET_DIAG_REQ_BYTECODE,
196 },
197 .op = {
198 INET_DIAG_BC_S_COND,
199 yesjump,
200 nojump,
201 },
202 .cond = {
203 family,
204 prefixlen,
205 -1,
206 {}
207 },
208 };
209
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900210 attrs.nla.nla_len = sizeof(attrs) + addrlen;
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900211
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900212 iovec iov[] = {
Lorenzo Colittifbe76b92016-09-14 02:25:05 +0900213 { nullptr, 0 },
214 { &attrs, sizeof(attrs) },
215 { addr, addrlen },
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900216 };
217
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900218 uint32_t states = ~(1 << TCP_TIME_WAIT);
Hugo Benichidee94812018-01-12 14:47:00 +0900219 return sendDumpRequest(proto, family, 0, states, iov, ARRAY_SIZE(iov));
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900220}
221
Lorenzo Colitti0b733e42017-02-13 16:29:00 +0900222int SockDiag::readDiagMsg(uint8_t proto, const SockDiag::DestroyFilter& shouldDestroy) {
223 NetlinkDumpCallback callback = [this, proto, shouldDestroy] (nlmsghdr *nlh) {
Lorenzo Colitti0b733e42017-02-13 16:29:00 +0900224 const inet_diag_msg *msg = reinterpret_cast<inet_diag_msg *>(NLMSG_DATA(nlh));
225 if (shouldDestroy(proto, msg)) {
226 sockDestroy(proto, msg);
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900227 }
Lorenzo Colitti0b733e42017-02-13 16:29:00 +0900228 };
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900229
Lorenzo Colitti0b733e42017-02-13 16:29:00 +0900230 return processNetlinkDump(mSock, callback);
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900231}
232
Hugo Benichidee94812018-01-12 14:47:00 +0900233int SockDiag::readDiagMsgWithTcpInfo(const TcpInfoReader& tcpInfoReader) {
234 NetlinkDumpCallback callback = [tcpInfoReader] (nlmsghdr *nlh) {
Hugo Benichi321b22c2018-01-30 11:37:27 +0900235 if (nlh->nlmsg_type != SOCK_DIAG_BY_FAMILY) {
236 ALOGE("expected nlmsg_type=SOCK_DIAG_BY_FAMILY, got nlmsg_type=%d", nlh->nlmsg_type);
237 return;
238 }
Hugo Benichicbaa36b2018-01-17 12:11:43 +0900239 Fwmark mark;
Hugo Benichidee94812018-01-12 14:47:00 +0900240 struct tcp_info *tcpinfo = nullptr;
Hugo Benichi54bfc7c2018-01-23 14:16:52 +0900241 uint32_t tcpinfoLength = 0;
Hugo Benichidee94812018-01-12 14:47:00 +0900242 inet_diag_msg *msg = reinterpret_cast<inet_diag_msg *>(NLMSG_DATA(nlh));
243 uint32_t attr_len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*msg));
244 struct rtattr *attr = reinterpret_cast<struct rtattr*>(msg+1);
245 while (RTA_OK(attr, attr_len)) {
246 if (attr->rta_type == INET_DIAG_INFO) {
247 tcpinfo = reinterpret_cast<struct tcp_info*>(RTA_DATA(attr));
Hugo Benichi54bfc7c2018-01-23 14:16:52 +0900248 tcpinfoLength = RTA_PAYLOAD(attr);
Hugo Benichicbaa36b2018-01-17 12:11:43 +0900249 }
250 if (attr->rta_type == INET_DIAG_MARK) {
251 mark.intValue = *reinterpret_cast<uint32_t*>(RTA_DATA(attr));
Hugo Benichidee94812018-01-12 14:47:00 +0900252 }
253 attr = RTA_NEXT(attr, attr_len);
254 }
255
Hugo Benichi54bfc7c2018-01-23 14:16:52 +0900256 tcpInfoReader(mark, msg, tcpinfo, tcpinfoLength);
Hugo Benichidee94812018-01-12 14:47:00 +0900257 };
258
259 return processNetlinkDump(mSock, callback);
260}
261
Lorenzo Colittie5c3c992016-07-26 17:53:50 +0900262// Determines whether a socket is a loopback socket. Does not check socket state.
263bool SockDiag::isLoopbackSocket(const inet_diag_msg *msg) {
264 switch (msg->idiag_family) {
265 case AF_INET:
266 // Old kernels only copy the IPv4 address and leave the other 12 bytes uninitialized.
267 return IN_LOOPBACK(htonl(msg->id.idiag_src[0])) ||
268 IN_LOOPBACK(htonl(msg->id.idiag_dst[0])) ||
269 msg->id.idiag_src[0] == msg->id.idiag_dst[0];
270
271 case AF_INET6: {
272 const struct in6_addr *src = (const struct in6_addr *) &msg->id.idiag_src;
273 const struct in6_addr *dst = (const struct in6_addr *) &msg->id.idiag_dst;
274 return (IN6_IS_ADDR_V4MAPPED(src) && IN_LOOPBACK(src->s6_addr32[3])) ||
275 (IN6_IS_ADDR_V4MAPPED(dst) && IN_LOOPBACK(dst->s6_addr32[3])) ||
276 IN6_IS_ADDR_LOOPBACK(src) || IN6_IS_ADDR_LOOPBACK(dst) ||
277 !memcmp(src, dst, sizeof(*src));
278 }
279 default:
280 return false;
281 }
282}
283
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900284int SockDiag::sockDestroy(uint8_t proto, const inet_diag_msg *msg) {
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900285 if (msg == nullptr) {
286 return 0;
287 }
288
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900289 DestroyRequest request = {
290 .nlh = {
291 .nlmsg_type = SOCK_DESTROY,
292 .nlmsg_flags = NLM_F_REQUEST,
293 },
294 .req = {
295 .sdiag_family = msg->idiag_family,
296 .sdiag_protocol = proto,
297 .idiag_states = (uint32_t) (1 << msg->idiag_state),
298 .id = msg->id,
299 },
300 };
301 request.nlh.nlmsg_len = sizeof(request);
302
303 if (write(mWriteSock, &request, sizeof(request)) < (ssize_t) sizeof(request)) {
304 return -errno;
305 }
306
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900307 int ret = checkError(mWriteSock);
308 if (!ret) mSocketsDestroyed++;
309 return ret;
310}
311
Lorenzo Colitticaccab42021-06-17 12:16:37 +0900312int SockDiag::destroySockets(uint8_t proto, int family, const char* addrstr, int ifindex) {
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900313 if (!hasSocks()) {
314 return -EBADFD;
315 }
316
317 if (int ret = sendDumpRequest(proto, family, addrstr)) {
318 return ret;
319 }
320
Lorenzo Colitti582b0242021-06-17 23:19:22 +0900321 // Destroy all sockets on the address, except link-local sockets where ifindex doesn't match.
322 auto shouldDestroy = [ifindex](uint8_t, const inet_diag_msg* msg) {
Lorenzo Colitticaccab42021-06-17 12:16:37 +0900323 return ifindex == 0 || ifindex == (int)msg->id.idiag_if;
324 };
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900325
Lorenzo Colitti582b0242021-06-17 23:19:22 +0900326 return readDiagMsg(proto, shouldDestroy);
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900327}
328
Lorenzo Colitticaccab42021-06-17 12:16:37 +0900329int SockDiag::destroySockets(const char* addrstr, int ifindex) {
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900330 Stopwatch s;
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900331 mSocketsDestroyed = 0;
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900332
Lorenzo Colitticaccab42021-06-17 12:16:37 +0900333 std::string where = addrstr;
334 if (ifindex) where += StringPrintf(" ifindex %d", ifindex);
335
336 if (!strchr(addrstr, ':')) { // inet_ntop never returns something like ::ffff:192.0.2.1
337 if (int ret = destroySockets(IPPROTO_TCP, AF_INET, addrstr, ifindex)) {
338 ALOGE("Failed to destroy IPv4 sockets on %s: %s", where.c_str(), strerror(-ret));
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900339 return ret;
340 }
341 }
Lorenzo Colitticaccab42021-06-17 12:16:37 +0900342 if (int ret = destroySockets(IPPROTO_TCP, AF_INET6, addrstr, ifindex)) {
343 ALOGE("Failed to destroy IPv6 sockets on %s: %s", where.c_str(), strerror(-ret));
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900344 return ret;
345 }
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900346
347 if (mSocketsDestroyed > 0) {
Lorenzo Colitticaccab42021-06-17 12:16:37 +0900348 ALOGI("Destroyed %d sockets on %s in %" PRId64 "us", mSocketsDestroyed, where.c_str(),
Bernie Innocenti196f1b82019-05-20 16:34:16 +0900349 s.timeTakenUs());
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900350 }
351
352 return mSocketsDestroyed;
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900353}
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900354
Bernie Innocenti15bb55c2018-06-03 16:19:51 +0900355int SockDiag::destroyLiveSockets(const DestroyFilter& destroyFilter, const char *what,
Lorenzo Colittifbe76b92016-09-14 02:25:05 +0900356 iovec *iov, int iovcnt) {
Hugo Benichidee94812018-01-12 14:47:00 +0900357 const int proto = IPPROTO_TCP;
358 const uint32_t states = (1 << TCP_ESTABLISHED) | (1 << TCP_SYN_SENT) | (1 << TCP_SYN_RECV);
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900359
360 for (const int family : {AF_INET, AF_INET6}) {
361 const char *familyName = (family == AF_INET) ? "IPv4" : "IPv6";
Hugo Benichidee94812018-01-12 14:47:00 +0900362 if (int ret = sendDumpRequest(proto, family, 0, states, iov, iovcnt)) {
Lorenzo Colittifbe76b92016-09-14 02:25:05 +0900363 ALOGE("Failed to dump %s sockets for %s: %s", familyName, what, strerror(-ret));
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900364 return ret;
365 }
366 if (int ret = readDiagMsg(proto, destroyFilter)) {
Lorenzo Colittifbe76b92016-09-14 02:25:05 +0900367 ALOGE("Failed to destroy %s sockets for %s: %s", familyName, what, strerror(-ret));
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900368 return ret;
369 }
370 }
371
372 return 0;
373}
374
Hugo Benichidee94812018-01-12 14:47:00 +0900375int SockDiag::getLiveTcpInfos(const TcpInfoReader& tcpInfoReader) {
376 const int proto = IPPROTO_TCP;
377 const uint32_t states = (1 << TCP_ESTABLISHED) | (1 << TCP_SYN_SENT) | (1 << TCP_SYN_RECV);
378 const uint8_t extensions = (1 << INET_DIAG_MEMINFO); // flag for dumping struct tcp_info.
379
380 iovec iov[] = {
381 { nullptr, 0 },
382 };
383
384 for (const int family : {AF_INET, AF_INET6}) {
385 const char *familyName = (family == AF_INET) ? "IPv4" : "IPv6";
386 if (int ret = sendDumpRequest(proto, family, extensions, states, iov, ARRAY_SIZE(iov))) {
387 ALOGE("Failed to dump %s sockets struct tcp_info: %s", familyName, strerror(-ret));
388 return ret;
389 }
390 if (int ret = readDiagMsgWithTcpInfo(tcpInfoReader)) {
391 ALOGE("Failed to read %s sockets struct tcp_info: %s", familyName, strerror(-ret));
392 return ret;
393 }
394 }
395
396 return 0;
397}
398
Lorenzo Colittie5c3c992016-07-26 17:53:50 +0900399int SockDiag::destroySockets(uint8_t proto, const uid_t uid, bool excludeLoopback) {
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900400 mSocketsDestroyed = 0;
401 Stopwatch s;
402
Lorenzo Colittie5c3c992016-07-26 17:53:50 +0900403 auto shouldDestroy = [uid, excludeLoopback] (uint8_t, const inet_diag_msg *msg) {
404 return msg != nullptr &&
405 msg->idiag_uid == uid &&
406 !(excludeLoopback && isLoopbackSocket(msg));
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900407 };
408
409 for (const int family : {AF_INET, AF_INET6}) {
410 const char *familyName = family == AF_INET ? "IPv4" : "IPv6";
411 uint32_t states = (1 << TCP_ESTABLISHED) | (1 << TCP_SYN_SENT) | (1 << TCP_SYN_RECV);
412 if (int ret = sendDumpRequest(proto, family, states)) {
413 ALOGE("Failed to dump %s sockets for UID: %s", familyName, strerror(-ret));
414 return ret;
415 }
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900416 if (int ret = readDiagMsg(proto, shouldDestroy)) {
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900417 ALOGE("Failed to destroy %s sockets for UID: %s", familyName, strerror(-ret));
418 return ret;
419 }
420 }
421
422 if (mSocketsDestroyed > 0) {
Bernie Innocenti196f1b82019-05-20 16:34:16 +0900423 ALOGI("Destroyed %d sockets for UID in %" PRId64 "us", mSocketsDestroyed, s.timeTakenUs());
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900424 }
425
426 return 0;
427}
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900428
Lorenzo Colittie5c3c992016-07-26 17:53:50 +0900429int SockDiag::destroySockets(const UidRanges& uidRanges, const std::set<uid_t>& skipUids,
430 bool excludeLoopback) {
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900431 mSocketsDestroyed = 0;
432 Stopwatch s;
433
434 auto shouldDestroy = [&] (uint8_t, const inet_diag_msg *msg) {
435 return msg != nullptr &&
436 uidRanges.hasUid(msg->idiag_uid) &&
Lorenzo Colittie5c3c992016-07-26 17:53:50 +0900437 skipUids.find(msg->idiag_uid) == skipUids.end() &&
steven_fannf3cfb3a2021-01-20 14:43:00 +0800438 !(excludeLoopback && isLoopbackSocket(msg)) &&
439 !isAdbSocket(msg, getAdbPort());
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900440 };
441
Lorenzo Colittifbe76b92016-09-14 02:25:05 +0900442 iovec iov[] = {
443 { nullptr, 0 },
444 };
445
446 if (int ret = destroyLiveSockets(shouldDestroy, "UID", iov, ARRAY_SIZE(iov))) {
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900447 return ret;
448 }
449
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900450 if (mSocketsDestroyed > 0) {
Bernie Innocenti196f1b82019-05-20 16:34:16 +0900451 ALOGI("Destroyed %d sockets for %s skip={%s} in %" PRId64 "us", mSocketsDestroyed,
452 uidRanges.toString().c_str(), android::base::Join(skipUids, " ").c_str(),
453 s.timeTakenUs());
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900454 }
455
456 return 0;
457}
Lorenzo Colittifbe76b92016-09-14 02:25:05 +0900458
459// Destroys all "live" (CONNECTED, SYN_SENT, SYN_RECV) TCP sockets on the specified netId where:
460// 1. The opening app no longer has permission to use this network, or:
461// 2. The opening app does have permission, but did not explicitly select this network.
462//
463// We destroy sockets without the explicit bit because we want to avoid the situation where a
464// privileged app uses its privileges without knowing it is doing so. For example, a privileged app
465// might have opened a socket on this network just because it was the default network at the
466// time. If we don't kill these sockets, those apps could continue to use them without realizing
467// that they are now sending and receiving traffic on a network that is now restricted.
468int SockDiag::destroySocketsLackingPermission(unsigned netId, Permission permission,
469 bool excludeLoopback) {
470 struct markmatch {
471 inet_diag_bc_op op;
472 // TODO: switch to inet_diag_markcond
473 __u32 mark;
474 __u32 mask;
475 } __attribute__((packed));
476 constexpr uint8_t matchlen = sizeof(markmatch);
477
478 Fwmark netIdMark, netIdMask;
479 netIdMark.netId = netId;
480 netIdMask.netId = 0xffff;
481
482 Fwmark controlMark;
483 controlMark.explicitlySelected = true;
484 controlMark.permission = permission;
485
486 // A SOCK_DIAG bytecode program that accepts the sockets we intend to destroy.
487 struct bytecode {
488 markmatch netIdMatch;
489 markmatch controlMatch;
490 inet_diag_bc_op controlJump;
491 } __attribute__((packed)) bytecode;
492
493 // The length of the INET_DIAG_BC_JMP instruction.
494 constexpr uint8_t jmplen = sizeof(inet_diag_bc_op);
495 // Jump exactly this far past the end of the program to reject.
496 constexpr uint8_t rejectoffset = sizeof(inet_diag_bc_op);
497 // Total length of the program.
498 constexpr uint8_t bytecodelen = sizeof(bytecode);
499
500 bytecode = (struct bytecode) {
501 // If netId matches, continue, otherwise, reject (i.e., leave socket alone).
502 { { INET_DIAG_BC_MARK_COND, matchlen, bytecodelen + rejectoffset },
503 netIdMark.intValue, netIdMask.intValue },
504
505 // If explicit and permission bits match, go to the JMP below which rejects the socket
506 // (i.e., we leave it alone). Otherwise, jump to the end of the program, which accepts the
507 // socket (so we destroy it).
508 { { INET_DIAG_BC_MARK_COND, matchlen, matchlen + jmplen },
509 controlMark.intValue, controlMark.intValue },
510
511 // This JMP unconditionally rejects the packet by jumping to the reject target. It is
512 // necessary to keep the kernel bytecode verifier happy. If we don't have a JMP the bytecode
513 // is invalid because the target of every no jump must always be reachable by yes jumps.
514 // Without this JMP, the accept target is not reachable by yes jumps and the program will
515 // be rejected by the validator.
516 { INET_DIAG_BC_JMP, jmplen, jmplen + rejectoffset },
517
518 // We have reached the end of the program. Accept the socket, and destroy it below.
519 };
520
521 struct nlattr nla = {
Nick Desaulniers6b357502019-10-11 09:26:44 -0700522 .nla_len = sizeof(struct nlattr) + bytecodelen,
523 .nla_type = INET_DIAG_REQ_BYTECODE,
Lorenzo Colittifbe76b92016-09-14 02:25:05 +0900524 };
525
526 iovec iov[] = {
527 { nullptr, 0 },
528 { &nla, sizeof(nla) },
529 { &bytecode, bytecodelen },
530 };
531
532 mSocketsDestroyed = 0;
533 Stopwatch s;
534
535 auto shouldDestroy = [&] (uint8_t, const inet_diag_msg *msg) {
536 return msg != nullptr && !(excludeLoopback && isLoopbackSocket(msg));
537 };
538
539 if (int ret = destroyLiveSockets(shouldDestroy, "permission change", iov, ARRAY_SIZE(iov))) {
540 return ret;
541 }
542
543 if (mSocketsDestroyed > 0) {
Bernie Innocenti196f1b82019-05-20 16:34:16 +0900544 ALOGI("Destroyed %d sockets for netId %d permission=%d in %" PRId64 "us", mSocketsDestroyed,
545 netId, permission, s.timeTakenUs());
Lorenzo Colittifbe76b92016-09-14 02:25:05 +0900546 }
547
548 return 0;
549}
Lorenzo Colitti7035f222017-02-13 18:29:00 +0900550
551} // namespace net
552} // namespace android