The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/uipc_syscalls.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 263ad2f80393ef6cf5fb1426dd93aca1


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.