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