xref: /xnu-12377.81.4/bsd/kern/uipc_syscalls.c (revision 043036a2b3718f7f0be807e2870f8f47d3fa0796)
1 /*
2  * Copyright (c) 2000-2024 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 /*
29  * Copyright (c) 1982, 1986, 1989, 1990, 1993
30  *	The Regents of the University of California.  All rights reserved.
31  *
32  * sendfile(2) and related extensions:
33  * Copyright (c) 1998, David Greenman. All rights reserved.
34  *
35  * Redistribution and use in source and binary forms, with or without
36  * modification, are permitted provided that the following conditions
37  * are met:
38  * 1. Redistributions of source code must retain the above copyright
39  *    notice, this list of conditions and the following disclaimer.
40  * 2. Redistributions in binary form must reproduce the above copyright
41  *    notice, this list of conditions and the following disclaimer in the
42  *    documentation and/or other materials provided with the distribution.
43  * 3. All advertising materials mentioning features or use of this software
44  *    must display the following acknowledgement:
45  *	This product includes software developed by the University of
46  *	California, Berkeley and its contributors.
47  * 4. Neither the name of the University nor the names of its contributors
48  *    may be used to endorse or promote products derived from this software
49  *    without specific prior written permission.
50  *
51  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61  * SUCH DAMAGE.
62  *
63  *	@(#)uipc_syscalls.c	8.4 (Berkeley) 2/21/94
64  */
65 /*
66  * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
67  * support for mandatory and extensible security protections.  This notice
68  * is included in support of clause 2.2 (b) of the Apple Public License,
69  * Version 2.0.
70  */
71 
72 #include <sys/cdefs.h>
73 #include <sys/param.h>
74 #include <sys/systm.h>
75 #include <sys/filedesc.h>
76 #include <sys/proc_internal.h>
77 #include <sys/file_internal.h>
78 #include <sys/vnode_internal.h>
79 #include <sys/malloc.h>
80 #include <sys/mcache.h>
81 #include <sys/mbuf.h>
82 #include <kern/locks.h>
83 #include <sys/domain.h>
84 #include <sys/protosw.h>
85 #include <sys/signalvar.h>
86 #include <sys/socket.h>
87 #include <sys/socketvar.h>
88 #include <sys/kernel.h>
89 #include <sys/uio_internal.h>
90 #include <sys/kauth.h>
91 #include <kern/task.h>
92 #include <sys/priv.h>
93 #include <sys/sysctl.h>
94 #include <sys/sys_domain.h>
95 #include <sys/types.h>
96 
97 #include <security/audit/audit.h>
98 
99 #include <sys/kdebug.h>
100 #include <sys/sysproto.h>
101 #include <netinet/in.h>
102 #include <net/route.h>
103 #include <netinet/in_pcb.h>
104 
105 #include <os/log.h>
106 #include <os/ptrtools.h>
107 
108 #include <os/log.h>
109 
110 #if CONFIG_MACF_SOCKET_SUBSET
111 #include <security/mac_framework.h>
112 #endif /* MAC_SOCKET_SUBSET */
113 
114 #include <net/sockaddr_utils.h>
115 
116 extern char *proc_name_address(void *p);
117 
118 #define f_flag fp_glob->fg_flag
119 #define f_ops fp_glob->fg_ops
120 
121 #define DBG_LAYER_IN_BEG        NETDBG_CODE(DBG_NETSOCK, 0)
122 #define DBG_LAYER_IN_END        NETDBG_CODE(DBG_NETSOCK, 2)
123 #define DBG_LAYER_OUT_BEG       NETDBG_CODE(DBG_NETSOCK, 1)
124 #define DBG_LAYER_OUT_END       NETDBG_CODE(DBG_NETSOCK, 3)
125 #define DBG_FNC_SENDMSG         NETDBG_CODE(DBG_NETSOCK, (1 << 8) | 1)
126 #define DBG_FNC_SENDTO          NETDBG_CODE(DBG_NETSOCK, (2 << 8) | 1)
127 #define DBG_FNC_SENDIT          NETDBG_CODE(DBG_NETSOCK, (3 << 8) | 1)
128 #define DBG_FNC_RECVFROM        NETDBG_CODE(DBG_NETSOCK, (5 << 8))
129 #define DBG_FNC_RECVMSG         NETDBG_CODE(DBG_NETSOCK, (6 << 8))
130 #define DBG_FNC_RECVIT          NETDBG_CODE(DBG_NETSOCK, (7 << 8))
131 #define DBG_FNC_SENDFILE        NETDBG_CODE(DBG_NETSOCK, (10 << 8))
132 #define DBG_FNC_SENDFILE_WAIT   NETDBG_CODE(DBG_NETSOCK, ((10 << 8) | 1))
133 #define DBG_FNC_SENDFILE_READ   NETDBG_CODE(DBG_NETSOCK, ((10 << 8) | 2))
134 #define DBG_FNC_SENDFILE_SEND   NETDBG_CODE(DBG_NETSOCK, ((10 << 8) | 3))
135 #define DBG_FNC_SENDMSG_X       NETDBG_CODE(DBG_NETSOCK, (11 << 8))
136 #define DBG_FNC_RECVMSG_X       NETDBG_CODE(DBG_NETSOCK, (12 << 8))
137 
138 /* Forward declarations for referenced types */
139 __CCT_DECLARE_CONSTRAINED_PTR_TYPE(void, void, __CCT_PTR);
140 __CCT_DECLARE_CONSTRAINED_PTR_TYPE(uint8_t, uint8_t, __CCT_PTR);
141 __CCT_DECLARE_CONSTRAINED_PTR_TYPE(int32_t, int32, __CCT_REF);
142 __CCT_DECLARE_CONSTRAINED_PTR_TYPE(int, int, __CCT_REF);
143 __CCT_DECLARE_CONSTRAINED_PTR_TYPE(user_ssize_t, user_ssize, __CCT_REF);
144 __CCT_DECLARE_CONSTRAINED_PTR_TYPE(unsigned int, uint, __CCT_REF);
145 __CCT_DECLARE_CONSTRAINED_PTR_TYPE(sae_connid_t, sae_connid, __CCT_REF);
146 __CCT_DECLARE_CONSTRAINED_PTR_TYPE(socklen_t, socklen, __CCT_REF);
147 __CCT_DECLARE_CONSTRAINED_PTR_TYPE(struct setsockopt_args, setsockopt_args, __CCT_REF);
148 __CCT_DECLARE_CONSTRAINED_PTR_TYPE(struct connectx_args, connectx_args, __CCT_REF);
149 __CCT_DECLARE_CONSTRAINED_PTR_TYPE(struct disconnectx_args, disconnectx_args, __CCT_REF);
150 __CCT_DECLARE_CONSTRAINED_PTR_TYPE(struct cmsghdr, cmsghdr, __CCT_REF);
151 __CCT_DECLARE_CONSTRAINED_PTR_TYPE(struct timeval, timeval, __CCT_REF);
152 __CCT_DECLARE_CONSTRAINED_PTR_TYPE(struct user64_timeval, user64_timeval, __CCT_REF);
153 __CCT_DECLARE_CONSTRAINED_PTR_TYPE(struct user32_timeval, user32_timeval, __CCT_REF);
154 
155 static int sendit(proc_ref_t, socket_ref_t, user_msghdr_ref_t, uio_t,
156     int, int32_ref_t );
157 static int recvit(proc_ref_t, int, user_msghdr_ref_t, uio_t, user_addr_t,
158     int32_ref_t);
159 static int connectit(socket_ref_t, sockaddr_ref_t);
160 static int getsockaddr(socket_ref_t, sockaddr_ref_ref_t, user_addr_t,
161     size_t, boolean_t);
162 static int getsockaddr_s(socket_ref_t, sockaddr_storage_ref_t,
163     user_addr_t, size_t, boolean_t);
164 #if SENDFILE
165 static void alloc_sendpkt(int, size_t, uint_ref_t, mbuf_ref_ref_t,
166     boolean_t);
167 #endif /* SENDFILE */
168 static int connectx_nocancel(proc_ref_t, connectx_args_ref_t, int_ref_t);
169 static int connectitx(socket_ref_t, sockaddr_ref_t,
170     sockaddr_ref_t, proc_ref_t, uint32_t, sae_associd_t,
171     sae_connid_ref_t, uio_t, unsigned int, user_ssize_ref_t);
172 static int disconnectx_nocancel(proc_ref_t, disconnectx_args_ref_t,
173     int_ref_t);
174 static int socket_common(proc_ref_t, int, int, int, pid_t, int32_ref_t, int);
175 
176 static int internalize_recv_msghdr_array(const void_ptr_t, int, int,
177     u_int count, user_msghdr_x_ptr_t, recv_msg_elem_ptr_t);
178 static u_int externalize_recv_msghdr_array(proc_ref_t, socket_ref_t, void_ptr_t,
179     u_int count, user_msghdr_x_ptr_t, recv_msg_elem_ptr_t, int_ref_t);
180 
181 static recv_msg_elem_ptr_t alloc_recv_msg_array(u_int count);
182 static int recv_msg_array_is_valid(recv_msg_elem_ptr_t, u_int count);
183 static void free_recv_msg_array(recv_msg_elem_ptr_t, u_int count);
184 static int copyout_control(proc_ref_t, mbuf_ref_t, user_addr_t control,
185     socklen_ref_t, int_ref_t, socket_ref_t);
186 
187 SYSCTL_DECL(_kern_ipc);
188 
189 #define SO_MAX_MSG_X_DEFAULT 256
190 
191 static u_int somaxsendmsgx = SO_MAX_MSG_X_DEFAULT;
192 SYSCTL_UINT(_kern_ipc, OID_AUTO, maxsendmsgx,
193     CTLFLAG_RW | CTLFLAG_LOCKED, &somaxsendmsgx, 0, "");
194 
195 static u_int somaxrecvmsgx = SO_MAX_MSG_X_DEFAULT;
196 SYSCTL_UINT(_kern_ipc, OID_AUTO, maxrecvmsgx,
197     CTLFLAG_RW | CTLFLAG_LOCKED, &somaxrecvmsgx, 0, "");
198 
199 static u_int missingpktinfo = 0;
200 SYSCTL_UINT(_kern_ipc, OID_AUTO, missingpktinfo,
201     CTLFLAG_RD | CTLFLAG_LOCKED, &missingpktinfo, 0, "");
202 
203 static int do_recvmsg_x_donttrunc = 0;
204 SYSCTL_INT(_kern_ipc, OID_AUTO, do_recvmsg_x_donttrunc,
205     CTLFLAG_RW | CTLFLAG_LOCKED, &do_recvmsg_x_donttrunc, 0, "");
206 
207 #if DEBUG || DEVELOPMENT
208 static int uipc_debug = 0;
209 SYSCTL_INT(_kern_ipc, OID_AUTO, debug,
210     CTLFLAG_RW | CTLFLAG_LOCKED, &uipc_debug, 0, "");
211 
212 #define DEBUG_KERNEL_ADDRPERM(_v) (_v)
213 #define DBG_PRINTF(...) if (uipc_debug != 0) {  \
214     os_log(OS_LOG_DEFAULT, __VA_ARGS__);        \
215 }
216 #else
217 #define DEBUG_KERNEL_ADDRPERM(_v) VM_KERNEL_ADDRPERM(_v)
218 #define DBG_PRINTF(...) do { } while (0)
219 #endif
220 
221 
222 /*
223  * Values for sendmsg_x_mode
224  * 0: default
225  * 1: sendit loop one at a time
226  * 2: old implementation
227  */
228 static u_int sendmsg_x_mode = 0;
229 SYSCTL_UINT(_kern_ipc, OID_AUTO, sendmsg_x_mode,
230     CTLFLAG_RW | CTLFLAG_LOCKED, &sendmsg_x_mode, 0, "");
231 
232 /*
233  * System call interface to the socket abstraction.
234  */
235 
236 extern const struct fileops socketops;
237 
238 /*
239  * Returns:	0			Success
240  *		EACCES			Mandatory Access Control failure
241  *	falloc:ENFILE
242  *	falloc:EMFILE
243  *	falloc:ENOMEM
244  *	socreate:EAFNOSUPPORT
245  *	socreate:EPROTOTYPE
246  *	socreate:EPROTONOSUPPORT
247  *	socreate:ENOBUFS
248  *	socreate:ENOMEM
249  *	socreate:???			[other protocol families, IPSEC]
250  */
251 int
socket(proc_ref_t p,struct socket_args * uap,int32_ref_t retval)252 socket(proc_ref_t p,
253     struct socket_args *uap,
254     int32_ref_t retval)
255 {
256 	return socket_common(p, uap->domain, uap->type, uap->protocol,
257 	           proc_selfpid(), retval, 0);
258 }
259 
260 int
socket_delegate(proc_ref_t p,struct socket_delegate_args * uap,int32_ref_t retval)261 socket_delegate(proc_ref_t p,
262     struct socket_delegate_args *uap,
263     int32_ref_t retval)
264 {
265 	return socket_common(p, uap->domain, uap->type, uap->protocol,
266 	           uap->epid, retval, 1);
267 }
268 
269 static int
socket_common(proc_ref_t p,int domain,int type,int protocol,pid_t epid,int32_ref_t retval,int delegate)270 socket_common(proc_ref_t p,
271     int domain,
272     int type,
273     int protocol,
274     pid_t epid,
275     int32_ref_t retval,
276     int delegate)
277 {
278 	socket_ref_t so;
279 	fileproc_ref_t  fp;
280 	int fd, error;
281 
282 	AUDIT_ARG(socket, domain, type, protocol);
283 #if CONFIG_MACF_SOCKET_SUBSET
284 	if ((error = mac_socket_check_create(kauth_cred_get(), domain,
285 	    type, protocol)) != 0) {
286 		return error;
287 	}
288 #endif /* MAC_SOCKET_SUBSET */
289 
290 	if (delegate) {
291 		error = priv_check_cred(kauth_cred_get(),
292 		    PRIV_NET_PRIVILEGED_SOCKET_DELEGATE, 0);
293 		if (error) {
294 			return EACCES;
295 		}
296 	}
297 
298 	error = falloc(p, &fp, &fd);
299 	if (error) {
300 		return error;
301 	}
302 	fp->f_flag = FREAD | FWRITE;
303 	fp->f_ops = &socketops;
304 
305 	if (delegate) {
306 		error = socreate_delegate(domain, &so, type, protocol, epid);
307 	} else {
308 		error = socreate(domain, &so, type, protocol);
309 	}
310 
311 	if (error) {
312 		fp_free(p, fd, fp);
313 	} else {
314 		fp_set_data(fp, so);
315 
316 		proc_fdlock(p);
317 		procfdtbl_releasefd(p, fd, NULL);
318 
319 		if (ENTR_SHOULDTRACE) {
320 			KERNEL_ENERGYTRACE(kEnTrActKernSocket, DBG_FUNC_START,
321 			    fd, 0, (int64_t)VM_KERNEL_ADDRPERM(so));
322 		}
323 		fp_drop(p, fd, fp, 1);
324 		proc_fdunlock(p);
325 
326 		*retval = fd;
327 	}
328 	return error;
329 }
330 
331 /*
332  * Returns:	0			Success
333  *		EDESTADDRREQ		Destination address required
334  *		EBADF			Bad file descriptor
335  *		EACCES			Mandatory Access Control failure
336  *	file_socket:ENOTSOCK
337  *	file_socket:EBADF
338  *	getsockaddr:ENAMETOOLONG	Filename too long
339  *	getsockaddr:EINVAL		Invalid argument
340  *	getsockaddr:ENOMEM		Not enough space
341  *	getsockaddr:EFAULT		Bad address
342  *	sobindlock:???
343  */
344 /* ARGSUSED */
345 int
bind(__unused proc_t p,struct bind_args * uap,__unused int32_ref_t retval)346 bind(__unused proc_t p, struct bind_args *uap, __unused int32_ref_t retval)
347 {
348 	struct sockaddr_storage ss;
349 	sockaddr_ref_t  sa = NULL;
350 	socket_ref_t so;
351 	boolean_t want_free = TRUE;
352 	int error;
353 
354 	AUDIT_ARG(fd, uap->s);
355 	error = file_socket(uap->s, &so);
356 	if (error != 0) {
357 		return error;
358 	}
359 	if (so == NULL) {
360 		error = EBADF;
361 		goto out;
362 	}
363 	if (uap->name == USER_ADDR_NULL) {
364 		error = EDESTADDRREQ;
365 		goto out;
366 	}
367 	if (uap->namelen > sizeof(ss)) {
368 		error = getsockaddr(so, &sa, uap->name, uap->namelen, TRUE);
369 	} else {
370 		error = getsockaddr_s(so, &ss, uap->name, uap->namelen, TRUE);
371 		if (error == 0) {
372 			sa = SA(&ss);
373 			want_free = FALSE;
374 		}
375 	}
376 	if (error != 0) {
377 		goto out;
378 	}
379 	AUDIT_ARG(sockaddr, vfs_context_cwd(vfs_context_current()), sa);
380 #if CONFIG_MACF_SOCKET_SUBSET
381 	if ((sa != NULL && sa->sa_family == AF_SYSTEM) ||
382 	    (error = mac_socket_check_bind(kauth_cred_get(), so, sa)) == 0) {
383 		error = sobindlock(so, sa, 1);  /* will lock socket */
384 	}
385 #else
386 	error = sobindlock(so, sa, 1);          /* will lock socket */
387 #endif /* MAC_SOCKET_SUBSET */
388 	if (want_free) {
389 		free_sockaddr(sa);
390 	}
391 out:
392 	file_drop(uap->s);
393 	return error;
394 }
395 
396 /*
397  * Returns:	0			Success
398  *		EBADF
399  *		EACCES			Mandatory Access Control failure
400  *	file_socket:ENOTSOCK
401  *	file_socket:EBADF
402  *	solisten:EINVAL
403  *	solisten:EOPNOTSUPP
404  *	solisten:???
405  */
406 int
listen(__unused proc_ref_t p,struct listen_args * uap,__unused int32_ref_t retval)407 listen(__unused proc_ref_t p, struct listen_args *uap,
408     __unused int32_ref_t retval)
409 {
410 	int error;
411 	socket_ref_t so;
412 
413 	AUDIT_ARG(fd, uap->s);
414 	error = file_socket(uap->s, &so);
415 	if (error) {
416 		return error;
417 	}
418 	if (so != NULL)
419 #if CONFIG_MACF_SOCKET_SUBSET
420 	{
421 		error = mac_socket_check_listen(kauth_cred_get(), so);
422 		if (error == 0) {
423 			error = solisten(so, uap->backlog);
424 		}
425 	}
426 #else
427 	{ error = solisten(so, uap->backlog);}
428 #endif /* MAC_SOCKET_SUBSET */
429 	else {
430 		error = EBADF;
431 	}
432 
433 	file_drop(uap->s);
434 	return error;
435 }
436 
437 /*
438  * Returns:	fp_get_ftype:EBADF	Bad file descriptor
439  *		fp_get_ftype:ENOTSOCK	Socket operation on non-socket
440  *		:EFAULT			Bad address on copyin/copyout
441  *		:EBADF			Bad file descriptor
442  *		:EOPNOTSUPP		Operation not supported on socket
443  *		:EINVAL			Invalid argument
444  *		:EWOULDBLOCK		Operation would block
445  *		:ECONNABORTED		Connection aborted
446  *		:EINTR			Interrupted function
447  *		:EACCES			Mandatory Access Control failure
448  *		falloc:ENFILE		Too many files open in system
449  *		falloc:EMFILE		Too many open files
450  *		falloc:ENOMEM		Not enough space
451  *		0			Success
452  */
453 int
accept_nocancel(proc_ref_t p,struct accept_nocancel_args * uap,int32_ref_t retval)454 accept_nocancel(proc_ref_t p, struct accept_nocancel_args *uap,
455     int32_ref_t retval)
456 {
457 	fileproc_ref_t  fp;
458 	sockaddr_ref_t  sa = NULL;
459 	socklen_t namelen;
460 	int error;
461 	socket_ref_t  head;
462 	socket_ref_t so = NULL;
463 	lck_mtx_t *mutex_held;
464 	int fd = uap->s;
465 	int newfd;
466 	unsigned int fflag;
467 	int dosocklock = 0;
468 
469 	*retval = -1;
470 
471 	AUDIT_ARG(fd, uap->s);
472 
473 	if (uap->name) {
474 		error = copyin(uap->anamelen, (caddr_t)&namelen,
475 		    sizeof(socklen_t));
476 		if (error) {
477 			return error;
478 		}
479 	}
480 	error = fp_get_ftype(p, fd, DTYPE_SOCKET, ENOTSOCK, &fp);
481 	if (error) {
482 		return error;
483 	}
484 	head = (struct socket *)fp_get_data(fp);
485 
486 #if CONFIG_MACF_SOCKET_SUBSET
487 	if ((error = mac_socket_check_accept(kauth_cred_get(), head)) != 0) {
488 		goto out;
489 	}
490 #endif /* MAC_SOCKET_SUBSET */
491 
492 	socket_lock(head, 1);
493 
494 	if (head->so_proto->pr_getlock != NULL) {
495 		mutex_held = (*head->so_proto->pr_getlock)(head, PR_F_WILLUNLOCK);
496 		dosocklock = 1;
497 	} else {
498 		mutex_held = head->so_proto->pr_domain->dom_mtx;
499 		dosocklock = 0;
500 	}
501 
502 	if ((head->so_options & SO_ACCEPTCONN) == 0) {
503 		if ((head->so_proto->pr_flags & PR_CONNREQUIRED) == 0) {
504 			error = EOPNOTSUPP;
505 		} else {
506 			/* POSIX: The socket is not accepting connections */
507 			error = EINVAL;
508 		}
509 		socket_unlock(head, 1);
510 		DBG_PRINTF("%s:%d accept() SO_ACCEPTCONN %d: msleep", proc_name_address(p), proc_selfpid(), error);
511 		goto out;
512 	}
513 check_again:
514 	if ((head->so_state & SS_NBIO) && head->so_comp.tqh_first == NULL) {
515 		socket_unlock(head, 1);
516 		error = EWOULDBLOCK;
517 		goto out;
518 	}
519 	while (TAILQ_EMPTY(&head->so_comp) && head->so_error == 0) {
520 		if (head->so_state & SS_CANTRCVMORE) {
521 			head->so_error = ECONNABORTED;
522 			break;
523 		}
524 		if (head->so_usecount < 1) {
525 			panic("accept: head=%p refcount=%d", head,
526 			    head->so_usecount);
527 		}
528 		error = msleep((caddr_t)&head->so_timeo, mutex_held,
529 		    PSOCK | PCATCH, "accept", 0);
530 		if (head->so_usecount < 1) {
531 			panic("accept: 2 head=%p refcount=%d", head,
532 			    head->so_usecount);
533 		}
534 		if ((head->so_state & SS_DRAINING)) {
535 			error = ECONNABORTED;
536 		}
537 		if (error) {
538 			DBG_PRINTF("%s:%d accept() error %d: msleep", proc_name_address(p), proc_selfpid(), error);
539 			socket_unlock(head, 1);
540 			goto out;
541 		}
542 	}
543 	if (head->so_error) {
544 		error = head->so_error;
545 		head->so_error = 0;
546 		socket_unlock(head, 1);
547 		DBG_PRINTF("%s:%d accept() error %d: head->so_error", proc_name_address(p), proc_selfpid(), error);
548 		goto out;
549 	}
550 
551 	/*
552 	 * At this point we know that there is at least one connection
553 	 * ready to be accepted. Remove it from the queue prior to
554 	 * allocating the file descriptor for it since falloc() may
555 	 * block allowing another process to accept the connection
556 	 * instead.
557 	 */
558 	lck_mtx_assert(mutex_held, LCK_MTX_ASSERT_OWNED);
559 
560 	so_acquire_accept_list(head, NULL);
561 	if (TAILQ_EMPTY(&head->so_comp)) {
562 		so_release_accept_list(head);
563 		goto check_again;
564 	}
565 
566 	so = TAILQ_FIRST(&head->so_comp);
567 	TAILQ_REMOVE(&head->so_comp, so, so_list);
568 	/*
569 	 * Acquire the lock of the new connection
570 	 * as we may be in the process of receiving
571 	 * a packet that may change its so_state
572 	 * (e.g.: a TCP FIN).
573 	 */
574 	if (dosocklock) {
575 		socket_lock(so, 0);
576 	}
577 	so->so_head = NULL;
578 	so->so_state &= ~SS_COMP;
579 	if (dosocklock) {
580 		socket_unlock(so, 0);
581 	}
582 	head->so_qlen--;
583 	so_release_accept_list(head);
584 
585 	/* unlock head to avoid deadlock with select, keep a ref on head */
586 	socket_unlock(head, 0);
587 
588 #if CONFIG_MACF_SOCKET_SUBSET
589 	/*
590 	 * Pass the pre-accepted socket to the MAC framework. This is
591 	 * cheaper than allocating a file descriptor for the socket,
592 	 * calling the protocol accept callback, and possibly freeing
593 	 * the file descriptor should the MAC check fails.
594 	 */
595 	if ((error = mac_socket_check_accepted(kauth_cred_get(), so)) != 0) {
596 		socket_lock(so, 1);
597 		so->so_state &= ~SS_NOFDREF;
598 		socket_unlock(so, 1);
599 		soclose(so);
600 		/* Drop reference on listening socket */
601 		sodereference(head);
602 		goto out;
603 	}
604 #endif /* MAC_SOCKET_SUBSET */
605 
606 	/*
607 	 * Pass the pre-accepted socket to any interested socket filter(s).
608 	 * Upon failure, the socket would have been closed by the callee.
609 	 */
610 	if (so->so_filt != NULL && (error = soacceptfilter(so, head)) != 0) {
611 		/* Drop reference on listening socket */
612 		sodereference(head);
613 		/* Propagate socket filter's error code to the caller */
614 		DBG_PRINTF("%s:%d accept() error %d: soacceptfilter", proc_name_address(p), proc_selfpid(), error);
615 		goto out;
616 	}
617 
618 	fflag = fp->f_flag;
619 	error = falloc(p, &fp, &newfd);
620 	if (error) {
621 		/*
622 		 * Probably ran out of file descriptors.
623 		 *
624 		 * <rdar://problem/8554930>
625 		 * Don't put this back on the socket like we used to, that
626 		 * just causes the client to spin. Drop the socket.
627 		 */
628 		socket_lock(so, 1);
629 		so->so_state &= ~SS_NOFDREF;
630 		socket_unlock(so, 1);
631 		soclose(so);
632 		sodereference(head);
633 		DBG_PRINTF("%s:%d accept() error %d: falloc", proc_name_address(p), proc_selfpid(), error);
634 		goto out;
635 	}
636 	*retval = newfd;
637 	fp->f_flag = fflag;
638 	fp->f_ops = &socketops;
639 	fp_set_data(fp, so);
640 
641 	socket_lock(head, 0);
642 	if (dosocklock) {
643 		socket_lock(so, 1);
644 	}
645 
646 	/* Sync socket non-blocking/async state with file flags */
647 	if (fp->f_flag & FNONBLOCK) {
648 		so->so_state |= SS_NBIO;
649 	} else {
650 		so->so_state &= ~SS_NBIO;
651 	}
652 
653 	if (fp->f_flag & FASYNC) {
654 		so->so_state |= SS_ASYNC;
655 		so->so_rcv.sb_flags |= SB_ASYNC;
656 		so->so_snd.sb_flags |= SB_ASYNC;
657 	} else {
658 		so->so_state &= ~SS_ASYNC;
659 		so->so_rcv.sb_flags &= ~SB_ASYNC;
660 		so->so_snd.sb_flags &= ~SB_ASYNC;
661 	}
662 
663 	(void) soacceptlock(so, &sa, 0);
664 	socket_unlock(head, 1);
665 	if (sa == NULL) {
666 		namelen = 0;
667 		if (uap->name) {
668 			goto gotnoname;
669 		}
670 		error = 0;
671 		goto releasefd;
672 	}
673 	AUDIT_ARG(sockaddr, vfs_context_cwd(vfs_context_current()), sa);
674 
675 	if (uap->name) {
676 		socklen_t       sa_len;
677 
678 		/* save sa_len before it is destroyed */
679 		sa_len = sa->sa_len;
680 		namelen = MIN(namelen, sa_len);
681 		error = copyout(__SA_UTILS_CONV_TO_BYTES(sa), uap->name, namelen);
682 		if (!error) {
683 			/* return the actual, untruncated address length */
684 			namelen = sa_len;
685 		}
686 gotnoname:
687 		error = copyout((caddr_t)&namelen, uap->anamelen,
688 		    sizeof(socklen_t));
689 		if (__improbable(error != 0)) {
690 			DBG_PRINTF("%s:%d accept() error %d: falloc", proc_name_address(p), proc_selfpid(), error);
691 		}
692 	}
693 	free_sockaddr(sa);
694 
695 releasefd:
696 	/*
697 	 * If the socket has been marked as inactive by sosetdefunct(),
698 	 * disallow further operations on it.
699 	 */
700 	if (so->so_flags & SOF_DEFUNCT) {
701 		sodefunct(current_proc(), so,
702 		    SHUTDOWN_SOCKET_LEVEL_DISCONNECT_INTERNAL);
703 	}
704 
705 	if (dosocklock) {
706 		socket_unlock(so, 1);
707 	}
708 
709 	proc_fdlock(p);
710 	procfdtbl_releasefd(p, newfd, NULL);
711 	fp_drop(p, newfd, fp, 1);
712 	proc_fdunlock(p);
713 
714 out:
715 	if (error == 0 && ENTR_SHOULDTRACE) {
716 		KERNEL_ENERGYTRACE(kEnTrActKernSocket, DBG_FUNC_START,
717 		    newfd, 0, (int64_t)VM_KERNEL_ADDRPERM(so));
718 	}
719 
720 	file_drop(fd);
721 	return error;
722 }
723 
724 int
accept(proc_ref_t p,struct accept_args * uap,int32_ref_t retval)725 accept(proc_ref_t p, struct accept_args *uap, int32_ref_t retval)
726 {
727 	__pthread_testcancel(1);
728 	return accept_nocancel(p, (struct accept_nocancel_args *)uap,
729 	           retval);
730 }
731 
732 /*
733  * Returns:	0			Success
734  *		EBADF			Bad file descriptor
735  *		EALREADY		Connection already in progress
736  *		EINPROGRESS		Operation in progress
737  *		ECONNABORTED		Connection aborted
738  *		EINTR			Interrupted function
739  *		EACCES			Mandatory Access Control failure
740  *	file_socket:ENOTSOCK
741  *	file_socket:EBADF
742  *	getsockaddr:ENAMETOOLONG	Filename too long
743  *	getsockaddr:EINVAL		Invalid argument
744  *	getsockaddr:ENOMEM		Not enough space
745  *	getsockaddr:EFAULT		Bad address
746  *	soconnectlock:EOPNOTSUPP
747  *	soconnectlock:EISCONN
748  *	soconnectlock:???		[depends on protocol, filters]
749  *	msleep:EINTR
750  *
751  * Imputed:	so_error		error may be set from so_error, which
752  *					may have been set by soconnectlock.
753  */
754 /* ARGSUSED */
755 int
connect(proc_ref_t p,struct connect_args * uap,int32_ref_t retval)756 connect(proc_ref_t p, struct connect_args *uap, int32_ref_t retval)
757 {
758 	__pthread_testcancel(1);
759 	return connect_nocancel(p, (struct connect_nocancel_args *)uap,
760 	           retval);
761 }
762 
763 int
connect_nocancel(proc_t p,struct connect_nocancel_args * uap,int32_ref_t retval)764 connect_nocancel(proc_t p, struct connect_nocancel_args *uap, int32_ref_t retval)
765 {
766 #pragma unused(p, retval)
767 	socket_ref_t so;
768 	struct sockaddr_storage ss;
769 	sockaddr_ref_t  sa = NULL;
770 	int error;
771 	int fd = uap->s;
772 	boolean_t dgram;
773 
774 	AUDIT_ARG(fd, uap->s);
775 	error = file_socket(fd, &so);
776 	if (error != 0) {
777 		return error;
778 	}
779 	if (so == NULL) {
780 		error = EBADF;
781 		goto out;
782 	}
783 
784 	/*
785 	 * Ask getsockaddr{_s} to not translate AF_UNSPEC to AF_INET
786 	 * if this is a datagram socket; translate for other types.
787 	 */
788 	dgram = (so->so_type == SOCK_DGRAM);
789 
790 	/* Get socket address now before we obtain socket lock */
791 	if (uap->namelen > sizeof(ss)) {
792 		error = getsockaddr(so, &sa, uap->name, uap->namelen, !dgram);
793 	} else {
794 		error = getsockaddr_s(so, &ss, uap->name, uap->namelen, !dgram);
795 		if (error == 0) {
796 			sa = SA(&ss);
797 		}
798 	}
799 	if (error != 0) {
800 		goto out;
801 	}
802 
803 	error = connectit(so, sa);
804 
805 	if (sa != NULL && sa != SA(&ss)) {
806 		free_sockaddr(sa);
807 	}
808 	if (error == ERESTART) {
809 		error = EINTR;
810 	}
811 out:
812 	file_drop(fd);
813 	return error;
814 }
815 
816 static int
connectx_nocancel(proc_ref_t p,connectx_args_ref_t uap,int_ref_t retval)817 connectx_nocancel(proc_ref_t p, connectx_args_ref_t uap, int_ref_t retval)
818 {
819 #pragma unused(p, retval)
820 	struct sockaddr_storage ss, sd;
821 	sockaddr_ref_t  src = NULL, dst = NULL;
822 	socket_ref_t so;
823 	int error, error1, fd = uap->socket;
824 	boolean_t dgram;
825 	sae_connid_t cid = SAE_CONNID_ANY;
826 	struct user32_sa_endpoints ep32;
827 	struct user64_sa_endpoints ep64;
828 	struct user_sa_endpoints ep;
829 	user_ssize_t bytes_written = 0;
830 	struct user_iovec *iovp;
831 	uio_t auio = NULL;
832 
833 	AUDIT_ARG(fd, uap->socket);
834 	error = file_socket(fd, &so);
835 	if (error != 0) {
836 		return error;
837 	}
838 	if (so == NULL) {
839 		error = EBADF;
840 		goto out;
841 	}
842 
843 	if (uap->endpoints == USER_ADDR_NULL) {
844 		error = EINVAL;
845 		goto out;
846 	}
847 
848 	if (IS_64BIT_PROCESS(p)) {
849 		error = copyin(uap->endpoints, (caddr_t)&ep64, sizeof(ep64));
850 		if (error != 0) {
851 			goto out;
852 		}
853 
854 		ep.sae_srcif = ep64.sae_srcif;
855 		ep.sae_srcaddr = (user_addr_t)ep64.sae_srcaddr;
856 		ep.sae_srcaddrlen = ep64.sae_srcaddrlen;
857 		ep.sae_dstaddr = (user_addr_t)ep64.sae_dstaddr;
858 		ep.sae_dstaddrlen = ep64.sae_dstaddrlen;
859 	} else {
860 		error = copyin(uap->endpoints, (caddr_t)&ep32, sizeof(ep32));
861 		if (error != 0) {
862 			goto out;
863 		}
864 
865 		ep.sae_srcif = ep32.sae_srcif;
866 		ep.sae_srcaddr = ep32.sae_srcaddr;
867 		ep.sae_srcaddrlen = ep32.sae_srcaddrlen;
868 		ep.sae_dstaddr = ep32.sae_dstaddr;
869 		ep.sae_dstaddrlen = ep32.sae_dstaddrlen;
870 	}
871 
872 	/*
873 	 * Ask getsockaddr{_s} to not translate AF_UNSPEC to AF_INET
874 	 * if this is a datagram socket; translate for other types.
875 	 */
876 	dgram = (so->so_type == SOCK_DGRAM);
877 
878 	/* Get socket address now before we obtain socket lock */
879 	if (ep.sae_srcaddr != USER_ADDR_NULL) {
880 		if (ep.sae_srcaddrlen > sizeof(ss)) {
881 			error = getsockaddr(so, &src, ep.sae_srcaddr, ep.sae_srcaddrlen, dgram);
882 		} else {
883 			error = getsockaddr_s(so, &ss, ep.sae_srcaddr, ep.sae_srcaddrlen, dgram);
884 			if (error == 0) {
885 				src = SA(&ss);
886 			}
887 		}
888 
889 		if (error) {
890 			goto out;
891 		}
892 	}
893 
894 	if (ep.sae_dstaddr == USER_ADDR_NULL) {
895 		error = EINVAL;
896 		goto out;
897 	}
898 
899 	/* Get socket address now before we obtain socket lock */
900 	if (ep.sae_dstaddrlen > sizeof(sd)) {
901 		error = getsockaddr(so, &dst, ep.sae_dstaddr, ep.sae_dstaddrlen, dgram);
902 	} else {
903 		error = getsockaddr_s(so, &sd, ep.sae_dstaddr, ep.sae_dstaddrlen, dgram);
904 		if (error == 0) {
905 			dst = SA(&sd);
906 		}
907 	}
908 
909 	if (error) {
910 		goto out;
911 	}
912 
913 	VERIFY(dst != NULL);
914 
915 	if (uap->iov != USER_ADDR_NULL) {
916 		/* Verify range before calling uio_create() */
917 		if (uap->iovcnt <= 0 || uap->iovcnt > UIO_MAXIOV) {
918 			error = EINVAL;
919 			goto out;
920 		}
921 
922 		if (uap->len == USER_ADDR_NULL) {
923 			error = EINVAL;
924 			goto out;
925 		}
926 
927 		/* allocate a uio to hold the number of iovecs passed */
928 		auio = uio_create(uap->iovcnt, 0,
929 		    (IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : UIO_USERSPACE32),
930 		    UIO_WRITE);
931 
932 		if (auio == NULL) {
933 			error = ENOMEM;
934 			goto out;
935 		}
936 
937 		/*
938 		 * get location of iovecs within the uio.
939 		 * then copyin the iovecs from user space.
940 		 */
941 		iovp = uio_iovsaddr_user(auio);
942 		if (iovp == NULL) {
943 			error = ENOMEM;
944 			goto out;
945 		}
946 		error = copyin_user_iovec_array(uap->iov,
947 		    IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : UIO_USERSPACE32,
948 		    uap->iovcnt, iovp);
949 		if (error != 0) {
950 			goto out;
951 		}
952 
953 		/* finish setup of uio_t */
954 		error = uio_calculateresid_user(auio);
955 		if (error != 0) {
956 			goto out;
957 		}
958 	}
959 
960 	error = connectitx(so, src, dst, p, ep.sae_srcif, uap->associd,
961 	    &cid, auio, uap->flags, &bytes_written);
962 	if (error == ERESTART) {
963 		error = EINTR;
964 	}
965 
966 	if (uap->len != USER_ADDR_NULL) {
967 		if (IS_64BIT_PROCESS(p)) {
968 			error1 = copyout(&bytes_written, uap->len, sizeof(user64_size_t));
969 		} else {
970 			error1 = copyout(&bytes_written, uap->len, sizeof(user32_size_t));
971 		}
972 		/* give precedence to connectitx errors */
973 		if ((error1 != 0) && (error == 0)) {
974 			error = error1;
975 		}
976 	}
977 
978 	if (uap->connid != USER_ADDR_NULL) {
979 		error1 = copyout(&cid, uap->connid, sizeof(cid));
980 		/* give precedence to connectitx errors */
981 		if ((error1 != 0) && (error == 0)) {
982 			error = error1;
983 		}
984 	}
985 out:
986 	file_drop(fd);
987 	if (auio != NULL) {
988 		uio_free(auio);
989 	}
990 	if (src != NULL && src != SA(&ss)) {
991 		free_sockaddr(src);
992 	}
993 	if (dst != NULL && dst != SA(&sd)) {
994 		free_sockaddr(dst);
995 	}
996 	return error;
997 }
998 
999 int
connectx(proc_ref_t p,struct connectx_args * uap,int * retval)1000 connectx(proc_ref_t p, struct connectx_args *uap, int *retval)
1001 {
1002 	/*
1003 	 * Due to similiarity with a POSIX interface, define as
1004 	 * an unofficial cancellation point.
1005 	 */
1006 	__pthread_testcancel(1);
1007 	return connectx_nocancel(p, uap, retval);
1008 }
1009 
1010 static int
connectit(struct socket * so,sockaddr_ref_t sa)1011 connectit(struct socket *so, sockaddr_ref_t sa)
1012 {
1013 	int error;
1014 
1015 	AUDIT_ARG(sockaddr, vfs_context_cwd(vfs_context_current()), sa);
1016 #if CONFIG_MACF_SOCKET_SUBSET
1017 	if ((error = mac_socket_check_connect(kauth_cred_get(), so, sa)) != 0) {
1018 		return error;
1019 	}
1020 #endif /* MAC_SOCKET_SUBSET */
1021 
1022 	socket_lock(so, 1);
1023 	if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
1024 		error = EALREADY;
1025 		goto out;
1026 	}
1027 	error = soconnectlock(so, sa, 0);
1028 	if (error != 0) {
1029 		goto out;
1030 	}
1031 	if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
1032 		error = EINPROGRESS;
1033 		goto out;
1034 	}
1035 	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
1036 		lck_mtx_t *mutex_held;
1037 
1038 		if (so->so_proto->pr_getlock != NULL) {
1039 			mutex_held = (*so->so_proto->pr_getlock)(so, PR_F_WILLUNLOCK);
1040 		} else {
1041 			mutex_held = so->so_proto->pr_domain->dom_mtx;
1042 		}
1043 		error = msleep((caddr_t)&so->so_timeo, mutex_held,
1044 		    PSOCK | PCATCH, __func__, 0);
1045 		if (so->so_state & SS_DRAINING) {
1046 			error = ECONNABORTED;
1047 		}
1048 		if (error != 0) {
1049 			break;
1050 		}
1051 	}
1052 	if (error == 0) {
1053 		error = so->so_error;
1054 		so->so_error = 0;
1055 	}
1056 out:
1057 	socket_unlock(so, 1);
1058 	return error;
1059 }
1060 
1061 static int
connectitx(struct socket * so,sockaddr_ref_t src,sockaddr_ref_t dst,proc_ref_t p,uint32_t ifscope,sae_associd_t aid,sae_connid_t * pcid,uio_t auio,unsigned int flags,user_ssize_t * bytes_written)1062 connectitx(struct socket *so, sockaddr_ref_t src,
1063     sockaddr_ref_t dst, proc_ref_t p, uint32_t ifscope,
1064     sae_associd_t aid, sae_connid_t *pcid, uio_t auio, unsigned int flags,
1065     user_ssize_t *bytes_written)
1066 {
1067 	int error;
1068 
1069 	VERIFY(dst != NULL);
1070 
1071 	AUDIT_ARG(sockaddr, vfs_context_cwd(vfs_context_current()), dst);
1072 #if CONFIG_MACF_SOCKET_SUBSET
1073 	if ((error = mac_socket_check_connect(kauth_cred_get(), so, dst)) != 0) {
1074 		return error;
1075 	}
1076 
1077 	if (auio != NULL) {
1078 		if ((error = mac_socket_check_send(kauth_cred_get(), so, dst)) != 0) {
1079 			return error;
1080 		}
1081 	}
1082 #endif /* MAC_SOCKET_SUBSET */
1083 
1084 	socket_lock(so, 1);
1085 	if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
1086 		error = EALREADY;
1087 		goto out;
1088 	}
1089 
1090 	error = soconnectxlocked(so, src, dst, p, ifscope,
1091 	    aid, pcid, flags, NULL, 0, auio, bytes_written);
1092 	if (error != 0) {
1093 		goto out;
1094 	}
1095 	/*
1096 	 * If, after the call to soconnectxlocked the flag is still set (in case
1097 	 * data has been queued and the connect() has actually been triggered,
1098 	 * it will have been unset by the transport), we exit immediately. There
1099 	 * is no reason to wait on any event.
1100 	 */
1101 	if (so->so_flags1 & SOF1_PRECONNECT_DATA) {
1102 		error = 0;
1103 		goto out;
1104 	}
1105 	if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
1106 		error = EINPROGRESS;
1107 		goto out;
1108 	}
1109 	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
1110 		lck_mtx_t *mutex_held;
1111 
1112 		if (so->so_proto->pr_getlock != NULL) {
1113 			mutex_held = (*so->so_proto->pr_getlock)(so, PR_F_WILLUNLOCK);
1114 		} else {
1115 			mutex_held = so->so_proto->pr_domain->dom_mtx;
1116 		}
1117 		error = msleep((caddr_t)&so->so_timeo, mutex_held,
1118 		    PSOCK | PCATCH, __func__, 0);
1119 		if (so->so_state & SS_DRAINING) {
1120 			error = ECONNABORTED;
1121 		}
1122 		if (error != 0) {
1123 			break;
1124 		}
1125 	}
1126 	if (error == 0) {
1127 		error = so->so_error;
1128 		so->so_error = 0;
1129 	}
1130 out:
1131 	socket_unlock(so, 1);
1132 	return error;
1133 }
1134 
1135 int
peeloff(proc_ref_t p,struct peeloff_args * uap,int * retval)1136 peeloff(proc_ref_t p, struct peeloff_args *uap, int *retval)
1137 {
1138 #pragma unused(p, uap, retval)
1139 	/*
1140 	 * Due to similiarity with a POSIX interface, define as
1141 	 * an unofficial cancellation point.
1142 	 */
1143 	__pthread_testcancel(1);
1144 	return 0;
1145 }
1146 
1147 int
disconnectx(proc_ref_t p,struct disconnectx_args * uap,int * retval)1148 disconnectx(proc_ref_t p, struct disconnectx_args *uap, int *retval)
1149 {
1150 	/*
1151 	 * Due to similiarity with a POSIX interface, define as
1152 	 * an unofficial cancellation point.
1153 	 */
1154 	__pthread_testcancel(1);
1155 	return disconnectx_nocancel(p, uap, retval);
1156 }
1157 
1158 static int
disconnectx_nocancel(proc_ref_t p,struct disconnectx_args * uap,int * retval)1159 disconnectx_nocancel(proc_ref_t p, struct disconnectx_args *uap, int *retval)
1160 {
1161 #pragma unused(p, retval)
1162 	socket_ref_t so;
1163 	int fd = uap->s;
1164 	int error;
1165 
1166 	error = file_socket(fd, &so);
1167 	if (error != 0) {
1168 		return error;
1169 	}
1170 	if (so == NULL) {
1171 		error = EBADF;
1172 		goto out;
1173 	}
1174 
1175 	error = sodisconnectx(so, uap->aid, uap->cid);
1176 out:
1177 	file_drop(fd);
1178 	return error;
1179 }
1180 
1181 /*
1182  * Returns:	0			Success
1183  *	socreate:EAFNOSUPPORT
1184  *	socreate:EPROTOTYPE
1185  *	socreate:EPROTONOSUPPORT
1186  *	socreate:ENOBUFS
1187  *	socreate:ENOMEM
1188  *	socreate:EISCONN
1189  *	socreate:???			[other protocol families, IPSEC]
1190  *	falloc:ENFILE
1191  *	falloc:EMFILE
1192  *	falloc:ENOMEM
1193  *	copyout:EFAULT
1194  *	soconnect2:EINVAL
1195  *	soconnect2:EPROTOTYPE
1196  *	soconnect2:???			[other protocol families[
1197  */
1198 int
socketpair(proc_ref_t p,struct socketpair_args * uap,__unused int32_ref_t retval)1199 socketpair(proc_ref_t p, struct socketpair_args *uap,
1200     __unused int32_ref_t retval)
1201 {
1202 	fileproc_ref_t  fp1, fp2;
1203 	socket_ref_t so1, so2;
1204 	int fd, error, sv[2];
1205 
1206 	AUDIT_ARG(socket, uap->domain, uap->type, uap->protocol);
1207 	error = socreate(uap->domain, &so1, uap->type, uap->protocol);
1208 	if (error) {
1209 		return error;
1210 	}
1211 	error = socreate(uap->domain, &so2, uap->type, uap->protocol);
1212 	if (error) {
1213 		goto free1;
1214 	}
1215 
1216 	error = falloc(p, &fp1, &fd);
1217 	if (error) {
1218 		goto free2;
1219 	}
1220 	fp1->f_flag = FREAD | FWRITE;
1221 	fp1->f_ops = &socketops;
1222 	fp_set_data(fp1, so1);
1223 	sv[0] = fd;
1224 
1225 	error = falloc(p, &fp2, &fd);
1226 	if (error) {
1227 		goto free3;
1228 	}
1229 	fp2->f_flag = FREAD | FWRITE;
1230 	fp2->f_ops = &socketops;
1231 	fp_set_data(fp2, so2);
1232 	sv[1] = fd;
1233 
1234 	error = soconnect2(so1, so2);
1235 	if (error) {
1236 		goto free4;
1237 	}
1238 	if (uap->type == SOCK_DGRAM) {
1239 		/*
1240 		 * Datagram socket connection is asymmetric.
1241 		 */
1242 		error = soconnect2(so2, so1);
1243 		if (error) {
1244 			goto free4;
1245 		}
1246 	}
1247 
1248 	if ((error = copyout(sv, uap->rsv, 2 * sizeof(int))) != 0) {
1249 		goto free4;
1250 	}
1251 
1252 	proc_fdlock(p);
1253 	procfdtbl_releasefd(p, sv[0], NULL);
1254 	procfdtbl_releasefd(p, sv[1], NULL);
1255 	fp_drop(p, sv[0], fp1, 1);
1256 	fp_drop(p, sv[1], fp2, 1);
1257 	proc_fdunlock(p);
1258 
1259 	return 0;
1260 free4:
1261 	fp_free(p, sv[1], fp2);
1262 free3:
1263 	fp_free(p, sv[0], fp1);
1264 free2:
1265 	(void) soclose(so2);
1266 free1:
1267 	(void) soclose(so1);
1268 	return error;
1269 }
1270 
1271 /*
1272  * Returns:	0			Success
1273  *		EINVAL
1274  *		ENOBUFS
1275  *		EBADF
1276  *		EPIPE
1277  *		EACCES			Mandatory Access Control failure
1278  *	file_socket:ENOTSOCK
1279  *	file_socket:EBADF
1280  *	getsockaddr:ENAMETOOLONG	Filename too long
1281  *	getsockaddr:EINVAL		Invalid argument
1282  *	getsockaddr:ENOMEM		Not enough space
1283  *	getsockaddr:EFAULT		Bad address
1284  *	<pru_sosend>:EACCES[TCP]
1285  *	<pru_sosend>:EADDRINUSE[TCP]
1286  *	<pru_sosend>:EADDRNOTAVAIL[TCP]
1287  *	<pru_sosend>:EAFNOSUPPORT[TCP]
1288  *	<pru_sosend>:EAGAIN[TCP]
1289  *	<pru_sosend>:EBADF
1290  *	<pru_sosend>:ECONNRESET[TCP]
1291  *	<pru_sosend>:EFAULT
1292  *	<pru_sosend>:EHOSTUNREACH[TCP]
1293  *	<pru_sosend>:EINTR
1294  *	<pru_sosend>:EINVAL
1295  *	<pru_sosend>:EISCONN[AF_INET]
1296  *	<pru_sosend>:EMSGSIZE[TCP]
1297  *	<pru_sosend>:ENETDOWN[TCP]
1298  *	<pru_sosend>:ENETUNREACH[TCP]
1299  *	<pru_sosend>:ENOBUFS
1300  *	<pru_sosend>:ENOMEM[TCP]
1301  *	<pru_sosend>:ENOTCONN[AF_INET]
1302  *	<pru_sosend>:EOPNOTSUPP
1303  *	<pru_sosend>:EPERM[TCP]
1304  *	<pru_sosend>:EPIPE
1305  *	<pru_sosend>:EWOULDBLOCK
1306  *	<pru_sosend>:???[TCP]		[ignorable: mostly IPSEC/firewall/DLIL]
1307  *	<pru_sosend>:???[AF_INET]	[whatever a filter author chooses]
1308  *	<pru_sosend>:???		[value from so_error]
1309  *	sockargs:???
1310  */
1311 static int
sendit(proc_ref_t p,struct socket * so,user_msghdr_ref_t mp,uio_t uiop,int flags,int32_ref_t retval)1312 sendit(proc_ref_t p, struct socket *so, user_msghdr_ref_t mp, uio_t uiop,
1313     int flags, int32_ref_t retval)
1314 {
1315 	mbuf_ref_t  control = NULL;
1316 	struct sockaddr_storage ss;
1317 	sockaddr_ref_t  to = NULL;
1318 	boolean_t want_free = TRUE;
1319 	int error;
1320 	user_ssize_t len;
1321 
1322 	KERNEL_DEBUG(DBG_FNC_SENDIT | DBG_FUNC_START, 0, 0, 0, 0, 0);
1323 
1324 	if (mp->msg_name != USER_ADDR_NULL) {
1325 		if (mp->msg_namelen > sizeof(ss)) {
1326 			error = getsockaddr(so, &to, mp->msg_name,
1327 			    mp->msg_namelen, TRUE);
1328 		} else {
1329 			error = getsockaddr_s(so, &ss, mp->msg_name,
1330 			    mp->msg_namelen, TRUE);
1331 			if (error == 0) {
1332 				to = SA(&ss);
1333 				want_free = FALSE;
1334 			}
1335 		}
1336 		if (error != 0) {
1337 			goto out;
1338 		}
1339 		AUDIT_ARG(sockaddr, vfs_context_cwd(vfs_context_current()), to);
1340 	}
1341 	if (mp->msg_control != USER_ADDR_NULL) {
1342 		if (mp->msg_controllen < sizeof(struct cmsghdr)) {
1343 			error = EINVAL;
1344 			goto bad;
1345 		}
1346 		error = sockargs(&control, mp->msg_control,
1347 		    mp->msg_controllen, MT_CONTROL);
1348 		if (error != 0) {
1349 			goto bad;
1350 		}
1351 	}
1352 
1353 #if CONFIG_MACF_SOCKET_SUBSET
1354 	/*
1355 	 * We check the state without holding the socket lock;
1356 	 * if a race condition occurs, it would simply result
1357 	 * in an extra call to the MAC check function.
1358 	 */
1359 	if (to != NULL &&
1360 	    !(so->so_state & SS_DEFUNCT) &&
1361 	    (error = mac_socket_check_send(kauth_cred_get(), so, to)) != 0) {
1362 		if (control != NULL) {
1363 			m_freem(control);
1364 		}
1365 
1366 		goto bad;
1367 	}
1368 #endif /* MAC_SOCKET_SUBSET */
1369 
1370 	len = uio_resid(uiop);
1371 	error = so->so_proto->pr_usrreqs->pru_sosend(so, to, uiop, 0,
1372 	    control, flags);
1373 	if (error != 0) {
1374 		if (uio_resid(uiop) != len && (error == ERESTART ||
1375 		    error == EINTR || error == EWOULDBLOCK)) {
1376 			error = 0;
1377 		}
1378 		/* Generation of SIGPIPE can be controlled per socket */
1379 		if (error == EPIPE && !(so->so_flags & SOF_NOSIGPIPE) &&
1380 		    !(flags & MSG_NOSIGNAL)) {
1381 			psignal(p, SIGPIPE);
1382 		}
1383 	}
1384 	if (error == 0) {
1385 		*retval = (int)(len - uio_resid(uiop));
1386 	}
1387 bad:
1388 	if (want_free) {
1389 		free_sockaddr(to);
1390 	}
1391 out:
1392 	KERNEL_DEBUG(DBG_FNC_SENDIT | DBG_FUNC_END, error, 0, 0, 0, 0);
1393 
1394 	return error;
1395 }
1396 
1397 /*
1398  * Returns:	0			Success
1399  *		ENOMEM
1400  *	sendit:???			[see sendit definition in this file]
1401  *	write:???			[4056224: applicable for pipes]
1402  */
1403 int
sendto(proc_ref_t p,struct sendto_args * uap,int32_ref_t retval)1404 sendto(proc_ref_t p, struct sendto_args *uap, int32_ref_t retval)
1405 {
1406 	__pthread_testcancel(1);
1407 	return sendto_nocancel(p, (struct sendto_nocancel_args *)uap, retval);
1408 }
1409 
1410 int
sendto_nocancel(proc_ref_t p,struct sendto_nocancel_args * uap,int32_ref_t retval)1411 sendto_nocancel(proc_ref_t p,
1412     struct sendto_nocancel_args *uap,
1413     int32_ref_t retval)
1414 {
1415 	struct user_msghdr msg;
1416 	int error;
1417 	uio_t auio = NULL;
1418 	socket_ref_t so;
1419 
1420 	KERNEL_DEBUG(DBG_FNC_SENDTO | DBG_FUNC_START, 0, 0, 0, 0, 0);
1421 	AUDIT_ARG(fd, uap->s);
1422 
1423 	if (uap->flags & MSG_SKIPCFIL) {
1424 		error = EPERM;
1425 		goto done;
1426 	}
1427 
1428 	if (uap->len > LONG_MAX) {
1429 		error = EINVAL;
1430 		goto done;
1431 	}
1432 
1433 	auio = uio_create(1, 0,
1434 	    (IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : UIO_USERSPACE32),
1435 	    UIO_WRITE);
1436 	if (auio == NULL) {
1437 		error = ENOMEM;
1438 		goto done;
1439 	}
1440 	uio_addiov(auio, uap->buf, uap->len);
1441 
1442 	msg.msg_name = uap->to;
1443 	msg.msg_namelen = uap->tolen;
1444 	/* no need to set up msg_iov.  sendit uses uio_t we send it */
1445 	msg.msg_iov = 0;
1446 	msg.msg_iovlen = 0;
1447 	msg.msg_control = 0;
1448 	msg.msg_flags = 0;
1449 
1450 	error = file_socket(uap->s, &so);
1451 	if (error) {
1452 		goto done;
1453 	}
1454 
1455 	if (so == NULL) {
1456 		error = EBADF;
1457 	} else {
1458 		error = sendit(p, so, &msg, auio, uap->flags, retval);
1459 	}
1460 
1461 	file_drop(uap->s);
1462 done:
1463 	if (auio != NULL) {
1464 		uio_free(auio);
1465 	}
1466 
1467 	KERNEL_DEBUG(DBG_FNC_SENDTO | DBG_FUNC_END, error, *retval, 0, 0, 0);
1468 
1469 	return error;
1470 }
1471 
1472 /*
1473  * Returns:	0			Success
1474  *		ENOBUFS
1475  *	copyin:EFAULT
1476  *	sendit:???			[see sendit definition in this file]
1477  */
1478 int
sendmsg(proc_ref_t p,struct sendmsg_args * uap,int32_ref_t retval)1479 sendmsg(proc_ref_t p, struct sendmsg_args *uap, int32_ref_t retval)
1480 {
1481 	__pthread_testcancel(1);
1482 	return sendmsg_nocancel(p, (struct sendmsg_nocancel_args *)uap,
1483 	           retval);
1484 }
1485 
1486 int
sendmsg_nocancel(proc_ref_t p,struct sendmsg_nocancel_args * uap,int32_ref_t retval)1487 sendmsg_nocancel(proc_ref_t p, struct sendmsg_nocancel_args *uap,
1488     int32_ref_t retval)
1489 {
1490 	struct user32_msghdr msg32;
1491 	struct user64_msghdr msg64;
1492 	struct user_msghdr user_msg;
1493 	caddr_t msghdrp;
1494 	int     size_of_msghdr;
1495 	int error;
1496 	uio_t auio = NULL;
1497 	struct user_iovec *iovp;
1498 	socket_ref_t so;
1499 
1500 	const bool is_p_64bit_process = IS_64BIT_PROCESS(p);
1501 
1502 	KERNEL_DEBUG(DBG_FNC_SENDMSG | DBG_FUNC_START, 0, 0, 0, 0, 0);
1503 	AUDIT_ARG(fd, uap->s);
1504 
1505 	if (uap->flags & MSG_SKIPCFIL) {
1506 		error = EPERM;
1507 		goto done;
1508 	}
1509 
1510 	if (is_p_64bit_process) {
1511 		msghdrp = (caddr_t)&msg64;
1512 		size_of_msghdr = sizeof(msg64);
1513 	} else {
1514 		msghdrp = (caddr_t)&msg32;
1515 		size_of_msghdr = sizeof(msg32);
1516 	}
1517 	error = copyin(uap->msg, msghdrp, size_of_msghdr);
1518 	if (error) {
1519 		KERNEL_DEBUG(DBG_FNC_SENDMSG | DBG_FUNC_END, error, 0, 0, 0, 0);
1520 		return error;
1521 	}
1522 
1523 	if (is_p_64bit_process) {
1524 		user_msg.msg_flags = msg64.msg_flags;
1525 		user_msg.msg_controllen = msg64.msg_controllen;
1526 		user_msg.msg_control = (user_addr_t)msg64.msg_control;
1527 		user_msg.msg_iovlen = msg64.msg_iovlen;
1528 		user_msg.msg_iov = (user_addr_t)msg64.msg_iov;
1529 		user_msg.msg_namelen = msg64.msg_namelen;
1530 		user_msg.msg_name = (user_addr_t)msg64.msg_name;
1531 	} else {
1532 		user_msg.msg_flags = msg32.msg_flags;
1533 		user_msg.msg_controllen = msg32.msg_controllen;
1534 		user_msg.msg_control = msg32.msg_control;
1535 		user_msg.msg_iovlen = msg32.msg_iovlen;
1536 		user_msg.msg_iov = msg32.msg_iov;
1537 		user_msg.msg_namelen = msg32.msg_namelen;
1538 		user_msg.msg_name = msg32.msg_name;
1539 	}
1540 
1541 	if (user_msg.msg_iovlen <= 0 || user_msg.msg_iovlen > UIO_MAXIOV) {
1542 		KERNEL_DEBUG(DBG_FNC_SENDMSG | DBG_FUNC_END, EMSGSIZE,
1543 		    0, 0, 0, 0);
1544 		return EMSGSIZE;
1545 	}
1546 
1547 	/* allocate a uio large enough to hold the number of iovecs passed */
1548 	auio = uio_create(user_msg.msg_iovlen, 0,
1549 	    (is_p_64bit_process ? UIO_USERSPACE64 : UIO_USERSPACE32),
1550 	    UIO_WRITE);
1551 	if (auio == NULL) {
1552 		error = ENOBUFS;
1553 		goto done;
1554 	}
1555 
1556 	if (user_msg.msg_iovlen) {
1557 		/*
1558 		 * get location of iovecs within the uio.
1559 		 * then copyin the iovecs from user space.
1560 		 */
1561 		iovp = uio_iovsaddr_user(auio);
1562 		if (iovp == NULL) {
1563 			error = ENOBUFS;
1564 			goto done;
1565 		}
1566 		error = copyin_user_iovec_array(user_msg.msg_iov,
1567 		    is_p_64bit_process ? UIO_USERSPACE64 : UIO_USERSPACE32,
1568 		    user_msg.msg_iovlen, iovp);
1569 		if (error) {
1570 			goto done;
1571 		}
1572 		user_msg.msg_iov = CAST_USER_ADDR_T(iovp);
1573 
1574 		/* finish setup of uio_t */
1575 		error = uio_calculateresid_user(auio);
1576 		if (error) {
1577 			goto done;
1578 		}
1579 	} else {
1580 		user_msg.msg_iov = 0;
1581 	}
1582 
1583 	/* msg_flags is ignored for send */
1584 	user_msg.msg_flags = 0;
1585 
1586 	error = file_socket(uap->s, &so);
1587 	if (error) {
1588 		goto done;
1589 	}
1590 	if (so == NULL) {
1591 		error = EBADF;
1592 	} else {
1593 		error = sendit(p, so, &user_msg, auio, uap->flags, retval);
1594 	}
1595 	file_drop(uap->s);
1596 done:
1597 	if (auio != NULL) {
1598 		uio_free(auio);
1599 	}
1600 	KERNEL_DEBUG(DBG_FNC_SENDMSG | DBG_FUNC_END, error, 0, 0, 0, 0);
1601 
1602 	return error;
1603 }
1604 
1605 static int
internalize_user_msg_x(struct user_msghdr * user_msg,uio_t * auiop,proc_ref_t p,void_ptr_t user_msghdr_x_src)1606 internalize_user_msg_x(struct user_msghdr *user_msg, uio_t *auiop, proc_ref_t p, void_ptr_t user_msghdr_x_src)
1607 {
1608 	const bool is_p_64bit_process = IS_64BIT_PROCESS(p);
1609 	uio_t auio = *auiop;
1610 	int error;
1611 
1612 	if (is_p_64bit_process) {
1613 		struct user64_msghdr_x msghdrx64;
1614 
1615 		error = copyin((user_addr_t)user_msghdr_x_src,
1616 		    &msghdrx64, sizeof(msghdrx64));
1617 		if (error != 0) {
1618 			DBG_PRINTF("%s copyin() msghdrx64 failed %d",
1619 			    __func__, error);
1620 			goto done;
1621 		}
1622 		user_msg->msg_name = msghdrx64.msg_name;
1623 		user_msg->msg_namelen = msghdrx64.msg_namelen;
1624 		user_msg->msg_iov = msghdrx64.msg_iov;
1625 		user_msg->msg_iovlen = msghdrx64.msg_iovlen;
1626 		user_msg->msg_control = msghdrx64.msg_control;
1627 		user_msg->msg_controllen = msghdrx64.msg_controllen;
1628 	} else {
1629 		struct user32_msghdr_x msghdrx32;
1630 
1631 		error = copyin((user_addr_t)user_msghdr_x_src,
1632 		    &msghdrx32, sizeof(msghdrx32));
1633 		if (error != 0) {
1634 			DBG_PRINTF("%s copyin() msghdrx32 failed %d",
1635 			    __func__, error);
1636 			goto done;
1637 		}
1638 		user_msg->msg_name = msghdrx32.msg_name;
1639 		user_msg->msg_namelen = msghdrx32.msg_namelen;
1640 		user_msg->msg_iov = msghdrx32.msg_iov;
1641 		user_msg->msg_iovlen = msghdrx32.msg_iovlen;
1642 		user_msg->msg_control = msghdrx32.msg_control;
1643 		user_msg->msg_controllen = msghdrx32.msg_controllen;
1644 	}
1645 	/* msg_flags is ignored for send */
1646 	user_msg->msg_flags = 0;
1647 
1648 	if (user_msg->msg_iovlen <= 0 || user_msg->msg_iovlen > UIO_MAXIOV) {
1649 		error = EMSGSIZE;
1650 		DBG_PRINTF("%s bad msg_iovlen, error %d",
1651 		    __func__, error);
1652 		goto done;
1653 	}
1654 	/*
1655 	 * Attempt to reuse the uio if large enough, otherwise we need
1656 	 * a new one
1657 	 */
1658 	if (auio != NULL) {
1659 		if (auio->uio_max_iovs >= user_msg->msg_iovlen) {
1660 			uio_reset_fast(auio, 0,
1661 			    is_p_64bit_process ? UIO_USERSPACE64 : UIO_USERSPACE32,
1662 			    UIO_WRITE);
1663 		} else {
1664 			uio_free(auio);
1665 			auio = NULL;
1666 		}
1667 	}
1668 	if (auio == NULL) {
1669 		auio = uio_create(user_msg->msg_iovlen, 0,
1670 		    is_p_64bit_process ? UIO_USERSPACE64 : UIO_USERSPACE32,
1671 		    UIO_WRITE);
1672 		if (auio == NULL) {
1673 			error = ENOBUFS;
1674 			DBG_PRINTF("%s uio_create() failed %d",
1675 			    __func__, error);
1676 			goto done;
1677 		}
1678 	}
1679 
1680 	if (user_msg->msg_iovlen) {
1681 		/*
1682 		 * get location of iovecs within the uio.
1683 		 * then copyin the iovecs from user space.
1684 		 */
1685 		struct user_iovec *iovp = uio_iovsaddr_user(auio);
1686 		if (iovp == NULL) {
1687 			error = ENOBUFS;
1688 			goto done;
1689 		}
1690 		error = copyin_user_iovec_array(user_msg->msg_iov,
1691 		    is_p_64bit_process ? UIO_USERSPACE64 : UIO_USERSPACE32,
1692 		    user_msg->msg_iovlen, iovp);
1693 		if (error != 0) {
1694 			goto done;
1695 		}
1696 		user_msg->msg_iov = CAST_USER_ADDR_T(iovp);
1697 
1698 		/* finish setup of uio_t */
1699 		error = uio_calculateresid_user(auio);
1700 		if (error) {
1701 			goto done;
1702 		}
1703 	} else {
1704 		user_msg->msg_iov = 0;
1705 	}
1706 
1707 done:
1708 	*auiop = auio;
1709 	return error;
1710 }
1711 
1712 static int
mbuf_packet_from_uio(socket_ref_t so,mbuf_ref_ref_t mp,uio_t auio)1713 mbuf_packet_from_uio(socket_ref_t so, mbuf_ref_ref_t mp, uio_t auio)
1714 {
1715 	int error = 0;
1716 	uint16_t headroom = 0;
1717 	size_t bytes_to_alloc;
1718 	mbuf_ref_t top = NULL, m;
1719 
1720 	if (soreserveheadroom != 0) {
1721 		headroom = so->so_pktheadroom;
1722 	}
1723 	bytes_to_alloc = headroom + uio_resid(auio);
1724 
1725 	error = mbuf_allocpacket(MBUF_WAITOK, bytes_to_alloc, NULL, &top);
1726 	if (error != 0) {
1727 		os_log(OS_LOG_DEFAULT, "mbuf_packet_from_uio: mbuf_allocpacket %zu error %d",
1728 		    bytes_to_alloc, error);
1729 		goto done;
1730 	}
1731 
1732 	if (headroom > 0 && headroom < mbuf_maxlen(top)) {
1733 		top->m_data += headroom;
1734 	}
1735 
1736 	for (m = top; m != NULL; m = m->m_next) {
1737 		int bytes_to_copy = (int)uio_resid(auio);
1738 		ssize_t mlen;
1739 
1740 		if ((m->m_flags & M_EXT)) {
1741 			mlen = m->m_ext.ext_size -
1742 			    M_LEADINGSPACE(m);
1743 		} else if ((m->m_flags & M_PKTHDR)) {
1744 			mlen = MHLEN - M_LEADINGSPACE(m);
1745 			m_add_crumb(m, PKT_CRUMB_SOSEND);
1746 		} else {
1747 			mlen = MLEN - M_LEADINGSPACE(m);
1748 		}
1749 		int len = imin((int)mlen, bytes_to_copy);
1750 
1751 		error = uio_copyin_user(mtod(m, caddr_t), (int)len, auio);
1752 		if (error != 0) {
1753 			os_log(OS_LOG_DEFAULT, "mbuf_packet_from_uio: len %d error %d",
1754 			    len, error);
1755 			goto done;
1756 		}
1757 		m->m_len = len;
1758 		top->m_pkthdr.len += len;
1759 	}
1760 
1761 done:
1762 	if (error != 0) {
1763 		m_freem(top);
1764 	} else {
1765 		*mp = top;
1766 	}
1767 	return error;
1768 }
1769 
1770 static int
sendit_x(proc_ref_t p,socket_ref_t so,struct sendmsg_x_args * uap,u_int * retval)1771 sendit_x(proc_ref_t p, socket_ref_t so, struct sendmsg_x_args *uap, u_int *retval)
1772 {
1773 	int error = 0;
1774 	UIO_STACKBUF(uio_buf, UIO_SMALLIOV);
1775 	uio_t __single auio;
1776 	const bool is_p_64bit_process = IS_64BIT_PROCESS(p);
1777 	void *src;
1778 	MBUFQ_HEAD() pktlist = {};
1779 	size_t total_pkt_len = 0;
1780 	u_int pkt_cnt = 0;
1781 	int flags = uap->flags;
1782 	mbuf_ref_t top;
1783 
1784 	MBUFQ_INIT(&pktlist);
1785 
1786 	*retval = 0;
1787 
1788 	/* We re-use the uio when possible */
1789 	auio = uio_createwithbuffer(UIO_SMALLIOV, 0,
1790 	    (is_p_64bit_process ? UIO_USERSPACE64 : UIO_USERSPACE32),
1791 	    UIO_WRITE, &uio_buf[0],
1792 	    UIO_SIZEOF(UIO_SMALLIOV));
1793 
1794 	src = __unsafe_forge_bidi_indexable(void *, uap->msgp, uap->cnt);
1795 
1796 	/*
1797 	 * Create a list of packets
1798 	 */
1799 	for (u_int i = 0; i < uap->cnt; i++) {
1800 		struct user_msghdr user_msg = {};
1801 		mbuf_ref_t m = NULL;
1802 
1803 		if (is_p_64bit_process) {
1804 			error = internalize_user_msg_x(&user_msg, &auio, p, ((struct user64_msghdr_x *)src) + i);
1805 			if (error != 0) {
1806 				os_log(OS_LOG_DEFAULT, "sendit_x: internalize_user_msg_x error %d\n", error);
1807 				goto done;
1808 			}
1809 		} else {
1810 			error = internalize_user_msg_x(&user_msg, &auio, p, ((struct user32_msghdr_x *)src) + i);
1811 			if (error != 0) {
1812 				os_log(OS_LOG_DEFAULT, "sendit_x: internalize_user_msg_x error %d\n", error);
1813 				goto done;
1814 			}
1815 		}
1816 		/*
1817 		 * Stop on the first datagram that is too large
1818 		 */
1819 		if (uio_resid(auio) > so->so_snd.sb_hiwat) {
1820 			if (i == 0) {
1821 				error = EMSGSIZE;
1822 				goto done;
1823 			}
1824 			break;
1825 		}
1826 		/*
1827 		 * An mbuf packet has the control mbuf(s) followed by data
1828 		 * We allocate the mbufs in reverse order
1829 		 */
1830 		error = mbuf_packet_from_uio(so, &m, auio);
1831 		if (error != 0) {
1832 			os_log(OS_LOG_DEFAULT, "sendit_x: mbuf_packet_from_uio error %d\n", error);
1833 			goto done;
1834 		}
1835 		total_pkt_len += m->m_pkthdr.len;
1836 
1837 		if (user_msg.msg_control != USER_ADDR_NULL && user_msg.msg_controllen != 0) {
1838 			mbuf_ref_t control = NULL;
1839 
1840 			error = sockargs(&control, user_msg.msg_control, user_msg.msg_controllen, MT_CONTROL);
1841 			if (error != 0) {
1842 				os_log(OS_LOG_DEFAULT, "sendit_x: sockargs error %d\n", error);
1843 				goto done;
1844 			}
1845 			control->m_next = m;
1846 			m = control;
1847 		}
1848 		MBUFQ_ENQUEUE(&pktlist, m);
1849 
1850 		pkt_cnt += 1;
1851 	}
1852 
1853 	top = MBUFQ_FIRST(&pktlist);
1854 	MBUFQ_INIT(&pktlist);
1855 	error = sosend_list(so, top, total_pkt_len, &pkt_cnt, flags);
1856 	if (error != 0 && error != ENOBUFS) {
1857 		os_log(OS_LOG_DEFAULT, "sendit_x: sosend_list error %d\n", error);
1858 	}
1859 done:
1860 	*retval = pkt_cnt;
1861 
1862 	if (auio != NULL) {
1863 		uio_free(auio);
1864 	}
1865 	MBUFQ_DRAIN(&pktlist);
1866 	return error;
1867 }
1868 
1869 int
sendmsg_x(proc_ref_t p,struct sendmsg_x_args * uap,user_ssize_t * retval)1870 sendmsg_x(proc_ref_t p, struct sendmsg_x_args *uap, user_ssize_t *retval)
1871 {
1872 	void *src;
1873 	int error;
1874 	uio_t __single auio = NULL;
1875 	socket_ref_t so;
1876 	u_int uiocnt = 0;
1877 	const bool is_p_64bit_process = IS_64BIT_PROCESS(p);
1878 
1879 	KERNEL_DEBUG(DBG_FNC_SENDMSG_X | DBG_FUNC_START, 0, 0, 0, 0, 0);
1880 	AUDIT_ARG(fd, uap->s);
1881 
1882 	if (uap->flags & MSG_SKIPCFIL) {
1883 		error = EPERM;
1884 		goto done_no_filedrop;
1885 	}
1886 
1887 	error = file_socket(uap->s, &so);
1888 	if (error) {
1889 		goto done_no_filedrop;
1890 	}
1891 	if (so == NULL) {
1892 		error = EBADF;
1893 		goto done;
1894 	}
1895 
1896 	/*
1897 	 * For an atomic datagram connected socket we can build the list of
1898 	 * mbuf packets with sosend_list()
1899 	 */
1900 	if (so->so_type == SOCK_DGRAM && sosendallatonce(so) &&
1901 	    (so->so_state & SS_ISCONNECTED) && sendmsg_x_mode != 1) {
1902 		error = sendit_x(p, so, uap, &uiocnt);
1903 		if (error != 0) {
1904 			DBG_PRINTF("%s sendit_x() failed %d",
1905 			    __func__, error);
1906 		}
1907 		goto done;
1908 	}
1909 
1910 	src = __unsafe_forge_bidi_indexable(void *, uap->msgp, uap->cnt);
1911 
1912 	/* We re-use the uio when possible */
1913 	auio = uio_create(1, 0,
1914 	    (is_p_64bit_process ? UIO_USERSPACE64 : UIO_USERSPACE32),
1915 	    UIO_WRITE);
1916 	if (auio == NULL) {
1917 		error = ENOBUFS;
1918 		DBG_PRINTF("%s uio_create() failed %d",
1919 		    __func__, error);
1920 		goto done;
1921 	}
1922 
1923 	for (u_int i = 0; i < uap->cnt; i++) {
1924 		struct user_msghdr user_msg = {};
1925 
1926 		if (is_p_64bit_process) {
1927 			error = internalize_user_msg_x(&user_msg, &auio, p, ((struct user64_msghdr_x *)src) + i);
1928 			if (error != 0) {
1929 				goto done;
1930 			}
1931 		} else {
1932 			error = internalize_user_msg_x(&user_msg, &auio, p, ((struct user32_msghdr_x *)src) + i);
1933 			if (error != 0) {
1934 				goto done;
1935 			}
1936 		}
1937 
1938 		int32_t len = 0;
1939 		error = sendit(p, so, &user_msg, auio, uap->flags, &len);
1940 		if (error != 0) {
1941 			break;
1942 		}
1943 		uiocnt += 1;
1944 	}
1945 done:
1946 	if (error != 0) {
1947 		if (uiocnt != 0 && (error == ERESTART ||
1948 		    error == EINTR || error == EWOULDBLOCK ||
1949 		    error == ENOBUFS || error == EMSGSIZE)) {
1950 			error = 0;
1951 		}
1952 		/* Generation of SIGPIPE can be controlled per socket */
1953 		if (error == EPIPE && !(so->so_flags & SOF_NOSIGPIPE) &&
1954 		    !(uap->flags & MSG_NOSIGNAL)) {
1955 			psignal(p, SIGPIPE);
1956 		}
1957 	}
1958 	if (error == 0) {
1959 		*retval = (int)(uiocnt);
1960 	}
1961 	file_drop(uap->s);
1962 
1963 done_no_filedrop:
1964 	if (auio != NULL) {
1965 		uio_free(auio);
1966 	}
1967 	KERNEL_DEBUG(DBG_FNC_SENDMSG_X | DBG_FUNC_END, error, 0, 0, 0, 0);
1968 
1969 	return error;
1970 }
1971 
1972 
1973 static int
copyout_sa(sockaddr_ref_t fromsa,user_addr_t name,socklen_t * namelen)1974 copyout_sa(sockaddr_ref_t fromsa, user_addr_t name, socklen_t *namelen)
1975 {
1976 	int error = 0;
1977 	socklen_t sa_len = 0;
1978 	ssize_t len;
1979 
1980 	len = *namelen;
1981 	if (len <= 0 || fromsa == 0) {
1982 		len = 0;
1983 	} else {
1984 #ifndef MIN
1985 #define MIN(a, b) ((a) > (b) ? (b) : (a))
1986 #endif
1987 		sa_len = fromsa->sa_len;
1988 		len = MIN((unsigned int)len, sa_len);
1989 		error = copyout(__SA_UTILS_CONV_TO_BYTES(fromsa), name, (unsigned)len);
1990 		if (error) {
1991 			goto out;
1992 		}
1993 	}
1994 	*namelen = sa_len;
1995 out:
1996 	return 0;
1997 }
1998 
1999 static int
copyout_maddr(struct mbuf * m,user_addr_t name,socklen_t * namelen)2000 copyout_maddr(struct mbuf *m, user_addr_t name, socklen_t *namelen)
2001 {
2002 	int error = 0;
2003 	socklen_t sa_len = 0;
2004 	ssize_t len;
2005 
2006 	len = *namelen;
2007 	if (len <= 0 || m == NULL) {
2008 		len = 0;
2009 	} else {
2010 #ifndef MIN
2011 #define MIN(a, b) ((a) > (b) ? (b) : (a))
2012 #endif
2013 		struct sockaddr *fromsa = mtod(m, struct sockaddr *);
2014 
2015 		sa_len = fromsa->sa_len;
2016 		len = MIN((unsigned int)len, sa_len);
2017 		error = copyout(fromsa, name, (unsigned)len);
2018 		if (error != 0) {
2019 			goto out;
2020 		}
2021 	}
2022 	*namelen = sa_len;
2023 out:
2024 	return 0;
2025 }
2026 
2027 static int
copyout_control(proc_ref_t p,mbuf_ref_t m,user_addr_t control,socklen_ref_t controllen,int_ref_t flags,socket_ref_t so)2028 copyout_control(proc_ref_t p, mbuf_ref_t m, user_addr_t control,
2029     socklen_ref_t controllen, int_ref_t flags, socket_ref_t so)
2030 {
2031 	int error = 0;
2032 	socklen_t len;
2033 	user_addr_t ctlbuf;
2034 	struct inpcb *inp = NULL;
2035 	bool want_pktinfo = false;
2036 	bool seen_pktinfo = false;
2037 
2038 	if (so != NULL && (SOCK_DOM(so) == PF_INET6 || SOCK_DOM(so) == PF_INET)) {
2039 		inp = sotoinpcb(so);
2040 		want_pktinfo = (inp->inp_flags & IN6P_PKTINFO) != 0;
2041 	}
2042 
2043 	len = *controllen;
2044 	*controllen = 0;
2045 	ctlbuf = control;
2046 
2047 	while (m && len > 0) {
2048 		socklen_t tocopy;
2049 		struct cmsghdr *cp = mtod(m, struct cmsghdr *);
2050 		socklen_t cp_size = CMSG_ALIGN(cp->cmsg_len);
2051 		socklen_t buflen = m->m_len;
2052 
2053 		while (buflen > 0 && len > 0) {
2054 			/*
2055 			 * SCM_TIMESTAMP hack because  struct timeval has a
2056 			 * different size for 32 bits and 64 bits processes
2057 			 */
2058 			if (cp->cmsg_level == SOL_SOCKET && cp->cmsg_type == SCM_TIMESTAMP) {
2059 				unsigned char tmp_buffer[CMSG_SPACE(sizeof(struct user64_timeval))] = {};
2060 				struct cmsghdr *tmp_cp = (struct cmsghdr *)(void *)tmp_buffer;
2061 				socklen_t tmp_space;
2062 				struct timeval *tv = (struct timeval *)(void *)CMSG_DATA(cp);
2063 
2064 				tmp_cp->cmsg_level = SOL_SOCKET;
2065 				tmp_cp->cmsg_type = SCM_TIMESTAMP;
2066 
2067 				if (proc_is64bit(p)) {
2068 					struct user64_timeval *tv64 = (struct user64_timeval *)(void *)CMSG_DATA(tmp_cp);
2069 
2070 					os_unaligned_deref(&tv64->tv_sec) = tv->tv_sec;
2071 					os_unaligned_deref(&tv64->tv_usec) = tv->tv_usec;
2072 
2073 					tmp_cp->cmsg_len = CMSG_LEN(sizeof(struct user64_timeval));
2074 					tmp_space = CMSG_SPACE(sizeof(struct user64_timeval));
2075 				} else {
2076 					struct user32_timeval *tv32 = (struct user32_timeval *)(void *)CMSG_DATA(tmp_cp);
2077 
2078 					tv32->tv_sec = (user32_time_t)tv->tv_sec;
2079 					tv32->tv_usec = tv->tv_usec;
2080 
2081 					tmp_cp->cmsg_len = CMSG_LEN(sizeof(struct user32_timeval));
2082 					tmp_space = CMSG_SPACE(sizeof(struct user32_timeval));
2083 				}
2084 				if (len >= tmp_space) {
2085 					tocopy = tmp_space;
2086 				} else {
2087 					*flags |= MSG_CTRUNC;
2088 					tocopy = len;
2089 				}
2090 				error = copyout(tmp_buffer, ctlbuf, tocopy);
2091 				if (error) {
2092 					goto out;
2093 				}
2094 			} else {
2095 				/* If socket has flow tracking and socket did not request address, ignore it */
2096 				if (SOFLOW_ENABLED(so) &&
2097 				    ((cp->cmsg_level == IPPROTO_IP && cp->cmsg_type == IP_RECVDSTADDR && inp != NULL &&
2098 				    !(inp->inp_flags & INP_RECVDSTADDR)) ||
2099 				    (cp->cmsg_level == IPPROTO_IPV6 && (cp->cmsg_type == IPV6_PKTINFO || cp->cmsg_type == IPV6_2292PKTINFO) && inp &&
2100 				    !(inp->inp_flags & IN6P_PKTINFO)))) {
2101 					tocopy = 0;
2102 				} else {
2103 					if (cp_size > buflen) {
2104 						panic("cp_size > buflen, something wrong with alignment!");
2105 					}
2106 					if (len >= cp_size) {
2107 						tocopy = cp_size;
2108 					} else {
2109 						*flags |= MSG_CTRUNC;
2110 						tocopy = len;
2111 					}
2112 					error = copyout((caddr_t) cp, ctlbuf, tocopy);
2113 					if (error) {
2114 						goto out;
2115 					}
2116 					if (want_pktinfo && cp->cmsg_level == IPPROTO_IPV6 &&
2117 					    (cp->cmsg_type == IPV6_PKTINFO || cp->cmsg_type == IPV6_2292PKTINFO)) {
2118 						seen_pktinfo = true;
2119 					}
2120 				}
2121 			}
2122 
2123 
2124 			ctlbuf += tocopy;
2125 			len -= tocopy;
2126 
2127 			buflen -= cp_size;
2128 			cp = (struct cmsghdr *)(void *)
2129 			    ((unsigned char *) cp + cp_size);
2130 			cp_size = CMSG_ALIGN(cp->cmsg_len);
2131 		}
2132 
2133 		m = m->m_next;
2134 	}
2135 	*controllen = (socklen_t)(ctlbuf - control);
2136 out:
2137 	if (want_pktinfo && !seen_pktinfo) {
2138 		missingpktinfo += 1;
2139 #if (DEBUG || DEVELOPMENT)
2140 		char pname[MAXCOMLEN];
2141 		char local[MAX_IPv6_STR_LEN + 6];
2142 		char remote[MAX_IPv6_STR_LEN + 6];
2143 
2144 		proc_name(so->last_pid, pname, sizeof(MAXCOMLEN));
2145 		if (inp->inp_vflag & INP_IPV6) {
2146 			inet_ntop(AF_INET6, &inp->in6p_laddr.s6_addr, local, sizeof(local));
2147 			inet_ntop(AF_INET6, &inp->in6p_faddr.s6_addr, remote, sizeof(local));
2148 		} else {
2149 			inet_ntop(AF_INET, &inp->inp_laddr.s_addr, local, sizeof(local));
2150 			inet_ntop(AF_INET, &inp->inp_faddr.s_addr, remote, sizeof(local));
2151 		}
2152 
2153 		os_log(OS_LOG_DEFAULT,
2154 		    "cmsg IPV6_PKTINFO missing for %s:%u > %s:%u proc %s.%u error %d\n",
2155 		    local, ntohs(inp->inp_lport), remote, ntohs(inp->inp_fport),
2156 		    pname, so->last_pid, error);
2157 #endif /* (DEBUG || DEVELOPMENT) */
2158 	}
2159 	return error;
2160 }
2161 
2162 /*
2163  * Returns:	0			Success
2164  *		ENOTSOCK
2165  *		EINVAL
2166  *		EBADF
2167  *		EACCES			Mandatory Access Control failure
2168  *	copyout:EFAULT
2169  *	fp_lookup:EBADF
2170  *	<pru_soreceive>:ENOBUFS
2171  *	<pru_soreceive>:ENOTCONN
2172  *	<pru_soreceive>:EWOULDBLOCK
2173  *	<pru_soreceive>:EFAULT
2174  *	<pru_soreceive>:EINTR
2175  *	<pru_soreceive>:EBADF
2176  *	<pru_soreceive>:EINVAL
2177  *	<pru_soreceive>:EMSGSIZE
2178  *	<pru_soreceive>:???
2179  *
2180  * Notes:	Additional return values from calls through <pru_soreceive>
2181  *		depend on protocols other than TCP or AF_UNIX, which are
2182  *		documented above.
2183  */
2184 static int
recvit(proc_ref_t p,int s,user_msghdr_ref_t mp,uio_t uiop,user_addr_t namelenp,int32_ref_t retval)2185 recvit(proc_ref_t p, int s, user_msghdr_ref_t mp, uio_t uiop,
2186     user_addr_t namelenp, int32_ref_t retval)
2187 {
2188 	ssize_t len;
2189 	int error;
2190 	mbuf_ref_t  control = 0;
2191 	socket_ref_t so;
2192 	sockaddr_ref_t  fromsa = 0;
2193 	fileproc_ref_t  fp;
2194 
2195 	KERNEL_DEBUG(DBG_FNC_RECVIT | DBG_FUNC_START, 0, 0, 0, 0, 0);
2196 	if ((error = fp_get_ftype(p, s, DTYPE_SOCKET, ENOTSOCK, &fp))) {
2197 		KERNEL_DEBUG(DBG_FNC_RECVIT | DBG_FUNC_END, error, 0, 0, 0, 0);
2198 		return error;
2199 	}
2200 	so = (struct socket *)fp_get_data(fp);
2201 
2202 #if CONFIG_MACF_SOCKET_SUBSET
2203 	/*
2204 	 * We check the state without holding the socket lock;
2205 	 * if a race condition occurs, it would simply result
2206 	 * in an extra call to the MAC check function.
2207 	 */
2208 	if (!(so->so_state & SS_DEFUNCT) &&
2209 	    !(so->so_state & SS_ISCONNECTED) &&
2210 	    !(so->so_proto->pr_flags & PR_CONNREQUIRED) &&
2211 	    (error = mac_socket_check_receive(kauth_cred_get(), so)) != 0) {
2212 		goto out1;
2213 	}
2214 #endif /* MAC_SOCKET_SUBSET */
2215 	if (uio_resid(uiop) < 0 || uio_resid(uiop) > INT_MAX) {
2216 		KERNEL_DEBUG(DBG_FNC_RECVIT | DBG_FUNC_END, EINVAL, 0, 0, 0, 0);
2217 		error = EINVAL;
2218 		goto out1;
2219 	}
2220 
2221 	len = uio_resid(uiop);
2222 	error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, uiop,
2223 	    NULL, mp->msg_control ? &control : NULL,
2224 	    &mp->msg_flags);
2225 	if (fromsa) {
2226 		AUDIT_ARG(sockaddr, vfs_context_cwd(vfs_context_current()),
2227 		    fromsa);
2228 	}
2229 	if (error) {
2230 		if (uio_resid(uiop) != len && (error == ERESTART ||
2231 		    error == EINTR || error == EWOULDBLOCK)) {
2232 			error = 0;
2233 		}
2234 	}
2235 	if (error) {
2236 		goto out;
2237 	}
2238 
2239 	*retval = (int32_t)(len - uio_resid(uiop));
2240 
2241 	if (mp->msg_name) {
2242 		error = copyout_sa(fromsa, mp->msg_name, &mp->msg_namelen);
2243 		if (error) {
2244 			goto out;
2245 		}
2246 		/* return the actual, untruncated address length */
2247 		if (namelenp &&
2248 		    (error = copyout((caddr_t)&mp->msg_namelen, namelenp,
2249 		    sizeof(int)))) {
2250 			goto out;
2251 		}
2252 	}
2253 
2254 	if (mp->msg_control) {
2255 		error = copyout_control(p, control, mp->msg_control,
2256 		    &mp->msg_controllen, &mp->msg_flags, so);
2257 	}
2258 out:
2259 	free_sockaddr(fromsa);
2260 	if (control) {
2261 		m_freem(control);
2262 	}
2263 	KERNEL_DEBUG(DBG_FNC_RECVIT | DBG_FUNC_END, error, 0, 0, 0, 0);
2264 out1:
2265 	fp_drop(p, s, fp, 0);
2266 	return error;
2267 }
2268 
2269 /*
2270  * Returns:	0			Success
2271  *		ENOMEM
2272  *	copyin:EFAULT
2273  *	recvit:???
2274  *	read:???			[4056224: applicable for pipes]
2275  *
2276  * Notes:	The read entry point is only called as part of support for
2277  *		binary backward compatability; new code should use read
2278  *		instead of recv or recvfrom when attempting to read data
2279  *		from pipes.
2280  *
2281  *		For full documentation of the return codes from recvit, see
2282  *		the block header for the recvit function.
2283  */
2284 int
recvfrom(proc_ref_t p,struct recvfrom_args * uap,int32_ref_t retval)2285 recvfrom(proc_ref_t p, struct recvfrom_args *uap, int32_ref_t retval)
2286 {
2287 	__pthread_testcancel(1);
2288 	return recvfrom_nocancel(p, (struct recvfrom_nocancel_args *)uap,
2289 	           retval);
2290 }
2291 
2292 int
recvfrom_nocancel(proc_ref_t p,struct recvfrom_nocancel_args * uap,int32_ref_t retval)2293 recvfrom_nocancel(proc_ref_t p, struct recvfrom_nocancel_args *uap,
2294     int32_ref_t retval)
2295 {
2296 	struct user_msghdr msg;
2297 	int error;
2298 	uio_t __single auio = NULL;
2299 
2300 	KERNEL_DEBUG(DBG_FNC_RECVFROM | DBG_FUNC_START, 0, 0, 0, 0, 0);
2301 	AUDIT_ARG(fd, uap->s);
2302 
2303 	if (uap->fromlenaddr) {
2304 		error = copyin(uap->fromlenaddr,
2305 		    (caddr_t)&msg.msg_namelen, sizeof(msg.msg_namelen));
2306 		if (error) {
2307 			return error;
2308 		}
2309 	} else {
2310 		msg.msg_namelen = 0;
2311 	}
2312 	msg.msg_name = uap->from;
2313 	auio = uio_create(1, 0,
2314 	    (IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : UIO_USERSPACE32),
2315 	    UIO_READ);
2316 	if (auio == NULL) {
2317 		return ENOMEM;
2318 	}
2319 
2320 	uio_addiov(auio, uap->buf, uap->len);
2321 	/* no need to set up msg_iov.  recvit uses uio_t we send it */
2322 	msg.msg_iov = 0;
2323 	msg.msg_iovlen = 0;
2324 	msg.msg_control = 0;
2325 	msg.msg_controllen = 0;
2326 	msg.msg_flags = uap->flags;
2327 	error = recvit(p, uap->s, &msg, auio, uap->fromlenaddr, retval);
2328 	if (auio != NULL) {
2329 		uio_free(auio);
2330 	}
2331 
2332 	KERNEL_DEBUG(DBG_FNC_RECVFROM | DBG_FUNC_END, error, 0, 0, 0, 0);
2333 
2334 	return error;
2335 }
2336 
2337 /*
2338  * Returns:	0			Success
2339  *		EMSGSIZE
2340  *		ENOMEM
2341  *	copyin:EFAULT
2342  *	copyout:EFAULT
2343  *	recvit:???
2344  *
2345  * Notes:	For full documentation of the return codes from recvit, see
2346  *		the block header for the recvit function.
2347  */
2348 int
recvmsg(proc_ref_t p,struct recvmsg_args * uap,int32_ref_t retval)2349 recvmsg(proc_ref_t p, struct recvmsg_args *uap, int32_ref_t retval)
2350 {
2351 	__pthread_testcancel(1);
2352 	return recvmsg_nocancel(p, (struct recvmsg_nocancel_args *)uap,
2353 	           retval);
2354 }
2355 
2356 int
recvmsg_nocancel(proc_ref_t p,struct recvmsg_nocancel_args * uap,int32_ref_t retval)2357 recvmsg_nocancel(proc_ref_t p, struct recvmsg_nocancel_args *uap,
2358     int32_ref_t retval)
2359 {
2360 	struct user32_msghdr msg32;
2361 	struct user64_msghdr msg64;
2362 	struct user_msghdr user_msg;
2363 	caddr_t msghdrp;
2364 	int     size_of_msghdr;
2365 	user_addr_t uiov;
2366 	int error;
2367 	uio_t __single auio = NULL;
2368 	struct user_iovec *iovp;
2369 
2370 	const bool is_p_64bit_process = IS_64BIT_PROCESS(p);
2371 
2372 	KERNEL_DEBUG(DBG_FNC_RECVMSG | DBG_FUNC_START, 0, 0, 0, 0, 0);
2373 	AUDIT_ARG(fd, uap->s);
2374 	if (is_p_64bit_process) {
2375 		msghdrp = (caddr_t)&msg64;
2376 		size_of_msghdr = sizeof(msg64);
2377 	} else {
2378 		msghdrp = (caddr_t)&msg32;
2379 		size_of_msghdr = sizeof(msg32);
2380 	}
2381 	error = copyin(uap->msg, msghdrp, size_of_msghdr);
2382 	if (error) {
2383 		KERNEL_DEBUG(DBG_FNC_RECVMSG | DBG_FUNC_END, error, 0, 0, 0, 0);
2384 		return error;
2385 	}
2386 
2387 	/* only need to copy if user process is not 64-bit */
2388 	if (is_p_64bit_process) {
2389 		user_msg.msg_flags = msg64.msg_flags;
2390 		user_msg.msg_controllen = msg64.msg_controllen;
2391 		user_msg.msg_control = (user_addr_t)msg64.msg_control;
2392 		user_msg.msg_iovlen = msg64.msg_iovlen;
2393 		user_msg.msg_iov = (user_addr_t)msg64.msg_iov;
2394 		user_msg.msg_namelen = msg64.msg_namelen;
2395 		user_msg.msg_name = (user_addr_t)msg64.msg_name;
2396 	} else {
2397 		user_msg.msg_flags = msg32.msg_flags;
2398 		user_msg.msg_controllen = msg32.msg_controllen;
2399 		user_msg.msg_control = msg32.msg_control;
2400 		user_msg.msg_iovlen = msg32.msg_iovlen;
2401 		user_msg.msg_iov = msg32.msg_iov;
2402 		user_msg.msg_namelen = msg32.msg_namelen;
2403 		user_msg.msg_name = msg32.msg_name;
2404 	}
2405 
2406 	if (user_msg.msg_iovlen <= 0 || user_msg.msg_iovlen > UIO_MAXIOV) {
2407 		KERNEL_DEBUG(DBG_FNC_RECVMSG | DBG_FUNC_END, EMSGSIZE,
2408 		    0, 0, 0, 0);
2409 		return EMSGSIZE;
2410 	}
2411 
2412 	user_msg.msg_flags = uap->flags;
2413 
2414 	/* allocate a uio large enough to hold the number of iovecs passed */
2415 	auio = uio_create(user_msg.msg_iovlen, 0,
2416 	    (is_p_64bit_process ? UIO_USERSPACE64 : UIO_USERSPACE32),
2417 	    UIO_READ);
2418 	if (auio == NULL) {
2419 		error = ENOMEM;
2420 		goto done;
2421 	}
2422 
2423 	/*
2424 	 * get location of iovecs within the uio.  then copyin the iovecs from
2425 	 * user space.
2426 	 */
2427 	iovp = uio_iovsaddr_user(auio);
2428 	if (iovp == NULL) {
2429 		error = ENOMEM;
2430 		goto done;
2431 	}
2432 	uiov = user_msg.msg_iov;
2433 	user_msg.msg_iov = CAST_USER_ADDR_T(iovp);
2434 	error = copyin_user_iovec_array(uiov,
2435 	    is_p_64bit_process ? UIO_USERSPACE64 : UIO_USERSPACE32,
2436 	    user_msg.msg_iovlen, iovp);
2437 	if (error) {
2438 		goto done;
2439 	}
2440 
2441 	/* finish setup of uio_t */
2442 	error = uio_calculateresid_user(auio);
2443 	if (error) {
2444 		goto done;
2445 	}
2446 
2447 	error = recvit(p, uap->s, &user_msg, auio, 0, retval);
2448 	if (!error) {
2449 		user_msg.msg_iov = uiov;
2450 		if (is_p_64bit_process) {
2451 			msg64.msg_flags = user_msg.msg_flags;
2452 			msg64.msg_controllen = user_msg.msg_controllen;
2453 			msg64.msg_control = user_msg.msg_control;
2454 			msg64.msg_iovlen = user_msg.msg_iovlen;
2455 			msg64.msg_iov = user_msg.msg_iov;
2456 			msg64.msg_namelen = user_msg.msg_namelen;
2457 			msg64.msg_name = user_msg.msg_name;
2458 		} else {
2459 			msg32.msg_flags = user_msg.msg_flags;
2460 			msg32.msg_controllen = user_msg.msg_controllen;
2461 			msg32.msg_control = (user32_addr_t)user_msg.msg_control;
2462 			msg32.msg_iovlen = user_msg.msg_iovlen;
2463 			msg32.msg_iov = (user32_addr_t)user_msg.msg_iov;
2464 			msg32.msg_namelen = user_msg.msg_namelen;
2465 			msg32.msg_name = (user32_addr_t)user_msg.msg_name;
2466 		}
2467 		error = copyout(msghdrp, uap->msg, size_of_msghdr);
2468 	}
2469 done:
2470 	if (auio != NULL) {
2471 		uio_free(auio);
2472 	}
2473 	KERNEL_DEBUG(DBG_FNC_RECVMSG | DBG_FUNC_END, error, 0, 0, 0, 0);
2474 	return error;
2475 }
2476 
2477 __attribute__((noinline))
2478 static int
recvmsg_x_array(proc_ref_t p,socket_ref_t so,struct recvmsg_x_args * uap,user_ssize_t * retval)2479 recvmsg_x_array(proc_ref_t p, socket_ref_t so, struct recvmsg_x_args *uap, user_ssize_t *retval)
2480 {
2481 	int error = EOPNOTSUPP;
2482 	user_msghdr_x_ptr_t user_msg_x = NULL;
2483 	recv_msg_elem_ptr_t recv_msg_array = NULL;
2484 	user_ssize_t len_before = 0, len_after;
2485 	size_t size_of_msghdr;
2486 	void_ptr_t umsgp = NULL;
2487 	u_int i;
2488 	u_int uiocnt;
2489 	int flags = uap->flags;
2490 
2491 	const bool is_p_64bit_process = IS_64BIT_PROCESS(p);
2492 
2493 	size_of_msghdr = is_p_64bit_process ?
2494 	    sizeof(struct user64_msghdr_x) : sizeof(struct user32_msghdr_x);
2495 
2496 	/*
2497 	 * Support only a subset of message flags
2498 	 */
2499 	if (uap->flags & ~(MSG_PEEK | MSG_WAITALL | MSG_DONTWAIT | MSG_NEEDSA |  MSG_NBIO)) {
2500 		return EOPNOTSUPP;
2501 	}
2502 	/*
2503 	 * Input parameter range check
2504 	 */
2505 	if (uap->cnt == 0 || uap->cnt > UIO_MAXIOV) {
2506 		error = EINVAL;
2507 		goto out;
2508 	}
2509 	if (uap->cnt > somaxrecvmsgx) {
2510 		uap->cnt = somaxrecvmsgx > 0 ? somaxrecvmsgx : 1;
2511 	}
2512 
2513 	user_msg_x = kalloc_type(struct user_msghdr_x, uap->cnt,
2514 	    Z_WAITOK | Z_ZERO);
2515 	if (user_msg_x == NULL) {
2516 		DBG_PRINTF("%s user_msg_x alloc failed", __func__);
2517 		error = ENOMEM;
2518 		goto out;
2519 	}
2520 	recv_msg_array = alloc_recv_msg_array(uap->cnt);
2521 	if (recv_msg_array == NULL) {
2522 		DBG_PRINTF("%s alloc_recv_msg_array() failed", __func__);
2523 		error = ENOMEM;
2524 		goto out;
2525 	}
2526 
2527 	umsgp = kalloc_data(uap->cnt * size_of_msghdr, Z_WAITOK | Z_ZERO);
2528 	if (umsgp == NULL) {
2529 		DBG_PRINTF("%s umsgp alloc failed", __func__);
2530 		error = ENOMEM;
2531 		goto out;
2532 	}
2533 	error = copyin(uap->msgp, umsgp, uap->cnt * size_of_msghdr);
2534 	if (error) {
2535 		DBG_PRINTF("%s copyin() failed", __func__);
2536 		goto out;
2537 	}
2538 	error = internalize_recv_msghdr_array(umsgp,
2539 	    is_p_64bit_process ? UIO_USERSPACE64 : UIO_USERSPACE32,
2540 	    UIO_READ, uap->cnt, user_msg_x, recv_msg_array);
2541 	if (error) {
2542 		DBG_PRINTF("%s copyin_user_msghdr_array() failed", __func__);
2543 		goto out;
2544 	}
2545 	/*
2546 	 * Make sure the size of each message iovec and
2547 	 * the aggregate size of all the iovec is valid
2548 	 */
2549 	if (recv_msg_array_is_valid(recv_msg_array, uap->cnt) == 0) {
2550 		error = EINVAL;
2551 		goto out;
2552 	}
2553 	/*
2554 	 * Sanity check on passed arguments
2555 	 */
2556 	for (i = 0; i < uap->cnt; i++) {
2557 		struct user_msghdr_x *mp = user_msg_x + i;
2558 
2559 		if (mp->msg_flags != 0) {
2560 			error = EINVAL;
2561 			goto out;
2562 		}
2563 	}
2564 #if CONFIG_MACF_SOCKET_SUBSET
2565 	/*
2566 	 * We check the state without holding the socket lock;
2567 	 * if a race condition occurs, it would simply result
2568 	 * in an extra call to the MAC check function.
2569 	 */
2570 	if (!(so->so_state & SS_DEFUNCT) &&
2571 	    !(so->so_state & SS_ISCONNECTED) &&
2572 	    !(so->so_proto->pr_flags & PR_CONNREQUIRED) &&
2573 	    (error = mac_socket_check_receive(kauth_cred_get(), so)) != 0) {
2574 		goto out;
2575 	}
2576 #endif /* MAC_SOCKET_SUBSET */
2577 
2578 	len_before = recv_msg_array_resid(recv_msg_array, uap->cnt);
2579 
2580 	for (i = 0; i < uap->cnt; i++) {
2581 		struct recv_msg_elem *recv_msg_elem;
2582 		uio_t auio;
2583 		sockaddr_ref_ref_t psa;
2584 		struct mbuf **controlp;
2585 
2586 		recv_msg_elem = recv_msg_array + i;
2587 		auio = recv_msg_elem->uio;
2588 
2589 		/*
2590 		 * Do not block if we got at least one packet
2591 		 */
2592 		if (i > 0) {
2593 			flags |= MSG_DONTWAIT;
2594 		}
2595 
2596 		psa = (recv_msg_elem->which & SOCK_MSG_SA) ?
2597 		    &recv_msg_elem->psa : NULL;
2598 		controlp = (recv_msg_elem->which & SOCK_MSG_CONTROL) ?
2599 		    &recv_msg_elem->controlp : NULL;
2600 
2601 		error = so->so_proto->pr_usrreqs->pru_soreceive(so, psa,
2602 		    auio, NULL, controlp, &flags);
2603 		if (error) {
2604 			break;
2605 		}
2606 		/*
2607 		 * We have some data
2608 		 */
2609 		recv_msg_elem->which |= SOCK_MSG_DATA;
2610 		/*
2611 		 * Set the messages flags for this packet
2612 		 */
2613 		flags &= ~MSG_DONTWAIT;
2614 		recv_msg_elem->flags = flags;
2615 		/*
2616 		 * Stop on partial copy
2617 		 */
2618 		if (recv_msg_elem->flags & (MSG_RCVMORE | MSG_TRUNC)) {
2619 			break;
2620 		}
2621 	}
2622 
2623 	len_after = recv_msg_array_resid(recv_msg_array, uap->cnt);
2624 
2625 	if (error) {
2626 		if (len_after != len_before && (error == ERESTART ||
2627 		    error == EINTR || error == EWOULDBLOCK)) {
2628 			error = 0;
2629 		} else {
2630 			goto out;
2631 		}
2632 	}
2633 
2634 	uiocnt = externalize_recv_msghdr_array(p, so, umsgp,
2635 	    uap->cnt, user_msg_x, recv_msg_array, &error);
2636 	if (error != 0) {
2637 		goto out;
2638 	}
2639 
2640 	error = copyout(umsgp, uap->msgp, uap->cnt * size_of_msghdr);
2641 	if (error) {
2642 		DBG_PRINTF("%s copyout() failed", __func__);
2643 		goto out;
2644 	}
2645 	*retval = (int)(uiocnt);
2646 
2647 out:
2648 	kfree_data(umsgp, uap->cnt * size_of_msghdr);
2649 	free_recv_msg_array(recv_msg_array, uap->cnt);
2650 	kfree_type(struct user_msghdr_x, uap->cnt, user_msg_x);
2651 
2652 	return error;
2653 }
2654 
2655 int
recvmsg_x(struct proc * p,struct recvmsg_x_args * uap,user_ssize_t * retval)2656 recvmsg_x(struct proc *p, struct recvmsg_x_args *uap, user_ssize_t *retval)
2657 {
2658 	int error = EOPNOTSUPP;
2659 	socket_ref_t so;
2660 	size_t size_of_msghdrx;
2661 	caddr_t msghdrxp;
2662 	struct user32_msghdr_x msghdrx32 = {};
2663 	struct user64_msghdr_x msghdrx64 = {};
2664 	int spacetype;
2665 	u_int i;
2666 	uio_t auio = NULL;
2667 	caddr_t src;
2668 	int flags;
2669 	mbuf_ref_t pkt_list = NULL, m;
2670 	mbuf_ref_t addr_list = NULL, m_addr;
2671 	mbuf_ref_t ctl_list = NULL, control;
2672 	u_int pktcnt;
2673 
2674 	KERNEL_DEBUG(DBG_FNC_RECVMSG_X | DBG_FUNC_START, 0, 0, 0, 0, 0);
2675 
2676 	error = file_socket(uap->s, &so);
2677 	if (error) {
2678 		goto done_no_filedrop;
2679 	}
2680 	if (so == NULL) {
2681 		error = EBADF;
2682 		goto done;
2683 	}
2684 
2685 #if CONFIG_MACF_SOCKET_SUBSET
2686 	/*
2687 	 * We check the state without holding the socket lock;
2688 	 * if a race condition occurs, it would simply result
2689 	 * in an extra call to the MAC check function.
2690 	 */
2691 	if (!(so->so_state & SS_DEFUNCT) &&
2692 	    !(so->so_state & SS_ISCONNECTED) &&
2693 	    !(so->so_proto->pr_flags & PR_CONNREQUIRED) &&
2694 	    (error = mac_socket_check_receive(kauth_cred_get(), so)) != 0) {
2695 		goto done;
2696 	}
2697 #endif /* MAC_SOCKET_SUBSET */
2698 
2699 	/*
2700 	 * With soreceive_m_list, all packets must be uniform, with address and
2701 	 * control as they are returned in parallel lists and it's only guaranteed
2702 	 * when pru_send_list is supported
2703 	 */
2704 	if (do_recvmsg_x_donttrunc != 0 || (so->so_options & SO_DONTTRUNC)) {
2705 		error = recvmsg_x_array(p, so, uap, retval);
2706 		goto done;
2707 	}
2708 
2709 	/*
2710 	 * Input parameter range check
2711 	 */
2712 	if (uap->cnt == 0 || uap->cnt > UIO_MAXIOV) {
2713 		error = EINVAL;
2714 		goto done;
2715 	}
2716 	if (uap->cnt > somaxrecvmsgx) {
2717 		uap->cnt = somaxrecvmsgx > 0 ? somaxrecvmsgx : 1;
2718 	}
2719 
2720 	if (IS_64BIT_PROCESS(p)) {
2721 		msghdrxp = (caddr_t)&msghdrx64;
2722 		size_of_msghdrx = sizeof(struct user64_msghdr_x);
2723 		spacetype = UIO_USERSPACE64;
2724 	} else {
2725 		msghdrxp = (caddr_t)&msghdrx32;
2726 		size_of_msghdrx = sizeof(struct user32_msghdr_x);
2727 		spacetype = UIO_USERSPACE32;
2728 	}
2729 	src = __unsafe_forge_bidi_indexable(caddr_t, uap->msgp, uap->cnt);
2730 
2731 	flags = uap->flags;
2732 
2733 	/*
2734 	 * Only allow MSG_DONTWAIT
2735 	 */
2736 	if ((flags & ~(MSG_DONTWAIT | MSG_NBIO)) != 0) {
2737 		error = EINVAL;
2738 		goto done;
2739 	}
2740 
2741 	/*
2742 	 * Receive list of packet in a single call
2743 	 */
2744 	pktcnt = uap->cnt;
2745 	error = soreceive_m_list(so, &pktcnt, &addr_list, &pkt_list, &ctl_list,
2746 	    &flags);
2747 	if (error != 0) {
2748 		if (pktcnt != 0 && (error == ERESTART ||
2749 		    error == EINTR || error == EWOULDBLOCK)) {
2750 			error = 0;
2751 		} else {
2752 			goto done;
2753 		}
2754 	}
2755 
2756 	m_addr = addr_list;
2757 	m = pkt_list;
2758 	control = ctl_list;
2759 
2760 	for (i = 0; i < pktcnt; i++) {
2761 		struct user_msghdr user_msg;
2762 		ssize_t len;
2763 		struct user_iovec *iovp;
2764 		struct mbuf *n;
2765 
2766 		if (!m_has_mtype(m, MTF_DATA | MTF_HEADER | MTF_OOBDATA)) {
2767 			panic("%s: m %p m_type %d != MT_DATA", __func__, m, m->m_type);
2768 		}
2769 
2770 		error = copyin((user_addr_t)(src + i * size_of_msghdrx),
2771 		    msghdrxp, size_of_msghdrx);
2772 		if (error) {
2773 			DBG_PRINTF("%s copyin() msghdrx failed %d\n",
2774 			    __func__, error);
2775 			goto done;
2776 		}
2777 		if (spacetype == UIO_USERSPACE64) {
2778 			user_msg.msg_name = msghdrx64.msg_name;
2779 			user_msg.msg_namelen = msghdrx64.msg_namelen;
2780 			user_msg.msg_iov = msghdrx64.msg_iov;
2781 			user_msg.msg_iovlen = msghdrx64.msg_iovlen;
2782 			user_msg.msg_control = msghdrx64.msg_control;
2783 			user_msg.msg_controllen = msghdrx64.msg_controllen;
2784 		} else {
2785 			user_msg.msg_name = msghdrx32.msg_name;
2786 			user_msg.msg_namelen = msghdrx32.msg_namelen;
2787 			user_msg.msg_iov = msghdrx32.msg_iov;
2788 			user_msg.msg_iovlen = msghdrx32.msg_iovlen;
2789 			user_msg.msg_control = msghdrx32.msg_control;
2790 			user_msg.msg_controllen = msghdrx32.msg_controllen;
2791 		}
2792 		user_msg.msg_flags = 0;
2793 		if (user_msg.msg_iovlen <= 0 ||
2794 		    user_msg.msg_iovlen > UIO_MAXIOV) {
2795 			error = EMSGSIZE;
2796 			DBG_PRINTF("%s bad msg_iovlen, error %d\n",
2797 			    __func__, error);
2798 			goto done;
2799 		}
2800 		/*
2801 		 * Attempt to reuse the uio if large enough, otherwise we need
2802 		 * a new one
2803 		 */
2804 		if (auio != NULL) {
2805 			if (auio->uio_max_iovs <= user_msg.msg_iovlen) {
2806 				uio_reset_fast(auio, 0, spacetype, UIO_READ);
2807 			} else {
2808 				uio_free(auio);
2809 				auio = NULL;
2810 			}
2811 		}
2812 		if (auio == NULL) {
2813 			auio = uio_create(user_msg.msg_iovlen, 0, spacetype,
2814 			    UIO_READ);
2815 			if (auio == NULL) {
2816 				error = ENOBUFS;
2817 				DBG_PRINTF("%s uio_create() failed %d\n",
2818 				    __func__, error);
2819 				goto done;
2820 			}
2821 		}
2822 		/*
2823 		 * get location of iovecs within the uio then copy the iovecs
2824 		 * from user space.
2825 		 */
2826 		iovp = uio_iovsaddr_user(auio);
2827 		if (iovp == NULL) {
2828 			error = ENOMEM;
2829 			DBG_PRINTF("%s uio_iovsaddr() failed %d\n",
2830 			    __func__, error);
2831 			goto done;
2832 		}
2833 		error = copyin_user_iovec_array(user_msg.msg_iov,
2834 		    spacetype, user_msg.msg_iovlen, iovp);
2835 		if (error != 0) {
2836 			DBG_PRINTF("%s copyin_user_iovec_array() failed %d\n",
2837 			    __func__, error);
2838 			goto done;
2839 		}
2840 		error = uio_calculateresid_user(auio);
2841 		if (error != 0) {
2842 			DBG_PRINTF("%s uio_calculateresid() failed %d\n",
2843 			    __func__, error);
2844 			goto done;
2845 		}
2846 		user_msg.msg_iov = CAST_USER_ADDR_T(iovp);
2847 
2848 		len = uio_resid(auio);
2849 		for (n = m; n != NULL; n = n->m_next) {
2850 			user_ssize_t resid = uio_resid(auio);
2851 			if (resid < n->m_len) {
2852 				error = uio_copyout_user(mtod(n, caddr_t), (int)n->m_len, auio);
2853 				if (error != 0) {
2854 					DBG_PRINTF("%s uiomove() failed\n",
2855 					    __func__);
2856 					goto done;
2857 				}
2858 				flags |= MSG_TRUNC;
2859 				break;
2860 			}
2861 
2862 			error = uio_copyout_user(mtod(n, caddr_t), (int)n->m_len, auio);
2863 			if (error != 0) {
2864 				DBG_PRINTF("%s uiomove() failed\n",
2865 				    __func__);
2866 				goto done;
2867 			}
2868 		}
2869 		len -= uio_resid(auio);
2870 
2871 		if (user_msg.msg_name != 0 && user_msg.msg_namelen != 0) {
2872 			error = copyout_maddr(m_addr, user_msg.msg_name,
2873 			    &user_msg.msg_namelen);
2874 			if (error) {
2875 				DBG_PRINTF("%s copyout_maddr()  failed\n",
2876 				    __func__);
2877 				goto done;
2878 			}
2879 		}
2880 		if (user_msg.msg_control != 0 && user_msg.msg_controllen != 0) {
2881 			error = copyout_control(p, control,
2882 			    user_msg.msg_control, &user_msg.msg_controllen,
2883 			    &user_msg.msg_flags, so);
2884 			if (error) {
2885 				DBG_PRINTF("%s copyout_control() failed\n",
2886 				    __func__);
2887 				goto done;
2888 			}
2889 		}
2890 		/*
2891 		 * Note: the original msg_iovlen and msg_iov do not change
2892 		 */
2893 		if (spacetype == UIO_USERSPACE64) {
2894 			msghdrx64.msg_flags = user_msg.msg_flags;
2895 			msghdrx64.msg_controllen = user_msg.msg_controllen;
2896 			msghdrx64.msg_control = user_msg.msg_control;
2897 			msghdrx64.msg_namelen = user_msg.msg_namelen;
2898 			msghdrx64.msg_name = user_msg.msg_name;
2899 			msghdrx64.msg_datalen = len;
2900 		} else {
2901 			msghdrx32.msg_flags = user_msg.msg_flags;
2902 			msghdrx32.msg_controllen = user_msg.msg_controllen;
2903 			msghdrx32.msg_control = (user32_addr_t) user_msg.msg_control;
2904 			msghdrx32.msg_name = user_msg.msg_namelen;
2905 			msghdrx32.msg_name = (user32_addr_t) user_msg.msg_name;
2906 			msghdrx32.msg_datalen = (user32_size_t) len;
2907 		}
2908 		error = copyout(msghdrxp,
2909 		    (user_addr_t)(src + i * size_of_msghdrx),
2910 		    size_of_msghdrx);
2911 		if (error) {
2912 			DBG_PRINTF("%s copyout() msghdrx failed\n", __func__);
2913 			goto done;
2914 		}
2915 
2916 		m = m->m_nextpkt;
2917 		if (control != NULL) {
2918 			control = control->m_nextpkt;
2919 		}
2920 		if (m_addr != NULL) {
2921 			m_addr = m_addr->m_nextpkt;
2922 		}
2923 	}
2924 
2925 	uap->flags = flags;
2926 
2927 	*retval = (int)i;
2928 done:
2929 	file_drop(uap->s);
2930 
2931 done_no_filedrop:
2932 	if (pkt_list != NULL) {
2933 		m_freem_list(pkt_list);
2934 	}
2935 	if (addr_list != NULL) {
2936 		m_freem_list(addr_list);
2937 	}
2938 	if (ctl_list != NULL) {
2939 		m_freem_list(ctl_list);
2940 	}
2941 	if (auio != NULL) {
2942 		uio_free(auio);
2943 	}
2944 
2945 	KERNEL_DEBUG(DBG_FNC_RECVMSG_X | DBG_FUNC_END, error, 0, 0, 0, 0);
2946 
2947 	return error;
2948 }
2949 
2950 /*
2951  * Returns:	0			Success
2952  *		EBADF
2953  *	file_socket:ENOTSOCK
2954  *	file_socket:EBADF
2955  *	soshutdown:EINVAL
2956  *	soshutdown:ENOTCONN
2957  *	soshutdown:EADDRNOTAVAIL[TCP]
2958  *	soshutdown:ENOBUFS[TCP]
2959  *	soshutdown:EMSGSIZE[TCP]
2960  *	soshutdown:EHOSTUNREACH[TCP]
2961  *	soshutdown:ENETUNREACH[TCP]
2962  *	soshutdown:ENETDOWN[TCP]
2963  *	soshutdown:ENOMEM[TCP]
2964  *	soshutdown:EACCES[TCP]
2965  *	soshutdown:EMSGSIZE[TCP]
2966  *	soshutdown:ENOBUFS[TCP]
2967  *	soshutdown:???[TCP]		[ignorable: mostly IPSEC/firewall/DLIL]
2968  *	soshutdown:???			[other protocol families]
2969  */
2970 /* ARGSUSED */
2971 int
shutdown(__unused proc_ref_t p,struct shutdown_args * uap,__unused int32_ref_t retval)2972 shutdown(__unused proc_ref_t p, struct shutdown_args *uap,
2973     __unused int32_ref_t retval)
2974 {
2975 	socket_ref_t so;
2976 	int error;
2977 
2978 	AUDIT_ARG(fd, uap->s);
2979 	error = file_socket(uap->s, &so);
2980 	if (error) {
2981 		return error;
2982 	}
2983 	if (so == NULL) {
2984 		error = EBADF;
2985 		goto out;
2986 	}
2987 	error =  soshutdown((struct socket *)so, uap->how);
2988 out:
2989 	file_drop(uap->s);
2990 	return error;
2991 }
2992 
2993 /*
2994  * Returns:	0			Success
2995  *		EFAULT
2996  *		EINVAL
2997  *		EACCES			Mandatory Access Control failure
2998  *	file_socket:ENOTSOCK
2999  *	file_socket:EBADF
3000  *	sosetopt:EINVAL
3001  *	sosetopt:ENOPROTOOPT
3002  *	sosetopt:ENOBUFS
3003  *	sosetopt:EDOM
3004  *	sosetopt:EFAULT
3005  *	sosetopt:EOPNOTSUPP[AF_UNIX]
3006  *	sosetopt:???
3007  */
3008 /* ARGSUSED */
3009 int
setsockopt(proc_ref_t p,setsockopt_args_ref_t uap,__unused int32_ref_t retval)3010 setsockopt(proc_ref_t p, setsockopt_args_ref_t uap,
3011     __unused int32_ref_t retval)
3012 {
3013 	socket_ref_t so;
3014 	struct sockopt sopt;
3015 	int error;
3016 
3017 	AUDIT_ARG(fd, uap->s);
3018 	if (uap->val == 0 && uap->valsize != 0) {
3019 		return EFAULT;
3020 	}
3021 	/* No bounds checking on size (it's unsigned) */
3022 
3023 	error = file_socket(uap->s, &so);
3024 	if (error) {
3025 		return error;
3026 	}
3027 
3028 	sopt.sopt_dir = SOPT_SET;
3029 	sopt.sopt_level = uap->level;
3030 	sopt.sopt_name = uap->name;
3031 	sopt.sopt_val = uap->val;
3032 	sopt.sopt_valsize = uap->valsize;
3033 	sopt.sopt_p = p;
3034 
3035 	if (so == NULL) {
3036 		error = EINVAL;
3037 		goto out;
3038 	}
3039 #if CONFIG_MACF_SOCKET_SUBSET
3040 	if ((error = mac_socket_check_setsockopt(kauth_cred_get(), so,
3041 	    &sopt)) != 0) {
3042 		goto out;
3043 	}
3044 #endif /* MAC_SOCKET_SUBSET */
3045 	error = sosetoptlock(so, &sopt, 1);     /* will lock socket */
3046 out:
3047 	file_drop(uap->s);
3048 	return error;
3049 }
3050 
3051 /*
3052  * Returns:	0			Success
3053  *		EINVAL
3054  *		EBADF
3055  *		EACCES			Mandatory Access Control failure
3056  *	copyin:EFAULT
3057  *	copyout:EFAULT
3058  *	file_socket:ENOTSOCK
3059  *	file_socket:EBADF
3060  *	sogetopt:???
3061  */
3062 int
getsockopt(proc_ref_t p,struct getsockopt_args * uap,__unused int32_ref_t retval)3063 getsockopt(proc_ref_t p, struct getsockopt_args  *uap,
3064     __unused int32_ref_t retval)
3065 {
3066 	int             error;
3067 	socklen_t       valsize;
3068 	struct sockopt  sopt;
3069 	socket_ref_t so;
3070 
3071 	error = file_socket(uap->s, &so);
3072 	if (error) {
3073 		return error;
3074 	}
3075 	if (uap->val) {
3076 		error = copyin(uap->avalsize, (caddr_t)&valsize,
3077 		    sizeof(valsize));
3078 		if (error) {
3079 			goto out;
3080 		}
3081 		/* No bounds checking on size (it's unsigned) */
3082 	} else {
3083 		valsize = 0;
3084 	}
3085 	sopt.sopt_dir = SOPT_GET;
3086 	sopt.sopt_level = uap->level;
3087 	sopt.sopt_name = uap->name;
3088 	sopt.sopt_val = uap->val;
3089 	sopt.sopt_valsize = (size_t)valsize; /* checked non-negative above */
3090 	sopt.sopt_p = p;
3091 
3092 	if (so == NULL) {
3093 		error = EBADF;
3094 		goto out;
3095 	}
3096 #if CONFIG_MACF_SOCKET_SUBSET
3097 	if ((error = mac_socket_check_getsockopt(kauth_cred_get(), so,
3098 	    &sopt)) != 0) {
3099 		goto out;
3100 	}
3101 #endif /* MAC_SOCKET_SUBSET */
3102 	error = sogetoptlock((struct socket *)so, &sopt, 1);    /* will lock */
3103 	if (error == 0) {
3104 		valsize = (socklen_t)sopt.sopt_valsize;
3105 		error = copyout((caddr_t)&valsize, uap->avalsize,
3106 		    sizeof(valsize));
3107 	}
3108 out:
3109 	file_drop(uap->s);
3110 	return error;
3111 }
3112 
3113 
3114 /*
3115  * Get socket name.
3116  *
3117  * Returns:	0			Success
3118  *		EBADF
3119  *	file_socket:ENOTSOCK
3120  *	file_socket:EBADF
3121  *	copyin:EFAULT
3122  *	copyout:EFAULT
3123  *	<pru_sockaddr>:ENOBUFS[TCP]
3124  *	<pru_sockaddr>:ECONNRESET[TCP]
3125  *	<pru_sockaddr>:EINVAL[AF_UNIX]
3126  *	<sf_getsockname>:???
3127  */
3128 /* ARGSUSED */
3129 int
getsockname(__unused proc_ref_t p,struct getsockname_args * uap,__unused int32_ref_t retval)3130 getsockname(__unused proc_ref_t p, struct getsockname_args *uap,
3131     __unused int32_ref_t retval)
3132 {
3133 	socket_ref_t so;
3134 	sockaddr_ref_t  sa;
3135 	socklen_t len;
3136 	socklen_t sa_len;
3137 	int error;
3138 
3139 	error = file_socket(uap->fdes, &so);
3140 	if (error) {
3141 		return error;
3142 	}
3143 	error = copyin(uap->alen, (caddr_t)&len, sizeof(socklen_t));
3144 	if (error) {
3145 		goto out;
3146 	}
3147 	if (so == NULL) {
3148 		error = EBADF;
3149 		goto out;
3150 	}
3151 	sa = 0;
3152 	socket_lock(so, 1);
3153 	error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, &sa);
3154 	if (error == 0) {
3155 		error = sflt_getsockname(so, &sa);
3156 		if (error == EJUSTRETURN) {
3157 			error = 0;
3158 		}
3159 	}
3160 	socket_unlock(so, 1);
3161 	if (error) {
3162 		goto bad;
3163 	}
3164 	if (sa == 0) {
3165 		len = 0;
3166 		goto gotnothing;
3167 	}
3168 
3169 	sa_len = sa->sa_len;
3170 	len = MIN(len, sa_len);
3171 	error = copyout(__SA_UTILS_CONV_TO_BYTES(sa), uap->asa, len);
3172 	if (error) {
3173 		goto bad;
3174 	}
3175 	/* return the actual, untruncated address length */
3176 	len = sa_len;
3177 gotnothing:
3178 	error = copyout((caddr_t)&len, uap->alen, sizeof(socklen_t));
3179 bad:
3180 	free_sockaddr(sa);
3181 out:
3182 	file_drop(uap->fdes);
3183 	return error;
3184 }
3185 
3186 /*
3187  * Get name of peer for connected socket.
3188  *
3189  * Returns:	0			Success
3190  *		EBADF
3191  *		EINVAL
3192  *		ENOTCONN
3193  *	file_socket:ENOTSOCK
3194  *	file_socket:EBADF
3195  *	copyin:EFAULT
3196  *	copyout:EFAULT
3197  *	<pru_peeraddr>:???
3198  *	<sf_getpeername>:???
3199  */
3200 /* ARGSUSED */
3201 int
getpeername(__unused proc_ref_t p,struct getpeername_args * uap,__unused int32_ref_t retval)3202 getpeername(__unused proc_ref_t p, struct getpeername_args *uap,
3203     __unused int32_ref_t retval)
3204 {
3205 	socket_ref_t so;
3206 	sockaddr_ref_t  sa;
3207 	socklen_t len;
3208 	socklen_t sa_len;
3209 	int error;
3210 
3211 	error = file_socket(uap->fdes, &so);
3212 	if (error) {
3213 		return error;
3214 	}
3215 	if (so == NULL) {
3216 		error = EBADF;
3217 		goto out;
3218 	}
3219 
3220 	socket_lock(so, 1);
3221 
3222 	if ((so->so_state & (SS_CANTRCVMORE | SS_CANTSENDMORE)) ==
3223 	    (SS_CANTRCVMORE | SS_CANTSENDMORE)) {
3224 		/* the socket has been shutdown, no more getpeername's */
3225 		socket_unlock(so, 1);
3226 		error = EINVAL;
3227 		goto out;
3228 	}
3229 
3230 	if ((so->so_state & (SS_ISCONNECTED | SS_ISCONFIRMING)) == 0) {
3231 		socket_unlock(so, 1);
3232 		error = ENOTCONN;
3233 		goto out;
3234 	}
3235 	error = copyin(uap->alen, (caddr_t)&len, sizeof(socklen_t));
3236 	if (error) {
3237 		socket_unlock(so, 1);
3238 		goto out;
3239 	}
3240 	sa = 0;
3241 	error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, &sa);
3242 	if (error == 0) {
3243 		error = sflt_getpeername(so, &sa);
3244 		if (error == EJUSTRETURN) {
3245 			error = 0;
3246 		}
3247 	}
3248 	socket_unlock(so, 1);
3249 	if (error) {
3250 		goto bad;
3251 	}
3252 	if (sa == 0) {
3253 		len = 0;
3254 		goto gotnothing;
3255 	}
3256 	sa_len = sa->sa_len;
3257 	len = MIN(len, sa_len);
3258 	error = copyout(__SA_UTILS_CONV_TO_BYTES(sa), uap->asa, len);
3259 	if (error) {
3260 		goto bad;
3261 	}
3262 	/* return the actual, untruncated address length */
3263 	len = sa_len;
3264 gotnothing:
3265 	error = copyout((caddr_t)&len, uap->alen, sizeof(socklen_t));
3266 bad:
3267 	free_sockaddr(sa);
3268 out:
3269 	file_drop(uap->fdes);
3270 	return error;
3271 }
3272 
3273 int
sockargs(struct mbuf ** mp,user_addr_t data,socklen_t buflen,int type)3274 sockargs(struct mbuf **mp, user_addr_t data, socklen_t buflen, int type)
3275 {
3276 	sockaddr_ref_t sa;
3277 	struct mbuf *m;
3278 	int error;
3279 	socklen_t alloc_buflen = buflen;
3280 
3281 	if (buflen > INT_MAX / 2) {
3282 		return EINVAL;
3283 	}
3284 	if (type == MT_SONAME && (buflen > SOCK_MAXADDRLEN ||
3285 	    buflen < offsetof(struct sockaddr, sa_data[0]))) {
3286 		return EINVAL;
3287 	}
3288 	if (type == MT_CONTROL && buflen < sizeof(struct cmsghdr)) {
3289 		return EINVAL;
3290 	}
3291 
3292 #ifdef __LP64__
3293 	/*
3294 	 * The fd's in the buffer must expand to be pointers, thus we need twice
3295 	 * as much space
3296 	 */
3297 	if (type == MT_CONTROL) {
3298 		alloc_buflen = ((buflen - sizeof(struct cmsghdr)) * 2) +
3299 		    sizeof(struct cmsghdr);
3300 	}
3301 #endif
3302 	if (alloc_buflen > MLEN) {
3303 		if (type == MT_SONAME && alloc_buflen <= 112) {
3304 			alloc_buflen = MLEN;    /* unix domain compat. hack */
3305 		} else if (alloc_buflen > MCLBYTES) {
3306 			return EINVAL;
3307 		}
3308 	}
3309 	m = m_get(M_WAIT, type);
3310 	if (m == NULL) {
3311 		return ENOBUFS;
3312 	}
3313 	if (alloc_buflen > MLEN) {
3314 		MCLGET(m, M_WAIT);
3315 		if ((m->m_flags & M_EXT) == 0) {
3316 			m_free(m);
3317 			return ENOBUFS;
3318 		}
3319 	}
3320 	/*
3321 	 * K64: We still copyin the original buflen because it gets expanded
3322 	 * later and we lie about the size of the mbuf because it only affects
3323 	 * unp_* functions
3324 	 */
3325 	m->m_len = buflen;
3326 	error = copyin(data, mtod(m, caddr_t), (u_int)buflen);
3327 	if (error) {
3328 		(void) m_free(m);
3329 	} else {
3330 		*mp = m;
3331 		if (type == MT_SONAME) {
3332 			VERIFY(buflen <= SOCK_MAXADDRLEN);
3333 			sa = mtod(m, sockaddr_ref_t);
3334 			sa->sa_len = (__uint8_t)buflen;
3335 		}
3336 	}
3337 	return error;
3338 }
3339 
3340 /*
3341  * Given a user_addr_t of length len, allocate and fill out a *sa.
3342  *
3343  * Returns:	0			Success
3344  *		ENAMETOOLONG		Filename too long
3345  *		EINVAL			Invalid argument
3346  *		ENOMEM			Not enough space
3347  *		copyin:EFAULT		Bad address
3348  */
3349 static int
getsockaddr(struct socket * so,sockaddr_ref_ref_t namp,user_addr_t uaddr,size_t len,boolean_t translate_unspec)3350 getsockaddr(struct socket *so, sockaddr_ref_ref_t namp, user_addr_t uaddr,
3351     size_t len, boolean_t translate_unspec)
3352 {
3353 	struct sockaddr *sa;
3354 	int error;
3355 
3356 	if (len > SOCK_MAXADDRLEN) {
3357 		return ENAMETOOLONG;
3358 	}
3359 
3360 	if (len < offsetof(struct sockaddr, sa_data[0])) {
3361 		return EINVAL;
3362 	}
3363 
3364 	sa = alloc_sockaddr(len, Z_WAITOK | Z_NOFAIL);
3365 
3366 	error = copyin(uaddr, (caddr_t)sa, len);
3367 	if (error) {
3368 		free_sockaddr(sa);
3369 	} else {
3370 		/*
3371 		 * Force sa_family to AF_INET on AF_INET sockets to handle
3372 		 * legacy applications that use AF_UNSPEC (0).  On all other
3373 		 * sockets we leave it unchanged and let the lower layer
3374 		 * handle it.
3375 		 */
3376 		if (translate_unspec && sa->sa_family == AF_UNSPEC &&
3377 		    SOCK_CHECK_DOM(so, PF_INET) &&
3378 		    len == sizeof(struct sockaddr_in)) {
3379 			sa->sa_family = AF_INET;
3380 		}
3381 		VERIFY(len <= SOCK_MAXADDRLEN);
3382 		sa = *&sa;
3383 		sa->sa_len = (__uint8_t)len;
3384 		*namp = sa;
3385 	}
3386 	return error;
3387 }
3388 
3389 static int
getsockaddr_s(struct socket * so,sockaddr_storage_ref_t ss,user_addr_t uaddr,size_t len,boolean_t translate_unspec)3390 getsockaddr_s(struct socket *so, sockaddr_storage_ref_t ss,
3391     user_addr_t uaddr, size_t len, boolean_t translate_unspec)
3392 {
3393 	int error;
3394 
3395 	if (ss == NULL || uaddr == USER_ADDR_NULL ||
3396 	    len < offsetof(struct sockaddr, sa_data[0])) {
3397 		return EINVAL;
3398 	}
3399 
3400 	/*
3401 	 * sockaddr_storage size is less than SOCK_MAXADDRLEN,
3402 	 * so the check here is inclusive.
3403 	 */
3404 	if (len > sizeof(*ss)) {
3405 		return ENAMETOOLONG;
3406 	}
3407 
3408 	bzero(ss, sizeof(*ss));
3409 	error = copyin(uaddr, __SA_UTILS_CONV_TO_BYTES(ss), len);
3410 	if (error == 0) {
3411 		/*
3412 		 * Force sa_family to AF_INET on AF_INET sockets to handle
3413 		 * legacy applications that use AF_UNSPEC (0).  On all other
3414 		 * sockets we leave it unchanged and let the lower layer
3415 		 * handle it.
3416 		 */
3417 		if (translate_unspec && ss->ss_family == AF_UNSPEC &&
3418 		    SOCK_CHECK_DOM(so, PF_INET) &&
3419 		    len == sizeof(struct sockaddr_in)) {
3420 			ss->ss_family = AF_INET;
3421 		}
3422 
3423 		ss->ss_len = (__uint8_t)len;
3424 	}
3425 	return error;
3426 }
3427 
3428 int
internalize_recv_msghdr_array(const void_ptr_t src,int spacetype,int direction,u_int count,user_msghdr_x_ptr_t dst,recv_msg_elem_ptr_t recv_msg_array)3429 internalize_recv_msghdr_array(const void_ptr_t src, int spacetype, int direction,
3430     u_int count, user_msghdr_x_ptr_t dst,
3431     recv_msg_elem_ptr_t recv_msg_array)
3432 {
3433 	int error = 0;
3434 	u_int i;
3435 
3436 	for (i = 0; i < count; i++) {
3437 		struct user_iovec *iovp;
3438 		struct user_msghdr_x *user_msg = dst + i;
3439 		struct recv_msg_elem *recv_msg_elem = recv_msg_array + i;
3440 
3441 		if (spacetype == UIO_USERSPACE64) {
3442 			const struct user64_msghdr_x *msghdr64;
3443 
3444 			msghdr64 = ((const struct user64_msghdr_x *)src) + i;
3445 
3446 			user_msg->msg_name = (user_addr_t)msghdr64->msg_name;
3447 			user_msg->msg_namelen = msghdr64->msg_namelen;
3448 			user_msg->msg_iov = (user_addr_t)msghdr64->msg_iov;
3449 			user_msg->msg_iovlen = msghdr64->msg_iovlen;
3450 			user_msg->msg_control = (user_addr_t)msghdr64->msg_control;
3451 			user_msg->msg_controllen = msghdr64->msg_controllen;
3452 			user_msg->msg_flags = msghdr64->msg_flags;
3453 			user_msg->msg_datalen = (size_t)msghdr64->msg_datalen;
3454 		} else {
3455 			const struct user32_msghdr_x *msghdr32;
3456 
3457 			msghdr32 = ((const struct user32_msghdr_x *)src) + i;
3458 
3459 			user_msg->msg_name = msghdr32->msg_name;
3460 			user_msg->msg_namelen = msghdr32->msg_namelen;
3461 			user_msg->msg_iov = msghdr32->msg_iov;
3462 			user_msg->msg_iovlen = msghdr32->msg_iovlen;
3463 			user_msg->msg_control = msghdr32->msg_control;
3464 			user_msg->msg_controllen = msghdr32->msg_controllen;
3465 			user_msg->msg_flags = msghdr32->msg_flags;
3466 			user_msg->msg_datalen = msghdr32->msg_datalen;
3467 		}
3468 
3469 		if (user_msg->msg_iovlen <= 0 ||
3470 		    user_msg->msg_iovlen > UIO_MAXIOV) {
3471 			error = EMSGSIZE;
3472 			goto done;
3473 		}
3474 		recv_msg_elem->uio = uio_create(user_msg->msg_iovlen, 0,
3475 		    spacetype, direction);
3476 		if (recv_msg_elem->uio == NULL) {
3477 			error = ENOMEM;
3478 			goto done;
3479 		}
3480 
3481 		iovp = uio_iovsaddr_user(recv_msg_elem->uio);
3482 		if (iovp == NULL) {
3483 			error = ENOMEM;
3484 			goto done;
3485 		}
3486 		error = copyin_user_iovec_array(user_msg->msg_iov,
3487 		    spacetype, user_msg->msg_iovlen, iovp);
3488 		if (error) {
3489 			goto done;
3490 		}
3491 		user_msg->msg_iov = CAST_USER_ADDR_T(iovp);
3492 
3493 		error = uio_calculateresid_user(recv_msg_elem->uio);
3494 		if (error) {
3495 			goto done;
3496 		}
3497 		user_msg->msg_datalen = uio_resid(recv_msg_elem->uio);
3498 
3499 		if (user_msg->msg_name && user_msg->msg_namelen) {
3500 			recv_msg_elem->which |= SOCK_MSG_SA;
3501 		}
3502 		if (user_msg->msg_control && user_msg->msg_controllen) {
3503 			recv_msg_elem->which |= SOCK_MSG_CONTROL;
3504 		}
3505 	}
3506 done:
3507 
3508 	return error;
3509 }
3510 
3511 u_int
externalize_recv_msghdr_array(proc_ref_t p,socket_ref_t so,void_ptr_t dst,u_int count,user_msghdr_x_ptr_t src,recv_msg_elem_ptr_t recv_msg_array,int_ref_t ret_error)3512 externalize_recv_msghdr_array(proc_ref_t p, socket_ref_t so, void_ptr_t dst,
3513     u_int count, user_msghdr_x_ptr_t src,
3514     recv_msg_elem_ptr_t recv_msg_array, int_ref_t ret_error)
3515 {
3516 	u_int i;
3517 	u_int retcnt = 0;
3518 	int spacetype = IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : UIO_USERSPACE32;
3519 
3520 	*ret_error = 0;
3521 
3522 	for (i = 0; i < count; i++) {
3523 		struct user_msghdr_x *user_msg = src + i;
3524 		struct recv_msg_elem *recv_msg_elem = recv_msg_array + i;
3525 		user_ssize_t len = 0;
3526 		int error;
3527 
3528 		len = user_msg->msg_datalen - uio_resid(recv_msg_elem->uio);
3529 
3530 		if ((recv_msg_elem->which & SOCK_MSG_DATA)) {
3531 			retcnt++;
3532 
3533 			if (recv_msg_elem->which & SOCK_MSG_SA) {
3534 				error = copyout_sa(recv_msg_elem->psa, user_msg->msg_name,
3535 				    &user_msg->msg_namelen);
3536 				if (error != 0) {
3537 					*ret_error = error;
3538 					return 0;
3539 				}
3540 			}
3541 			if (recv_msg_elem->which & SOCK_MSG_CONTROL) {
3542 				error = copyout_control(p, recv_msg_elem->controlp,
3543 				    user_msg->msg_control, &user_msg->msg_controllen,
3544 				    &recv_msg_elem->flags, so);
3545 				if (error != 0) {
3546 					*ret_error = error;
3547 					return 0;
3548 				}
3549 			}
3550 		}
3551 
3552 		if (spacetype == UIO_USERSPACE64) {
3553 			struct user64_msghdr_x *msghdr64 = ((struct user64_msghdr_x *)dst) + i;
3554 
3555 			msghdr64->msg_namelen = user_msg->msg_namelen;
3556 			msghdr64->msg_controllen = user_msg->msg_controllen;
3557 			msghdr64->msg_flags = recv_msg_elem->flags;
3558 			msghdr64->msg_datalen = len;
3559 		} else {
3560 			struct user32_msghdr_x *msghdr32 = ((struct user32_msghdr_x *)dst) + i;
3561 
3562 			msghdr32->msg_namelen = user_msg->msg_namelen;
3563 			msghdr32->msg_controllen = user_msg->msg_controllen;
3564 			msghdr32->msg_flags = recv_msg_elem->flags;
3565 			msghdr32->msg_datalen = (user32_size_t)len;
3566 		}
3567 	}
3568 	return retcnt;
3569 }
3570 
3571 recv_msg_elem_ptr_t
alloc_recv_msg_array(u_int count)3572 alloc_recv_msg_array(u_int count)
3573 {
3574 	return kalloc_type(struct recv_msg_elem, count, Z_WAITOK | Z_ZERO);
3575 }
3576 
3577 void
free_recv_msg_array(recv_msg_elem_ptr_t recv_msg_array,u_int count)3578 free_recv_msg_array(recv_msg_elem_ptr_t recv_msg_array, u_int count)
3579 {
3580 	if (recv_msg_array == NULL) {
3581 		return;
3582 	}
3583 	for (uint32_t i = 0; i < count; i++) {
3584 		struct recv_msg_elem *recv_msg_elem = recv_msg_array + i;
3585 
3586 		if (recv_msg_elem->uio != NULL) {
3587 			uio_free(recv_msg_elem->uio);
3588 		}
3589 		free_sockaddr(recv_msg_elem->psa);
3590 		if (recv_msg_elem->controlp != NULL) {
3591 			m_freem(recv_msg_elem->controlp);
3592 		}
3593 	}
3594 	kfree_type(struct recv_msg_elem, count, recv_msg_array);
3595 }
3596 
3597 
3598 /* Extern linkage requires using __counted_by instead of bptr */
3599 __private_extern__ user_ssize_t
recv_msg_array_resid(struct recv_msg_elem * __counted_by (count)recv_msg_array,u_int count)3600 recv_msg_array_resid(struct recv_msg_elem * __counted_by(count)recv_msg_array, u_int count)
3601 {
3602 	user_ssize_t len = 0;
3603 	u_int i;
3604 
3605 	for (i = 0; i < count; i++) {
3606 		struct recv_msg_elem *recv_msg_elem = recv_msg_array + i;
3607 
3608 		if (recv_msg_elem->uio != NULL) {
3609 			len += uio_resid(recv_msg_elem->uio);
3610 		}
3611 	}
3612 	return len;
3613 }
3614 
3615 int
recv_msg_array_is_valid(recv_msg_elem_ptr_t recv_msg_array,u_int count)3616 recv_msg_array_is_valid(recv_msg_elem_ptr_t recv_msg_array, u_int count)
3617 {
3618 	user_ssize_t len = 0;
3619 	u_int i;
3620 
3621 	for (i = 0; i < count; i++) {
3622 		struct recv_msg_elem *recv_msg_elem = recv_msg_array + i;
3623 
3624 		if (recv_msg_elem->uio != NULL) {
3625 			user_ssize_t resid = uio_resid(recv_msg_elem->uio);
3626 
3627 			/*
3628 			 * Sanity check on the validity of the iovec:
3629 			 * no point of going over sb_max
3630 			 */
3631 			if (resid < 0 || (u_int32_t)resid > sb_max) {
3632 				return 0;
3633 			}
3634 
3635 			len += resid;
3636 			if (len < 0 || (u_int32_t)len > sb_max) {
3637 				return 0;
3638 			}
3639 		}
3640 	}
3641 	return 1;
3642 }
3643 
3644 #if SENDFILE
3645 
3646 #define SFUIOBUFS 64
3647 
3648 /* Macros to compute the number of mbufs needed depending on cluster size */
3649 #define HOWMANY_16K(n)  ((((unsigned int)(n) - 1) >> M16KCLSHIFT) + 1)
3650 #define HOWMANY_4K(n)   ((((unsigned int)(n) - 1) >> MBIGCLSHIFT) + 1)
3651 
3652 /* Upper send limit in bytes (SFUIOBUFS * PAGESIZE) */
3653 #define SENDFILE_MAX_BYTES      (SFUIOBUFS << PGSHIFT)
3654 
3655 /* Upper send limit in the number of mbuf clusters */
3656 #define SENDFILE_MAX_16K        HOWMANY_16K(SENDFILE_MAX_BYTES)
3657 #define SENDFILE_MAX_4K         HOWMANY_4K(SENDFILE_MAX_BYTES)
3658 
3659 static void
alloc_sendpkt(int how,size_t pktlen,unsigned int * maxchunks,mbuf_ref_ref_t m,boolean_t jumbocl)3660 alloc_sendpkt(int how, size_t pktlen, unsigned int *maxchunks,
3661     mbuf_ref_ref_t m, boolean_t jumbocl)
3662 {
3663 	unsigned int needed;
3664 
3665 	if (pktlen == 0) {
3666 		panic("%s: pktlen (%ld) must be non-zero", __func__, pktlen);
3667 	}
3668 
3669 	/*
3670 	 * Try to allocate for the whole thing.  Since we want full control
3671 	 * over the buffer size and be able to accept partial result, we can't
3672 	 * use mbuf_allocpacket().  The logic below is similar to sosend().
3673 	 */
3674 	*m = NULL;
3675 	if (pktlen > MBIGCLBYTES && jumbocl) {
3676 		needed = MIN(SENDFILE_MAX_16K, HOWMANY_16K(pktlen));
3677 		*m = m_getpackets_internal(&needed, 1, how, 0, M16KCLBYTES);
3678 	}
3679 	if (*m == NULL) {
3680 		needed = MIN(SENDFILE_MAX_4K, HOWMANY_4K(pktlen));
3681 		*m = m_getpackets_internal(&needed, 1, how, 0, MBIGCLBYTES);
3682 	}
3683 
3684 	/*
3685 	 * Our previous attempt(s) at allocation had failed; the system
3686 	 * may be short on mbufs, and we want to block until they are
3687 	 * available.  This time, ask just for 1 mbuf and don't return
3688 	 * until we get it.
3689 	 */
3690 	if (*m == NULL) {
3691 		needed = 1;
3692 		*m = m_getpackets_internal(&needed, 1, M_WAIT, 1, MBIGCLBYTES);
3693 	}
3694 	if (*m == NULL) {
3695 		panic("%s: blocking allocation returned NULL", __func__);
3696 	}
3697 
3698 	*maxchunks = needed;
3699 }
3700 
3701 /*
3702  * sendfile(2).
3703  * int sendfile(int fd, int s, off_t offset, off_t *nbytes,
3704  *	 struct sf_hdtr *hdtr, int flags)
3705  *
3706  * Send a file specified by 'fd' and starting at 'offset' to a socket
3707  * specified by 's'. Send only '*nbytes' of the file or until EOF if
3708  * *nbytes == 0. Optionally add a header and/or trailer to the socket
3709  * output. If specified, write the total number of bytes sent into *nbytes.
3710  */
3711 int
sendfile(proc_ref_t p,struct sendfile_args * uap,__unused int * retval)3712 sendfile(proc_ref_t p, struct sendfile_args *uap, __unused int *retval)
3713 {
3714 	fileproc_ref_t  fp;
3715 	vnode_ref_t  vp;
3716 	socket_ref_t so;
3717 	struct writev_nocancel_args nuap;
3718 	user_ssize_t writev_retval;
3719 	struct user_sf_hdtr user_hdtr;
3720 	struct user32_sf_hdtr user32_hdtr;
3721 	struct user64_sf_hdtr user64_hdtr;
3722 	off_t off, xfsize;
3723 	off_t nbytes = 0, sbytes = 0;
3724 	int error = 0;
3725 	size_t sizeof_hdtr;
3726 	off_t file_size;
3727 	struct vfs_context context = *vfs_context_current();
3728 	bool got_vnode_ref = false;
3729 
3730 	const bool is_p_64bit_process = IS_64BIT_PROCESS(p);
3731 
3732 	KERNEL_DEBUG_CONSTANT((DBG_FNC_SENDFILE | DBG_FUNC_START), uap->s,
3733 	    0, 0, 0, 0);
3734 
3735 	AUDIT_ARG(fd, uap->fd);
3736 	AUDIT_ARG(value32, uap->s);
3737 
3738 	/*
3739 	 * Do argument checking. Must be a regular file in, stream
3740 	 * type and connected socket out, positive offset.
3741 	 */
3742 	if ((error = fp_getfvp(p, uap->fd, &fp, &vp))) {
3743 		goto done;
3744 	}
3745 	if ((error = vnode_getwithref(vp))) {
3746 		goto done;
3747 	}
3748 	got_vnode_ref = true;
3749 
3750 	if ((fp->f_flag & FREAD) == 0) {
3751 		error = EBADF;
3752 		goto done1;
3753 	}
3754 	if (vnode_isreg(vp) == 0) {
3755 		error = ENOTSUP;
3756 		goto done1;
3757 	}
3758 	error = file_socket(uap->s, &so);
3759 	if (error) {
3760 		goto done1;
3761 	}
3762 	if (so == NULL) {
3763 		error = EBADF;
3764 		goto done2;
3765 	}
3766 	if (so->so_type != SOCK_STREAM) {
3767 		error = EINVAL;
3768 		goto done2;
3769 	}
3770 	if ((so->so_state & SS_ISCONNECTED) == 0) {
3771 		error = ENOTCONN;
3772 		goto done2;
3773 	}
3774 	if (uap->offset < 0) {
3775 		error = EINVAL;
3776 		goto done2;
3777 	}
3778 	if (uap->nbytes == USER_ADDR_NULL) {
3779 		error = EINVAL;
3780 		goto done2;
3781 	}
3782 	if (uap->flags != 0) {
3783 		error = EINVAL;
3784 		goto done2;
3785 	}
3786 
3787 	context.vc_ucred = fp->fp_glob->fg_cred;
3788 
3789 #if CONFIG_MACF_SOCKET_SUBSET
3790 	/* JMM - fetch connected sockaddr? */
3791 	error = mac_socket_check_send(context.vc_ucred, so, NULL);
3792 	if (error) {
3793 		goto done2;
3794 	}
3795 #endif
3796 
3797 	/*
3798 	 * Get number of bytes to send
3799 	 * Should it applies to size of header and trailer?
3800 	 */
3801 	error = copyin(uap->nbytes, &nbytes, sizeof(off_t));
3802 	if (error) {
3803 		goto done2;
3804 	}
3805 
3806 	/*
3807 	 * If specified, get the pointer to the sf_hdtr struct for
3808 	 * any headers/trailers.
3809 	 */
3810 	if (uap->hdtr != USER_ADDR_NULL) {
3811 		caddr_t hdtrp;
3812 
3813 		bzero(&user_hdtr, sizeof(user_hdtr));
3814 		if (is_p_64bit_process) {
3815 			hdtrp = (caddr_t)&user64_hdtr;
3816 			sizeof_hdtr = sizeof(user64_hdtr);
3817 		} else {
3818 			hdtrp = (caddr_t)&user32_hdtr;
3819 			sizeof_hdtr = sizeof(user32_hdtr);
3820 		}
3821 		error = copyin(uap->hdtr, hdtrp, sizeof_hdtr);
3822 		if (error) {
3823 			goto done2;
3824 		}
3825 		if (is_p_64bit_process) {
3826 			user_hdtr.headers = user64_hdtr.headers;
3827 			user_hdtr.hdr_cnt = user64_hdtr.hdr_cnt;
3828 			user_hdtr.trailers = user64_hdtr.trailers;
3829 			user_hdtr.trl_cnt = user64_hdtr.trl_cnt;
3830 		} else {
3831 			user_hdtr.headers = user32_hdtr.headers;
3832 			user_hdtr.hdr_cnt = user32_hdtr.hdr_cnt;
3833 			user_hdtr.trailers = user32_hdtr.trailers;
3834 			user_hdtr.trl_cnt = user32_hdtr.trl_cnt;
3835 		}
3836 
3837 		/*
3838 		 * Send any headers. Wimp out and use writev(2).
3839 		 */
3840 		if (user_hdtr.headers != USER_ADDR_NULL) {
3841 			bzero(&nuap, sizeof(struct writev_args));
3842 			nuap.fd = uap->s;
3843 			nuap.iovp = user_hdtr.headers;
3844 			nuap.iovcnt = user_hdtr.hdr_cnt;
3845 			error = writev_nocancel(p, &nuap, &writev_retval);
3846 			if (error) {
3847 				goto done2;
3848 			}
3849 			sbytes += writev_retval;
3850 		}
3851 	}
3852 
3853 	/*
3854 	 * Get the file size for 2 reasons:
3855 	 *  1. We don't want to allocate more mbufs than necessary
3856 	 *  2. We don't want to read past the end of file
3857 	 */
3858 	if ((error = vnode_size(vp, &file_size, vfs_context_current())) != 0) {
3859 		goto done2;
3860 	}
3861 
3862 	/*
3863 	 * Simply read file data into a chain of mbufs that used with scatter
3864 	 * gather reads. We're not (yet?) setup to use zero copy external
3865 	 * mbufs that point to the file pages.
3866 	 */
3867 	socket_lock(so, 1);
3868 	error = sblock(&so->so_snd, SBL_WAIT);
3869 	if (error) {
3870 		socket_unlock(so, 1);
3871 		goto done2;
3872 	}
3873 	for (off = uap->offset;; off += xfsize, sbytes += xfsize) {
3874 		mbuf_ref_t m0 = NULL;
3875 		mbuf_t  m;
3876 		unsigned int    nbufs = SFUIOBUFS, i;
3877 		uio_t   auio;
3878 		UIO_STACKBUF(uio_buf, SFUIOBUFS);               /* 1KB !!! */
3879 		size_t  uiolen;
3880 		user_ssize_t    rlen;
3881 		off_t   pgoff;
3882 		size_t  pktlen;
3883 		boolean_t jumbocl;
3884 
3885 		/*
3886 		 * Calculate the amount to transfer.
3887 		 * Align to round number of pages.
3888 		 * Not to exceed send socket buffer,
3889 		 * the EOF, or the passed in nbytes.
3890 		 */
3891 		xfsize = sbspace(&so->so_snd);
3892 
3893 		if (xfsize <= 0) {
3894 			if (so->so_state & SS_CANTSENDMORE) {
3895 				error = EPIPE;
3896 				goto done3;
3897 			} else if ((so->so_state & SS_NBIO)) {
3898 				error = EAGAIN;
3899 				goto done3;
3900 			} else {
3901 				xfsize = PAGE_SIZE;
3902 			}
3903 		}
3904 
3905 		if (xfsize > SENDFILE_MAX_BYTES) {
3906 			xfsize = SENDFILE_MAX_BYTES;
3907 		} else if (xfsize > PAGE_SIZE) {
3908 			xfsize = trunc_page(xfsize);
3909 		}
3910 		pgoff = off & PAGE_MASK_64;
3911 		if (pgoff > 0 && PAGE_SIZE - pgoff < xfsize) {
3912 			xfsize = PAGE_SIZE_64 - pgoff;
3913 		}
3914 		if (nbytes && xfsize > (nbytes - sbytes)) {
3915 			xfsize = nbytes - sbytes;
3916 		}
3917 		if (xfsize <= 0) {
3918 			break;
3919 		}
3920 		if (off + xfsize > file_size) {
3921 			xfsize = file_size - off;
3922 		}
3923 		if (xfsize <= 0) {
3924 			break;
3925 		}
3926 
3927 		/*
3928 		 * Attempt to use larger than system page-size clusters for
3929 		 * large writes only if there is a jumbo cluster pool and
3930 		 * if the socket is marked accordingly.
3931 		 */
3932 		jumbocl = (so->so_flags & SOF_MULTIPAGES) != 0;
3933 
3934 		socket_unlock(so, 0);
3935 		alloc_sendpkt(M_WAIT, xfsize, &nbufs, &m0, jumbocl);
3936 		pktlen = mbuf_pkthdr_maxlen(m0);
3937 		if (pktlen < (size_t)xfsize) {
3938 			xfsize = pktlen;
3939 		}
3940 
3941 		auio = uio_createwithbuffer(nbufs, off, UIO_SYSSPACE,
3942 		    UIO_READ, &uio_buf[0], sizeof(uio_buf));
3943 		if (auio == NULL) {
3944 			DBG_PRINTF("sendfile failed. nbufs = %d. %s", nbufs,
3945 			    "File a radar related to rdar://10146739.\n");
3946 			mbuf_freem(m0);
3947 			error = ENXIO;
3948 			socket_lock(so, 0);
3949 			goto done3;
3950 		}
3951 
3952 		for (i = 0, m = m0, uiolen = 0;
3953 		    i < nbufs && m != NULL && uiolen < (size_t)xfsize;
3954 		    i++, m = mbuf_next(m)) {
3955 			size_t mlen = mbuf_maxlen(m);
3956 
3957 			if (mlen + uiolen > (size_t)xfsize) {
3958 				mlen = xfsize - uiolen;
3959 			}
3960 			mbuf_setlen(m, mlen);
3961 			uio_addiov(auio, CAST_USER_ADDR_T(mbuf_datastart(m)),
3962 			    mlen);
3963 			uiolen += mlen;
3964 		}
3965 
3966 		if (xfsize != uio_resid(auio)) {
3967 			DBG_PRINTF("sendfile: xfsize: %lld != uio_resid(auio): "
3968 			    "%lld\n", xfsize, (long long)uio_resid(auio));
3969 		}
3970 
3971 		KERNEL_DEBUG_CONSTANT((DBG_FNC_SENDFILE_READ | DBG_FUNC_START),
3972 		    uap->s, (unsigned int)((xfsize >> 32) & 0x0ffffffff),
3973 		    (unsigned int)(xfsize & 0x0ffffffff), 0, 0);
3974 		error = fo_read(fp, auio, FOF_OFFSET, &context);
3975 		socket_lock(so, 0);
3976 		if (error != 0) {
3977 			if (uio_resid(auio) != xfsize && (error == ERESTART ||
3978 			    error == EINTR || error == EWOULDBLOCK)) {
3979 				error = 0;
3980 			} else {
3981 				mbuf_freem(m0);
3982 				goto done3;
3983 			}
3984 		}
3985 		xfsize -= uio_resid(auio);
3986 		KERNEL_DEBUG_CONSTANT((DBG_FNC_SENDFILE_READ | DBG_FUNC_END),
3987 		    uap->s, (unsigned int)((xfsize >> 32) & 0x0ffffffff),
3988 		    (unsigned int)(xfsize & 0x0ffffffff), 0, 0);
3989 
3990 		if (xfsize == 0) {
3991 			break;
3992 		}
3993 		if (xfsize + off > file_size) {
3994 			DBG_PRINTF("sendfile: xfsize: %lld + off: %lld > file_size:"
3995 			    "%lld\n", xfsize, off, file_size);
3996 		}
3997 		for (i = 0, m = m0, rlen = 0;
3998 		    i < nbufs && m != NULL && rlen < xfsize;
3999 		    i++, m = mbuf_next(m)) {
4000 			size_t mlen = mbuf_maxlen(m);
4001 
4002 			if (rlen + mlen > (size_t)xfsize) {
4003 				mlen = xfsize - rlen;
4004 			}
4005 			mbuf_setlen(m, mlen);
4006 
4007 			rlen += mlen;
4008 		}
4009 		mbuf_pkthdr_setlen(m0, xfsize);
4010 
4011 retry_space:
4012 		/*
4013 		 * Make sure that the socket is still able to take more data.
4014 		 * CANTSENDMORE being true usually means that the connection
4015 		 * was closed. so_error is true when an error was sensed after
4016 		 * a previous send.
4017 		 * The state is checked after the page mapping and buffer
4018 		 * allocation above since those operations may block and make
4019 		 * any socket checks stale. From this point forward, nothing
4020 		 * blocks before the pru_send (or more accurately, any blocking
4021 		 * results in a loop back to here to re-check).
4022 		 */
4023 		if ((so->so_state & SS_CANTSENDMORE) || so->so_error) {
4024 			if (so->so_state & SS_CANTSENDMORE) {
4025 				error = EPIPE;
4026 			} else {
4027 				error = so->so_error;
4028 				so->so_error = 0;
4029 			}
4030 			m_freem(m0);
4031 			goto done3;
4032 		}
4033 		/*
4034 		 * Wait for socket space to become available. We do this just
4035 		 * after checking the connection state above in order to avoid
4036 		 * a race condition with sbwait().
4037 		 */
4038 		if (sbspace(&so->so_snd) < (long)so->so_snd.sb_lowat) {
4039 			if (so->so_state & SS_NBIO) {
4040 				m_freem(m0);
4041 				error = EAGAIN;
4042 				goto done3;
4043 			}
4044 			KERNEL_DEBUG_CONSTANT((DBG_FNC_SENDFILE_WAIT |
4045 			    DBG_FUNC_START), uap->s, 0, 0, 0, 0);
4046 			error = sbwait(&so->so_snd);
4047 			KERNEL_DEBUG_CONSTANT((DBG_FNC_SENDFILE_WAIT |
4048 			    DBG_FUNC_END), uap->s, 0, 0, 0, 0);
4049 			/*
4050 			 * An error from sbwait usually indicates that we've
4051 			 * been interrupted by a signal. If we've sent anything
4052 			 * then return bytes sent, otherwise return the error.
4053 			 */
4054 			if (error) {
4055 				m_freem(m0);
4056 				goto done3;
4057 			}
4058 			goto retry_space;
4059 		}
4060 
4061 		mbuf_ref_t  control = NULL;
4062 		{
4063 			/*
4064 			 * Socket filter processing
4065 			 */
4066 
4067 			error = sflt_data_out(so, NULL, &m0, &control, 0);
4068 			if (error) {
4069 				if (error == EJUSTRETURN) {
4070 					error = 0;
4071 					continue;
4072 				}
4073 				goto done3;
4074 			}
4075 			/*
4076 			 * End Socket filter processing
4077 			 */
4078 		}
4079 		KERNEL_DEBUG_CONSTANT((DBG_FNC_SENDFILE_SEND | DBG_FUNC_START),
4080 		    uap->s, 0, 0, 0, 0);
4081 		error = (*so->so_proto->pr_usrreqs->pru_send)(so, 0, m0,
4082 		    NULL, control, p);
4083 		if (error == EJUSTRETURN) {
4084 			error = 0;
4085 		}
4086 		KERNEL_DEBUG_CONSTANT((DBG_FNC_SENDFILE_SEND | DBG_FUNC_START),
4087 		    uap->s, 0, 0, 0, 0);
4088 		if (error) {
4089 			goto done3;
4090 		}
4091 	}
4092 	sbunlock(&so->so_snd, FALSE);   /* will unlock socket */
4093 	/*
4094 	 * Send trailers. Wimp out and use writev(2).
4095 	 */
4096 	if (uap->hdtr != USER_ADDR_NULL &&
4097 	    user_hdtr.trailers != USER_ADDR_NULL) {
4098 		bzero(&nuap, sizeof(struct writev_args));
4099 		nuap.fd = uap->s;
4100 		nuap.iovp = user_hdtr.trailers;
4101 		nuap.iovcnt = user_hdtr.trl_cnt;
4102 		error = writev_nocancel(p, &nuap, &writev_retval);
4103 		if (error) {
4104 			goto done2;
4105 		}
4106 		sbytes += writev_retval;
4107 	}
4108 done2:
4109 	file_drop(uap->s);
4110 done1:
4111 	file_drop(uap->fd);
4112 done:
4113 	if (got_vnode_ref) {
4114 		vnode_put(vp);
4115 	}
4116 	if (uap->nbytes != USER_ADDR_NULL) {
4117 		/* XXX this appears bogus for some early failure conditions */
4118 		copyout(&sbytes, uap->nbytes, sizeof(off_t));
4119 	}
4120 	KERNEL_DEBUG_CONSTANT((DBG_FNC_SENDFILE | DBG_FUNC_END), uap->s,
4121 	    (unsigned int)((sbytes >> 32) & 0x0ffffffff),
4122 	    (unsigned int)(sbytes & 0x0ffffffff), error, 0);
4123 	return error;
4124 done3:
4125 	sbunlock(&so->so_snd, FALSE);   /* will unlock socket */
4126 	goto done2;
4127 }
4128 
4129 
4130 #endif /* SENDFILE */
4131