1 /*- 2 * Copyright (c) 2015 Dmitry Chagin 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <opt_inet6.h> 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/ctype.h> 35 #include <sys/jail.h> 36 #include <sys/lock.h> 37 #include <sys/malloc.h> 38 #include <sys/signalvar.h> 39 #include <sys/socket.h> 40 #include <sys/socketvar.h> 41 42 #include <net/if.h> 43 #include <net/if_var.h> 44 #include <net/if_dl.h> 45 #include <net/if_types.h> 46 47 #include <sys/un.h> 48 #include <netinet/in.h> 49 50 #include <compat/linux/linux.h> 51 #include <compat/linux/linux_common.h> 52 #include <compat/linux/linux_util.h> 53 54 struct futex_list futex_list; 55 struct mtx futex_mtx; /* protects the futex list */ 56 57 CTASSERT(LINUX_IFNAMSIZ == IFNAMSIZ); 58 59 static int bsd_to_linux_sigtbl[LINUX_SIGTBLSZ] = { 60 LINUX_SIGHUP, /* SIGHUP */ 61 LINUX_SIGINT, /* SIGINT */ 62 LINUX_SIGQUIT, /* SIGQUIT */ 63 LINUX_SIGILL, /* SIGILL */ 64 LINUX_SIGTRAP, /* SIGTRAP */ 65 LINUX_SIGABRT, /* SIGABRT */ 66 0, /* SIGEMT */ 67 LINUX_SIGFPE, /* SIGFPE */ 68 LINUX_SIGKILL, /* SIGKILL */ 69 LINUX_SIGBUS, /* SIGBUS */ 70 LINUX_SIGSEGV, /* SIGSEGV */ 71 LINUX_SIGSYS, /* SIGSYS */ 72 LINUX_SIGPIPE, /* SIGPIPE */ 73 LINUX_SIGALRM, /* SIGALRM */ 74 LINUX_SIGTERM, /* SIGTERM */ 75 LINUX_SIGURG, /* SIGURG */ 76 LINUX_SIGSTOP, /* SIGSTOP */ 77 LINUX_SIGTSTP, /* SIGTSTP */ 78 LINUX_SIGCONT, /* SIGCONT */ 79 LINUX_SIGCHLD, /* SIGCHLD */ 80 LINUX_SIGTTIN, /* SIGTTIN */ 81 LINUX_SIGTTOU, /* SIGTTOU */ 82 LINUX_SIGIO, /* SIGIO */ 83 LINUX_SIGXCPU, /* SIGXCPU */ 84 LINUX_SIGXFSZ, /* SIGXFSZ */ 85 LINUX_SIGVTALRM,/* SIGVTALRM */ 86 LINUX_SIGPROF, /* SIGPROF */ 87 LINUX_SIGWINCH, /* SIGWINCH */ 88 0, /* SIGINFO */ 89 LINUX_SIGUSR1, /* SIGUSR1 */ 90 LINUX_SIGUSR2 /* SIGUSR2 */ 91 }; 92 93 static int linux_to_bsd_sigtbl[LINUX_SIGTBLSZ] = { 94 SIGHUP, /* LINUX_SIGHUP */ 95 SIGINT, /* LINUX_SIGINT */ 96 SIGQUIT, /* LINUX_SIGQUIT */ 97 SIGILL, /* LINUX_SIGILL */ 98 SIGTRAP, /* LINUX_SIGTRAP */ 99 SIGABRT, /* LINUX_SIGABRT */ 100 SIGBUS, /* LINUX_SIGBUS */ 101 SIGFPE, /* LINUX_SIGFPE */ 102 SIGKILL, /* LINUX_SIGKILL */ 103 SIGUSR1, /* LINUX_SIGUSR1 */ 104 SIGSEGV, /* LINUX_SIGSEGV */ 105 SIGUSR2, /* LINUX_SIGUSR2 */ 106 SIGPIPE, /* LINUX_SIGPIPE */ 107 SIGALRM, /* LINUX_SIGALRM */ 108 SIGTERM, /* LINUX_SIGTERM */ 109 SIGBUS, /* LINUX_SIGSTKFLT */ 110 SIGCHLD, /* LINUX_SIGCHLD */ 111 SIGCONT, /* LINUX_SIGCONT */ 112 SIGSTOP, /* LINUX_SIGSTOP */ 113 SIGTSTP, /* LINUX_SIGTSTP */ 114 SIGTTIN, /* LINUX_SIGTTIN */ 115 SIGTTOU, /* LINUX_SIGTTOU */ 116 SIGURG, /* LINUX_SIGURG */ 117 SIGXCPU, /* LINUX_SIGXCPU */ 118 SIGXFSZ, /* LINUX_SIGXFSZ */ 119 SIGVTALRM, /* LINUX_SIGVTALARM */ 120 SIGPROF, /* LINUX_SIGPROF */ 121 SIGWINCH, /* LINUX_SIGWINCH */ 122 SIGIO, /* LINUX_SIGIO */ 123 /* 124 * FreeBSD does not have SIGPWR signal, map Linux SIGPWR signal 125 * to the first unused FreeBSD signal number. Since Linux supports 126 * signals from 1 to 64 we are ok here as our SIGRTMIN = 65. 127 */ 128 SIGRTMIN, /* LINUX_SIGPWR */ 129 SIGSYS /* LINUX_SIGSYS */ 130 }; 131 132 /* 133 * Map Linux RT signals to the FreeBSD RT signals. 134 */ 135 static inline int 136 linux_to_bsd_rt_signal(int sig) 137 { 138 139 return (SIGRTMIN + 1 + sig - LINUX_SIGRTMIN); 140 } 141 142 static inline int 143 bsd_to_linux_rt_signal(int sig) 144 { 145 146 return (sig - SIGRTMIN - 1 + LINUX_SIGRTMIN); 147 } 148 149 int 150 linux_to_bsd_signal(int sig) 151 { 152 153 KASSERT(sig > 0 && sig <= LINUX_SIGRTMAX, ("invalid Linux signal %d\n", sig)); 154 155 if (sig < LINUX_SIGRTMIN) 156 return (linux_to_bsd_sigtbl[_SIG_IDX(sig)]); 157 158 return (linux_to_bsd_rt_signal(sig)); 159 } 160 161 int 162 bsd_to_linux_signal(int sig) 163 { 164 165 if (sig <= LINUX_SIGTBLSZ) 166 return (bsd_to_linux_sigtbl[_SIG_IDX(sig)]); 167 if (sig == SIGRTMIN) 168 return (LINUX_SIGPWR); 169 170 return (bsd_to_linux_rt_signal(sig)); 171 } 172 173 int 174 linux_to_bsd_sigaltstack(int lsa) 175 { 176 int bsa = 0; 177 178 if (lsa & LINUX_SS_DISABLE) 179 bsa |= SS_DISABLE; 180 /* 181 * Linux ignores SS_ONSTACK flag for ss 182 * parameter while FreeBSD prohibits it. 183 */ 184 return (bsa); 185 } 186 187 int 188 bsd_to_linux_sigaltstack(int bsa) 189 { 190 int lsa = 0; 191 192 if (bsa & SS_DISABLE) 193 lsa |= LINUX_SS_DISABLE; 194 if (bsa & SS_ONSTACK) 195 lsa |= LINUX_SS_ONSTACK; 196 return (lsa); 197 } 198 199 void 200 linux_to_bsd_sigset(l_sigset_t *lss, sigset_t *bss) 201 { 202 int b, l; 203 204 SIGEMPTYSET(*bss); 205 for (l = 1; l <= LINUX_SIGRTMAX; l++) { 206 if (LINUX_SIGISMEMBER(*lss, l)) { 207 b = linux_to_bsd_signal(l); 208 if (b) 209 SIGADDSET(*bss, b); 210 } 211 } 212 } 213 214 void 215 bsd_to_linux_sigset(sigset_t *bss, l_sigset_t *lss) 216 { 217 int b, l; 218 219 LINUX_SIGEMPTYSET(*lss); 220 for (b = 1; b <= SIGRTMAX; b++) { 221 if (SIGISMEMBER(*bss, b)) { 222 l = bsd_to_linux_signal(b); 223 if (l) 224 LINUX_SIGADDSET(*lss, l); 225 } 226 } 227 } 228 229 /* 230 * Translate a Linux interface name to a FreeBSD interface name, 231 * and return the associated ifnet structure 232 * bsdname and lxname need to be least IFNAMSIZ bytes long, but 233 * can point to the same buffer. 234 */ 235 struct ifnet * 236 ifname_linux_to_bsd(struct thread *td, const char *lxname, char *bsdname) 237 { 238 struct ifnet *ifp; 239 int len, unit; 240 char *ep; 241 int index; 242 bool is_eth, is_lo; 243 244 for (len = 0; len < LINUX_IFNAMSIZ; ++len) 245 if (!isalpha(lxname[len]) || lxname[len] == '\0') 246 break; 247 if (len == 0 || len == LINUX_IFNAMSIZ) 248 return (NULL); 249 /* Linux loopback interface name is lo (not lo0) */ 250 is_lo = (len == 2 && strncmp(lxname, "lo", len) == 0); 251 unit = (int)strtoul(lxname + len, &ep, 10); 252 if ((ep == NULL || ep == lxname + len || ep >= lxname + LINUX_IFNAMSIZ) && 253 is_lo == 0) 254 return (NULL); 255 index = 0; 256 is_eth = (len == 3 && strncmp(lxname, "eth", len) == 0); 257 258 CURVNET_SET(TD_TO_VNET(td)); 259 IFNET_RLOCK(); 260 CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { 261 /* 262 * Allow Linux programs to use FreeBSD names. Don't presume 263 * we never have an interface named "eth", so don't make 264 * the test optional based on is_eth. 265 */ 266 if (strncmp(ifp->if_xname, lxname, LINUX_IFNAMSIZ) == 0) 267 break; 268 if (is_eth && IFP_IS_ETH(ifp) && unit == index++) 269 break; 270 if (is_lo && IFP_IS_LOOP(ifp)) 271 break; 272 } 273 IFNET_RUNLOCK(); 274 CURVNET_RESTORE(); 275 if (ifp != NULL && bsdname != NULL) 276 strlcpy(bsdname, ifp->if_xname, IFNAMSIZ); 277 return (ifp); 278 } 279 280 void 281 linux_ifflags(struct ifnet *ifp, short *flags) 282 { 283 unsigned short fl; 284 285 fl = (ifp->if_flags | ifp->if_drv_flags) & 0xffff; 286 *flags = 0; 287 if (fl & IFF_UP) 288 *flags |= LINUX_IFF_UP; 289 if (fl & IFF_BROADCAST) 290 *flags |= LINUX_IFF_BROADCAST; 291 if (fl & IFF_DEBUG) 292 *flags |= LINUX_IFF_DEBUG; 293 if (fl & IFF_LOOPBACK) 294 *flags |= LINUX_IFF_LOOPBACK; 295 if (fl & IFF_POINTOPOINT) 296 *flags |= LINUX_IFF_POINTOPOINT; 297 if (fl & IFF_DRV_RUNNING) 298 *flags |= LINUX_IFF_RUNNING; 299 if (fl & IFF_NOARP) 300 *flags |= LINUX_IFF_NOARP; 301 if (fl & IFF_PROMISC) 302 *flags |= LINUX_IFF_PROMISC; 303 if (fl & IFF_ALLMULTI) 304 *flags |= LINUX_IFF_ALLMULTI; 305 if (fl & IFF_MULTICAST) 306 *flags |= LINUX_IFF_MULTICAST; 307 } 308 309 int 310 linux_ifhwaddr(struct ifnet *ifp, struct l_sockaddr *lsa) 311 { 312 struct ifaddr *ifa; 313 struct sockaddr_dl *sdl; 314 315 if (IFP_IS_LOOP(ifp)) { 316 bzero(lsa, sizeof(*lsa)); 317 lsa->sa_family = LINUX_ARPHRD_LOOPBACK; 318 return (0); 319 } 320 321 if (!IFP_IS_ETH(ifp)) 322 return (ENOENT); 323 324 CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 325 sdl = (struct sockaddr_dl*)ifa->ifa_addr; 326 if (sdl != NULL && (sdl->sdl_family == AF_LINK) && 327 (sdl->sdl_type == IFT_ETHER)) { 328 bzero(lsa, sizeof(*lsa)); 329 lsa->sa_family = LINUX_ARPHRD_ETHER; 330 bcopy(LLADDR(sdl), lsa->sa_data, LINUX_IFHWADDRLEN); 331 return (0); 332 } 333 } 334 335 return (ENOENT); 336 } 337 338 int 339 linux_to_bsd_domain(int domain) 340 { 341 342 switch (domain) { 343 case LINUX_AF_UNSPEC: 344 return (AF_UNSPEC); 345 case LINUX_AF_UNIX: 346 return (AF_LOCAL); 347 case LINUX_AF_INET: 348 return (AF_INET); 349 case LINUX_AF_INET6: 350 return (AF_INET6); 351 case LINUX_AF_AX25: 352 return (AF_CCITT); 353 case LINUX_AF_IPX: 354 return (AF_IPX); 355 case LINUX_AF_APPLETALK: 356 return (AF_APPLETALK); 357 } 358 return (-1); 359 } 360 361 int 362 bsd_to_linux_domain(int domain) 363 { 364 365 switch (domain) { 366 case AF_UNSPEC: 367 return (LINUX_AF_UNSPEC); 368 case AF_LOCAL: 369 return (LINUX_AF_UNIX); 370 case AF_INET: 371 return (LINUX_AF_INET); 372 case AF_INET6: 373 return (LINUX_AF_INET6); 374 case AF_CCITT: 375 return (LINUX_AF_AX25); 376 case AF_IPX: 377 return (LINUX_AF_IPX); 378 case AF_APPLETALK: 379 return (LINUX_AF_APPLETALK); 380 } 381 return (-1); 382 } 383 384 /* 385 * Based on the fact that: 386 * 1. Native and Linux storage of struct sockaddr 387 * and struct sockaddr_in6 are equal. 388 * 2. On Linux sa_family is the first member of all struct sockaddr. 389 */ 390 int 391 bsd_to_linux_sockaddr(const struct sockaddr *sa, struct l_sockaddr **lsa, 392 socklen_t len) 393 { 394 struct l_sockaddr *kosa; 395 int error, bdom; 396 397 *lsa = NULL; 398 if (len < 2 || len > UCHAR_MAX) 399 return (EINVAL); 400 401 kosa = malloc(len, M_SONAME, M_WAITOK); 402 bcopy(sa, kosa, len); 403 404 bdom = bsd_to_linux_domain(sa->sa_family); 405 if (bdom == -1) { 406 error = EAFNOSUPPORT; 407 goto out; 408 } 409 410 kosa->sa_family = bdom; 411 *lsa = kosa; 412 return (0); 413 414 out: 415 free(kosa, M_SONAME); 416 return (error); 417 } 418 419 int 420 linux_to_bsd_sockaddr(const struct l_sockaddr *osa, struct sockaddr **sap, 421 socklen_t *len) 422 { 423 struct sockaddr *sa; 424 struct l_sockaddr *kosa; 425 #ifdef INET6 426 struct sockaddr_in6 *sin6; 427 bool oldv6size; 428 #endif 429 char *name; 430 int salen, bdom, error, hdrlen, namelen; 431 432 if (*len < 2 || *len > UCHAR_MAX) 433 return (EINVAL); 434 435 salen = *len; 436 437 #ifdef INET6 438 oldv6size = false; 439 /* 440 * Check for old (pre-RFC2553) sockaddr_in6. We may accept it 441 * if it's a v4-mapped address, so reserve the proper space 442 * for it. 443 */ 444 if (salen == sizeof(struct sockaddr_in6) - sizeof(uint32_t)) { 445 salen += sizeof(uint32_t); 446 oldv6size = true; 447 } 448 #endif 449 450 kosa = malloc(salen, M_SONAME, M_WAITOK); 451 452 if ((error = copyin(osa, kosa, *len))) 453 goto out; 454 455 bdom = linux_to_bsd_domain(kosa->sa_family); 456 if (bdom == -1) { 457 error = EAFNOSUPPORT; 458 goto out; 459 } 460 461 #ifdef INET6 462 /* 463 * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6, 464 * which lacks the scope id compared with RFC2553 one. If we detect 465 * the situation, reject the address and write a message to system log. 466 * 467 * Still accept addresses for which the scope id is not used. 468 */ 469 if (oldv6size) { 470 if (bdom == AF_INET6) { 471 sin6 = (struct sockaddr_in6 *)kosa; 472 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) || 473 (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && 474 !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) && 475 !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) && 476 !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) && 477 !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) { 478 sin6->sin6_scope_id = 0; 479 } else { 480 linux_msg(curthread, 481 "obsolete pre-RFC2553 sockaddr_in6 rejected\n"); 482 error = EINVAL; 483 goto out; 484 } 485 } else 486 salen -= sizeof(uint32_t); 487 } 488 #endif 489 if (bdom == AF_INET) { 490 if (salen < sizeof(struct sockaddr_in)) { 491 error = EINVAL; 492 goto out; 493 } 494 salen = sizeof(struct sockaddr_in); 495 } 496 497 if (bdom == AF_LOCAL && salen > sizeof(struct sockaddr_un)) { 498 hdrlen = offsetof(struct sockaddr_un, sun_path); 499 name = ((struct sockaddr_un *)kosa)->sun_path; 500 if (*name == '\0') { 501 /* 502 * Linux abstract namespace starts with a NULL byte. 503 * XXX We do not support abstract namespace yet. 504 */ 505 namelen = strnlen(name + 1, salen - hdrlen - 1) + 1; 506 } else 507 namelen = strnlen(name, salen - hdrlen); 508 salen = hdrlen + namelen; 509 if (salen > sizeof(struct sockaddr_un)) { 510 error = ENAMETOOLONG; 511 goto out; 512 } 513 } 514 515 sa = (struct sockaddr *)kosa; 516 sa->sa_family = bdom; 517 sa->sa_len = salen; 518 519 *sap = sa; 520 *len = salen; 521 return (0); 522 523 out: 524 free(kosa, M_SONAME); 525 return (error); 526 } 527