1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1982, 1986, 1989, 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #include "opt_capsicum.h" 34 #include "opt_inet.h" 35 #include "opt_inet6.h" 36 #include "opt_ktrace.h" 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/capsicum.h> 41 #include <sys/kernel.h> 42 #include <sys/lock.h> 43 #include <sys/mutex.h> 44 #include <sys/sysproto.h> 45 #include <sys/malloc.h> 46 #include <sys/filedesc.h> 47 #include <sys/proc.h> 48 #include <sys/filio.h> 49 #include <sys/jail.h> 50 #include <sys/mbuf.h> 51 #include <sys/protosw.h> 52 #include <sys/rwlock.h> 53 #include <sys/socket.h> 54 #include <sys/socketvar.h> 55 #include <sys/syscallsubr.h> 56 #ifdef COMPAT_43 57 #include <sys/sysent.h> 58 #endif 59 #include <sys/uio.h> 60 #include <sys/un.h> 61 #include <sys/unpcb.h> 62 #ifdef KTRACE 63 #include <sys/ktrace.h> 64 #endif 65 #ifdef COMPAT_FREEBSD32 66 #include <compat/freebsd32/freebsd32_util.h> 67 #endif 68 69 #include <net/vnet.h> 70 71 #include <security/audit/audit.h> 72 #include <security/mac/mac_framework.h> 73 74 static int sendit(struct thread *td, int s, struct msghdr *mp, int flags); 75 static int recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp); 76 77 static int accept1(struct thread *td, int s, struct sockaddr *uname, 78 socklen_t *anamelen, int flags); 79 static int sockargs(struct mbuf **, char *, socklen_t, int); 80 81 /* 82 * Convert a user file descriptor to a kernel file entry and check if required 83 * capability rights are present. 84 * If required copy of current set of capability rights is returned. 85 * A reference on the file entry is held upon returning. 86 */ 87 int 88 getsock_cap(struct thread *td, int fd, cap_rights_t *rightsp, 89 struct file **fpp, struct filecaps *havecapsp) 90 { 91 struct file *fp; 92 int error; 93 94 error = fget_cap(td, fd, rightsp, &fp, havecapsp); 95 if (__predict_false(error != 0)) 96 return (error); 97 if (__predict_false(fp->f_type != DTYPE_SOCKET)) { 98 fdrop(fp, td); 99 if (havecapsp != NULL) 100 filecaps_free(havecapsp); 101 return (ENOTSOCK); 102 } 103 *fpp = fp; 104 return (0); 105 } 106 107 int 108 getsock(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp) 109 { 110 struct file *fp; 111 int error; 112 113 error = fget_unlocked(td, fd, rightsp, &fp); 114 if (__predict_false(error != 0)) 115 return (error); 116 if (__predict_false(fp->f_type != DTYPE_SOCKET)) { 117 fdrop(fp, td); 118 return (ENOTSOCK); 119 } 120 *fpp = fp; 121 return (0); 122 } 123 124 /* 125 * System call interface to the socket abstraction. 126 */ 127 #if defined(COMPAT_43) 128 #define COMPAT_OLDSOCK 129 #endif 130 131 int 132 sys_socket(struct thread *td, struct socket_args *uap) 133 { 134 135 return (kern_socket(td, uap->domain, uap->type, uap->protocol)); 136 } 137 138 int 139 kern_socket(struct thread *td, int domain, int type, int protocol) 140 { 141 struct socket *so; 142 struct file *fp; 143 int fd, error, oflag, fflag; 144 145 AUDIT_ARG_SOCKET(domain, type, protocol); 146 147 oflag = 0; 148 fflag = 0; 149 if ((type & SOCK_CLOEXEC) != 0) { 150 type &= ~SOCK_CLOEXEC; 151 oflag |= O_CLOEXEC; 152 } 153 if ((type & SOCK_NONBLOCK) != 0) { 154 type &= ~SOCK_NONBLOCK; 155 fflag |= FNONBLOCK; 156 } 157 158 #ifdef MAC 159 error = mac_socket_check_create(td->td_ucred, domain, type, protocol); 160 if (error != 0) 161 return (error); 162 #endif 163 error = falloc(td, &fp, &fd, oflag); 164 if (error != 0) 165 return (error); 166 /* An extra reference on `fp' has been held for us by falloc(). */ 167 error = socreate(domain, &so, type, protocol, td->td_ucred, td); 168 if (error != 0) { 169 fdclose(td, fp, fd); 170 } else { 171 finit(fp, FREAD | FWRITE | fflag, DTYPE_SOCKET, so, &socketops); 172 if ((fflag & FNONBLOCK) != 0) 173 (void) fo_ioctl(fp, FIONBIO, &fflag, td->td_ucred, td); 174 td->td_retval[0] = fd; 175 } 176 fdrop(fp, td); 177 return (error); 178 } 179 180 int 181 sys_bind(struct thread *td, struct bind_args *uap) 182 { 183 struct sockaddr *sa; 184 int error; 185 186 error = getsockaddr(&sa, uap->name, uap->namelen); 187 if (error == 0) { 188 error = kern_bindat(td, AT_FDCWD, uap->s, sa); 189 free(sa, M_SONAME); 190 } 191 return (error); 192 } 193 194 int 195 kern_bindat(struct thread *td, int dirfd, int fd, struct sockaddr *sa) 196 { 197 struct socket *so; 198 struct file *fp; 199 int error; 200 201 #ifdef CAPABILITY_MODE 202 if (IN_CAPABILITY_MODE(td) && (dirfd == AT_FDCWD)) 203 return (ECAPMODE); 204 #endif 205 206 AUDIT_ARG_FD(fd); 207 AUDIT_ARG_SOCKADDR(td, dirfd, sa); 208 error = getsock(td, fd, &cap_bind_rights, &fp); 209 if (error != 0) 210 return (error); 211 so = fp->f_data; 212 #ifdef KTRACE 213 if (KTRPOINT(td, KTR_STRUCT)) 214 ktrsockaddr(sa); 215 #endif 216 #ifdef MAC 217 error = mac_socket_check_bind(td->td_ucred, so, sa); 218 if (error == 0) { 219 #endif 220 if (dirfd == AT_FDCWD) 221 error = sobind(so, sa, td); 222 else 223 error = sobindat(dirfd, so, sa, td); 224 #ifdef MAC 225 } 226 #endif 227 fdrop(fp, td); 228 return (error); 229 } 230 231 int 232 sys_bindat(struct thread *td, struct bindat_args *uap) 233 { 234 struct sockaddr *sa; 235 int error; 236 237 error = getsockaddr(&sa, uap->name, uap->namelen); 238 if (error == 0) { 239 error = kern_bindat(td, uap->fd, uap->s, sa); 240 free(sa, M_SONAME); 241 } 242 return (error); 243 } 244 245 int 246 sys_listen(struct thread *td, struct listen_args *uap) 247 { 248 249 return (kern_listen(td, uap->s, uap->backlog)); 250 } 251 252 int 253 kern_listen(struct thread *td, int s, int backlog) 254 { 255 struct socket *so; 256 struct file *fp; 257 int error; 258 259 AUDIT_ARG_FD(s); 260 error = getsock(td, s, &cap_listen_rights, &fp); 261 if (error == 0) { 262 so = fp->f_data; 263 #ifdef MAC 264 error = mac_socket_check_listen(td->td_ucred, so); 265 if (error == 0) 266 #endif 267 error = solisten(so, backlog, td); 268 fdrop(fp, td); 269 } 270 return (error); 271 } 272 273 /* 274 * accept1() 275 */ 276 static int 277 accept1(struct thread *td, int s, struct sockaddr *uname, socklen_t *anamelen, 278 int flags) 279 { 280 struct sockaddr_storage ss = { .ss_len = sizeof(ss) }; 281 socklen_t addrlen; 282 struct file *fp; 283 int error; 284 285 if (uname != NULL) { 286 error = copyin(anamelen, &addrlen, sizeof(addrlen)); 287 if (error != 0) 288 return (error); 289 } 290 291 error = kern_accept4(td, s, (struct sockaddr *)&ss, flags, &fp); 292 293 if (error != 0) 294 return (error); 295 296 #ifdef COMPAT_OLDSOCK 297 if (SV_PROC_FLAG(td->td_proc, SV_AOUT) && 298 (flags & ACCEPT4_COMPAT) != 0) 299 ((struct osockaddr *)&ss)->sa_family = ss.ss_family; 300 #endif 301 if (uname != NULL) { 302 addrlen = min(ss.ss_len, addrlen); 303 error = copyout(&ss, uname, addrlen); 304 if (error == 0) { 305 addrlen = ss.ss_len; 306 error = copyout(&addrlen, anamelen, sizeof(addrlen)); 307 } 308 } 309 if (error != 0) 310 fdclose(td, fp, td->td_retval[0]); 311 fdrop(fp, td); 312 313 return (error); 314 } 315 316 int 317 kern_accept(struct thread *td, int s, struct sockaddr *sa, struct file **fp) 318 { 319 return (kern_accept4(td, s, sa, ACCEPT4_INHERIT, fp)); 320 } 321 322 int 323 kern_accept4(struct thread *td, int s, struct sockaddr *sa, int flags, 324 struct file **fp) 325 { 326 struct file *headfp, *nfp = NULL; 327 struct socket *head, *so; 328 struct filecaps fcaps; 329 u_int fflag; 330 pid_t pgid; 331 int error, fd, tmp; 332 333 AUDIT_ARG_FD(s); 334 error = getsock_cap(td, s, &cap_accept_rights, 335 &headfp, &fcaps); 336 if (error != 0) 337 return (error); 338 fflag = atomic_load_int(&headfp->f_flag); 339 head = headfp->f_data; 340 if (!SOLISTENING(head)) { 341 error = EINVAL; 342 goto done; 343 } 344 #ifdef MAC 345 error = mac_socket_check_accept(td->td_ucred, head); 346 if (error != 0) 347 goto done; 348 #endif 349 error = falloc_caps(td, &nfp, &fd, 350 (flags & SOCK_CLOEXEC) ? O_CLOEXEC : 0, &fcaps); 351 if (error != 0) 352 goto done; 353 SOCK_LOCK(head); 354 if (!SOLISTENING(head)) { 355 SOCK_UNLOCK(head); 356 error = EINVAL; 357 goto noconnection; 358 } 359 360 error = solisten_dequeue(head, &so, flags); 361 if (error != 0) 362 goto noconnection; 363 364 /* An extra reference on `nfp' has been held for us by falloc(). */ 365 td->td_retval[0] = fd; 366 367 /* Connection has been removed from the listen queue. */ 368 KNOTE_UNLOCKED(&head->so_rdsel.si_note, 0); 369 370 if (flags & ACCEPT4_INHERIT) { 371 pgid = fgetown(&head->so_sigio); 372 if (pgid != 0) 373 fsetown(pgid, &so->so_sigio); 374 } else { 375 fflag &= ~(FNONBLOCK | FASYNC); 376 if (flags & SOCK_NONBLOCK) 377 fflag |= FNONBLOCK; 378 } 379 380 finit(nfp, fflag, DTYPE_SOCKET, so, &socketops); 381 /* Sync socket nonblocking/async state with file flags */ 382 tmp = fflag & FNONBLOCK; 383 (void) fo_ioctl(nfp, FIONBIO, &tmp, td->td_ucred, td); 384 tmp = fflag & FASYNC; 385 (void) fo_ioctl(nfp, FIOASYNC, &tmp, td->td_ucred, td); 386 387 if ((error = soaccept(so, sa)) == 0) { 388 AUDIT_ARG_SOCKADDR(td, AT_FDCWD, sa); 389 #ifdef KTRACE 390 if (KTRPOINT(td, KTR_STRUCT)) 391 ktrsockaddr(sa); 392 #endif 393 } 394 noconnection: 395 /* 396 * close the new descriptor, assuming someone hasn't ripped it 397 * out from under us. 398 */ 399 if (error != 0) 400 fdclose(td, nfp, fd); 401 402 /* 403 * Release explicitly held references before returning. We return 404 * a reference on nfp to the caller on success if they request it. 405 */ 406 done: 407 if (nfp == NULL) 408 filecaps_free(&fcaps); 409 if (fp != NULL) { 410 if (error == 0) { 411 *fp = nfp; 412 nfp = NULL; 413 } else 414 *fp = NULL; 415 } 416 if (nfp != NULL) 417 fdrop(nfp, td); 418 fdrop(headfp, td); 419 return (error); 420 } 421 422 int 423 sys_accept(struct thread *td, struct accept_args *uap) 424 { 425 426 return (accept1(td, uap->s, uap->name, uap->anamelen, ACCEPT4_INHERIT)); 427 } 428 429 int 430 sys_accept4(struct thread *td, struct accept4_args *uap) 431 { 432 433 if (uap->flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 434 return (EINVAL); 435 436 return (accept1(td, uap->s, uap->name, uap->anamelen, uap->flags)); 437 } 438 439 #ifdef COMPAT_OLDSOCK 440 int 441 oaccept(struct thread *td, struct oaccept_args *uap) 442 { 443 444 return (accept1(td, uap->s, uap->name, uap->anamelen, 445 ACCEPT4_INHERIT | ACCEPT4_COMPAT)); 446 } 447 #endif /* COMPAT_OLDSOCK */ 448 449 int 450 sys_connect(struct thread *td, struct connect_args *uap) 451 { 452 struct sockaddr *sa; 453 int error; 454 455 error = getsockaddr(&sa, uap->name, uap->namelen); 456 if (error == 0) { 457 error = kern_connectat(td, AT_FDCWD, uap->s, sa); 458 free(sa, M_SONAME); 459 } 460 return (error); 461 } 462 463 int 464 kern_connectat(struct thread *td, int dirfd, int fd, struct sockaddr *sa) 465 { 466 struct socket *so; 467 struct file *fp; 468 int error; 469 470 #ifdef CAPABILITY_MODE 471 if (IN_CAPABILITY_MODE(td) && (dirfd == AT_FDCWD)) 472 return (ECAPMODE); 473 #endif 474 475 AUDIT_ARG_FD(fd); 476 AUDIT_ARG_SOCKADDR(td, dirfd, sa); 477 error = getsock(td, fd, &cap_connect_rights, &fp); 478 if (error != 0) 479 return (error); 480 so = fp->f_data; 481 if (so->so_state & SS_ISCONNECTING) { 482 error = EALREADY; 483 goto done1; 484 } 485 #ifdef KTRACE 486 if (KTRPOINT(td, KTR_STRUCT)) 487 ktrsockaddr(sa); 488 #endif 489 #ifdef MAC 490 error = mac_socket_check_connect(td->td_ucred, so, sa); 491 if (error != 0) 492 goto bad; 493 #endif 494 error = soconnectat(dirfd, so, sa, td); 495 if (error != 0) 496 goto bad; 497 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { 498 error = EINPROGRESS; 499 goto done1; 500 } 501 SOCK_LOCK(so); 502 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { 503 error = msleep(&so->so_timeo, &so->so_lock, PSOCK | PCATCH, 504 "connec", 0); 505 if (error != 0) 506 break; 507 } 508 if (error == 0) { 509 error = so->so_error; 510 so->so_error = 0; 511 } 512 SOCK_UNLOCK(so); 513 bad: 514 if (error == ERESTART) 515 error = EINTR; 516 done1: 517 fdrop(fp, td); 518 return (error); 519 } 520 521 int 522 sys_connectat(struct thread *td, struct connectat_args *uap) 523 { 524 struct sockaddr *sa; 525 int error; 526 527 error = getsockaddr(&sa, uap->name, uap->namelen); 528 if (error == 0) { 529 error = kern_connectat(td, uap->fd, uap->s, sa); 530 free(sa, M_SONAME); 531 } 532 return (error); 533 } 534 535 int 536 kern_socketpair(struct thread *td, int domain, int type, int protocol, 537 int *rsv) 538 { 539 struct file *fp1, *fp2; 540 struct socket *so1, *so2; 541 int fd, error, oflag, fflag; 542 543 AUDIT_ARG_SOCKET(domain, type, protocol); 544 545 oflag = 0; 546 fflag = 0; 547 if ((type & SOCK_CLOEXEC) != 0) { 548 type &= ~SOCK_CLOEXEC; 549 oflag |= O_CLOEXEC; 550 } 551 if ((type & SOCK_NONBLOCK) != 0) { 552 type &= ~SOCK_NONBLOCK; 553 fflag |= FNONBLOCK; 554 } 555 #ifdef MAC 556 /* We might want to have a separate check for socket pairs. */ 557 error = mac_socket_check_create(td->td_ucred, domain, type, 558 protocol); 559 if (error != 0) 560 return (error); 561 #endif 562 error = socreate(domain, &so1, type, protocol, td->td_ucred, td); 563 if (error != 0) 564 return (error); 565 error = socreate(domain, &so2, type, protocol, td->td_ucred, td); 566 if (error != 0) 567 goto free1; 568 /* On success extra reference to `fp1' and 'fp2' is set by falloc. */ 569 error = falloc(td, &fp1, &fd, oflag); 570 if (error != 0) 571 goto free2; 572 rsv[0] = fd; 573 fp1->f_data = so1; /* so1 already has ref count */ 574 error = falloc(td, &fp2, &fd, oflag); 575 if (error != 0) 576 goto free3; 577 fp2->f_data = so2; /* so2 already has ref count */ 578 rsv[1] = fd; 579 error = soconnect2(so1, so2); 580 if (error != 0) 581 goto free4; 582 if (type == SOCK_DGRAM) { 583 /* 584 * Datagram socket connection is asymmetric. 585 */ 586 error = soconnect2(so2, so1); 587 if (error != 0) 588 goto free4; 589 } else if (so1->so_proto->pr_flags & PR_CONNREQUIRED) { 590 struct unpcb *unp, *unp2; 591 unp = sotounpcb(so1); 592 unp2 = sotounpcb(so2); 593 /* 594 * No need to lock the unps, because the sockets are brand-new. 595 * No other threads can be using them yet 596 */ 597 unp_copy_peercred(td, unp, unp2, unp); 598 } 599 finit(fp1, FREAD | FWRITE | fflag, DTYPE_SOCKET, fp1->f_data, 600 &socketops); 601 finit(fp2, FREAD | FWRITE | fflag, DTYPE_SOCKET, fp2->f_data, 602 &socketops); 603 if ((fflag & FNONBLOCK) != 0) { 604 (void) fo_ioctl(fp1, FIONBIO, &fflag, td->td_ucred, td); 605 (void) fo_ioctl(fp2, FIONBIO, &fflag, td->td_ucred, td); 606 } 607 fdrop(fp1, td); 608 fdrop(fp2, td); 609 return (0); 610 free4: 611 fdclose(td, fp2, rsv[1]); 612 fdrop(fp2, td); 613 free3: 614 fdclose(td, fp1, rsv[0]); 615 fdrop(fp1, td); 616 free2: 617 if (so2 != NULL) 618 (void)soclose(so2); 619 free1: 620 if (so1 != NULL) 621 (void)soclose(so1); 622 return (error); 623 } 624 625 int 626 sys_socketpair(struct thread *td, struct socketpair_args *uap) 627 { 628 int error, sv[2]; 629 630 error = kern_socketpair(td, uap->domain, uap->type, 631 uap->protocol, sv); 632 if (error != 0) 633 return (error); 634 error = copyout(sv, uap->rsv, 2 * sizeof(int)); 635 if (error != 0) { 636 (void)kern_close(td, sv[0]); 637 (void)kern_close(td, sv[1]); 638 } 639 return (error); 640 } 641 642 static int 643 sendit(struct thread *td, int s, struct msghdr *mp, int flags) 644 { 645 struct mbuf *control; 646 struct sockaddr *to; 647 int error; 648 649 #ifdef CAPABILITY_MODE 650 if (IN_CAPABILITY_MODE(td) && (mp->msg_name != NULL)) 651 return (ECAPMODE); 652 #endif 653 654 if (mp->msg_name != NULL) { 655 error = getsockaddr(&to, mp->msg_name, mp->msg_namelen); 656 if (error != 0) { 657 to = NULL; 658 goto bad; 659 } 660 mp->msg_name = to; 661 } else { 662 to = NULL; 663 } 664 665 if (mp->msg_control) { 666 if (mp->msg_controllen < sizeof(struct cmsghdr) 667 #ifdef COMPAT_OLDSOCK 668 && (mp->msg_flags != MSG_COMPAT || 669 !SV_PROC_FLAG(td->td_proc, SV_AOUT)) 670 #endif 671 ) { 672 error = EINVAL; 673 goto bad; 674 } 675 error = sockargs(&control, mp->msg_control, 676 mp->msg_controllen, MT_CONTROL); 677 if (error != 0) 678 goto bad; 679 #ifdef COMPAT_OLDSOCK 680 if (mp->msg_flags == MSG_COMPAT && 681 SV_PROC_FLAG(td->td_proc, SV_AOUT)) { 682 struct cmsghdr *cm; 683 684 M_PREPEND(control, sizeof(*cm), M_WAITOK); 685 cm = mtod(control, struct cmsghdr *); 686 cm->cmsg_len = control->m_len; 687 cm->cmsg_level = SOL_SOCKET; 688 cm->cmsg_type = SCM_RIGHTS; 689 } 690 #endif 691 } else { 692 control = NULL; 693 } 694 695 error = kern_sendit(td, s, mp, flags, control, UIO_USERSPACE); 696 697 bad: 698 free(to, M_SONAME); 699 return (error); 700 } 701 702 int 703 kern_sendit(struct thread *td, int s, struct msghdr *mp, int flags, 704 struct mbuf *control, enum uio_seg segflg) 705 { 706 struct file *fp; 707 struct uio auio; 708 struct iovec *iov; 709 struct socket *so; 710 cap_rights_t *rights; 711 #ifdef KTRACE 712 struct uio *ktruio = NULL; 713 #endif 714 ssize_t len; 715 int i, error; 716 717 AUDIT_ARG_FD(s); 718 rights = &cap_send_rights; 719 if (mp->msg_name != NULL) { 720 AUDIT_ARG_SOCKADDR(td, AT_FDCWD, mp->msg_name); 721 rights = &cap_send_connect_rights; 722 } 723 error = getsock(td, s, rights, &fp); 724 if (error != 0) { 725 m_freem(control); 726 return (error); 727 } 728 so = (struct socket *)fp->f_data; 729 730 #ifdef KTRACE 731 if (mp->msg_name != NULL && KTRPOINT(td, KTR_STRUCT)) 732 ktrsockaddr(mp->msg_name); 733 #endif 734 #ifdef MAC 735 if (mp->msg_name != NULL) { 736 error = mac_socket_check_connect(td->td_ucred, so, 737 mp->msg_name); 738 if (error != 0) { 739 m_freem(control); 740 goto bad; 741 } 742 } 743 error = mac_socket_check_send(td->td_ucred, so); 744 if (error != 0) { 745 m_freem(control); 746 goto bad; 747 } 748 #endif 749 750 auio.uio_iov = mp->msg_iov; 751 auio.uio_iovcnt = mp->msg_iovlen; 752 auio.uio_segflg = segflg; 753 auio.uio_rw = UIO_WRITE; 754 auio.uio_td = td; 755 auio.uio_offset = 0; /* XXX */ 756 auio.uio_resid = 0; 757 iov = mp->msg_iov; 758 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 759 if ((auio.uio_resid += iov->iov_len) < 0) { 760 error = EINVAL; 761 m_freem(control); 762 goto bad; 763 } 764 } 765 #ifdef KTRACE 766 if (KTRPOINT(td, KTR_GENIO)) 767 ktruio = cloneuio(&auio); 768 #endif 769 len = auio.uio_resid; 770 error = sousrsend(so, mp->msg_name, &auio, control, flags, NULL); 771 if (error == 0) 772 td->td_retval[0] = len - auio.uio_resid; 773 #ifdef KTRACE 774 if (ktruio != NULL) { 775 if (error == 0) 776 ktruio->uio_resid = td->td_retval[0]; 777 ktrgenio(s, UIO_WRITE, ktruio, error); 778 } 779 #endif 780 bad: 781 fdrop(fp, td); 782 return (error); 783 } 784 785 int 786 sys_sendto(struct thread *td, struct sendto_args *uap) 787 { 788 struct msghdr msg; 789 struct iovec aiov; 790 791 msg.msg_name = __DECONST(void *, uap->to); 792 msg.msg_namelen = uap->tolen; 793 msg.msg_iov = &aiov; 794 msg.msg_iovlen = 1; 795 msg.msg_control = 0; 796 #ifdef COMPAT_OLDSOCK 797 if (SV_PROC_FLAG(td->td_proc, SV_AOUT)) 798 msg.msg_flags = 0; 799 #endif 800 aiov.iov_base = __DECONST(void *, uap->buf); 801 aiov.iov_len = uap->len; 802 return (sendit(td, uap->s, &msg, uap->flags)); 803 } 804 805 #ifdef COMPAT_OLDSOCK 806 int 807 osend(struct thread *td, struct osend_args *uap) 808 { 809 struct msghdr msg; 810 struct iovec aiov; 811 812 msg.msg_name = 0; 813 msg.msg_namelen = 0; 814 msg.msg_iov = &aiov; 815 msg.msg_iovlen = 1; 816 aiov.iov_base = __DECONST(void *, uap->buf); 817 aiov.iov_len = uap->len; 818 msg.msg_control = 0; 819 msg.msg_flags = 0; 820 return (sendit(td, uap->s, &msg, uap->flags)); 821 } 822 823 int 824 osendmsg(struct thread *td, struct osendmsg_args *uap) 825 { 826 struct msghdr msg; 827 struct iovec *iov; 828 int error; 829 830 error = copyin(uap->msg, &msg, sizeof (struct omsghdr)); 831 if (error != 0) 832 return (error); 833 error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE); 834 if (error != 0) 835 return (error); 836 msg.msg_iov = iov; 837 msg.msg_flags = MSG_COMPAT; 838 error = sendit(td, uap->s, &msg, uap->flags); 839 free(iov, M_IOV); 840 return (error); 841 } 842 #endif 843 844 int 845 sys_sendmsg(struct thread *td, struct sendmsg_args *uap) 846 { 847 struct msghdr msg; 848 struct iovec *iov; 849 int error; 850 851 error = copyin(uap->msg, &msg, sizeof (msg)); 852 if (error != 0) 853 return (error); 854 error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE); 855 if (error != 0) 856 return (error); 857 msg.msg_iov = iov; 858 #ifdef COMPAT_OLDSOCK 859 if (SV_PROC_FLAG(td->td_proc, SV_AOUT)) 860 msg.msg_flags = 0; 861 #endif 862 error = sendit(td, uap->s, &msg, uap->flags); 863 free(iov, M_IOV); 864 return (error); 865 } 866 867 int 868 kern_recvit(struct thread *td, int s, struct msghdr *mp, enum uio_seg fromseg, 869 struct mbuf **controlp) 870 { 871 struct uio auio; 872 struct iovec *iov; 873 struct mbuf *control, *m; 874 caddr_t ctlbuf; 875 struct file *fp; 876 struct socket *so; 877 struct sockaddr *fromsa = NULL; 878 #ifdef KTRACE 879 struct uio *ktruio = NULL; 880 #endif 881 ssize_t len; 882 int error, i; 883 884 if (controlp != NULL) 885 *controlp = NULL; 886 887 AUDIT_ARG_FD(s); 888 error = getsock(td, s, &cap_recv_rights, &fp); 889 if (error != 0) 890 return (error); 891 so = fp->f_data; 892 893 #ifdef MAC 894 error = mac_socket_check_receive(td->td_ucred, so); 895 if (error != 0) { 896 fdrop(fp, td); 897 return (error); 898 } 899 #endif 900 901 auio.uio_iov = mp->msg_iov; 902 auio.uio_iovcnt = mp->msg_iovlen; 903 auio.uio_segflg = UIO_USERSPACE; 904 auio.uio_rw = UIO_READ; 905 auio.uio_td = td; 906 auio.uio_offset = 0; /* XXX */ 907 auio.uio_resid = 0; 908 iov = mp->msg_iov; 909 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 910 if ((auio.uio_resid += iov->iov_len) < 0) { 911 fdrop(fp, td); 912 return (EINVAL); 913 } 914 } 915 #ifdef KTRACE 916 if (KTRPOINT(td, KTR_GENIO)) 917 ktruio = cloneuio(&auio); 918 #endif 919 control = NULL; 920 len = auio.uio_resid; 921 error = soreceive(so, &fromsa, &auio, NULL, 922 (mp->msg_control || controlp) ? &control : NULL, 923 &mp->msg_flags); 924 if (error != 0) { 925 if (auio.uio_resid != len && (error == ERESTART || 926 error == EINTR || error == EWOULDBLOCK)) 927 error = 0; 928 } 929 if (fromsa != NULL) 930 AUDIT_ARG_SOCKADDR(td, AT_FDCWD, fromsa); 931 #ifdef KTRACE 932 if (ktruio != NULL) { 933 /* MSG_TRUNC can trigger underflow of uio_resid. */ 934 ktruio->uio_resid = MIN(len - auio.uio_resid, len); 935 ktrgenio(s, UIO_READ, ktruio, error); 936 } 937 #endif 938 if (error != 0) 939 goto out; 940 td->td_retval[0] = len - auio.uio_resid; 941 if (mp->msg_name) { 942 len = mp->msg_namelen; 943 if (len <= 0 || fromsa == NULL) 944 len = 0; 945 else { 946 /* save sa_len before it is destroyed by MSG_COMPAT */ 947 len = MIN(len, fromsa->sa_len); 948 #ifdef COMPAT_OLDSOCK 949 if ((mp->msg_flags & MSG_COMPAT) != 0 && 950 SV_PROC_FLAG(td->td_proc, SV_AOUT)) 951 ((struct osockaddr *)fromsa)->sa_family = 952 fromsa->sa_family; 953 #endif 954 if (fromseg == UIO_USERSPACE) { 955 error = copyout(fromsa, mp->msg_name, 956 (unsigned)len); 957 if (error != 0) 958 goto out; 959 } else 960 bcopy(fromsa, mp->msg_name, len); 961 } 962 mp->msg_namelen = len; 963 } 964 if (mp->msg_control && controlp == NULL) { 965 #ifdef COMPAT_OLDSOCK 966 /* 967 * We assume that old recvmsg calls won't receive access 968 * rights and other control info, esp. as control info 969 * is always optional and those options didn't exist in 4.3. 970 * If we receive rights, trim the cmsghdr; anything else 971 * is tossed. 972 */ 973 if (control && (mp->msg_flags & MSG_COMPAT) != 0 && 974 SV_PROC_FLAG(td->td_proc, SV_AOUT)) { 975 if (mtod(control, struct cmsghdr *)->cmsg_level != 976 SOL_SOCKET || 977 mtod(control, struct cmsghdr *)->cmsg_type != 978 SCM_RIGHTS) { 979 mp->msg_controllen = 0; 980 goto out; 981 } 982 control->m_len -= sizeof (struct cmsghdr); 983 control->m_data += sizeof (struct cmsghdr); 984 } 985 #endif 986 ctlbuf = mp->msg_control; 987 len = mp->msg_controllen; 988 mp->msg_controllen = 0; 989 for (m = control; m != NULL && len >= m->m_len; m = m->m_next) { 990 if ((error = copyout(mtod(m, caddr_t), ctlbuf, 991 m->m_len)) != 0) 992 goto out; 993 994 ctlbuf += m->m_len; 995 len -= m->m_len; 996 mp->msg_controllen += m->m_len; 997 } 998 if (m != NULL) { 999 mp->msg_flags |= MSG_CTRUNC; 1000 m_dispose_extcontrolm(m); 1001 } 1002 } 1003 out: 1004 fdrop(fp, td); 1005 #ifdef KTRACE 1006 if (fromsa && KTRPOINT(td, KTR_STRUCT)) 1007 ktrsockaddr(fromsa); 1008 #endif 1009 free(fromsa, M_SONAME); 1010 1011 if (error == 0 && controlp != NULL) 1012 *controlp = control; 1013 else if (control != NULL) { 1014 if (error != 0) 1015 m_dispose_extcontrolm(control); 1016 m_freem(control); 1017 } 1018 1019 return (error); 1020 } 1021 1022 static int 1023 recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp) 1024 { 1025 int error; 1026 1027 error = kern_recvit(td, s, mp, UIO_USERSPACE, NULL); 1028 if (error != 0) 1029 return (error); 1030 if (namelenp != NULL) { 1031 error = copyout(&mp->msg_namelen, namelenp, sizeof (socklen_t)); 1032 #ifdef COMPAT_OLDSOCK 1033 if ((mp->msg_flags & MSG_COMPAT) != 0 && 1034 SV_PROC_FLAG(td->td_proc, SV_AOUT)) 1035 error = 0; /* old recvfrom didn't check */ 1036 #endif 1037 } 1038 return (error); 1039 } 1040 1041 static int 1042 kern_recvfrom(struct thread *td, int s, void *buf, size_t len, int flags, 1043 struct sockaddr *from, socklen_t *fromlenaddr) 1044 { 1045 struct msghdr msg; 1046 struct iovec aiov; 1047 int error; 1048 1049 if (fromlenaddr != NULL) { 1050 error = copyin(fromlenaddr, &msg.msg_namelen, 1051 sizeof (msg.msg_namelen)); 1052 if (error != 0) 1053 goto done2; 1054 } else { 1055 msg.msg_namelen = 0; 1056 } 1057 msg.msg_name = from; 1058 msg.msg_iov = &aiov; 1059 msg.msg_iovlen = 1; 1060 aiov.iov_base = buf; 1061 aiov.iov_len = len; 1062 msg.msg_control = 0; 1063 msg.msg_flags = flags; 1064 error = recvit(td, s, &msg, fromlenaddr); 1065 done2: 1066 return (error); 1067 } 1068 1069 int 1070 sys_recvfrom(struct thread *td, struct recvfrom_args *uap) 1071 { 1072 return (kern_recvfrom(td, uap->s, uap->buf, uap->len, 1073 uap->flags, uap->from, uap->fromlenaddr)); 1074 } 1075 1076 1077 #ifdef COMPAT_OLDSOCK 1078 int 1079 orecvfrom(struct thread *td, struct orecvfrom_args *uap) 1080 { 1081 return (kern_recvfrom(td, uap->s, uap->buf, uap->len, 1082 uap->flags | MSG_COMPAT, uap->from, uap->fromlenaddr)); 1083 } 1084 #endif 1085 1086 #ifdef COMPAT_OLDSOCK 1087 int 1088 orecv(struct thread *td, struct orecv_args *uap) 1089 { 1090 struct msghdr msg; 1091 struct iovec aiov; 1092 1093 msg.msg_name = 0; 1094 msg.msg_namelen = 0; 1095 msg.msg_iov = &aiov; 1096 msg.msg_iovlen = 1; 1097 aiov.iov_base = uap->buf; 1098 aiov.iov_len = uap->len; 1099 msg.msg_control = 0; 1100 msg.msg_flags = uap->flags; 1101 return (recvit(td, uap->s, &msg, NULL)); 1102 } 1103 1104 /* 1105 * Old recvmsg. This code takes advantage of the fact that the old msghdr 1106 * overlays the new one, missing only the flags, and with the (old) access 1107 * rights where the control fields are now. 1108 */ 1109 int 1110 orecvmsg(struct thread *td, struct orecvmsg_args *uap) 1111 { 1112 struct msghdr msg; 1113 struct iovec *iov; 1114 int error; 1115 1116 error = copyin(uap->msg, &msg, sizeof (struct omsghdr)); 1117 if (error != 0) 1118 return (error); 1119 error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE); 1120 if (error != 0) 1121 return (error); 1122 msg.msg_flags = uap->flags | MSG_COMPAT; 1123 msg.msg_iov = iov; 1124 error = recvit(td, uap->s, &msg, &uap->msg->msg_namelen); 1125 if (msg.msg_controllen && error == 0) 1126 error = copyout(&msg.msg_controllen, 1127 &uap->msg->msg_accrightslen, sizeof (int)); 1128 free(iov, M_IOV); 1129 return (error); 1130 } 1131 #endif 1132 1133 int 1134 sys_recvmsg(struct thread *td, struct recvmsg_args *uap) 1135 { 1136 struct msghdr msg; 1137 struct iovec *uiov, *iov; 1138 int error; 1139 1140 error = copyin(uap->msg, &msg, sizeof (msg)); 1141 if (error != 0) 1142 return (error); 1143 error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE); 1144 if (error != 0) 1145 return (error); 1146 msg.msg_flags = uap->flags; 1147 #ifdef COMPAT_OLDSOCK 1148 if (SV_PROC_FLAG(td->td_proc, SV_AOUT)) 1149 msg.msg_flags &= ~MSG_COMPAT; 1150 #endif 1151 uiov = msg.msg_iov; 1152 msg.msg_iov = iov; 1153 error = recvit(td, uap->s, &msg, NULL); 1154 if (error == 0) { 1155 msg.msg_iov = uiov; 1156 error = copyout(&msg, uap->msg, sizeof(msg)); 1157 } 1158 free(iov, M_IOV); 1159 return (error); 1160 } 1161 1162 int 1163 sys_shutdown(struct thread *td, struct shutdown_args *uap) 1164 { 1165 1166 return (kern_shutdown(td, uap->s, uap->how)); 1167 } 1168 1169 int 1170 kern_shutdown(struct thread *td, int s, int how) 1171 { 1172 struct socket *so; 1173 struct file *fp; 1174 int error; 1175 1176 if (__predict_false(how < SHUT_RD || how > SHUT_RDWR)) 1177 return (EINVAL); 1178 1179 AUDIT_ARG_FD(s); 1180 error = getsock(td, s, &cap_shutdown_rights, &fp); 1181 if (error == 0) { 1182 so = fp->f_data; 1183 error = soshutdown(so, how); 1184 /* 1185 * Previous versions did not return ENOTCONN, but 0 in 1186 * case the socket was not connected. Some important 1187 * programs like syslogd up to r279016, 2015-02-19, 1188 * still depend on this behavior. 1189 */ 1190 if (error == ENOTCONN && 1191 td->td_proc->p_osrel < P_OSREL_SHUTDOWN_ENOTCONN) 1192 error = 0; 1193 fdrop(fp, td); 1194 } 1195 return (error); 1196 } 1197 1198 int 1199 sys_setsockopt(struct thread *td, struct setsockopt_args *uap) 1200 { 1201 1202 return (kern_setsockopt(td, uap->s, uap->level, uap->name, 1203 uap->val, UIO_USERSPACE, uap->valsize)); 1204 } 1205 1206 int 1207 kern_setsockopt(struct thread *td, int s, int level, int name, const void *val, 1208 enum uio_seg valseg, socklen_t valsize) 1209 { 1210 struct socket *so; 1211 struct file *fp; 1212 struct sockopt sopt; 1213 int error; 1214 1215 if (val == NULL && valsize != 0) 1216 return (EFAULT); 1217 if ((int)valsize < 0) 1218 return (EINVAL); 1219 1220 sopt.sopt_dir = SOPT_SET; 1221 sopt.sopt_level = level; 1222 sopt.sopt_name = name; 1223 sopt.sopt_val = __DECONST(void *, val); 1224 sopt.sopt_valsize = valsize; 1225 switch (valseg) { 1226 case UIO_USERSPACE: 1227 sopt.sopt_td = td; 1228 break; 1229 case UIO_SYSSPACE: 1230 sopt.sopt_td = NULL; 1231 break; 1232 default: 1233 panic("kern_setsockopt called with bad valseg"); 1234 } 1235 1236 AUDIT_ARG_FD(s); 1237 error = getsock(td, s, &cap_setsockopt_rights, &fp); 1238 if (error == 0) { 1239 so = fp->f_data; 1240 error = sosetopt(so, &sopt); 1241 fdrop(fp, td); 1242 } 1243 return(error); 1244 } 1245 1246 int 1247 sys_getsockopt(struct thread *td, struct getsockopt_args *uap) 1248 { 1249 socklen_t valsize; 1250 int error; 1251 1252 if (uap->val) { 1253 error = copyin(uap->avalsize, &valsize, sizeof (valsize)); 1254 if (error != 0) 1255 return (error); 1256 } 1257 1258 error = kern_getsockopt(td, uap->s, uap->level, uap->name, 1259 uap->val, UIO_USERSPACE, &valsize); 1260 1261 if (error == 0) 1262 error = copyout(&valsize, uap->avalsize, sizeof (valsize)); 1263 return (error); 1264 } 1265 1266 /* 1267 * Kernel version of getsockopt. 1268 * optval can be a userland or userspace. optlen is always a kernel pointer. 1269 */ 1270 int 1271 kern_getsockopt(struct thread *td, int s, int level, int name, void *val, 1272 enum uio_seg valseg, socklen_t *valsize) 1273 { 1274 struct socket *so; 1275 struct file *fp; 1276 struct sockopt sopt; 1277 int error; 1278 1279 if (val == NULL) 1280 *valsize = 0; 1281 if ((int)*valsize < 0) 1282 return (EINVAL); 1283 1284 sopt.sopt_dir = SOPT_GET; 1285 sopt.sopt_level = level; 1286 sopt.sopt_name = name; 1287 sopt.sopt_val = val; 1288 sopt.sopt_valsize = (size_t)*valsize; /* checked non-negative above */ 1289 switch (valseg) { 1290 case UIO_USERSPACE: 1291 sopt.sopt_td = td; 1292 break; 1293 case UIO_SYSSPACE: 1294 sopt.sopt_td = NULL; 1295 break; 1296 default: 1297 panic("kern_getsockopt called with bad valseg"); 1298 } 1299 1300 AUDIT_ARG_FD(s); 1301 error = getsock(td, s, &cap_getsockopt_rights, &fp); 1302 if (error == 0) { 1303 so = fp->f_data; 1304 error = sogetopt(so, &sopt); 1305 *valsize = sopt.sopt_valsize; 1306 fdrop(fp, td); 1307 } 1308 return (error); 1309 } 1310 1311 static int 1312 user_getsockname(struct thread *td, int fdes, struct sockaddr *asa, 1313 socklen_t *alen, bool compat) 1314 { 1315 struct sockaddr_storage ss = { .ss_len = sizeof(ss) }; 1316 socklen_t len; 1317 int error; 1318 1319 error = copyin(alen, &len, sizeof(len)); 1320 if (error != 0) 1321 return (error); 1322 1323 error = kern_getsockname(td, fdes, (struct sockaddr *)&ss); 1324 if (error != 0) 1325 return (error); 1326 1327 #ifdef COMPAT_OLDSOCK 1328 if (compat && SV_PROC_FLAG(td->td_proc, SV_AOUT)) 1329 ((struct osockaddr *)&ss)->sa_family = ss.ss_family; 1330 #endif 1331 len = min(ss.ss_len, len); 1332 error = copyout(&ss, asa, len); 1333 if (error == 0) { 1334 len = ss.ss_len; 1335 error = copyout(&len, alen, sizeof(len)); 1336 } 1337 return (error); 1338 } 1339 1340 int 1341 kern_getsockname(struct thread *td, int fd, struct sockaddr *sa) 1342 { 1343 struct socket *so; 1344 struct file *fp; 1345 int error; 1346 1347 AUDIT_ARG_FD(fd); 1348 error = getsock(td, fd, &cap_getsockname_rights, &fp); 1349 if (error != 0) 1350 return (error); 1351 so = fp->f_data; 1352 error = sosockaddr(so, sa); 1353 #ifdef KTRACE 1354 if (error == 0 && KTRPOINT(td, KTR_STRUCT)) 1355 ktrsockaddr(sa); 1356 #endif 1357 fdrop(fp, td); 1358 return (error); 1359 } 1360 1361 int 1362 sys_getsockname(struct thread *td, struct getsockname_args *uap) 1363 { 1364 return (user_getsockname(td, uap->fdes, uap->asa, uap->alen, false)); 1365 } 1366 1367 #ifdef COMPAT_OLDSOCK 1368 int 1369 ogetsockname(struct thread *td, struct ogetsockname_args *uap) 1370 { 1371 return (user_getsockname(td, uap->fdes, uap->asa, uap->alen, true)); 1372 } 1373 #endif /* COMPAT_OLDSOCK */ 1374 1375 static int 1376 user_getpeername(struct thread *td, int fdes, struct sockaddr *asa, 1377 socklen_t *alen, bool compat) 1378 { 1379 struct sockaddr_storage ss = { .ss_len = sizeof(ss) }; 1380 socklen_t len; 1381 int error; 1382 1383 error = copyin(alen, &len, sizeof (len)); 1384 if (error != 0) 1385 return (error); 1386 1387 error = kern_getpeername(td, fdes, (struct sockaddr *)&ss); 1388 if (error != 0) 1389 return (error); 1390 1391 #ifdef COMPAT_OLDSOCK 1392 if (compat && SV_PROC_FLAG(td->td_proc, SV_AOUT)) 1393 ((struct osockaddr *)&ss)->sa_family = ss.ss_family; 1394 #endif 1395 len = min(ss.ss_len, len); 1396 error = copyout(&ss, asa, len); 1397 if (error == 0) { 1398 len = ss.ss_len; 1399 error = copyout(&len, alen, sizeof(len)); 1400 } 1401 return (error); 1402 } 1403 1404 int 1405 kern_getpeername(struct thread *td, int fd, struct sockaddr *sa) 1406 { 1407 struct socket *so; 1408 struct file *fp; 1409 int error; 1410 1411 AUDIT_ARG_FD(fd); 1412 error = getsock(td, fd, &cap_getpeername_rights, &fp); 1413 if (error != 0) 1414 return (error); 1415 so = fp->f_data; 1416 if ((so->so_state & SS_ISCONNECTED) == 0) { 1417 error = ENOTCONN; 1418 goto done; 1419 } 1420 error = sopeeraddr(so, sa); 1421 #ifdef KTRACE 1422 if (error == 0 && KTRPOINT(td, KTR_STRUCT)) 1423 ktrsockaddr(sa); 1424 #endif 1425 done: 1426 fdrop(fp, td); 1427 return (error); 1428 } 1429 1430 int 1431 sys_getpeername(struct thread *td, struct getpeername_args *uap) 1432 { 1433 return (user_getpeername(td, uap->fdes, uap->asa, uap->alen, false)); 1434 } 1435 1436 #ifdef COMPAT_OLDSOCK 1437 int 1438 ogetpeername(struct thread *td, struct ogetpeername_args *uap) 1439 { 1440 return (user_getpeername(td, uap->fdes, uap->asa, uap->alen, true)); 1441 } 1442 #endif /* COMPAT_OLDSOCK */ 1443 1444 static int 1445 sockargs(struct mbuf **mp, char *buf, socklen_t buflen, int type) 1446 { 1447 struct sockaddr *sa; 1448 struct mbuf *m; 1449 int error; 1450 1451 if (buflen > MLEN) { 1452 #ifdef COMPAT_OLDSOCK 1453 if (type == MT_SONAME && buflen <= 112 && 1454 SV_CURPROC_FLAG(SV_AOUT)) 1455 buflen = MLEN; /* unix domain compat. hack */ 1456 else 1457 #endif 1458 if (buflen > MCLBYTES) 1459 return (EMSGSIZE); 1460 } 1461 m = m_get2(buflen, M_WAITOK, type, 0); 1462 m->m_len = buflen; 1463 error = copyin(buf, mtod(m, void *), buflen); 1464 if (error != 0) 1465 (void) m_free(m); 1466 else { 1467 *mp = m; 1468 if (type == MT_SONAME) { 1469 sa = mtod(m, struct sockaddr *); 1470 1471 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN 1472 if (sa->sa_family == 0 && sa->sa_len < AF_MAX && 1473 SV_CURPROC_FLAG(SV_AOUT)) 1474 sa->sa_family = sa->sa_len; 1475 #endif 1476 sa->sa_len = buflen; 1477 } 1478 } 1479 return (error); 1480 } 1481 1482 int 1483 getsockaddr(struct sockaddr **namp, const struct sockaddr *uaddr, size_t len) 1484 { 1485 struct sockaddr *sa; 1486 int error; 1487 1488 if (len > SOCK_MAXADDRLEN) 1489 return (ENAMETOOLONG); 1490 if (len < offsetof(struct sockaddr, sa_data[0])) 1491 return (EINVAL); 1492 sa = malloc(len, M_SONAME, M_WAITOK); 1493 error = copyin(uaddr, sa, len); 1494 if (error != 0) { 1495 free(sa, M_SONAME); 1496 } else { 1497 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN 1498 if (sa->sa_family == 0 && sa->sa_len < AF_MAX && 1499 SV_CURPROC_FLAG(SV_AOUT)) 1500 sa->sa_family = sa->sa_len; 1501 #endif 1502 sa->sa_len = len; 1503 *namp = sa; 1504 } 1505 return (error); 1506 } 1507 1508 /* 1509 * Dispose of externalized rights from an SCM_RIGHTS message. This function 1510 * should be used in error or truncation cases to avoid leaking file descriptors 1511 * into the recipient's (the current thread's) table. 1512 */ 1513 void 1514 m_dispose_extcontrolm(struct mbuf *m) 1515 { 1516 struct cmsghdr *cm; 1517 struct file *fp; 1518 struct thread *td; 1519 socklen_t clen, datalen; 1520 int error, fd, *fds, nfd; 1521 1522 td = curthread; 1523 for (; m != NULL; m = m->m_next) { 1524 if (m->m_type != MT_EXTCONTROL) 1525 continue; 1526 cm = mtod(m, struct cmsghdr *); 1527 clen = m->m_len; 1528 while (clen > 0) { 1529 if (clen < sizeof(*cm)) 1530 panic("%s: truncated mbuf %p", __func__, m); 1531 datalen = CMSG_SPACE(cm->cmsg_len - CMSG_SPACE(0)); 1532 if (clen < datalen) 1533 panic("%s: truncated mbuf %p", __func__, m); 1534 1535 if (cm->cmsg_level == SOL_SOCKET && 1536 cm->cmsg_type == SCM_RIGHTS) { 1537 fds = (int *)CMSG_DATA(cm); 1538 nfd = (cm->cmsg_len - CMSG_SPACE(0)) / 1539 sizeof(int); 1540 1541 while (nfd-- > 0) { 1542 fd = *fds++; 1543 error = fget(td, fd, &cap_no_rights, 1544 &fp); 1545 if (error == 0) { 1546 fdclose(td, fp, fd); 1547 fdrop(fp, td); 1548 } 1549 } 1550 } 1551 clen -= datalen; 1552 cm = (struct cmsghdr *)((uint8_t *)cm + datalen); 1553 } 1554 m_chtype(m, MT_CONTROL); 1555 } 1556 } 1557