blob: f6b8b1067c7288f663353425d8c8c4e5fe3bb872 [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
17#include <errno.h>
18#include <netdb.h>
19#include <string.h>
20#include <netinet/in.h>
21#include <netinet/tcp.h>
22#include <sys/socket.h>
23#include <sys/uio.h>
24
25#include <linux/netlink.h>
26#include <linux/sock_diag.h>
27#include <linux/inet_diag.h>
28
29#define LOG_TAG "Netd"
30
Lorenzo Colittifff4bd32016-04-14 00:56:01 +090031#include <android-base/strings.h>
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +090032#include <cutils/log.h>
33
Lorenzo Colittifbe76b92016-09-14 02:25:05 +090034#include "Fwmark.h"
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +090035#include "NetdConstants.h"
Lorenzo Colittifbe76b92016-09-14 02:25:05 +090036#include "Permission.h"
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +090037#include "SockDiag.h"
38
Lorenzo Colittif32fc592016-02-15 01:09:14 +090039#include <chrono>
40
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 Colitti8464e1e2016-02-05 00:57:26 +090047namespace {
48
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +090049int checkError(int fd) {
50 struct {
51 nlmsghdr h;
52 nlmsgerr err;
53 } __attribute__((__packed__)) ack;
54 ssize_t bytesread = recv(fd, &ack, sizeof(ack), MSG_DONTWAIT | MSG_PEEK);
55 if (bytesread == -1) {
56 // Read failed (error), or nothing to read (good).
57 return (errno == EAGAIN) ? 0 : -errno;
58 } else if (bytesread == (ssize_t) sizeof(ack) && ack.h.nlmsg_type == NLMSG_ERROR) {
59 // We got an error. Consume it.
60 recv(fd, &ack, sizeof(ack), 0);
61 return ack.err.error;
62 } else {
63 // The kernel replied with something. Leave it to the caller.
64 return 0;
65 }
66}
67
68} // namespace
69
70bool SockDiag::open() {
71 if (hasSocks()) {
72 return false;
73 }
74
75 mSock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_INET_DIAG);
76 mWriteSock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_INET_DIAG);
77 if (!hasSocks()) {
78 closeSocks();
79 return false;
80 }
81
82 sockaddr_nl nl = { .nl_family = AF_NETLINK };
83 if ((connect(mSock, reinterpret_cast<sockaddr *>(&nl), sizeof(nl)) == -1) ||
84 (connect(mWriteSock, reinterpret_cast<sockaddr *>(&nl), sizeof(nl)) == -1)) {
85 closeSocks();
86 return false;
87 }
88
89 return true;
90}
91
Lorenzo Colitti94a7b432016-03-24 16:47:12 +090092int SockDiag::sendDumpRequest(uint8_t proto, uint8_t family, uint32_t states,
93 iovec *iov, int iovcnt) {
94 struct {
95 nlmsghdr nlh;
96 inet_diag_req_v2 req;
97 } __attribute__((__packed__)) request = {
98 .nlh = {
99 .nlmsg_type = SOCK_DIAG_BY_FAMILY,
100 .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
101 },
102 .req = {
103 .sdiag_family = family,
104 .sdiag_protocol = proto,
105 .idiag_states = states,
106 },
107 };
108
109 size_t len = 0;
110 iov[0].iov_base = &request;
111 iov[0].iov_len = sizeof(request);
112 for (int i = 0; i < iovcnt; i++) {
113 len += iov[i].iov_len;
114 }
115 request.nlh.nlmsg_len = len;
116
117 if (writev(mSock, iov, iovcnt) != (ssize_t) len) {
118 return -errno;
119 }
120
121 return checkError(mSock);
122}
123
124int SockDiag::sendDumpRequest(uint8_t proto, uint8_t family, uint32_t states) {
125 iovec iov[] = {
126 { nullptr, 0 },
127 };
128 return sendDumpRequest(proto, family, states, iov, ARRAY_SIZE(iov));
129}
130
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900131int SockDiag::sendDumpRequest(uint8_t proto, uint8_t family, const char *addrstr) {
132 addrinfo hints = { .ai_flags = AI_NUMERICHOST };
133 addrinfo *res;
134 in6_addr mapped = { .s6_addr32 = { 0, 0, htonl(0xffff), 0 } };
135 int ret;
136
137 // TODO: refactor the netlink parsing code out of system/core, bring it into netd, and stop
138 // doing string conversions when they're not necessary.
139 if ((ret = getaddrinfo(addrstr, nullptr, &hints, &res)) != 0) {
140 return -EINVAL;
141 }
142
143 // So we don't have to call freeaddrinfo on every failure path.
144 ScopedAddrinfo resP(res);
145
146 void *addr;
147 uint8_t addrlen;
148 if (res->ai_family == AF_INET && family == AF_INET) {
149 in_addr& ina = reinterpret_cast<sockaddr_in*>(res->ai_addr)->sin_addr;
150 addr = &ina;
151 addrlen = sizeof(ina);
152 } else if (res->ai_family == AF_INET && family == AF_INET6) {
153 in_addr& ina = reinterpret_cast<sockaddr_in*>(res->ai_addr)->sin_addr;
154 mapped.s6_addr32[3] = ina.s_addr;
155 addr = &mapped;
156 addrlen = sizeof(mapped);
157 } else if (res->ai_family == AF_INET6 && family == AF_INET6) {
158 in6_addr& in6a = reinterpret_cast<sockaddr_in6*>(res->ai_addr)->sin6_addr;
159 addr = &in6a;
160 addrlen = sizeof(in6a);
161 } else {
162 return -EAFNOSUPPORT;
163 }
164
165 uint8_t prefixlen = addrlen * 8;
166 uint8_t yesjump = sizeof(inet_diag_bc_op) + sizeof(inet_diag_hostcond) + addrlen;
167 uint8_t nojump = yesjump + 4;
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900168
169 struct {
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900170 nlattr nla;
171 inet_diag_bc_op op;
172 inet_diag_hostcond cond;
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900173 } __attribute__((__packed__)) attrs = {
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900174 .nla = {
175 .nla_type = INET_DIAG_REQ_BYTECODE,
176 },
177 .op = {
178 INET_DIAG_BC_S_COND,
179 yesjump,
180 nojump,
181 },
182 .cond = {
183 family,
184 prefixlen,
185 -1,
186 {}
187 },
188 };
189
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900190 attrs.nla.nla_len = sizeof(attrs) + addrlen;
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900191
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900192 iovec iov[] = {
Lorenzo Colittifbe76b92016-09-14 02:25:05 +0900193 { nullptr, 0 },
194 { &attrs, sizeof(attrs) },
195 { addr, addrlen },
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900196 };
197
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900198 uint32_t states = ~(1 << TCP_TIME_WAIT);
199 return sendDumpRequest(proto, family, states, iov, ARRAY_SIZE(iov));
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900200}
201
Chih-Hung Hsiehb22e4d22016-07-28 14:13:11 -0700202int SockDiag::readDiagMsg(uint8_t proto, const SockDiag::DumpCallback& callback) {
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900203 char buf[kBufferSize];
204
205 ssize_t bytesread;
206 do {
207 bytesread = read(mSock, buf, sizeof(buf));
208
209 if (bytesread < 0) {
210 return -errno;
211 }
212
213 uint32_t len = bytesread;
214 for (nlmsghdr *nlh = reinterpret_cast<nlmsghdr *>(buf);
215 NLMSG_OK(nlh, len);
216 nlh = NLMSG_NEXT(nlh, len)) {
217 switch (nlh->nlmsg_type) {
218 case NLMSG_DONE:
219 callback(proto, NULL);
220 return 0;
221 case NLMSG_ERROR: {
222 nlmsgerr *err = reinterpret_cast<nlmsgerr *>(NLMSG_DATA(nlh));
223 return err->error;
224 }
225 default:
226 inet_diag_msg *msg = reinterpret_cast<inet_diag_msg *>(NLMSG_DATA(nlh));
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900227 if (callback(proto, msg)) {
228 sockDestroy(proto, msg);
229 }
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900230 }
231 }
232 } while (bytesread > 0);
233
234 return 0;
235}
236
Lorenzo Colittie5c3c992016-07-26 17:53:50 +0900237// Determines whether a socket is a loopback socket. Does not check socket state.
238bool SockDiag::isLoopbackSocket(const inet_diag_msg *msg) {
239 switch (msg->idiag_family) {
240 case AF_INET:
241 // Old kernels only copy the IPv4 address and leave the other 12 bytes uninitialized.
242 return IN_LOOPBACK(htonl(msg->id.idiag_src[0])) ||
243 IN_LOOPBACK(htonl(msg->id.idiag_dst[0])) ||
244 msg->id.idiag_src[0] == msg->id.idiag_dst[0];
245
246 case AF_INET6: {
247 const struct in6_addr *src = (const struct in6_addr *) &msg->id.idiag_src;
248 const struct in6_addr *dst = (const struct in6_addr *) &msg->id.idiag_dst;
249 return (IN6_IS_ADDR_V4MAPPED(src) && IN_LOOPBACK(src->s6_addr32[3])) ||
250 (IN6_IS_ADDR_V4MAPPED(dst) && IN_LOOPBACK(dst->s6_addr32[3])) ||
251 IN6_IS_ADDR_LOOPBACK(src) || IN6_IS_ADDR_LOOPBACK(dst) ||
252 !memcmp(src, dst, sizeof(*src));
253 }
254 default:
255 return false;
256 }
257}
258
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900259int SockDiag::sockDestroy(uint8_t proto, const inet_diag_msg *msg) {
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900260 if (msg == nullptr) {
261 return 0;
262 }
263
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900264 DestroyRequest request = {
265 .nlh = {
266 .nlmsg_type = SOCK_DESTROY,
267 .nlmsg_flags = NLM_F_REQUEST,
268 },
269 .req = {
270 .sdiag_family = msg->idiag_family,
271 .sdiag_protocol = proto,
272 .idiag_states = (uint32_t) (1 << msg->idiag_state),
273 .id = msg->id,
274 },
275 };
276 request.nlh.nlmsg_len = sizeof(request);
277
278 if (write(mWriteSock, &request, sizeof(request)) < (ssize_t) sizeof(request)) {
279 return -errno;
280 }
281
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900282 int ret = checkError(mWriteSock);
283 if (!ret) mSocketsDestroyed++;
284 return ret;
285}
286
287int SockDiag::destroySockets(uint8_t proto, int family, const char *addrstr) {
288 if (!hasSocks()) {
289 return -EBADFD;
290 }
291
292 if (int ret = sendDumpRequest(proto, family, addrstr)) {
293 return ret;
294 }
295
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900296 auto destroyAll = [] (uint8_t, const inet_diag_msg*) { return true; };
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900297
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900298 return readDiagMsg(proto, destroyAll);
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900299}
300
301int SockDiag::destroySockets(const char *addrstr) {
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900302 Stopwatch s;
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900303 mSocketsDestroyed = 0;
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900304
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900305 if (!strchr(addrstr, ':')) {
306 if (int ret = destroySockets(IPPROTO_TCP, AF_INET, addrstr)) {
307 ALOGE("Failed to destroy IPv4 sockets on %s: %s", addrstr, strerror(-ret));
308 return ret;
309 }
310 }
311 if (int ret = destroySockets(IPPROTO_TCP, AF_INET6, addrstr)) {
312 ALOGE("Failed to destroy IPv6 sockets on %s: %s", addrstr, strerror(-ret));
313 return ret;
314 }
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900315
316 if (mSocketsDestroyed > 0) {
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900317 ALOGI("Destroyed %d sockets on %s in %.1f ms", mSocketsDestroyed, addrstr, s.timeTaken());
Lorenzo Colittif32fc592016-02-15 01:09:14 +0900318 }
319
320 return mSocketsDestroyed;
Lorenzo Colitti8464e1e2016-02-05 00:57:26 +0900321}
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900322
Lorenzo Colittifbe76b92016-09-14 02:25:05 +0900323int SockDiag::destroyLiveSockets(DumpCallback destroyFilter, const char *what,
324 iovec *iov, int iovcnt) {
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900325 int proto = IPPROTO_TCP;
326
327 for (const int family : {AF_INET, AF_INET6}) {
328 const char *familyName = (family == AF_INET) ? "IPv4" : "IPv6";
329 uint32_t states = (1 << TCP_ESTABLISHED) | (1 << TCP_SYN_SENT) | (1 << TCP_SYN_RECV);
Lorenzo Colittifbe76b92016-09-14 02:25:05 +0900330 if (int ret = sendDumpRequest(proto, family, states, iov, iovcnt)) {
331 ALOGE("Failed to dump %s sockets for %s: %s", familyName, what, strerror(-ret));
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900332 return ret;
333 }
334 if (int ret = readDiagMsg(proto, destroyFilter)) {
Lorenzo Colittifbe76b92016-09-14 02:25:05 +0900335 ALOGE("Failed to destroy %s sockets for %s: %s", familyName, what, strerror(-ret));
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900336 return ret;
337 }
338 }
339
340 return 0;
341}
342
Lorenzo Colittie5c3c992016-07-26 17:53:50 +0900343int SockDiag::destroySockets(uint8_t proto, const uid_t uid, bool excludeLoopback) {
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900344 mSocketsDestroyed = 0;
345 Stopwatch s;
346
Lorenzo Colittie5c3c992016-07-26 17:53:50 +0900347 auto shouldDestroy = [uid, excludeLoopback] (uint8_t, const inet_diag_msg *msg) {
348 return msg != nullptr &&
349 msg->idiag_uid == uid &&
350 !(excludeLoopback && isLoopbackSocket(msg));
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900351 };
352
353 for (const int family : {AF_INET, AF_INET6}) {
354 const char *familyName = family == AF_INET ? "IPv4" : "IPv6";
355 uint32_t states = (1 << TCP_ESTABLISHED) | (1 << TCP_SYN_SENT) | (1 << TCP_SYN_RECV);
356 if (int ret = sendDumpRequest(proto, family, states)) {
357 ALOGE("Failed to dump %s sockets for UID: %s", familyName, strerror(-ret));
358 return ret;
359 }
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900360 if (int ret = readDiagMsg(proto, shouldDestroy)) {
Lorenzo Colitti94a7b432016-03-24 16:47:12 +0900361 ALOGE("Failed to destroy %s sockets for UID: %s", familyName, strerror(-ret));
362 return ret;
363 }
364 }
365
366 if (mSocketsDestroyed > 0) {
367 ALOGI("Destroyed %d sockets for UID in %.1f ms", mSocketsDestroyed, s.timeTaken());
368 }
369
370 return 0;
371}
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900372
Lorenzo Colittie5c3c992016-07-26 17:53:50 +0900373int SockDiag::destroySockets(const UidRanges& uidRanges, const std::set<uid_t>& skipUids,
374 bool excludeLoopback) {
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900375 mSocketsDestroyed = 0;
376 Stopwatch s;
377
378 auto shouldDestroy = [&] (uint8_t, const inet_diag_msg *msg) {
379 return msg != nullptr &&
380 uidRanges.hasUid(msg->idiag_uid) &&
Lorenzo Colittie5c3c992016-07-26 17:53:50 +0900381 skipUids.find(msg->idiag_uid) == skipUids.end() &&
382 !(excludeLoopback && isLoopbackSocket(msg));
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900383 };
384
Lorenzo Colittifbe76b92016-09-14 02:25:05 +0900385 iovec iov[] = {
386 { nullptr, 0 },
387 };
388
389 if (int ret = destroyLiveSockets(shouldDestroy, "UID", iov, ARRAY_SIZE(iov))) {
Lorenzo Colittifff4bd32016-04-14 00:56:01 +0900390 return ret;
391 }
392
393 std::vector<uid_t> skipUidStrings;
394 for (uid_t uid : skipUids) {
395 skipUidStrings.push_back(uid);
396 }
397 std::sort(skipUidStrings.begin(), skipUidStrings.end());
398
399 if (mSocketsDestroyed > 0) {
400 ALOGI("Destroyed %d sockets for %s skip={%s} in %.1f ms",
401 mSocketsDestroyed, uidRanges.toString().c_str(),
402 android::base::Join(skipUidStrings, " ").c_str(), s.timeTaken());
403 }
404
405 return 0;
406}
Lorenzo Colittifbe76b92016-09-14 02:25:05 +0900407
408// Destroys all "live" (CONNECTED, SYN_SENT, SYN_RECV) TCP sockets on the specified netId where:
409// 1. The opening app no longer has permission to use this network, or:
410// 2. The opening app does have permission, but did not explicitly select this network.
411//
412// We destroy sockets without the explicit bit because we want to avoid the situation where a
413// privileged app uses its privileges without knowing it is doing so. For example, a privileged app
414// might have opened a socket on this network just because it was the default network at the
415// time. If we don't kill these sockets, those apps could continue to use them without realizing
416// that they are now sending and receiving traffic on a network that is now restricted.
417int SockDiag::destroySocketsLackingPermission(unsigned netId, Permission permission,
418 bool excludeLoopback) {
419 struct markmatch {
420 inet_diag_bc_op op;
421 // TODO: switch to inet_diag_markcond
422 __u32 mark;
423 __u32 mask;
424 } __attribute__((packed));
425 constexpr uint8_t matchlen = sizeof(markmatch);
426
427 Fwmark netIdMark, netIdMask;
428 netIdMark.netId = netId;
429 netIdMask.netId = 0xffff;
430
431 Fwmark controlMark;
432 controlMark.explicitlySelected = true;
433 controlMark.permission = permission;
434
435 // A SOCK_DIAG bytecode program that accepts the sockets we intend to destroy.
436 struct bytecode {
437 markmatch netIdMatch;
438 markmatch controlMatch;
439 inet_diag_bc_op controlJump;
440 } __attribute__((packed)) bytecode;
441
442 // The length of the INET_DIAG_BC_JMP instruction.
443 constexpr uint8_t jmplen = sizeof(inet_diag_bc_op);
444 // Jump exactly this far past the end of the program to reject.
445 constexpr uint8_t rejectoffset = sizeof(inet_diag_bc_op);
446 // Total length of the program.
447 constexpr uint8_t bytecodelen = sizeof(bytecode);
448
449 bytecode = (struct bytecode) {
450 // If netId matches, continue, otherwise, reject (i.e., leave socket alone).
451 { { INET_DIAG_BC_MARK_COND, matchlen, bytecodelen + rejectoffset },
452 netIdMark.intValue, netIdMask.intValue },
453
454 // If explicit and permission bits match, go to the JMP below which rejects the socket
455 // (i.e., we leave it alone). Otherwise, jump to the end of the program, which accepts the
456 // socket (so we destroy it).
457 { { INET_DIAG_BC_MARK_COND, matchlen, matchlen + jmplen },
458 controlMark.intValue, controlMark.intValue },
459
460 // This JMP unconditionally rejects the packet by jumping to the reject target. It is
461 // necessary to keep the kernel bytecode verifier happy. If we don't have a JMP the bytecode
462 // is invalid because the target of every no jump must always be reachable by yes jumps.
463 // Without this JMP, the accept target is not reachable by yes jumps and the program will
464 // be rejected by the validator.
465 { INET_DIAG_BC_JMP, jmplen, jmplen + rejectoffset },
466
467 // We have reached the end of the program. Accept the socket, and destroy it below.
468 };
469
470 struct nlattr nla = {
471 .nla_type = INET_DIAG_REQ_BYTECODE,
472 .nla_len = sizeof(struct nlattr) + bytecodelen,
473 };
474
475 iovec iov[] = {
476 { nullptr, 0 },
477 { &nla, sizeof(nla) },
478 { &bytecode, bytecodelen },
479 };
480
481 mSocketsDestroyed = 0;
482 Stopwatch s;
483
484 auto shouldDestroy = [&] (uint8_t, const inet_diag_msg *msg) {
485 return msg != nullptr && !(excludeLoopback && isLoopbackSocket(msg));
486 };
487
488 if (int ret = destroyLiveSockets(shouldDestroy, "permission change", iov, ARRAY_SIZE(iov))) {
489 return ret;
490 }
491
492 if (mSocketsDestroyed > 0) {
493 ALOGI("Destroyed %d sockets for netId %d permission=%d in %.1f ms",
494 mSocketsDestroyed, netId, permission, s.timeTaken());
495 }
496
497 return 0;
498}