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