blob: 3e1f384ed9336954383cfa88cd5539701f3d5589 [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
Lorenzo Colittifff4bd32016-04-14 00:56:01 +090034#include <android-base/strings.h>
Logan Chien3f461482018-04-23 14:31:32 +080035#include <log/log.h>
Luke Huang25599322019-06-14 00:34:05 +080036#include <netdutils/InternetAddresses.h>
Mike Yue7e332f2019-03-13 17:15:48 +080037#include <netdutils/Stopwatch.h>
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +090038
Lorenzo Colittifbe76b92016-09-14 02:25:05 +090039#include "Permission.h"
Lorenzo Colittif32fc592016-02-15 01:09:14 +090040
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +090041#ifndef SOCK_DESTROY
42#define SOCK_DESTROY 21
43#endif
44
Lorenzo Colittifbe76b92016-09-14 02:25:05 +090045#define INET_DIAG_BC_MARK_COND 10
46
Lorenzo Colitti7035f222017-02-13 18:29:00 +090047namespace android {
Lorenzo Colitti7035f222017-02-13 18:29:00 +090048
Luke Huang25599322019-06-14 00:34:05 +080049using netdutils::ScopedAddrinfo;
Mike Yue7e332f2019-03-13 17:15:48 +080050using netdutils::Stopwatch;
51
52namespace net {
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +090053namespace {
54
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +090055int checkError(int fd) {
56 struct {
57 nlmsghdr h;
58 nlmsgerr err;
59 } __attribute__((__packed__)) ack;
60 ssize_t bytesread = recv(fd, &ack, sizeof(ack), MSG_DONTWAIT | MSG_PEEK);
61 if (bytesread == -1) {
62 // Read failed (error), or nothing to read (good).
63 return (errno == EAGAIN) ? 0 : -errno;
64 } else if (bytesread == (ssize_t) sizeof(ack) && ack.h.nlmsg_type == NLMSG_ERROR) {
65 // We got an error. Consume it.
66 recv(fd, &ack, sizeof(ack), 0);
67 return ack.err.error;
68 } else {
69 // The kernel replied with something. Leave it to the caller.
70 return 0;
71 }
72}
73
74} // namespace
75
76bool SockDiag::open() {
77 if (hasSocks()) {
78 return false;
79 }
80
Nick Kralevichaf02b552016-12-20 08:40:35 -080081 mSock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_INET_DIAG);
82 mWriteSock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_INET_DIAG);
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +090083 if (!hasSocks()) {
84 closeSocks();
85 return false;
86 }
87
88 sockaddr_nl nl = { .nl_family = AF_NETLINK };
89 if ((connect(mSock, reinterpret_cast<sockaddr *>(&nl), sizeof(nl)) == -1) ||
90 (connect(mWriteSock, reinterpret_cast<sockaddr *>(&nl), sizeof(nl)) == -1)) {
91 closeSocks();
92 return false;
93 }
94
95 return true;
96}
97
Hugo Benichidee94812018-01-12 14:47:00 +090098int SockDiag::sendDumpRequest(uint8_t proto, uint8_t family, uint8_t extensions, uint32_t states,
Lorenzo Colitti94a7b432016-03-24 16:47:12 +090099 iovec *iov, int iovcnt) {
100 struct {
101 nlmsghdr nlh;
102 inet_diag_req_v2 req;
103 } __attribute__((__packed__)) request = {
104 .nlh = {
105 .nlmsg_type = SOCK_DIAG_BY_FAMILY,
106 .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
107 },
108 .req = {
109 .sdiag_family = family,
110 .sdiag_protocol = proto,
Hugo Benichidee94812018-01-12 14:47:00 +0900111 .idiag_ext = extensions,
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900112 .idiag_states = states,
113 },
114 };
115
116 size_t len = 0;
117 iov[0].iov_base = &request;
118 iov[0].iov_len = sizeof(request);
119 for (int i = 0; i < iovcnt; i++) {
120 len += iov[i].iov_len;
121 }
122 request.nlh.nlmsg_len = len;
123
124 if (writev(mSock, iov, iovcnt) != (ssize_t) len) {
125 return -errno;
126 }
127
128 return checkError(mSock);
129}
130
131int SockDiag::sendDumpRequest(uint8_t proto, uint8_t family, uint32_t states) {
132 iovec iov[] = {
133 { nullptr, 0 },
134 };
Hugo Benichidee94812018-01-12 14:47:00 +0900135 return sendDumpRequest(proto, family, 0, states, iov, ARRAY_SIZE(iov));
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900136}
137
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900138int SockDiag::sendDumpRequest(uint8_t proto, uint8_t family, const char *addrstr) {
139 addrinfo hints = { .ai_flags = AI_NUMERICHOST };
140 addrinfo *res;
141 in6_addr mapped = { .s6_addr32 = { 0, 0, htonl(0xffff), 0 } };
142 int ret;
143
144 // TODO: refactor the netlink parsing code out of system/core, bring it into netd, and stop
145 // doing string conversions when they're not necessary.
146 if ((ret = getaddrinfo(addrstr, nullptr, &hints, &res)) != 0) {
147 return -EINVAL;
148 }
149
150 // So we don't have to call freeaddrinfo on every failure path.
151 ScopedAddrinfo resP(res);
152
153 void *addr;
154 uint8_t addrlen;
155 if (res->ai_family == AF_INET && family == AF_INET) {
156 in_addr& ina = reinterpret_cast<sockaddr_in*>(res->ai_addr)->sin_addr;
157 addr = &ina;
158 addrlen = sizeof(ina);
159 } else if (res->ai_family == AF_INET && family == AF_INET6) {
160 in_addr& ina = reinterpret_cast<sockaddr_in*>(res->ai_addr)->sin_addr;
161 mapped.s6_addr32[3] = ina.s_addr;
162 addr = &mapped;
163 addrlen = sizeof(mapped);
164 } else if (res->ai_family == AF_INET6 && family == AF_INET6) {
165 in6_addr& in6a = reinterpret_cast<sockaddr_in6*>(res->ai_addr)->sin6_addr;
166 addr = &in6a;
167 addrlen = sizeof(in6a);
168 } else {
169 return -EAFNOSUPPORT;
170 }
171
172 uint8_t prefixlen = addrlen * 8;
173 uint8_t yesjump = sizeof(inet_diag_bc_op) + sizeof(inet_diag_hostcond) + addrlen;
174 uint8_t nojump = yesjump + 4;
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900175
176 struct {
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900177 nlattr nla;
178 inet_diag_bc_op op;
179 inet_diag_hostcond cond;
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900180 } __attribute__((__packed__)) attrs = {
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900181 .nla = {
182 .nla_type = INET_DIAG_REQ_BYTECODE,
183 },
184 .op = {
185 INET_DIAG_BC_S_COND,
186 yesjump,
187 nojump,
188 },
189 .cond = {
190 family,
191 prefixlen,
192 -1,
193 {}
194 },
195 };
196
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900197 attrs.nla.nla_len = sizeof(attrs) + addrlen;
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900198
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900199 iovec iov[] = {
Lorenzo Colittifbe76b92016-09-14 02:25:05 +0900200 { nullptr, 0 },
201 { &attrs, sizeof(attrs) },
202 { addr, addrlen },
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900203 };
204
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900205 uint32_t states = ~(1 << TCP_TIME_WAIT);
Hugo Benichidee94812018-01-12 14:47:00 +0900206 return sendDumpRequest(proto, family, 0, states, iov, ARRAY_SIZE(iov));
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900207}
208
Lorenzo Colitti0b733e42017-02-13 16:29:00 +0900209int SockDiag::readDiagMsg(uint8_t proto, const SockDiag::DestroyFilter& shouldDestroy) {
210 NetlinkDumpCallback callback = [this, proto, shouldDestroy] (nlmsghdr *nlh) {
Lorenzo Colitti0b733e42017-02-13 16:29:00 +0900211 const inet_diag_msg *msg = reinterpret_cast<inet_diag_msg *>(NLMSG_DATA(nlh));
212 if (shouldDestroy(proto, msg)) {
213 sockDestroy(proto, msg);
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900214 }
Lorenzo Colitti0b733e42017-02-13 16:29:00 +0900215 };
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900216
Lorenzo Colitti0b733e42017-02-13 16:29:00 +0900217 return processNetlinkDump(mSock, callback);
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900218}
219
Hugo Benichidee94812018-01-12 14:47:00 +0900220int SockDiag::readDiagMsgWithTcpInfo(const TcpInfoReader& tcpInfoReader) {
221 NetlinkDumpCallback callback = [tcpInfoReader] (nlmsghdr *nlh) {
Hugo Benichi321b22c2018-01-30 11:37:27 +0900222 if (nlh->nlmsg_type != SOCK_DIAG_BY_FAMILY) {
223 ALOGE("expected nlmsg_type=SOCK_DIAG_BY_FAMILY, got nlmsg_type=%d", nlh->nlmsg_type);
224 return;
225 }
Hugo Benichicbaa36b2018-01-17 12:11:43 +0900226 Fwmark mark;
Hugo Benichidee94812018-01-12 14:47:00 +0900227 struct tcp_info *tcpinfo = nullptr;
Hugo Benichi54bfc7c2018-01-23 14:16:52 +0900228 uint32_t tcpinfoLength = 0;
Hugo Benichidee94812018-01-12 14:47:00 +0900229 inet_diag_msg *msg = reinterpret_cast<inet_diag_msg *>(NLMSG_DATA(nlh));
230 uint32_t attr_len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*msg));
231 struct rtattr *attr = reinterpret_cast<struct rtattr*>(msg+1);
232 while (RTA_OK(attr, attr_len)) {
233 if (attr->rta_type == INET_DIAG_INFO) {
234 tcpinfo = reinterpret_cast<struct tcp_info*>(RTA_DATA(attr));
Hugo Benichi54bfc7c2018-01-23 14:16:52 +0900235 tcpinfoLength = RTA_PAYLOAD(attr);
Hugo Benichicbaa36b2018-01-17 12:11:43 +0900236 }
237 if (attr->rta_type == INET_DIAG_MARK) {
238 mark.intValue = *reinterpret_cast<uint32_t*>(RTA_DATA(attr));
Hugo Benichidee94812018-01-12 14:47:00 +0900239 }
240 attr = RTA_NEXT(attr, attr_len);
241 }
242
Hugo Benichi54bfc7c2018-01-23 14:16:52 +0900243 tcpInfoReader(mark, msg, tcpinfo, tcpinfoLength);
Hugo Benichidee94812018-01-12 14:47:00 +0900244 };
245
246 return processNetlinkDump(mSock, callback);
247}
248
Lorenzo Colittie5c3c992016-07-26 17:53:50 +0900249// Determines whether a socket is a loopback socket. Does not check socket state.
250bool SockDiag::isLoopbackSocket(const inet_diag_msg *msg) {
251 switch (msg->idiag_family) {
252 case AF_INET:
253 // Old kernels only copy the IPv4 address and leave the other 12 bytes uninitialized.
254 return IN_LOOPBACK(htonl(msg->id.idiag_src[0])) ||
255 IN_LOOPBACK(htonl(msg->id.idiag_dst[0])) ||
256 msg->id.idiag_src[0] == msg->id.idiag_dst[0];
257
258 case AF_INET6: {
259 const struct in6_addr *src = (const struct in6_addr *) &msg->id.idiag_src;
260 const struct in6_addr *dst = (const struct in6_addr *) &msg->id.idiag_dst;
261 return (IN6_IS_ADDR_V4MAPPED(src) && IN_LOOPBACK(src->s6_addr32[3])) ||
262 (IN6_IS_ADDR_V4MAPPED(dst) && IN_LOOPBACK(dst->s6_addr32[3])) ||
263 IN6_IS_ADDR_LOOPBACK(src) || IN6_IS_ADDR_LOOPBACK(dst) ||
264 !memcmp(src, dst, sizeof(*src));
265 }
266 default:
267 return false;
268 }
269}
270
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900271int SockDiag::sockDestroy(uint8_t proto, const inet_diag_msg *msg) {
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900272 if (msg == nullptr) {
273 return 0;
274 }
275
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900276 DestroyRequest request = {
277 .nlh = {
278 .nlmsg_type = SOCK_DESTROY,
279 .nlmsg_flags = NLM_F_REQUEST,
280 },
281 .req = {
282 .sdiag_family = msg->idiag_family,
283 .sdiag_protocol = proto,
284 .idiag_states = (uint32_t) (1 << msg->idiag_state),
285 .id = msg->id,
286 },
287 };
288 request.nlh.nlmsg_len = sizeof(request);
289
290 if (write(mWriteSock, &request, sizeof(request)) < (ssize_t) sizeof(request)) {
291 return -errno;
292 }
293
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900294 int ret = checkError(mWriteSock);
295 if (!ret) mSocketsDestroyed++;
296 return ret;
297}
298
299int SockDiag::destroySockets(uint8_t proto, int family, const char *addrstr) {
300 if (!hasSocks()) {
301 return -EBADFD;
302 }
303
304 if (int ret = sendDumpRequest(proto, family, addrstr)) {
305 return ret;
306 }
307
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900308 auto destroyAll = [] (uint8_t, const inet_diag_msg*) { return true; };
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900309
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900310 return readDiagMsg(proto, destroyAll);
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900311}
312
313int SockDiag::destroySockets(const char *addrstr) {
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900314 Stopwatch s;
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900315 mSocketsDestroyed = 0;
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900316
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900317 if (!strchr(addrstr, ':')) {
318 if (int ret = destroySockets(IPPROTO_TCP, AF_INET, addrstr)) {
319 ALOGE("Failed to destroy IPv4 sockets on %s: %s", addrstr, strerror(-ret));
320 return ret;
321 }
322 }
323 if (int ret = destroySockets(IPPROTO_TCP, AF_INET6, addrstr)) {
324 ALOGE("Failed to destroy IPv6 sockets on %s: %s", addrstr, strerror(-ret));
325 return ret;
326 }
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900327
328 if (mSocketsDestroyed > 0) {
Bernie Innocenti196f1b82019-05-20 16:34:16 +0900329 ALOGI("Destroyed %d sockets on %s in %" PRId64 "us", mSocketsDestroyed, addrstr,
330 s.timeTakenUs());
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900331 }
332
333 return mSocketsDestroyed;
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900334}
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900335
Bernie Innocenti15bb55c2018-06-03 16:19:51 +0900336int SockDiag::destroyLiveSockets(const DestroyFilter& destroyFilter, const char *what,
Lorenzo Colittifbe76b92016-09-14 02:25:05 +0900337 iovec *iov, int iovcnt) {
Hugo Benichidee94812018-01-12 14:47:00 +0900338 const int proto = IPPROTO_TCP;
339 const uint32_t states = (1 << TCP_ESTABLISHED) | (1 << TCP_SYN_SENT) | (1 << TCP_SYN_RECV);
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900340
341 for (const int family : {AF_INET, AF_INET6}) {
342 const char *familyName = (family == AF_INET) ? "IPv4" : "IPv6";
Hugo Benichidee94812018-01-12 14:47:00 +0900343 if (int ret = sendDumpRequest(proto, family, 0, states, iov, iovcnt)) {
Lorenzo Colittifbe76b92016-09-14 02:25:05 +0900344 ALOGE("Failed to dump %s sockets for %s: %s", familyName, what, strerror(-ret));
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900345 return ret;
346 }
347 if (int ret = readDiagMsg(proto, destroyFilter)) {
Lorenzo Colittifbe76b92016-09-14 02:25:05 +0900348 ALOGE("Failed to destroy %s sockets for %s: %s", familyName, what, strerror(-ret));
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900349 return ret;
350 }
351 }
352
353 return 0;
354}
355
Hugo Benichidee94812018-01-12 14:47:00 +0900356int SockDiag::getLiveTcpInfos(const TcpInfoReader& tcpInfoReader) {
357 const int proto = IPPROTO_TCP;
358 const uint32_t states = (1 << TCP_ESTABLISHED) | (1 << TCP_SYN_SENT) | (1 << TCP_SYN_RECV);
359 const uint8_t extensions = (1 << INET_DIAG_MEMINFO); // flag for dumping struct tcp_info.
360
361 iovec iov[] = {
362 { nullptr, 0 },
363 };
364
365 for (const int family : {AF_INET, AF_INET6}) {
366 const char *familyName = (family == AF_INET) ? "IPv4" : "IPv6";
367 if (int ret = sendDumpRequest(proto, family, extensions, states, iov, ARRAY_SIZE(iov))) {
368 ALOGE("Failed to dump %s sockets struct tcp_info: %s", familyName, strerror(-ret));
369 return ret;
370 }
371 if (int ret = readDiagMsgWithTcpInfo(tcpInfoReader)) {
372 ALOGE("Failed to read %s sockets struct tcp_info: %s", familyName, strerror(-ret));
373 return ret;
374 }
375 }
376
377 return 0;
378}
379
Lorenzo Colittie5c3c992016-07-26 17:53:50 +0900380int SockDiag::destroySockets(uint8_t proto, const uid_t uid, bool excludeLoopback) {
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900381 mSocketsDestroyed = 0;
382 Stopwatch s;
383
Lorenzo Colittie5c3c992016-07-26 17:53:50 +0900384 auto shouldDestroy = [uid, excludeLoopback] (uint8_t, const inet_diag_msg *msg) {
385 return msg != nullptr &&
386 msg->idiag_uid == uid &&
387 !(excludeLoopback && isLoopbackSocket(msg));
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900388 };
389
390 for (const int family : {AF_INET, AF_INET6}) {
391 const char *familyName = family == AF_INET ? "IPv4" : "IPv6";
392 uint32_t states = (1 << TCP_ESTABLISHED) | (1 << TCP_SYN_SENT) | (1 << TCP_SYN_RECV);
393 if (int ret = sendDumpRequest(proto, family, states)) {
394 ALOGE("Failed to dump %s sockets for UID: %s", familyName, strerror(-ret));
395 return ret;
396 }
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900397 if (int ret = readDiagMsg(proto, shouldDestroy)) {
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900398 ALOGE("Failed to destroy %s sockets for UID: %s", familyName, strerror(-ret));
399 return ret;
400 }
401 }
402
403 if (mSocketsDestroyed > 0) {
Bernie Innocenti196f1b82019-05-20 16:34:16 +0900404 ALOGI("Destroyed %d sockets for UID in %" PRId64 "us", mSocketsDestroyed, s.timeTakenUs());
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900405 }
406
407 return 0;
408}
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900409
Lorenzo Colittie5c3c992016-07-26 17:53:50 +0900410int SockDiag::destroySockets(const UidRanges& uidRanges, const std::set<uid_t>& skipUids,
411 bool excludeLoopback) {
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900412 mSocketsDestroyed = 0;
413 Stopwatch s;
414
415 auto shouldDestroy = [&] (uint8_t, const inet_diag_msg *msg) {
416 return msg != nullptr &&
417 uidRanges.hasUid(msg->idiag_uid) &&
Lorenzo Colittie5c3c992016-07-26 17:53:50 +0900418 skipUids.find(msg->idiag_uid) == skipUids.end() &&
419 !(excludeLoopback && isLoopbackSocket(msg));
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900420 };
421
Lorenzo Colittifbe76b92016-09-14 02:25:05 +0900422 iovec iov[] = {
423 { nullptr, 0 },
424 };
425
426 if (int ret = destroyLiveSockets(shouldDestroy, "UID", iov, ARRAY_SIZE(iov))) {
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900427 return ret;
428 }
429
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900430 if (mSocketsDestroyed > 0) {
Bernie Innocenti196f1b82019-05-20 16:34:16 +0900431 ALOGI("Destroyed %d sockets for %s skip={%s} in %" PRId64 "us", mSocketsDestroyed,
432 uidRanges.toString().c_str(), android::base::Join(skipUids, " ").c_str(),
433 s.timeTakenUs());
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900434 }
435
436 return 0;
437}
Lorenzo Colittifbe76b92016-09-14 02:25:05 +0900438
439// Destroys all "live" (CONNECTED, SYN_SENT, SYN_RECV) TCP sockets on the specified netId where:
440// 1. The opening app no longer has permission to use this network, or:
441// 2. The opening app does have permission, but did not explicitly select this network.
442//
443// We destroy sockets without the explicit bit because we want to avoid the situation where a
444// privileged app uses its privileges without knowing it is doing so. For example, a privileged app
445// might have opened a socket on this network just because it was the default network at the
446// time. If we don't kill these sockets, those apps could continue to use them without realizing
447// that they are now sending and receiving traffic on a network that is now restricted.
448int SockDiag::destroySocketsLackingPermission(unsigned netId, Permission permission,
449 bool excludeLoopback) {
450 struct markmatch {
451 inet_diag_bc_op op;
452 // TODO: switch to inet_diag_markcond
453 __u32 mark;
454 __u32 mask;
455 } __attribute__((packed));
456 constexpr uint8_t matchlen = sizeof(markmatch);
457
458 Fwmark netIdMark, netIdMask;
459 netIdMark.netId = netId;
460 netIdMask.netId = 0xffff;
461
462 Fwmark controlMark;
463 controlMark.explicitlySelected = true;
464 controlMark.permission = permission;
465
466 // A SOCK_DIAG bytecode program that accepts the sockets we intend to destroy.
467 struct bytecode {
468 markmatch netIdMatch;
469 markmatch controlMatch;
470 inet_diag_bc_op controlJump;
471 } __attribute__((packed)) bytecode;
472
473 // The length of the INET_DIAG_BC_JMP instruction.
474 constexpr uint8_t jmplen = sizeof(inet_diag_bc_op);
475 // Jump exactly this far past the end of the program to reject.
476 constexpr uint8_t rejectoffset = sizeof(inet_diag_bc_op);
477 // Total length of the program.
478 constexpr uint8_t bytecodelen = sizeof(bytecode);
479
480 bytecode = (struct bytecode) {
481 // If netId matches, continue, otherwise, reject (i.e., leave socket alone).
482 { { INET_DIAG_BC_MARK_COND, matchlen, bytecodelen + rejectoffset },
483 netIdMark.intValue, netIdMask.intValue },
484
485 // If explicit and permission bits match, go to the JMP below which rejects the socket
486 // (i.e., we leave it alone). Otherwise, jump to the end of the program, which accepts the
487 // socket (so we destroy it).
488 { { INET_DIAG_BC_MARK_COND, matchlen, matchlen + jmplen },
489 controlMark.intValue, controlMark.intValue },
490
491 // This JMP unconditionally rejects the packet by jumping to the reject target. It is
492 // necessary to keep the kernel bytecode verifier happy. If we don't have a JMP the bytecode
493 // is invalid because the target of every no jump must always be reachable by yes jumps.
494 // Without this JMP, the accept target is not reachable by yes jumps and the program will
495 // be rejected by the validator.
496 { INET_DIAG_BC_JMP, jmplen, jmplen + rejectoffset },
497
498 // We have reached the end of the program. Accept the socket, and destroy it below.
499 };
500
501 struct nlattr nla = {
Nick Desaulniers6b357502019-10-11 09:26:44 -0700502 .nla_len = sizeof(struct nlattr) + bytecodelen,
503 .nla_type = INET_DIAG_REQ_BYTECODE,
Lorenzo Colittifbe76b92016-09-14 02:25:05 +0900504 };
505
506 iovec iov[] = {
507 { nullptr, 0 },
508 { &nla, sizeof(nla) },
509 { &bytecode, bytecodelen },
510 };
511
512 mSocketsDestroyed = 0;
513 Stopwatch s;
514
515 auto shouldDestroy = [&] (uint8_t, const inet_diag_msg *msg) {
516 return msg != nullptr && !(excludeLoopback && isLoopbackSocket(msg));
517 };
518
519 if (int ret = destroyLiveSockets(shouldDestroy, "permission change", iov, ARRAY_SIZE(iov))) {
520 return ret;
521 }
522
523 if (mSocketsDestroyed > 0) {
Bernie Innocenti196f1b82019-05-20 16:34:16 +0900524 ALOGI("Destroyed %d sockets for netId %d permission=%d in %" PRId64 "us", mSocketsDestroyed,
525 netId, permission, s.timeTakenUs());
Lorenzo Colittifbe76b92016-09-14 02:25:05 +0900526 }
527
528 return 0;
529}
Lorenzo Colitti7035f222017-02-13 18:29:00 +0900530
531} // namespace net
532} // namespace android