sctp_syscalls.c revision 321017
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 321017 2017-07-15 16:55:02Z 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->td_proc->p_fd, nfp, fd, td);
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->td_proc->p_fd, 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	len = auio.uio_resid = uap->mlen;
281	CURVNET_SET(so->so_vnet);
282	error = sctp_lower_sosend(so, to, &auio, (struct mbuf *)NULL,
283	    (struct mbuf *)NULL, uap->flags, u_sinfo, td);
284	CURVNET_RESTORE();
285	if (error != 0) {
286		if (auio.uio_resid != len && (error == ERESTART ||
287		    error == EINTR || error == EWOULDBLOCK))
288			error = 0;
289		/* Generation of SIGPIPE can be controlled per socket. */
290		if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) &&
291		    !(uap->flags & MSG_NOSIGNAL)) {
292			PROC_LOCK(td->td_proc);
293			tdsignal(td, SIGPIPE);
294			PROC_UNLOCK(td->td_proc);
295		}
296	}
297	if (error == 0)
298		td->td_retval[0] = len - auio.uio_resid;
299#ifdef KTRACE
300	if (ktruio != NULL) {
301		ktruio->uio_resid = td->td_retval[0];
302		ktrgenio(uap->sd, UIO_WRITE, ktruio, error);
303	}
304#endif /* KTRACE */
305sctp_bad:
306	if (fp != NULL)
307		fdrop(fp, td);
308sctp_bad2:
309	free(to, M_SONAME);
310	return (error);
311#else  /* SCTP */
312	return (EOPNOTSUPP);
313#endif /* SCTP */
314}
315
316int
317sys_sctp_generic_sendmsg_iov(td, uap)
318	struct thread *td;
319	struct sctp_generic_sendmsg_iov_args /* {
320		int sd,
321		struct iovec *iov,
322		int iovlen,
323		caddr_t to,
324		__socklen_t tolen,
325		struct sctp_sndrcvinfo *sinfo,
326		int flags
327	} */ *uap;
328{
329#if (defined(INET) || defined(INET6)) && defined(SCTP)
330	struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL;
331	struct socket *so;
332	struct file *fp = NULL;
333	struct sockaddr *to = NULL;
334#ifdef KTRACE
335	struct uio *ktruio = NULL;
336#endif
337	struct uio auio;
338	struct iovec *iov, *tiov;
339	cap_rights_t rights;
340	ssize_t len;
341	int error, i;
342
343	if (uap->sinfo != NULL) {
344		error = copyin(uap->sinfo, &sinfo, sizeof (sinfo));
345		if (error != 0)
346			return (error);
347		u_sinfo = &sinfo;
348	}
349	cap_rights_init(&rights, CAP_SEND);
350	if (uap->tolen != 0) {
351		error = getsockaddr(&to, uap->to, uap->tolen);
352		if (error != 0) {
353			to = NULL;
354			goto sctp_bad2;
355		}
356		cap_rights_set(&rights, CAP_CONNECT);
357	}
358
359	AUDIT_ARG_FD(uap->sd);
360	error = getsock_cap(td->td_proc->p_fd, uap->sd, &rights, &fp, NULL);
361	if (error != 0)
362		goto sctp_bad1;
363
364#ifdef COMPAT_FREEBSD32
365	if (SV_CURPROC_FLAG(SV_ILP32))
366		error = freebsd32_copyiniov((struct iovec32 *)uap->iov,
367		    uap->iovlen, &iov, EMSGSIZE);
368	else
369#endif
370		error = copyiniov(uap->iov, uap->iovlen, &iov, EMSGSIZE);
371	if (error != 0)
372		goto sctp_bad1;
373#ifdef KTRACE
374	if (to && (KTRPOINT(td, KTR_STRUCT)))
375		ktrsockaddr(to);
376#endif
377
378	so = (struct socket *)fp->f_data;
379	if (so->so_proto->pr_protocol != IPPROTO_SCTP) {
380		error = EOPNOTSUPP;
381		goto sctp_bad;
382	}
383#ifdef MAC
384	error = mac_socket_check_send(td->td_ucred, so);
385	if (error != 0)
386		goto sctp_bad;
387#endif /* MAC */
388
389	auio.uio_iov = iov;
390	auio.uio_iovcnt = uap->iovlen;
391	auio.uio_segflg = UIO_USERSPACE;
392	auio.uio_rw = UIO_WRITE;
393	auio.uio_td = td;
394	auio.uio_offset = 0;			/* XXX */
395	auio.uio_resid = 0;
396	tiov = iov;
397	for (i = 0; i <uap->iovlen; i++, tiov++) {
398		if ((auio.uio_resid += tiov->iov_len) < 0) {
399			error = EINVAL;
400			goto sctp_bad;
401		}
402	}
403	len = auio.uio_resid;
404	CURVNET_SET(so->so_vnet);
405	error = sctp_lower_sosend(so, to, &auio,
406		    (struct mbuf *)NULL, (struct mbuf *)NULL,
407		    uap->flags, u_sinfo, td);
408	CURVNET_RESTORE();
409	if (error != 0) {
410		if (auio.uio_resid != len && (error == ERESTART ||
411		    error == EINTR || error == EWOULDBLOCK))
412			error = 0;
413		/* Generation of SIGPIPE can be controlled per socket */
414		if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) &&
415		    !(uap->flags & MSG_NOSIGNAL)) {
416			PROC_LOCK(td->td_proc);
417			tdsignal(td, SIGPIPE);
418			PROC_UNLOCK(td->td_proc);
419		}
420	}
421	if (error == 0)
422		td->td_retval[0] = len - auio.uio_resid;
423#ifdef KTRACE
424	if (ktruio != NULL) {
425		ktruio->uio_resid = td->td_retval[0];
426		ktrgenio(uap->sd, UIO_WRITE, ktruio, error);
427	}
428#endif /* KTRACE */
429sctp_bad:
430	free(iov, M_IOV);
431sctp_bad1:
432	if (fp != NULL)
433		fdrop(fp, td);
434sctp_bad2:
435	free(to, M_SONAME);
436	return (error);
437#else  /* SCTP */
438	return (EOPNOTSUPP);
439#endif /* SCTP */
440}
441
442int
443sys_sctp_generic_recvmsg(td, uap)
444	struct thread *td;
445	struct sctp_generic_recvmsg_args /* {
446		int sd,
447		struct iovec *iov,
448		int iovlen,
449		struct sockaddr *from,
450		__socklen_t *fromlenaddr,
451		struct sctp_sndrcvinfo *sinfo,
452		int *msg_flags
453	} */ *uap;
454{
455#if (defined(INET) || defined(INET6)) && defined(SCTP)
456	uint8_t sockbufstore[256];
457	struct uio auio;
458	struct iovec *iov, *tiov;
459	struct sctp_sndrcvinfo sinfo;
460	struct socket *so;
461	struct file *fp = NULL;
462	struct sockaddr *fromsa;
463	cap_rights_t rights;
464#ifdef KTRACE
465	struct uio *ktruio = NULL;
466#endif
467	ssize_t len;
468	int error, fromlen, i, msg_flags;
469
470	AUDIT_ARG_FD(uap->sd);
471	error = getsock_cap(td->td_proc->p_fd, uap->sd,
472	    cap_rights_init(&rights, CAP_RECV), &fp, NULL);
473	if (error != 0)
474		return (error);
475#ifdef COMPAT_FREEBSD32
476	if (SV_CURPROC_FLAG(SV_ILP32))
477		error = freebsd32_copyiniov((struct iovec32 *)uap->iov,
478		    uap->iovlen, &iov, EMSGSIZE);
479	else
480#endif
481		error = copyiniov(uap->iov, uap->iovlen, &iov, EMSGSIZE);
482	if (error != 0)
483		goto out1;
484
485	so = fp->f_data;
486	if (so->so_proto->pr_protocol != IPPROTO_SCTP) {
487		error = EOPNOTSUPP;
488		goto out;
489	}
490#ifdef MAC
491	error = mac_socket_check_receive(td->td_ucred, so);
492	if (error != 0)
493		goto out;
494#endif /* MAC */
495
496	if (uap->fromlenaddr != NULL) {
497		error = copyin(uap->fromlenaddr, &fromlen, sizeof (fromlen));
498		if (error != 0)
499			goto out;
500	} else {
501		fromlen = 0;
502	}
503	if (uap->msg_flags) {
504		error = copyin(uap->msg_flags, &msg_flags, sizeof (int));
505		if (error != 0)
506			goto out;
507	} else {
508		msg_flags = 0;
509	}
510	auio.uio_iov = iov;
511	auio.uio_iovcnt = uap->iovlen;
512	auio.uio_segflg = UIO_USERSPACE;
513	auio.uio_rw = UIO_READ;
514	auio.uio_td = td;
515	auio.uio_offset = 0;			/* XXX */
516	auio.uio_resid = 0;
517	tiov = iov;
518	for (i = 0; i <uap->iovlen; i++, tiov++) {
519		if ((auio.uio_resid += tiov->iov_len) < 0) {
520			error = EINVAL;
521			goto out;
522		}
523	}
524	len = auio.uio_resid;
525	fromsa = (struct sockaddr *)sockbufstore;
526
527#ifdef KTRACE
528	if (KTRPOINT(td, KTR_GENIO))
529		ktruio = cloneuio(&auio);
530#endif /* KTRACE */
531	memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
532	CURVNET_SET(so->so_vnet);
533	error = sctp_sorecvmsg(so, &auio, (struct mbuf **)NULL,
534		    fromsa, fromlen, &msg_flags,
535		    (struct sctp_sndrcvinfo *)&sinfo, 1);
536	CURVNET_RESTORE();
537	if (error != 0) {
538		if (auio.uio_resid != len && (error == ERESTART ||
539		    error == EINTR || error == EWOULDBLOCK))
540			error = 0;
541	} else {
542		if (uap->sinfo)
543			error = copyout(&sinfo, uap->sinfo, sizeof (sinfo));
544	}
545#ifdef KTRACE
546	if (ktruio != NULL) {
547		ktruio->uio_resid = len - auio.uio_resid;
548		ktrgenio(uap->sd, UIO_READ, ktruio, error);
549	}
550#endif /* KTRACE */
551	if (error != 0)
552		goto out;
553	td->td_retval[0] = len - auio.uio_resid;
554
555	if (fromlen && uap->from) {
556		len = fromlen;
557		if (len <= 0 || fromsa == 0)
558			len = 0;
559		else {
560			len = MIN(len, fromsa->sa_len);
561			error = copyout(fromsa, uap->from, (size_t)len);
562			if (error != 0)
563				goto out;
564		}
565		error = copyout(&len, uap->fromlenaddr, sizeof (socklen_t));
566		if (error != 0)
567			goto out;
568	}
569#ifdef KTRACE
570	if (KTRPOINT(td, KTR_STRUCT))
571		ktrsockaddr(fromsa);
572#endif
573	if (uap->msg_flags) {
574		error = copyout(&msg_flags, uap->msg_flags, sizeof (int));
575		if (error != 0)
576			goto out;
577	}
578out:
579	free(iov, M_IOV);
580out1:
581	if (fp != NULL)
582		fdrop(fp, td);
583
584	return (error);
585#else  /* SCTP */
586	return (EOPNOTSUPP);
587#endif /* SCTP */
588}
589