1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2023 Gleb Smirnoff <glebius@FreeBSD.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/param.h> 29 #include <sys/ioctl.h> 30 #include <sys/time.h> 31 #include <sys/socket.h> 32 #include <sys/module.h> 33 #include <errno.h> 34 #include <fcntl.h> 35 #include <signal.h> 36 #include <stdlib.h> 37 #include <unistd.h> 38 39 #include <netlink/netlink.h> 40 #include <netlink/netlink_route.h> 41 42 #include <netinet/in.h> 43 #include <arpa/inet.h> 44 45 #include <atf-c.h> 46 47 static struct itimerval itv = { 48 .it_interval = { 0, 0 }, 49 .it_value = { 1, 0 }, /* one second */ 50 }; 51 static sig_atomic_t timer_done = 0; 52 static void 53 sigalarm(int sig __unused) 54 { 55 56 timer_done = 1; 57 } 58 59 static struct sigaction sigact = { 60 .sa_handler = sigalarm, 61 }; 62 63 static struct nlmsghdr hdr = (struct nlmsghdr) { 64 .nlmsg_type = RTM_GETLINK, 65 .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK, 66 .nlmsg_len = sizeof(struct nlmsghdr), 67 }; 68 69 #define BUFLEN 1000 70 71 static int 72 fullsocket(void) 73 { 74 char buf[BUFLEN]; 75 socklen_t slen = sizeof(int); 76 int fd, sendspace, recvspace, sendavail, recvavail, rsize; 77 u_int cnt = 0; 78 79 ATF_REQUIRE((fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) != -1); 80 ATF_REQUIRE(getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sendspace, 81 &slen) == 0); 82 ATF_REQUIRE(getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &recvspace, 83 &slen) == 0); 84 85 /* Check the expected size of reply on a single RTM_GETLINK. */ 86 ATF_REQUIRE(send(fd, &hdr, sizeof(hdr), 0) == sizeof(hdr)); 87 ATF_REQUIRE(recv(fd, buf, sizeof(hdr), MSG_WAITALL | MSG_PEEK) == 88 sizeof(hdr)); 89 ATF_REQUIRE(ioctl(fd, FIONREAD, &rsize) != -1); 90 91 92 /* 93 * Flood the socket with requests, without reading out the replies. 94 * While we are flooding, the kernel tries to process the requests. 95 * Kernel takes off requests from the send buffer and puts replies 96 * on receive buffer. Once the receive buffer is full it stops working 97 * on queue in the send buffer. At this point we must get a solid 98 * failure. However, if we flood faster than kernel taskqueue runs, 99 * we may get intermittent failures. 100 */ 101 do { 102 ssize_t rv; 103 104 rv = send(fd, &hdr, sizeof(hdr), MSG_DONTWAIT); 105 if (__predict_true(rv == sizeof(hdr))) 106 cnt++; 107 else { 108 ATF_REQUIRE(errno == EAGAIN); 109 ATF_REQUIRE(sizeof(hdr) * cnt > sendspace); 110 } 111 ATF_REQUIRE(ioctl(fd, FIONREAD, &recvavail) != -1); 112 ATF_REQUIRE(ioctl(fd, FIONWRITE, &sendavail) != -1); 113 } while (recvavail <= recvspace - rsize || 114 sendavail <= sendspace - sizeof(hdr)); 115 116 return (fd); 117 } 118 119 ATF_TC(overflow); 120 ATF_TC_HEAD(overflow, tc) 121 { 122 atf_tc_set_md_var(tc, "require.kmods", "netlink"); 123 } 124 ATF_TC_BODY(overflow, tc) 125 { 126 char buf[BUFLEN]; 127 int fd; 128 129 fd = fullsocket(); 130 131 /* Both buffers full: block. */ 132 timer_done = 0; 133 ATF_REQUIRE(sigaction(SIGALRM, &sigact, NULL) == 0); 134 ATF_REQUIRE(setitimer(ITIMER_REAL, &itv, NULL) == 0); 135 ATF_REQUIRE(send(fd, &hdr, sizeof(hdr), 0) == -1); 136 ATF_REQUIRE(errno == EINTR); 137 ATF_REQUIRE(timer_done == 1); 138 139 /* 140 * Now, reading something from the receive buffer should wake up the 141 * taskqueue and send buffer should start getting drained. 142 */ 143 ATF_REQUIRE(recv(fd, buf, BUFLEN, 0) > sizeof(hdr)); 144 timer_done = 0; 145 ATF_REQUIRE(setitimer(ITIMER_REAL, &itv, NULL) == 0); 146 ATF_REQUIRE(send(fd, &hdr, sizeof(hdr), 0) == sizeof(hdr)); 147 ATF_REQUIRE(timer_done == 0); 148 } 149 150 ATF_TC(peek); 151 ATF_TC_HEAD(peek, tc) 152 { 153 atf_tc_set_md_var(tc, "require.kmods", "netlink"); 154 } 155 ATF_TC_BODY(peek, tc) 156 { 157 char *buf; 158 ssize_t ss, ss1; 159 int fd; 160 161 ATF_REQUIRE((fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) != -1); 162 163 ATF_REQUIRE(send(fd, &hdr, sizeof(hdr), 0) == sizeof(hdr)); 164 ss = recv(fd, buf, 0, MSG_WAITALL | MSG_PEEK | MSG_TRUNC); 165 ATF_REQUIRE((buf = malloc(ss)) != NULL); 166 ATF_REQUIRE(recv(fd, buf, ss, MSG_WAITALL) == ss); 167 } 168 169 struct nl_control { 170 struct nlattr nla; 171 uint32_t val; 172 }; 173 174 static void 175 cmsg_check(struct msghdr *msg) 176 { 177 static pid_t pid = 0; 178 struct cmsghdr *cmsg; 179 struct nl_control *nlc; 180 181 ATF_REQUIRE((cmsg = CMSG_FIRSTHDR(msg)) != NULL); 182 ATF_REQUIRE(cmsg->cmsg_level == SOL_NETLINK); 183 ATF_REQUIRE(cmsg->cmsg_type == NETLINK_MSG_INFO); 184 nlc = (struct nl_control *)CMSG_DATA(cmsg); 185 ATF_REQUIRE(nlc[0].nla.nla_type == NLMSGINFO_ATTR_PROCESS_ID); 186 if (pid == 0) 187 pid = getpid(); 188 ATF_REQUIRE(nlc[0].val == pid); 189 ATF_REQUIRE(nlc[1].nla.nla_type == NLMSGINFO_ATTR_PORT_ID); 190 /* XXX need another test to test port id */ 191 ATF_REQUIRE(nlc[1].val == 0); 192 ATF_REQUIRE(CMSG_NXTHDR(msg, cmsg) == NULL); 193 ATF_REQUIRE((msg->msg_flags & MSG_CTRUNC) == 0); 194 } 195 196 ATF_TC(sizes); 197 ATF_TC_HEAD(sizes, tc) 198 { 199 atf_tc_set_md_var(tc, "require.kmods", "netlink"); 200 } 201 ATF_TC_BODY(sizes, tc) 202 { 203 #define NLMSG_LARGE 2048 /* XXX: match kernel nl_buf */ 204 char buf[NLMSG_LARGE * 10]; 205 char cbuf[CMSG_SPACE(sizeof(struct nl_control) * 2)]; 206 struct iovec iov; 207 struct msghdr msg = { 208 .msg_iov = &iov, 209 .msg_iovlen = 1, 210 .msg_control = cbuf, 211 .msg_controllen = sizeof(cbuf), 212 }; 213 ssize_t ss; 214 int fd, size, msize, rsize; 215 216 /* 217 * Create a socket with NMSGS messages in the receive buffer. 218 */ 219 #define NMSGS 5 220 ATF_REQUIRE((fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) != -1); 221 ATF_REQUIRE(send(fd, &hdr, sizeof(hdr), 0) == sizeof(hdr)); 222 ATF_REQUIRE(recv(fd, buf, sizeof(hdr), MSG_WAITALL | MSG_PEEK) == 223 sizeof(hdr)); 224 ATF_REQUIRE(ioctl(fd, FIONREAD, &msize) != -1); 225 for (u_int i = 0; i < NMSGS; i++) 226 ATF_REQUIRE(send(fd, &hdr, sizeof(hdr), 0) == sizeof(hdr)); 227 do { 228 ATF_REQUIRE(ioctl(fd, FIONREAD, &rsize) != -1); 229 } while (rsize < msize * (NMSGS + 1)); 230 231 /* 232 * Set NETLINK_MSG_INFO, so that later cmsg_check will check that any 233 * read is accompanied with control data. 234 */ 235 ATF_REQUIRE(setsockopt(fd, SOL_NETLINK, NETLINK_MSG_INFO, 236 &(int){1}, sizeof(int)) == 0); 237 238 iov = (struct iovec ){ 239 .iov_base = &hdr, 240 .iov_len = sizeof(hdr), 241 }; 242 /* Obtain size of the first message in the socket. */ 243 ss = recvmsg(fd, &msg, MSG_WAITALL | MSG_PEEK | MSG_TRUNC); 244 ATF_REQUIRE(ss == hdr.nlmsg_len); 245 /* And overall amount of data in the socket. */ 246 ATF_REQUIRE(ioctl(fd, FIONREAD, &rsize) != -1); 247 cmsg_check(&msg); 248 249 /* Zero-sized read should not affect state of the socket buffer. */ 250 ATF_REQUIRE(recv(fd, buf, 0, 0) == 0); 251 ATF_REQUIRE(ioctl(fd, FIONREAD, &size) != -1); 252 ATF_REQUIRE(size == rsize); 253 254 /* 255 * Undersized read should lose a message. This isn't exactly 256 * pronounced in the Netlink RFC, but it always says that Netlink 257 * socket is an analog of the BSD routing socket, and this is how 258 * a route(4) socket deals with undersized read. 259 */ 260 iov = (struct iovec ){ 261 .iov_base = buf, 262 .iov_len = sizeof(hdr), 263 }; 264 ATF_REQUIRE(recvmsg(fd, &msg, 0) == sizeof(hdr)); 265 ATF_REQUIRE(msg.msg_flags & MSG_TRUNC); 266 ATF_REQUIRE(hdr.nlmsg_len > sizeof(hdr)); 267 size = rsize - hdr.nlmsg_len; 268 ATF_REQUIRE(ioctl(fd, FIONREAD, &rsize) != -1); 269 ATF_REQUIRE(size == rsize); 270 cmsg_check(&msg); 271 272 /* 273 * Large read should span several nl_bufs, seeing no boundaries. 274 */ 275 iov = (struct iovec ){ 276 .iov_base = buf, 277 .iov_len = sizeof(buf) < rsize ? sizeof(buf) : rsize, 278 }; 279 ss = recvmsg(fd, &msg, 0); 280 ATF_REQUIRE(ss > hdr.nlmsg_len); 281 ATF_REQUIRE(ss > NLMSG_LARGE * 9 || ss == rsize); 282 cmsg_check(&msg); 283 } 284 285 static struct nlattr * 286 nla_RTA_DST(struct nlattr *start, ssize_t len) 287 { 288 struct nlattr *nla; 289 290 for (nla = start; (char *)nla < (char *)start + len; 291 nla = (struct nlattr *)((char *)nla + NLA_ALIGN(nla->nla_len))) { 292 if (nla->nla_type == RTA_DST) 293 return (nla); 294 } 295 296 return (NULL); 297 } 298 /* 299 * Check that NETLINK_ADD_MEMBERSHIP subscribes us. Add & delete a temporary 300 * route and check if announcements came in. 301 */ 302 ATF_TC(membership); 303 ATF_TC_HEAD(membership, tc) 304 { 305 atf_tc_set_md_var(tc, "require.kmods", "netlink"); 306 } 307 ATF_TC_BODY(membership, tc) 308 { 309 struct { 310 struct nlmsghdr hdr; 311 struct rtmsg rtm; 312 struct nlattr rta_dst; 313 struct in_addr dst; 314 struct nlattr rta_oif; 315 uint32_t oif; 316 } reply, msg = { 317 .hdr.nlmsg_type = RTM_NEWROUTE, 318 .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL, 319 .hdr.nlmsg_len = sizeof(msg), 320 .rtm.rtm_family = AF_INET, 321 .rtm.rtm_protocol = RTPROT_STATIC, 322 .rtm.rtm_type = RTN_UNICAST, 323 .rtm.rtm_dst_len = 32, 324 .rta_dst.nla_type = RTA_DST, 325 .rta_dst.nla_len = sizeof(struct in_addr) + 326 sizeof(struct nlattr), 327 .dst.s_addr = inet_addr("127.0.0.127"), 328 .rta_oif.nla_type = RTA_OIF, 329 .rta_oif.nla_len = sizeof(uint32_t) + sizeof(struct nlattr), 330 .oif = 1, 331 }; 332 struct nlattr *nla; 333 int fd; 334 335 ATF_REQUIRE((fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) != -1); 336 ATF_REQUIRE(setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, 337 &(int){RTNLGRP_IPV4_ROUTE}, sizeof(int)) == 0); 338 339 ATF_REQUIRE(send(fd, &msg, sizeof(msg), 0) == sizeof(msg)); 340 ATF_REQUIRE(recv(fd, &reply, sizeof(reply), 0) == sizeof(reply)); 341 ATF_REQUIRE(reply.hdr.nlmsg_type == msg.hdr.nlmsg_type); 342 ATF_REQUIRE(reply.rtm.rtm_type == msg.rtm.rtm_type); 343 ATF_REQUIRE(reply.rtm.rtm_dst_len == msg.rtm.rtm_dst_len); 344 ATF_REQUIRE(nla = nla_RTA_DST(&reply.rta_dst, sizeof(reply))); 345 ATF_REQUIRE(memcmp(&msg.dst, (char *)nla + sizeof(struct nlattr), 346 sizeof(struct in_addr)) == 0); 347 348 msg.hdr.nlmsg_type = RTM_DELROUTE; 349 msg.hdr.nlmsg_len -= sizeof(struct nlattr) + sizeof(uint32_t); 350 ATF_REQUIRE(send(fd, &msg, msg.hdr.nlmsg_len, 0) == msg.hdr.nlmsg_len); 351 ATF_REQUIRE(recv(fd, &reply, sizeof(reply), 0) == sizeof(reply)); 352 ATF_REQUIRE(reply.hdr.nlmsg_type == msg.hdr.nlmsg_type); 353 ATF_REQUIRE(reply.rtm.rtm_type == msg.rtm.rtm_type); 354 ATF_REQUIRE(reply.rtm.rtm_dst_len == msg.rtm.rtm_dst_len); 355 ATF_REQUIRE(nla = nla_RTA_DST(&reply.rta_dst, sizeof(reply))); 356 ATF_REQUIRE(memcmp(&msg.dst, (char *)nla + sizeof(struct nlattr), 357 sizeof(struct in_addr)) == 0); 358 } 359 360 ATF_TP_ADD_TCS(tp) 361 { 362 ATF_TP_ADD_TC(tp, overflow); 363 ATF_TP_ADD_TC(tp, peek); 364 ATF_TP_ADD_TC(tp, sizes); 365 ATF_TP_ADD_TC(tp, membership); 366 367 return (atf_no_error()); 368 } 369