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