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 sockargs(struct mbuf **, char *, socklen_t, int);
84
85 /*
86 * Convert a user file descriptor to a kernel file entry and check if required
87 * capability rights are present.
88 * If required copy of current set of capability rights is returned.
89 * A reference on the file entry is held upon returning.
90 */
91 int
92 getsock_cap(struct thread *td, int fd, cap_rights_t *rightsp,
93 struct file **fpp, struct filecaps *havecapsp)
94 {
95 struct file *fp;
96 int error;
97
98 error = fget_cap(td, fd, rightsp, &fp, havecapsp);
99 if (__predict_false(error != 0))
100 return (error);
101 if (__predict_false(fp->f_type != DTYPE_SOCKET)) {
102 fdrop(fp, td);
103 if (havecapsp != NULL)
104 filecaps_free(havecapsp);
105 return (ENOTSOCK);
106 }
107 *fpp = fp;
108 return (0);
109 }
110
111 int
112 getsock(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp)
113 {
114 struct file *fp;
115 int error;
116
117 error = fget_unlocked(td, fd, rightsp, &fp);
118 if (__predict_false(error != 0))
119 return (error);
120 if (__predict_false(fp->f_type != DTYPE_SOCKET)) {
121 fdrop(fp, td);
122 return (ENOTSOCK);
123 }
124 *fpp = fp;
125 return (0);
126 }
127
128 /*
129 * System call interface to the socket abstraction.
130 */
131 #if defined(COMPAT_43)
132 #define COMPAT_OLDSOCK
133 #endif
134
135 int
136 sys_socket(struct thread *td, struct socket_args *uap)
137 {
138
139 return (kern_socket(td, uap->domain, uap->type, uap->protocol));
140 }
141
142 int
143 kern_socket(struct thread *td, int domain, int type, int protocol)
144 {
145 struct socket *so;
146 struct file *fp;
147 int fd, error, oflag, fflag;
148
149 AUDIT_ARG_SOCKET(domain, type, protocol);
150
151 oflag = 0;
152 fflag = 0;
153 if ((type & SOCK_CLOEXEC) != 0) {
154 type &= ~SOCK_CLOEXEC;
155 oflag |= O_CLOEXEC;
156 }
157 if ((type & SOCK_NONBLOCK) != 0) {
158 type &= ~SOCK_NONBLOCK;
159 fflag |= FNONBLOCK;
160 }
161
162 #ifdef MAC
163 error = mac_socket_check_create(td->td_ucred, domain, type, protocol);
164 if (error != 0)
165 return (error);
166 #endif
167 error = falloc(td, &fp, &fd, oflag);
168 if (error != 0)
169 return (error);
170 /* An extra reference on `fp' has been held for us by falloc(). */
171 error = socreate(domain, &so, type, protocol, td->td_ucred, td);
172 if (error != 0) {
173 fdclose(td, fp, fd);
174 } else {
175 finit(fp, FREAD | FWRITE | fflag, DTYPE_SOCKET, so, &socketops);
176 if ((fflag & FNONBLOCK) != 0)
177 (void) fo_ioctl(fp, FIONBIO, &fflag, td->td_ucred, td);
178 td->td_retval[0] = fd;
179 }
180 fdrop(fp, td);
181 return (error);
182 }
183
184 int
185 sys_bind(struct thread *td, struct bind_args *uap)
186 {
187 struct sockaddr *sa;
188 int error;
189
190 error = getsockaddr(&sa, uap->name, uap->namelen);
191 if (error == 0) {
192 error = kern_bindat(td, AT_FDCWD, uap->s, sa);
193 free(sa, M_SONAME);
194 }
195 return (error);
196 }
197
198 int
199 kern_bindat(struct thread *td, int dirfd, int fd, struct sockaddr *sa)
200 {
201 struct socket *so;
202 struct file *fp;
203 int error;
204
205 #ifdef CAPABILITY_MODE
206 if (IN_CAPABILITY_MODE(td) && (dirfd == AT_FDCWD))
207 return (ECAPMODE);
208 #endif
209
210 AUDIT_ARG_FD(fd);
211 AUDIT_ARG_SOCKADDR(td, dirfd, sa);
212 error = getsock(td, fd, &cap_bind_rights, &fp);
213 if (error != 0)
214 return (error);
215 so = fp->f_data;
216 #ifdef KTRACE
217 if (KTRPOINT(td, KTR_STRUCT))
218 ktrsockaddr(sa);
219 #endif
220 #ifdef MAC
221 error = mac_socket_check_bind(td->td_ucred, so, sa);
222 if (error == 0) {
223 #endif
224 if (dirfd == AT_FDCWD)
225 error = sobind(so, sa, td);
226 else
227 error = sobindat(dirfd, so, sa, td);
228 #ifdef MAC
229 }
230 #endif
231 fdrop(fp, td);
232 return (error);
233 }
234
235 int
236 sys_bindat(struct thread *td, struct bindat_args *uap)
237 {
238 struct sockaddr *sa;
239 int error;
240
241 error = getsockaddr(&sa, uap->name, uap->namelen);
242 if (error == 0) {
243 error = kern_bindat(td, uap->fd, uap->s, sa);
244 free(sa, M_SONAME);
245 }
246 return (error);
247 }
248
249 int
250 sys_listen(struct thread *td, struct listen_args *uap)
251 {
252
253 return (kern_listen(td, uap->s, uap->backlog));
254 }
255
256 int
257 kern_listen(struct thread *td, int s, int backlog)
258 {
259 struct socket *so;
260 struct file *fp;
261 int error;
262
263 AUDIT_ARG_FD(s);
264 error = getsock(td, s, &cap_listen_rights, &fp);
265 if (error == 0) {
266 so = fp->f_data;
267 #ifdef MAC
268 error = mac_socket_check_listen(td->td_ucred, so);
269 if (error == 0)
270 #endif
271 error = solisten(so, backlog, td);
272 fdrop(fp, td);
273 }
274 return (error);
275 }
276
277 /*
278 * accept1()
279 */
280 static int
281 accept1(td, s, uname, anamelen, flags)
282 struct thread *td;
283 int s;
284 struct sockaddr *uname;
285 socklen_t *anamelen;
286 int flags;
287 {
288 struct sockaddr *name;
289 socklen_t namelen;
290 struct file *fp;
291 int error;
292
293 if (uname == NULL)
294 return (kern_accept4(td, s, NULL, NULL, flags, NULL));
295
296 error = copyin(anamelen, &namelen, sizeof (namelen));
297 if (error != 0)
298 return (error);
299
300 error = kern_accept4(td, s, &name, &namelen, flags, &fp);
301
302 if (error != 0)
303 return (error);
304
305 if (error == 0 && uname != NULL) {
306 #ifdef COMPAT_OLDSOCK
307 if (SV_PROC_FLAG(td->td_proc, SV_AOUT) &&
308 (flags & ACCEPT4_COMPAT) != 0)
309 ((struct osockaddr *)name)->sa_family =
310 name->sa_family;
311 #endif
312 error = copyout(name, uname, namelen);
313 }
314 if (error == 0)
315 error = copyout(&namelen, anamelen,
316 sizeof(namelen));
317 if (error != 0)
318 fdclose(td, fp, td->td_retval[0]);
319 fdrop(fp, td);
320 free(name, M_SONAME);
321 return (error);
322 }
323
324 int
325 kern_accept(struct thread *td, int s, struct sockaddr **name,
326 socklen_t *namelen, struct file **fp)
327 {
328 return (kern_accept4(td, s, name, namelen, ACCEPT4_INHERIT, fp));
329 }
330
331 int
332 kern_accept4(struct thread *td, int s, struct sockaddr **name,
333 socklen_t *namelen, int flags, struct file **fp)
334 {
335 struct file *headfp, *nfp = NULL;
336 struct sockaddr *sa = NULL;
337 struct socket *head, *so;
338 struct filecaps fcaps;
339 u_int fflag;
340 pid_t pgid;
341 int error, fd, tmp;
342
343 if (name != NULL)
344 *name = NULL;
345
346 AUDIT_ARG_FD(s);
347 error = getsock_cap(td, s, &cap_accept_rights,
348 &headfp, &fcaps);
349 if (error != 0)
350 return (error);
351 fflag = atomic_load_int(&headfp->f_flag);
352 head = headfp->f_data;
353 if (!SOLISTENING(head)) {
354 error = EINVAL;
355 goto done;
356 }
357 #ifdef MAC
358 error = mac_socket_check_accept(td->td_ucred, head);
359 if (error != 0)
360 goto done;
361 #endif
362 error = falloc_caps(td, &nfp, &fd,
363 (flags & SOCK_CLOEXEC) ? O_CLOEXEC : 0, &fcaps);
364 if (error != 0)
365 goto done;
366 SOCK_LOCK(head);
367 if (!SOLISTENING(head)) {
368 SOCK_UNLOCK(head);
369 error = EINVAL;
370 goto noconnection;
371 }
372
373 error = solisten_dequeue(head, &so, flags);
374 if (error != 0)
375 goto noconnection;
376
377 /* An extra reference on `nfp' has been held for us by falloc(). */
378 td->td_retval[0] = fd;
379
380 /* Connection has been removed from the listen queue. */
381 KNOTE_UNLOCKED(&head->so_rdsel.si_note, 0);
382
383 if (flags & ACCEPT4_INHERIT) {
384 pgid = fgetown(&head->so_sigio);
385 if (pgid != 0)
386 fsetown(pgid, &so->so_sigio);
387 } else {
388 fflag &= ~(FNONBLOCK | FASYNC);
389 if (flags & SOCK_NONBLOCK)
390 fflag |= FNONBLOCK;
391 }
392
393 finit(nfp, fflag, DTYPE_SOCKET, so, &socketops);
394 /* Sync socket nonblocking/async state with file flags */
395 tmp = fflag & FNONBLOCK;
396 (void) fo_ioctl(nfp, FIONBIO, &tmp, td->td_ucred, td);
397 tmp = fflag & FASYNC;
398 (void) fo_ioctl(nfp, FIOASYNC, &tmp, td->td_ucred, td);
399 error = soaccept(so, &sa);
400 if (error != 0)
401 goto noconnection;
402 if (sa == NULL) {
403 if (name)
404 *namelen = 0;
405 goto done;
406 }
407 AUDIT_ARG_SOCKADDR(td, AT_FDCWD, sa);
408 if (name) {
409 /* check sa_len before it is destroyed */
410 if (*namelen > sa->sa_len)
411 *namelen = sa->sa_len;
412 #ifdef KTRACE
413 if (KTRPOINT(td, KTR_STRUCT))
414 ktrsockaddr(sa);
415 #endif
416 *name = sa;
417 sa = NULL;
418 }
419 noconnection:
420 free(sa, M_SONAME);
421
422 /*
423 * close the new descriptor, assuming someone hasn't ripped it
424 * out from under us.
425 */
426 if (error != 0)
427 fdclose(td, nfp, fd);
428
429 /*
430 * Release explicitly held references before returning. We return
431 * a reference on nfp to the caller on success if they request it.
432 */
433 done:
434 if (nfp == NULL)
435 filecaps_free(&fcaps);
436 if (fp != NULL) {
437 if (error == 0) {
438 *fp = nfp;
439 nfp = NULL;
440 } else
441 *fp = NULL;
442 }
443 if (nfp != NULL)
444 fdrop(nfp, td);
445 fdrop(headfp, td);
446 return (error);
447 }
448
449 int
450 sys_accept(td, uap)
451 struct thread *td;
452 struct accept_args *uap;
453 {
454
455 return (accept1(td, uap->s, uap->name, uap->anamelen, ACCEPT4_INHERIT));
456 }
457
458 int
459 sys_accept4(td, uap)
460 struct thread *td;
461 struct accept4_args *uap;
462 {
463
464 if (uap->flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
465 return (EINVAL);
466
467 return (accept1(td, uap->s, uap->name, uap->anamelen, uap->flags));
468 }
469
470 #ifdef COMPAT_OLDSOCK
471 int
472 oaccept(struct thread *td, struct oaccept_args *uap)
473 {
474
475 return (accept1(td, uap->s, uap->name, uap->anamelen,
476 ACCEPT4_INHERIT | ACCEPT4_COMPAT));
477 }
478 #endif /* COMPAT_OLDSOCK */
479
480 int
481 sys_connect(struct thread *td, struct connect_args *uap)
482 {
483 struct sockaddr *sa;
484 int error;
485
486 error = getsockaddr(&sa, uap->name, uap->namelen);
487 if (error == 0) {
488 error = kern_connectat(td, AT_FDCWD, uap->s, sa);
489 free(sa, M_SONAME);
490 }
491 return (error);
492 }
493
494 int
495 kern_connectat(struct thread *td, int dirfd, int fd, struct sockaddr *sa)
496 {
497 struct socket *so;
498 struct file *fp;
499 int error;
500
501 #ifdef CAPABILITY_MODE
502 if (IN_CAPABILITY_MODE(td) && (dirfd == AT_FDCWD))
503 return (ECAPMODE);
504 #endif
505
506 AUDIT_ARG_FD(fd);
507 AUDIT_ARG_SOCKADDR(td, dirfd, sa);
508 error = getsock(td, fd, &cap_connect_rights, &fp);
509 if (error != 0)
510 return (error);
511 so = fp->f_data;
512 if (so->so_state & SS_ISCONNECTING) {
513 error = EALREADY;
514 goto done1;
515 }
516 #ifdef KTRACE
517 if (KTRPOINT(td, KTR_STRUCT))
518 ktrsockaddr(sa);
519 #endif
520 #ifdef MAC
521 error = mac_socket_check_connect(td->td_ucred, so, sa);
522 if (error != 0)
523 goto bad;
524 #endif
525 error = soconnectat(dirfd, so, sa, td);
526 if (error != 0)
527 goto bad;
528 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
529 error = EINPROGRESS;
530 goto done1;
531 }
532 SOCK_LOCK(so);
533 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
534 error = msleep(&so->so_timeo, &so->so_lock, PSOCK | PCATCH,
535 "connec", 0);
536 if (error != 0)
537 break;
538 }
539 if (error == 0) {
540 error = so->so_error;
541 so->so_error = 0;
542 }
543 SOCK_UNLOCK(so);
544 bad:
545 if (error == ERESTART)
546 error = EINTR;
547 done1:
548 fdrop(fp, td);
549 return (error);
550 }
551
552 int
553 sys_connectat(struct thread *td, struct connectat_args *uap)
554 {
555 struct sockaddr *sa;
556 int error;
557
558 error = getsockaddr(&sa, uap->name, uap->namelen);
559 if (error == 0) {
560 error = kern_connectat(td, uap->fd, uap->s, sa);
561 free(sa, M_SONAME);
562 }
563 return (error);
564 }
565
566 int
567 kern_socketpair(struct thread *td, int domain, int type, int protocol,
568 int *rsv)
569 {
570 struct file *fp1, *fp2;
571 struct socket *so1, *so2;
572 int fd, error, oflag, fflag;
573
574 AUDIT_ARG_SOCKET(domain, type, protocol);
575
576 oflag = 0;
577 fflag = 0;
578 if ((type & SOCK_CLOEXEC) != 0) {
579 type &= ~SOCK_CLOEXEC;
580 oflag |= O_CLOEXEC;
581 }
582 if ((type & SOCK_NONBLOCK) != 0) {
583 type &= ~SOCK_NONBLOCK;
584 fflag |= FNONBLOCK;
585 }
586 #ifdef MAC
587 /* We might want to have a separate check for socket pairs. */
588 error = mac_socket_check_create(td->td_ucred, domain, type,
589 protocol);
590 if (error != 0)
591 return (error);
592 #endif
593 error = socreate(domain, &so1, type, protocol, td->td_ucred, td);
594 if (error != 0)
595 return (error);
596 error = socreate(domain, &so2, type, protocol, td->td_ucred, td);
597 if (error != 0)
598 goto free1;
599 /* On success extra reference to `fp1' and 'fp2' is set by falloc. */
600 error = falloc(td, &fp1, &fd, oflag);
601 if (error != 0)
602 goto free2;
603 rsv[0] = fd;
604 fp1->f_data = so1; /* so1 already has ref count */
605 error = falloc(td, &fp2, &fd, oflag);
606 if (error != 0)
607 goto free3;
608 fp2->f_data = so2; /* so2 already has ref count */
609 rsv[1] = fd;
610 error = soconnect2(so1, so2);
611 if (error != 0)
612 goto free4;
613 if (type == SOCK_DGRAM) {
614 /*
615 * Datagram socket connection is asymmetric.
616 */
617 error = soconnect2(so2, so1);
618 if (error != 0)
619 goto free4;
620 } else if (so1->so_proto->pr_flags & PR_CONNREQUIRED) {
621 struct unpcb *unp, *unp2;
622 unp = sotounpcb(so1);
623 unp2 = sotounpcb(so2);
624 /*
625 * No need to lock the unps, because the sockets are brand-new.
626 * No other threads can be using them yet
627 */
628 unp_copy_peercred(td, unp, unp2, unp);
629 }
630 finit(fp1, FREAD | FWRITE | fflag, DTYPE_SOCKET, fp1->f_data,
631 &socketops);
632 finit(fp2, FREAD | FWRITE | fflag, DTYPE_SOCKET, fp2->f_data,
633 &socketops);
634 if ((fflag & FNONBLOCK) != 0) {
635 (void) fo_ioctl(fp1, FIONBIO, &fflag, td->td_ucred, td);
636 (void) fo_ioctl(fp2, FIONBIO, &fflag, td->td_ucred, td);
637 }
638 fdrop(fp1, td);
639 fdrop(fp2, td);
640 return (0);
641 free4:
642 fdclose(td, fp2, rsv[1]);
643 fdrop(fp2, td);
644 free3:
645 fdclose(td, fp1, rsv[0]);
646 fdrop(fp1, td);
647 free2:
648 if (so2 != NULL)
649 (void)soclose(so2);
650 free1:
651 if (so1 != NULL)
652 (void)soclose(so1);
653 return (error);
654 }
655
656 int
657 sys_socketpair(struct thread *td, struct socketpair_args *uap)
658 {
659 int error, sv[2];
660
661 error = kern_socketpair(td, uap->domain, uap->type,
662 uap->protocol, sv);
663 if (error != 0)
664 return (error);
665 error = copyout(sv, uap->rsv, 2 * sizeof(int));
666 if (error != 0) {
667 (void)kern_close(td, sv[0]);
668 (void)kern_close(td, sv[1]);
669 }
670 return (error);
671 }
672
673 static int
674 sendit(struct thread *td, int s, struct msghdr *mp, int flags)
675 {
676 struct mbuf *control;
677 struct sockaddr *to;
678 int error;
679
680 #ifdef CAPABILITY_MODE
681 if (IN_CAPABILITY_MODE(td) && (mp->msg_name != NULL))
682 return (ECAPMODE);
683 #endif
684
685 if (mp->msg_name != NULL) {
686 error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
687 if (error != 0) {
688 to = NULL;
689 goto bad;
690 }
691 mp->msg_name = to;
692 } else {
693 to = NULL;
694 }
695
696 if (mp->msg_control) {
697 if (mp->msg_controllen < sizeof(struct cmsghdr)
698 #ifdef COMPAT_OLDSOCK
699 && (mp->msg_flags != MSG_COMPAT ||
700 !SV_PROC_FLAG(td->td_proc, SV_AOUT))
701 #endif
702 ) {
703 error = EINVAL;
704 goto bad;
705 }
706 error = sockargs(&control, mp->msg_control,
707 mp->msg_controllen, MT_CONTROL);
708 if (error != 0)
709 goto bad;
710 #ifdef COMPAT_OLDSOCK
711 if (mp->msg_flags == MSG_COMPAT &&
712 SV_PROC_FLAG(td->td_proc, SV_AOUT)) {
713 struct cmsghdr *cm;
714
715 M_PREPEND(control, sizeof(*cm), M_WAITOK);
716 cm = mtod(control, struct cmsghdr *);
717 cm->cmsg_len = control->m_len;
718 cm->cmsg_level = SOL_SOCKET;
719 cm->cmsg_type = SCM_RIGHTS;
720 }
721 #endif
722 } else {
723 control = NULL;
724 }
725
726 error = kern_sendit(td, s, mp, flags, control, UIO_USERSPACE);
727
728 bad:
729 free(to, M_SONAME);
730 return (error);
731 }
732
733 int
734 kern_sendit(struct thread *td, int s, struct msghdr *mp, int flags,
735 struct mbuf *control, enum uio_seg segflg)
736 {
737 struct file *fp;
738 struct uio auio;
739 struct iovec *iov;
740 struct socket *so;
741 cap_rights_t *rights;
742 #ifdef KTRACE
743 struct uio *ktruio = NULL;
744 #endif
745 ssize_t len;
746 int i, error;
747
748 AUDIT_ARG_FD(s);
749 rights = &cap_send_rights;
750 if (mp->msg_name != NULL) {
751 AUDIT_ARG_SOCKADDR(td, AT_FDCWD, mp->msg_name);
752 rights = &cap_send_connect_rights;
753 }
754 error = getsock(td, s, rights, &fp);
755 if (error != 0) {
756 m_freem(control);
757 return (error);
758 }
759 so = (struct socket *)fp->f_data;
760
761 #ifdef KTRACE
762 if (mp->msg_name != NULL && KTRPOINT(td, KTR_STRUCT))
763 ktrsockaddr(mp->msg_name);
764 #endif
765 #ifdef MAC
766 if (mp->msg_name != NULL) {
767 error = mac_socket_check_connect(td->td_ucred, so,
768 mp->msg_name);
769 if (error != 0) {
770 m_freem(control);
771 goto bad;
772 }
773 }
774 error = mac_socket_check_send(td->td_ucred, so);
775 if (error != 0) {
776 m_freem(control);
777 goto bad;
778 }
779 #endif
780
781 auio.uio_iov = mp->msg_iov;
782 auio.uio_iovcnt = mp->msg_iovlen;
783 auio.uio_segflg = segflg;
784 auio.uio_rw = UIO_WRITE;
785 auio.uio_td = td;
786 auio.uio_offset = 0; /* XXX */
787 auio.uio_resid = 0;
788 iov = mp->msg_iov;
789 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
790 if ((auio.uio_resid += iov->iov_len) < 0) {
791 error = EINVAL;
792 m_freem(control);
793 goto bad;
794 }
795 }
796 #ifdef KTRACE
797 if (KTRPOINT(td, KTR_GENIO))
798 ktruio = cloneuio(&auio);
799 #endif
800 len = auio.uio_resid;
801 error = sousrsend(so, mp->msg_name, &auio, control, flags, NULL);
802 if (error == 0)
803 td->td_retval[0] = len - auio.uio_resid;
804 #ifdef KTRACE
805 if (ktruio != NULL) {
806 ktruio->uio_resid = td->td_retval[0];
807 ktrgenio(s, UIO_WRITE, ktruio, error);
808 }
809 #endif
810 bad:
811 fdrop(fp, td);
812 return (error);
813 }
814
815 int
816 sys_sendto(struct thread *td, struct sendto_args *uap)
817 {
818 struct msghdr msg;
819 struct iovec aiov;
820
821 msg.msg_name = __DECONST(void *, uap->to);
822 msg.msg_namelen = uap->tolen;
823 msg.msg_iov = &aiov;
824 msg.msg_iovlen = 1;
825 msg.msg_control = 0;
826 #ifdef COMPAT_OLDSOCK
827 if (SV_PROC_FLAG(td->td_proc, SV_AOUT))
828 msg.msg_flags = 0;
829 #endif
830 aiov.iov_base = __DECONST(void *, uap->buf);
831 aiov.iov_len = uap->len;
832 return (sendit(td, uap->s, &msg, uap->flags));
833 }
834
835 #ifdef COMPAT_OLDSOCK
836 int
837 osend(struct thread *td, struct osend_args *uap)
838 {
839 struct msghdr msg;
840 struct iovec aiov;
841
842 msg.msg_name = 0;
843 msg.msg_namelen = 0;
844 msg.msg_iov = &aiov;
845 msg.msg_iovlen = 1;
846 aiov.iov_base = __DECONST(void *, uap->buf);
847 aiov.iov_len = uap->len;
848 msg.msg_control = 0;
849 msg.msg_flags = 0;
850 return (sendit(td, uap->s, &msg, uap->flags));
851 }
852
853 int
854 osendmsg(struct thread *td, struct osendmsg_args *uap)
855 {
856 struct msghdr msg;
857 struct iovec *iov;
858 int error;
859
860 error = copyin(uap->msg, &msg, sizeof (struct omsghdr));
861 if (error != 0)
862 return (error);
863 error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
864 if (error != 0)
865 return (error);
866 msg.msg_iov = iov;
867 msg.msg_flags = MSG_COMPAT;
868 error = sendit(td, uap->s, &msg, uap->flags);
869 free(iov, M_IOV);
870 return (error);
871 }
872 #endif
873
874 int
875 sys_sendmsg(struct thread *td, struct sendmsg_args *uap)
876 {
877 struct msghdr msg;
878 struct iovec *iov;
879 int error;
880
881 error = copyin(uap->msg, &msg, sizeof (msg));
882 if (error != 0)
883 return (error);
884 error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
885 if (error != 0)
886 return (error);
887 msg.msg_iov = iov;
888 #ifdef COMPAT_OLDSOCK
889 if (SV_PROC_FLAG(td->td_proc, SV_AOUT))
890 msg.msg_flags = 0;
891 #endif
892 error = sendit(td, uap->s, &msg, uap->flags);
893 free(iov, M_IOV);
894 return (error);
895 }
896
897 int
898 kern_recvit(struct thread *td, int s, struct msghdr *mp, enum uio_seg fromseg,
899 struct mbuf **controlp)
900 {
901 struct uio auio;
902 struct iovec *iov;
903 struct mbuf *control, *m;
904 caddr_t ctlbuf;
905 struct file *fp;
906 struct socket *so;
907 struct sockaddr *fromsa = NULL;
908 #ifdef KTRACE
909 struct uio *ktruio = NULL;
910 #endif
911 ssize_t len;
912 int error, i;
913
914 if (controlp != NULL)
915 *controlp = NULL;
916
917 AUDIT_ARG_FD(s);
918 error = getsock(td, s, &cap_recv_rights, &fp);
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;
1029 m_dispose_extcontrolm(m);
1030 }
1031 }
1032 out:
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
1051 static int
1052 recvit(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
1070 static int
1071 kern_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);
1094 done2:
1095 return (error);
1096 }
1097
1098 int
1099 sys_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
1107 int
1108 orecvfrom(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
1116 int
1117 orecv(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 */
1138 int
1139 orecvmsg(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
1162 int
1163 sys_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
1191 int
1192 sys_shutdown(struct thread *td, struct shutdown_args *uap)
1193 {
1194
1195 return (kern_shutdown(td, uap->s, uap->how));
1196 }
1197
1198 int
1199 kern_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(td, s, &cap_shutdown_rights, &fp);
1207 if (error == 0) {
1208 so = fp->f_data;
1209 error = soshutdown(so, how);
1210 /*
1211 * Previous versions did not return ENOTCONN, but 0 in
1212 * case the socket was not connected. Some important
1213 * programs like syslogd up to r279016, 2015-02-19,
1214 * still depend on this behavior.
1215 */
1216 if (error == ENOTCONN &&
1217 td->td_proc->p_osrel < P_OSREL_SHUTDOWN_ENOTCONN)
1218 error = 0;
1219 fdrop(fp, td);
1220 }
1221 return (error);
1222 }
1223
1224 int
1225 sys_setsockopt(struct thread *td, struct setsockopt_args *uap)
1226 {
1227
1228 return (kern_setsockopt(td, uap->s, uap->level, uap->name,
1229 uap->val, UIO_USERSPACE, uap->valsize));
1230 }
1231
1232 int
1233 kern_setsockopt(struct thread *td, int s, int level, int name, const void *val,
1234 enum uio_seg valseg, socklen_t valsize)
1235 {
1236 struct socket *so;
1237 struct file *fp;
1238 struct sockopt sopt;
1239 int error;
1240
1241 if (val == NULL && valsize != 0)
1242 return (EFAULT);
1243 if ((int)valsize < 0)
1244 return (EINVAL);
1245
1246 sopt.sopt_dir = SOPT_SET;
1247 sopt.sopt_level = level;
1248 sopt.sopt_name = name;
1249 sopt.sopt_val = __DECONST(void *, val);
1250 sopt.sopt_valsize = valsize;
1251 switch (valseg) {
1252 case UIO_USERSPACE:
1253 sopt.sopt_td = td;
1254 break;
1255 case UIO_SYSSPACE:
1256 sopt.sopt_td = NULL;
1257 break;
1258 default:
1259 panic("kern_setsockopt called with bad valseg");
1260 }
1261
1262 AUDIT_ARG_FD(s);
1263 error = getsock(td, s, &cap_setsockopt_rights, &fp);
1264 if (error == 0) {
1265 so = fp->f_data;
1266 error = sosetopt(so, &sopt);
1267 fdrop(fp, td);
1268 }
1269 return(error);
1270 }
1271
1272 int
1273 sys_getsockopt(struct thread *td, struct getsockopt_args *uap)
1274 {
1275 socklen_t valsize;
1276 int error;
1277
1278 if (uap->val) {
1279 error = copyin(uap->avalsize, &valsize, sizeof (valsize));
1280 if (error != 0)
1281 return (error);
1282 }
1283
1284 error = kern_getsockopt(td, uap->s, uap->level, uap->name,
1285 uap->val, UIO_USERSPACE, &valsize);
1286
1287 if (error == 0)
1288 error = copyout(&valsize, uap->avalsize, sizeof (valsize));
1289 return (error);
1290 }
1291
1292 /*
1293 * Kernel version of getsockopt.
1294 * optval can be a userland or userspace. optlen is always a kernel pointer.
1295 */
1296 int
1297 kern_getsockopt(struct thread *td, int s, int level, int name, void *val,
1298 enum uio_seg valseg, socklen_t *valsize)
1299 {
1300 struct socket *so;
1301 struct file *fp;
1302 struct sockopt sopt;
1303 int error;
1304
1305 if (val == NULL)
1306 *valsize = 0;
1307 if ((int)*valsize < 0)
1308 return (EINVAL);
1309
1310 sopt.sopt_dir = SOPT_GET;
1311 sopt.sopt_level = level;
1312 sopt.sopt_name = name;
1313 sopt.sopt_val = val;
1314 sopt.sopt_valsize = (size_t)*valsize; /* checked non-negative above */
1315 switch (valseg) {
1316 case UIO_USERSPACE:
1317 sopt.sopt_td = td;
1318 break;
1319 case UIO_SYSSPACE:
1320 sopt.sopt_td = NULL;
1321 break;
1322 default:
1323 panic("kern_getsockopt called with bad valseg");
1324 }
1325
1326 AUDIT_ARG_FD(s);
1327 error = getsock(td, s, &cap_getsockopt_rights, &fp);
1328 if (error == 0) {
1329 so = fp->f_data;
1330 error = sogetopt(so, &sopt);
1331 *valsize = sopt.sopt_valsize;
1332 fdrop(fp, td);
1333 }
1334 return (error);
1335 }
1336
1337 static int
1338 user_getsockname(struct thread *td, int fdes, struct sockaddr *asa,
1339 socklen_t *alen, bool compat)
1340 {
1341 struct sockaddr *sa;
1342 socklen_t len;
1343 int error;
1344
1345 error = copyin(alen, &len, sizeof(len));
1346 if (error != 0)
1347 return (error);
1348
1349 error = kern_getsockname(td, fdes, &sa, &len);
1350 if (error != 0)
1351 return (error);
1352
1353 if (len != 0) {
1354 #ifdef COMPAT_OLDSOCK
1355 if (compat && SV_PROC_FLAG(td->td_proc, SV_AOUT))
1356 ((struct osockaddr *)sa)->sa_family = sa->sa_family;
1357 #endif
1358 error = copyout(sa, asa, len);
1359 }
1360 free(sa, M_SONAME);
1361 if (error == 0)
1362 error = copyout(&len, alen, sizeof(len));
1363 return (error);
1364 }
1365
1366 int
1367 kern_getsockname(struct thread *td, int fd, struct sockaddr **sa,
1368 socklen_t *alen)
1369 {
1370 struct socket *so;
1371 struct file *fp;
1372 socklen_t len;
1373 int error;
1374
1375 AUDIT_ARG_FD(fd);
1376 error = getsock(td, fd, &cap_getsockname_rights, &fp);
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_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 return (user_getsockname(td, uap->fdes, uap->asa, uap->alen, false));
1408 }
1409
1410 #ifdef COMPAT_OLDSOCK
1411 int
1412 ogetsockname(struct thread *td, struct ogetsockname_args *uap)
1413 {
1414 return (user_getsockname(td, uap->fdes, uap->asa, uap->alen, true));
1415 }
1416 #endif /* COMPAT_OLDSOCK */
1417
1418 static int
1419 user_getpeername(struct thread *td, int fdes, struct sockaddr *asa,
1420 socklen_t *alen, bool compat)
1421 {
1422 struct sockaddr *sa;
1423 socklen_t len;
1424 int error;
1425
1426 error = copyin(alen, &len, sizeof (len));
1427 if (error != 0)
1428 return (error);
1429
1430 error = kern_getpeername(td, fdes, &sa, &len);
1431 if (error != 0)
1432 return (error);
1433
1434 if (len != 0) {
1435 #ifdef COMPAT_OLDSOCK
1436 if (compat && SV_PROC_FLAG(td->td_proc, SV_AOUT))
1437 ((struct osockaddr *)sa)->sa_family = sa->sa_family;
1438 #endif
1439 error = copyout(sa, asa, len);
1440 }
1441 free(sa, M_SONAME);
1442 if (error == 0)
1443 error = copyout(&len, alen, sizeof(len));
1444 return (error);
1445 }
1446
1447 int
1448 kern_getpeername(struct thread *td, int fd, struct sockaddr **sa,
1449 socklen_t *alen)
1450 {
1451 struct socket *so;
1452 struct file *fp;
1453 socklen_t len;
1454 int error;
1455
1456 AUDIT_ARG_FD(fd);
1457 error = getsock(td, fd, &cap_getpeername_rights, &fp);
1458 if (error != 0)
1459 return (error);
1460 so = fp->f_data;
1461 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
1462 error = ENOTCONN;
1463 goto done;
1464 }
1465 *sa = NULL;
1466 CURVNET_SET(so->so_vnet);
1467 error = so->so_proto->pr_peeraddr(so, sa);
1468 CURVNET_RESTORE();
1469 if (error != 0)
1470 goto bad;
1471 if (*sa == NULL)
1472 len = 0;
1473 else
1474 len = MIN(*alen, (*sa)->sa_len);
1475 *alen = len;
1476 #ifdef KTRACE
1477 if (KTRPOINT(td, KTR_STRUCT))
1478 ktrsockaddr(*sa);
1479 #endif
1480 bad:
1481 if (error != 0 && *sa != NULL) {
1482 free(*sa, M_SONAME);
1483 *sa = NULL;
1484 }
1485 done:
1486 fdrop(fp, td);
1487 return (error);
1488 }
1489
1490 int
1491 sys_getpeername(struct thread *td, struct getpeername_args *uap)
1492 {
1493 return (user_getpeername(td, uap->fdes, uap->asa, uap->alen, false));
1494 }
1495
1496 #ifdef COMPAT_OLDSOCK
1497 int
1498 ogetpeername(struct thread *td, struct ogetpeername_args *uap)
1499 {
1500 return (user_getpeername(td, uap->fdes, uap->asa, uap->alen, true));
1501 }
1502 #endif /* COMPAT_OLDSOCK */
1503
1504 static int
1505 sockargs(struct mbuf **mp, char *buf, socklen_t buflen, int type)
1506 {
1507 struct sockaddr *sa;
1508 struct mbuf *m;
1509 int error;
1510
1511 if (buflen > MLEN) {
1512 #ifdef COMPAT_OLDSOCK
1513 if (type == MT_SONAME && buflen <= 112 &&
1514 SV_CURPROC_FLAG(SV_AOUT))
1515 buflen = MLEN; /* unix domain compat. hack */
1516 else
1517 #endif
1518 if (buflen > MCLBYTES)
1519 return (EMSGSIZE);
1520 }
1521 m = m_get2(buflen, M_WAITOK, type, 0);
1522 m->m_len = buflen;
1523 error = copyin(buf, mtod(m, void *), buflen);
1524 if (error != 0)
1525 (void) m_free(m);
1526 else {
1527 *mp = m;
1528 if (type == MT_SONAME) {
1529 sa = mtod(m, struct sockaddr *);
1530
1531 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
1532 if (sa->sa_family == 0 && sa->sa_len < AF_MAX &&
1533 SV_CURPROC_FLAG(SV_AOUT))
1534 sa->sa_family = sa->sa_len;
1535 #endif
1536 sa->sa_len = buflen;
1537 }
1538 }
1539 return (error);
1540 }
1541
1542 int
1543 getsockaddr(struct sockaddr **namp, const struct sockaddr *uaddr, size_t len)
1544 {
1545 struct sockaddr *sa;
1546 int error;
1547
1548 if (len > SOCK_MAXADDRLEN)
1549 return (ENAMETOOLONG);
1550 if (len < offsetof(struct sockaddr, sa_data[0]))
1551 return (EINVAL);
1552 sa = malloc(len, M_SONAME, M_WAITOK);
1553 error = copyin(uaddr, sa, len);
1554 if (error != 0) {
1555 free(sa, M_SONAME);
1556 } else {
1557 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
1558 if (sa->sa_family == 0 && sa->sa_len < AF_MAX &&
1559 SV_CURPROC_FLAG(SV_AOUT))
1560 sa->sa_family = sa->sa_len;
1561 #endif
1562 sa->sa_len = len;
1563 *namp = sa;
1564 }
1565 return (error);
1566 }
1567
1568 /*
1569 * Dispose of externalized rights from an SCM_RIGHTS message. This function
1570 * should be used in error or truncation cases to avoid leaking file descriptors
1571 * into the recipient's (the current thread's) table.
1572 */
1573 void
1574 m_dispose_extcontrolm(struct mbuf *m)
1575 {
1576 struct cmsghdr *cm;
1577 struct file *fp;
1578 struct thread *td;
1579 socklen_t clen, datalen;
1580 int error, fd, *fds, nfd;
1581
1582 td = curthread;
1583 for (; m != NULL; m = m->m_next) {
1584 if (m->m_type != MT_EXTCONTROL)
1585 continue;
1586 cm = mtod(m, struct cmsghdr *);
1587 clen = m->m_len;
1588 while (clen > 0) {
1589 if (clen < sizeof(*cm))
1590 panic("%s: truncated mbuf %p", __func__, m);
1591 datalen = CMSG_SPACE(cm->cmsg_len - CMSG_SPACE(0));
1592 if (clen < datalen)
1593 panic("%s: truncated mbuf %p", __func__, m);
1594
1595 if (cm->cmsg_level == SOL_SOCKET &&
1596 cm->cmsg_type == SCM_RIGHTS) {
1597 fds = (int *)CMSG_DATA(cm);
1598 nfd = (cm->cmsg_len - CMSG_SPACE(0)) /
1599 sizeof(int);
1600
1601 while (nfd-- > 0) {
1602 fd = *fds++;
1603 error = fget(td, fd, &cap_no_rights,
1604 &fp);
1605 if (error == 0) {
1606 fdclose(td, fp, fd);
1607 fdrop(fp, td);
1608 }
1609 }
1610 }
1611 clen -= datalen;
1612 cm = (struct cmsghdr *)((uint8_t *)cm + datalen);
1613 }
1614 m_chtype(m, MT_CONTROL);
1615 }
1616 }
Cache object: 467455ffd395a76be18e801f2a2275b6
|