1/*-
2 * Copyright (c) 1982, 1986, 1989, 1990, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 4. Neither the name of the University nor the names of its contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: stable/10/sys/netinet/sctp_syscalls.c 321021 2017-07-15 17:28:03Z dchagin $");
33
34#include "opt_capsicum.h"
35#include "opt_inet.h"
36#include "opt_inet6.h"
37#include "opt_sctp.h"
38#include "opt_compat.h"
39#include "opt_ktrace.h"
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/capsicum.h>
44#include <sys/kernel.h>
45#include <sys/lock.h>
46#include <sys/mutex.h>
47#include <sys/sysproto.h>
48#include <sys/malloc.h>
49#include <sys/filedesc.h>
50#include <sys/event.h>
51#include <sys/proc.h>
52#include <sys/fcntl.h>
53#include <sys/file.h>
54#include <sys/filio.h>
55#include <sys/jail.h>
56#include <sys/mount.h>
57#include <sys/mbuf.h>
58#include <sys/protosw.h>
59#include <sys/sf_buf.h>
60#include <sys/sysent.h>
61#include <sys/socket.h>
62#include <sys/socketvar.h>
63#include <sys/signalvar.h>
64#include <sys/syscall.h>
65#include <sys/syscallsubr.h>
66#include <sys/sysctl.h>
67#include <sys/uio.h>
68#include <sys/vnode.h>
69#ifdef KTRACE
70#include <sys/ktrace.h>
71#endif
72#ifdef COMPAT_FREEBSD32
73#include <compat/freebsd32/freebsd32_util.h>
74#endif
75
76#include <net/vnet.h>
77
78#include <security/audit/audit.h>
79#include <security/mac/mac_framework.h>
80
81#include <netinet/sctp.h>
82#include <netinet/sctp_peeloff.h>
83
84static struct syscall_helper_data sctp_syscalls[] = {
85	SYSCALL_INIT_HELPER(sctp_peeloff),
86	SYSCALL_INIT_HELPER(sctp_generic_sendmsg),
87	SYSCALL_INIT_HELPER(sctp_generic_sendmsg_iov),
88	SYSCALL_INIT_HELPER(sctp_generic_recvmsg),
89	SYSCALL_INIT_LAST
90};
91
92static void
93sctp_syscalls_init(void *unused __unused)
94{
95	int error;
96
97	error = syscall_helper_register(sctp_syscalls);
98	KASSERT((error == 0),
99	    ("%s: syscall_helper_register failed for sctp syscalls", __func__));
100#ifdef COMPAT_FREEBSD32
101	error = syscall32_helper_register(sctp_syscalls);
102	KASSERT((error == 0),
103	    ("%s: syscall32_helper_register failed for sctp syscalls",
104	    __func__));
105#endif
106}
107SYSINIT(sctp_syscalls, SI_SUB_SYSCALLS, SI_ORDER_ANY, sctp_syscalls_init, NULL);
108
109/*
110 * SCTP syscalls.
111 * Functionality only compiled in if SCTP is defined in the kernel Makefile,
112 * otherwise all return EOPNOTSUPP.
113 * XXX: We should make this loadable one day.
114 */
115int
116sys_sctp_peeloff(td, uap)
117	struct thread *td;
118	struct sctp_peeloff_args /* {
119		int	sd;
120		caddr_t	name;
121	} */ *uap;
122{
123#if (defined(INET) || defined(INET6)) && defined(SCTP)
124	struct file *nfp = NULL;
125	struct socket *head, *so;
126	cap_rights_t rights;
127	u_int fflag;
128	int error, fd;
129
130	AUDIT_ARG_FD(uap->sd);
131	error = fgetsock(td, uap->sd, cap_rights_init(&rights, CAP_PEELOFF),
132	    &head, &fflag);
133	if (error != 0)
134		goto done2;
135	if (head->so_proto->pr_protocol != IPPROTO_SCTP) {
136		error = EOPNOTSUPP;
137		goto done;
138	}
139	error = sctp_can_peel_off(head, (sctp_assoc_t)uap->name);
140	if (error != 0)
141		goto done;
142	/*
143	 * At this point we know we do have a assoc to pull
144	 * we proceed to get the fd setup. This may block
145	 * but that is ok.
146	 */
147
148	error = falloc(td, &nfp, &fd, 0);
149	if (error != 0)
150		goto done;
151	td->td_retval[0] = fd;
152
153	CURVNET_SET(head->so_vnet);
154	so = sonewconn(head, SS_ISCONNECTED);
155	if (so == NULL) {
156		error = ENOMEM;
157		goto noconnection;
158	}
159	/*
160	 * Before changing the flags on the socket, we have to bump the
161	 * reference count.  Otherwise, if the protocol calls sofree(),
162	 * the socket will be released due to a zero refcount.
163	 */
164        SOCK_LOCK(so);
165        soref(so);                      /* file descriptor reference */
166        SOCK_UNLOCK(so);
167
168	ACCEPT_LOCK();
169
170	TAILQ_REMOVE(&head->so_comp, so, so_list);
171	head->so_qlen--;
172	so->so_state |= (head->so_state & SS_NBIO);
173	so->so_state &= ~SS_NOFDREF;
174	so->so_qstate &= ~SQ_COMP;
175	so->so_head = NULL;
176	ACCEPT_UNLOCK();
177	finit(nfp, fflag, DTYPE_SOCKET, so, &socketops);
178	error = sctp_do_peeloff(head, so, (sctp_assoc_t)uap->name);
179	if (error != 0)
180		goto noconnection;
181	if (head->so_sigio != NULL)
182		fsetown(fgetown(&head->so_sigio), &so->so_sigio);
183
184noconnection:
185	/*
186	 * close the new descriptor, assuming someone hasn't ripped it
187	 * out from under us.
188	 */
189	if (error != 0)
190		fdclose(td, nfp, fd);
191
192	/*
193	 * Release explicitly held references before returning.
194	 */
195	CURVNET_RESTORE();
196done:
197	if (nfp != NULL)
198		fdrop(nfp, td);
199	fputsock(head);
200done2:
201	return (error);
202#else  /* SCTP */
203	return (EOPNOTSUPP);
204#endif /* SCTP */
205}
206
207int
208sys_sctp_generic_sendmsg (td, uap)
209	struct thread *td;
210	struct sctp_generic_sendmsg_args /* {
211		int sd,
212		caddr_t msg,
213		int mlen,
214		caddr_t to,
215		__socklen_t tolen,
216		struct sctp_sndrcvinfo *sinfo,
217		int flags
218	} */ *uap;
219{
220#if (defined(INET) || defined(INET6)) && defined(SCTP)
221	struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL;
222	struct socket *so;
223	struct file *fp = NULL;
224	struct sockaddr *to = NULL;
225#ifdef KTRACE
226	struct uio *ktruio = NULL;
227#endif
228	struct uio auio;
229	struct iovec iov[1];
230	cap_rights_t rights;
231	int error = 0, len;
232
233	if (uap->sinfo != NULL) {
234		error = copyin(uap->sinfo, &sinfo, sizeof (sinfo));
235		if (error != 0)
236			return (error);
237		u_sinfo = &sinfo;
238	}
239
240	cap_rights_init(&rights, CAP_SEND);
241	if (uap->tolen != 0) {
242		error = getsockaddr(&to, uap->to, uap->tolen);
243		if (error != 0) {
244			to = NULL;
245			goto sctp_bad2;
246		}
247		cap_rights_set(&rights, CAP_CONNECT);
248	}
249
250	AUDIT_ARG_FD(uap->sd);
251	error = getsock_cap(td, uap->sd, &rights, &fp, NULL);
252	if (error != 0)
253		goto sctp_bad;
254#ifdef KTRACE
255	if (to && (KTRPOINT(td, KTR_STRUCT)))
256		ktrsockaddr(to);
257#endif
258
259	iov[0].iov_base = uap->msg;
260	iov[0].iov_len = uap->mlen;
261
262	so = (struct socket *)fp->f_data;
263	if (so->so_proto->pr_protocol != IPPROTO_SCTP) {
264		error = EOPNOTSUPP;
265		goto sctp_bad;
266	}
267#ifdef MAC
268	error = mac_socket_check_send(td->td_ucred, so);
269	if (error != 0)
270		goto sctp_bad;
271#endif /* MAC */
272
273	auio.uio_iov =  iov;
274	auio.uio_iovcnt = 1;
275	auio.uio_segflg = UIO_USERSPACE;
276	auio.uio_rw = UIO_WRITE;
277	auio.uio_td = td;
278	auio.uio_offset = 0;			/* XXX */
279	auio.uio_resid = 0;
280#ifdef KTRACE
281	if (KTRPOINT(td, KTR_GENIO))
282		ktruio = cloneuio(&auio);
283#endif /* KTRACE */
284	len = auio.uio_resid = uap->mlen;
285	CURVNET_SET(so->so_vnet);
286	error = sctp_lower_sosend(so, to, &auio, (struct mbuf *)NULL,
287	    (struct mbuf *)NULL, uap->flags, u_sinfo, td);
288	CURVNET_RESTORE();
289	if (error != 0) {
290		if (auio.uio_resid != len && (error == ERESTART ||
291		    error == EINTR || error == EWOULDBLOCK))
292			error = 0;
293		/* Generation of SIGPIPE can be controlled per socket. */
294		if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) &&
295		    !(uap->flags & MSG_NOSIGNAL)) {
296			PROC_LOCK(td->td_proc);
297			tdsignal(td, SIGPIPE);
298			PROC_UNLOCK(td->td_proc);
299		}
300	}
301	if (error == 0)
302		td->td_retval[0] = len - auio.uio_resid;
303#ifdef KTRACE
304	if (ktruio != NULL) {
305		ktruio->uio_resid = td->td_retval[0];
306		ktrgenio(uap->sd, UIO_WRITE, ktruio, error);
307	}
308#endif /* KTRACE */
309sctp_bad:
310	if (fp != NULL)
311		fdrop(fp, td);
312sctp_bad2:
313	free(to, M_SONAME);
314	return (error);
315#else  /* SCTP */
316	return (EOPNOTSUPP);
317#endif /* SCTP */
318}
319
320int
321sys_sctp_generic_sendmsg_iov(td, uap)
322	struct thread *td;
323	struct sctp_generic_sendmsg_iov_args /* {
324		int sd,
325		struct iovec *iov,
326		int iovlen,
327		caddr_t to,
328		__socklen_t tolen,
329		struct sctp_sndrcvinfo *sinfo,
330		int flags
331	} */ *uap;
332{
333#if (defined(INET) || defined(INET6)) && defined(SCTP)
334	struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL;
335	struct socket *so;
336	struct file *fp = NULL;
337	struct sockaddr *to = NULL;
338#ifdef KTRACE
339	struct uio *ktruio = NULL;
340#endif
341	struct uio auio;
342	struct iovec *iov, *tiov;
343	cap_rights_t rights;
344	ssize_t len;
345	int error, i;
346
347	if (uap->sinfo != NULL) {
348		error = copyin(uap->sinfo, &sinfo, sizeof (sinfo));
349		if (error != 0)
350			return (error);
351		u_sinfo = &sinfo;
352	}
353	cap_rights_init(&rights, CAP_SEND);
354	if (uap->tolen != 0) {
355		error = getsockaddr(&to, uap->to, uap->tolen);
356		if (error != 0) {
357			to = NULL;
358			goto sctp_bad2;
359		}
360		cap_rights_set(&rights, CAP_CONNECT);
361	}
362
363	AUDIT_ARG_FD(uap->sd);
364	error = getsock_cap(td, uap->sd, &rights, &fp, NULL);
365	if (error != 0)
366		goto sctp_bad1;
367
368#ifdef COMPAT_FREEBSD32
369	if (SV_CURPROC_FLAG(SV_ILP32))
370		error = freebsd32_copyiniov((struct iovec32 *)uap->iov,
371		    uap->iovlen, &iov, EMSGSIZE);
372	else
373#endif
374		error = copyiniov(uap->iov, uap->iovlen, &iov, EMSGSIZE);
375	if (error != 0)
376		goto sctp_bad1;
377#ifdef KTRACE
378	if (to && (KTRPOINT(td, KTR_STRUCT)))
379		ktrsockaddr(to);
380#endif
381
382	so = (struct socket *)fp->f_data;
383	if (so->so_proto->pr_protocol != IPPROTO_SCTP) {
384		error = EOPNOTSUPP;
385		goto sctp_bad;
386	}
387#ifdef MAC
388	error = mac_socket_check_send(td->td_ucred, so);
389	if (error != 0)
390		goto sctp_bad;
391#endif /* MAC */
392
393	auio.uio_iov = iov;
394	auio.uio_iovcnt = uap->iovlen;
395	auio.uio_segflg = UIO_USERSPACE;
396	auio.uio_rw = UIO_WRITE;
397	auio.uio_td = td;
398	auio.uio_offset = 0;			/* XXX */
399	auio.uio_resid = 0;
400	tiov = iov;
401	for (i = 0; i <uap->iovlen; i++, tiov++) {
402		if ((auio.uio_resid += tiov->iov_len) < 0) {
403			error = EINVAL;
404			goto sctp_bad;
405		}
406	}
407#ifdef KTRACE
408	if (KTRPOINT(td, KTR_GENIO))
409		ktruio = cloneuio(&auio);
410#endif /* KTRACE */
411	len = auio.uio_resid;
412	CURVNET_SET(so->so_vnet);
413	error = sctp_lower_sosend(so, to, &auio,
414		    (struct mbuf *)NULL, (struct mbuf *)NULL,
415		    uap->flags, u_sinfo, td);
416	CURVNET_RESTORE();
417	if (error != 0) {
418		if (auio.uio_resid != len && (error == ERESTART ||
419		    error == EINTR || error == EWOULDBLOCK))
420			error = 0;
421		/* Generation of SIGPIPE can be controlled per socket */
422		if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) &&
423		    !(uap->flags & MSG_NOSIGNAL)) {
424			PROC_LOCK(td->td_proc);
425			tdsignal(td, SIGPIPE);
426			PROC_UNLOCK(td->td_proc);
427		}
428	}
429	if (error == 0)
430		td->td_retval[0] = len - auio.uio_resid;
431#ifdef KTRACE
432	if (ktruio != NULL) {
433		ktruio->uio_resid = td->td_retval[0];
434		ktrgenio(uap->sd, UIO_WRITE, ktruio, error);
435	}
436#endif /* KTRACE */
437sctp_bad:
438	free(iov, M_IOV);
439sctp_bad1:
440	if (fp != NULL)
441		fdrop(fp, td);
442sctp_bad2:
443	free(to, M_SONAME);
444	return (error);
445#else  /* SCTP */
446	return (EOPNOTSUPP);
447#endif /* SCTP */
448}
449
450int
451sys_sctp_generic_recvmsg(td, uap)
452	struct thread *td;
453	struct sctp_generic_recvmsg_args /* {
454		int sd,
455		struct iovec *iov,
456		int iovlen,
457		struct sockaddr *from,
458		__socklen_t *fromlenaddr,
459		struct sctp_sndrcvinfo *sinfo,
460		int *msg_flags
461	} */ *uap;
462{
463#if (defined(INET) || defined(INET6)) && defined(SCTP)
464	uint8_t sockbufstore[256];
465	struct uio auio;
466	struct iovec *iov, *tiov;
467	struct sctp_sndrcvinfo sinfo;
468	struct socket *so;
469	struct file *fp = NULL;
470	struct sockaddr *fromsa;
471	cap_rights_t rights;
472#ifdef KTRACE
473	struct uio *ktruio = NULL;
474#endif
475	ssize_t len;
476	int error, fromlen, i, msg_flags;
477
478	AUDIT_ARG_FD(uap->sd);
479	error = getsock_cap(td, uap->sd, cap_rights_init(&rights, CAP_RECV),
480	    &fp, NULL);
481	if (error != 0)
482		return (error);
483#ifdef COMPAT_FREEBSD32
484	if (SV_CURPROC_FLAG(SV_ILP32))
485		error = freebsd32_copyiniov((struct iovec32 *)uap->iov,
486		    uap->iovlen, &iov, EMSGSIZE);
487	else
488#endif
489		error = copyiniov(uap->iov, uap->iovlen, &iov, EMSGSIZE);
490	if (error != 0)
491		goto out1;
492
493	so = fp->f_data;
494	if (so->so_proto->pr_protocol != IPPROTO_SCTP) {
495		error = EOPNOTSUPP;
496		goto out;
497	}
498#ifdef MAC
499	error = mac_socket_check_receive(td->td_ucred, so);
500	if (error != 0)
501		goto out;
502#endif /* MAC */
503
504	if (uap->fromlenaddr != NULL) {
505		error = copyin(uap->fromlenaddr, &fromlen, sizeof (fromlen));
506		if (error != 0)
507			goto out;
508	} else {
509		fromlen = 0;
510	}
511	if (uap->msg_flags) {
512		error = copyin(uap->msg_flags, &msg_flags, sizeof (int));
513		if (error != 0)
514			goto out;
515	} else {
516		msg_flags = 0;
517	}
518	auio.uio_iov = iov;
519	auio.uio_iovcnt = uap->iovlen;
520	auio.uio_segflg = UIO_USERSPACE;
521	auio.uio_rw = UIO_READ;
522	auio.uio_td = td;
523	auio.uio_offset = 0;			/* XXX */
524	auio.uio_resid = 0;
525	tiov = iov;
526	for (i = 0; i <uap->iovlen; i++, tiov++) {
527		if ((auio.uio_resid += tiov->iov_len) < 0) {
528			error = EINVAL;
529			goto out;
530		}
531	}
532	len = auio.uio_resid;
533	fromsa = (struct sockaddr *)sockbufstore;
534
535#ifdef KTRACE
536	if (KTRPOINT(td, KTR_GENIO))
537		ktruio = cloneuio(&auio);
538#endif /* KTRACE */
539	memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
540	CURVNET_SET(so->so_vnet);
541	error = sctp_sorecvmsg(so, &auio, (struct mbuf **)NULL,
542		    fromsa, fromlen, &msg_flags,
543		    (struct sctp_sndrcvinfo *)&sinfo, 1);
544	CURVNET_RESTORE();
545	if (error != 0) {
546		if (auio.uio_resid != len && (error == ERESTART ||
547		    error == EINTR || error == EWOULDBLOCK))
548			error = 0;
549	} else {
550		if (uap->sinfo)
551			error = copyout(&sinfo, uap->sinfo, sizeof (sinfo));
552	}
553#ifdef KTRACE
554	if (ktruio != NULL) {
555		ktruio->uio_resid = len - auio.uio_resid;
556		ktrgenio(uap->sd, UIO_READ, ktruio, error);
557	}
558#endif /* KTRACE */
559	if (error != 0)
560		goto out;
561	td->td_retval[0] = len - auio.uio_resid;
562
563	if (fromlen && uap->from) {
564		len = fromlen;
565		if (len <= 0 || fromsa == 0)
566			len = 0;
567		else {
568			len = MIN(len, fromsa->sa_len);
569			error = copyout(fromsa, uap->from, (size_t)len);
570			if (error != 0)
571				goto out;
572		}
573		error = copyout(&len, uap->fromlenaddr, sizeof (socklen_t));
574		if (error != 0)
575			goto out;
576	}
577#ifdef KTRACE
578	if (KTRPOINT(td, KTR_STRUCT))
579		ktrsockaddr(fromsa);
580#endif
581	if (uap->msg_flags) {
582		error = copyout(&msg_flags, uap->msg_flags, sizeof (int));
583		if (error != 0)
584			goto out;
585	}
586out:
587	free(iov, M_IOV);
588out1:
589	if (fp != NULL)
590		fdrop(fp, td);
591
592	return (error);
593#else  /* SCTP */
594	return (EOPNOTSUPP);
595#endif /* SCTP */
596}
597