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