2 * Copyright (c) 1982, 1986, 1989, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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 * 3. 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.
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
31 #include <sys/cdefs.h>
32 #include "opt_capsicum.h"
34 #include "opt_ktrace.h"
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/capsicum.h>
39 #include <sys/kernel.h>
41 #include <sys/mutex.h>
42 #include <sys/sysproto.h>
43 #include <sys/malloc.h>
44 #include <sys/filedesc.h>
45 #include <sys/event.h>
47 #include <sys/fcntl.h>
49 #include <sys/filio.h>
51 #include <sys/mount.h>
53 #include <sys/protosw.h>
54 #include <sys/sf_buf.h>
55 #include <sys/sysent.h>
56 #include <sys/socket.h>
57 #include <sys/socketvar.h>
58 #include <sys/signalvar.h>
59 #include <sys/syscall.h>
60 #include <sys/syscallsubr.h>
61 #include <sys/sysctl.h>
63 #include <sys/vnode.h>
65 #include <sys/ktrace.h>
67 #ifdef COMPAT_FREEBSD32
68 #include <compat/freebsd32/freebsd32.h>
69 #include <compat/freebsd32/freebsd32_syscall.h>
70 #include <compat/freebsd32/freebsd32_util.h>
75 #include <security/audit/audit.h>
76 #include <security/mac/mac_framework.h>
78 #include <netinet/sctp.h>
79 #include <netinet/sctp_os_bsd.h>
80 #include <netinet/sctp_peeloff.h>
82 static struct syscall_helper_data sctp_syscalls
[] = {
83 SYSCALL_INIT_HELPER_F(sctp_peeloff
, SYF_CAPENABLED
),
84 SYSCALL_INIT_HELPER_F(sctp_generic_sendmsg
, SYF_CAPENABLED
),
85 SYSCALL_INIT_HELPER_F(sctp_generic_sendmsg_iov
, SYF_CAPENABLED
),
86 SYSCALL_INIT_HELPER_F(sctp_generic_recvmsg
, SYF_CAPENABLED
),
90 #ifdef COMPAT_FREEBSD32
91 static struct syscall_helper_data sctp32_syscalls
[] = {
92 SYSCALL32_INIT_HELPER_COMPAT(sctp_peeloff
),
93 SYSCALL32_INIT_HELPER_COMPAT(sctp_generic_sendmsg
),
94 SYSCALL32_INIT_HELPER_COMPAT(sctp_generic_sendmsg_iov
),
95 SYSCALL32_INIT_HELPER_COMPAT(sctp_generic_recvmsg
),
101 sctp_syscalls_init(void)
105 error
= syscall_helper_register(sctp_syscalls
, SY_THR_STATIC_KLD
);
108 #ifdef COMPAT_FREEBSD32
109 error
= syscall32_helper_register(sctp32_syscalls
, SY_THR_STATIC_KLD
);
117 SYSINIT(sctp_syscalls
, SI_SUB_SYSCALLS
, SI_ORDER_ANY
, sctp_syscalls_init
, NULL
);
121 sctp_syscalls_uninit(void)
125 #ifdef COMPAT_FREEBSD32
126 error
= syscall32_helper_unregister(sctp32_syscalls
);
130 error
= syscall_helper_unregister(sctp_syscalls
);
140 sys_sctp_peeloff(struct thread
*td
, struct sctp_peeloff_args
*uap
)
142 struct file
*headfp
, *nfp
= NULL
;
143 struct socket
*head
, *so
;
144 struct filecaps fcaps
;
149 AUDIT_ARG_FD(uap
->sd
);
150 error
= getsock_cap(td
, uap
->sd
,
151 cap_rights_init_one(&rights
, CAP_PEELOFF
), &headfp
, &fcaps
);
154 fflag
= atomic_load_int(&headfp
->f_flag
);
155 head
= headfp
->f_data
;
156 if (head
->so_proto
->pr_protocol
!= IPPROTO_SCTP
) {
160 error
= sctp_can_peel_off(head
, (sctp_assoc_t
)uap
->name
);
164 * At this point we know we do have a assoc to pull
165 * we proceed to get the fd setup. This may block
169 error
= falloc_caps(td
, &nfp
, &fd
, 0, &fcaps
);
172 td
->td_retval
[0] = fd
;
174 CURVNET_SET(head
->so_vnet
);
175 so
= sopeeloff(head
);
180 finit(nfp
, fflag
, DTYPE_SOCKET
, so
, &socketops
);
181 error
= sctp_do_peeloff(head
, so
, (sctp_assoc_t
)uap
->name
);
184 if (head
->so_sigio
!= NULL
)
185 fsetown(fgetown(&head
->so_sigio
), &so
->so_sigio
);
189 * close the new descriptor, assuming someone hasn't ripped it
193 fdclose(td
, nfp
, fd
);
196 * Release explicitly held references before returning.
208 sys_sctp_generic_sendmsg(struct thread
*td
, struct sctp_generic_sendmsg_args
*uap
)
210 struct sctp_sndrcvinfo sinfo
, *u_sinfo
= NULL
;
212 struct file
*fp
= NULL
;
213 struct sockaddr
*to
= NULL
;
215 struct uio
*ktruio
= NULL
;
222 if (uap
->sinfo
!= NULL
) {
223 error
= copyin(uap
->sinfo
, &sinfo
, sizeof (sinfo
));
229 cap_rights_init_one(&rights
, CAP_SEND
);
230 if (uap
->tolen
!= 0) {
231 error
= getsockaddr(&to
, uap
->to
, uap
->tolen
);
236 cap_rights_set_one(&rights
, CAP_CONNECT
);
239 AUDIT_ARG_FD(uap
->sd
);
240 error
= getsock(td
, uap
->sd
, &rights
, &fp
);
244 if (to
&& (KTRPOINT(td
, KTR_STRUCT
)))
248 iov
[0].iov_base
= uap
->msg
;
249 iov
[0].iov_len
= uap
->mlen
;
251 so
= (struct socket
*)fp
->f_data
;
252 if (so
->so_proto
->pr_protocol
!= IPPROTO_SCTP
) {
257 error
= mac_socket_check_send(td
->td_ucred
, so
);
264 auio
.uio_segflg
= UIO_USERSPACE
;
265 auio
.uio_rw
= UIO_WRITE
;
267 auio
.uio_offset
= 0; /* XXX */
270 if (KTRPOINT(td
, KTR_GENIO
))
271 ktruio
= cloneuio(&auio
);
273 len
= auio
.uio_resid
= uap
->mlen
;
274 CURVNET_SET(so
->so_vnet
);
275 error
= sctp_lower_sosend(so
, to
, &auio
, (struct mbuf
*)NULL
,
276 (struct mbuf
*)NULL
, uap
->flags
, u_sinfo
, td
);
279 if (auio
.uio_resid
!= len
&& (error
== ERESTART
||
280 error
== EINTR
|| error
== EWOULDBLOCK
))
282 /* Generation of SIGPIPE can be controlled per socket. */
283 if (error
== EPIPE
&& !(so
->so_options
& SO_NOSIGPIPE
) &&
284 !(uap
->flags
& MSG_NOSIGNAL
)) {
285 PROC_LOCK(td
->td_proc
);
286 tdsignal(td
, SIGPIPE
);
287 PROC_UNLOCK(td
->td_proc
);
291 td
->td_retval
[0] = len
- auio
.uio_resid
;
293 if (ktruio
!= NULL
) {
295 ktruio
->uio_resid
= td
->td_retval
[0];
296 ktrgenio(uap
->sd
, UIO_WRITE
, ktruio
, error
);
308 sys_sctp_generic_sendmsg_iov(struct thread
*td
, struct sctp_generic_sendmsg_iov_args
*uap
)
310 struct sctp_sndrcvinfo sinfo
, *u_sinfo
= NULL
;
312 struct file
*fp
= NULL
;
313 struct sockaddr
*to
= NULL
;
315 struct uio
*ktruio
= NULL
;
318 struct iovec
*iov
, *tiov
;
323 if (uap
->sinfo
!= NULL
) {
324 error
= copyin(uap
->sinfo
, &sinfo
, sizeof (sinfo
));
329 cap_rights_init_one(&rights
, CAP_SEND
);
330 if (uap
->tolen
!= 0) {
331 error
= getsockaddr(&to
, uap
->to
, uap
->tolen
);
336 cap_rights_set_one(&rights
, CAP_CONNECT
);
339 AUDIT_ARG_FD(uap
->sd
);
340 error
= getsock(td
, uap
->sd
, &rights
, &fp
);
344 #ifdef COMPAT_FREEBSD32
345 if (SV_CURPROC_FLAG(SV_ILP32
))
346 error
= freebsd32_copyiniov((struct iovec32
*)uap
->iov
,
347 uap
->iovlen
, &iov
, EMSGSIZE
);
350 error
= copyiniov(uap
->iov
, uap
->iovlen
, &iov
, EMSGSIZE
);
354 if (to
&& (KTRPOINT(td
, KTR_STRUCT
)))
358 so
= (struct socket
*)fp
->f_data
;
359 if (so
->so_proto
->pr_protocol
!= IPPROTO_SCTP
) {
364 error
= mac_socket_check_send(td
->td_ucred
, so
);
370 auio
.uio_iovcnt
= uap
->iovlen
;
371 auio
.uio_segflg
= UIO_USERSPACE
;
372 auio
.uio_rw
= UIO_WRITE
;
374 auio
.uio_offset
= 0; /* XXX */
377 for (i
= 0; i
<uap
->iovlen
; i
++, tiov
++) {
378 if ((auio
.uio_resid
+= tiov
->iov_len
) < 0) {
384 if (KTRPOINT(td
, KTR_GENIO
))
385 ktruio
= cloneuio(&auio
);
387 len
= auio
.uio_resid
;
388 CURVNET_SET(so
->so_vnet
);
389 error
= sctp_lower_sosend(so
, to
, &auio
,
390 (struct mbuf
*)NULL
, (struct mbuf
*)NULL
,
391 uap
->flags
, u_sinfo
, td
);
394 if (auio
.uio_resid
!= len
&& (error
== ERESTART
||
395 error
== EINTR
|| error
== EWOULDBLOCK
))
397 /* Generation of SIGPIPE can be controlled per socket */
398 if (error
== EPIPE
&& !(so
->so_options
& SO_NOSIGPIPE
) &&
399 !(uap
->flags
& MSG_NOSIGNAL
)) {
400 PROC_LOCK(td
->td_proc
);
401 tdsignal(td
, SIGPIPE
);
402 PROC_UNLOCK(td
->td_proc
);
406 td
->td_retval
[0] = len
- auio
.uio_resid
;
408 if (ktruio
!= NULL
) {
410 ktruio
->uio_resid
= td
->td_retval
[0];
411 ktrgenio(uap
->sd
, UIO_WRITE
, ktruio
, error
);
425 sys_sctp_generic_recvmsg(struct thread
*td
, struct sctp_generic_recvmsg_args
*uap
)
427 uint8_t sockbufstore
[256];
429 struct iovec
*iov
, *tiov
;
430 struct sctp_sndrcvinfo sinfo
;
432 struct file
*fp
= NULL
;
433 struct sockaddr
*fromsa
;
436 struct uio
*ktruio
= NULL
;
439 int error
, fromlen
, i
, msg_flags
;
441 AUDIT_ARG_FD(uap
->sd
);
442 error
= getsock(td
, uap
->sd
, cap_rights_init_one(&rights
, CAP_RECV
),
446 #ifdef COMPAT_FREEBSD32
447 if (SV_CURPROC_FLAG(SV_ILP32
))
448 error
= freebsd32_copyiniov((struct iovec32
*)uap
->iov
,
449 uap
->iovlen
, &iov
, EMSGSIZE
);
452 error
= copyiniov(uap
->iov
, uap
->iovlen
, &iov
, EMSGSIZE
);
457 if (so
->so_proto
->pr_protocol
!= IPPROTO_SCTP
) {
462 error
= mac_socket_check_receive(td
->td_ucred
, so
);
467 if (uap
->fromlenaddr
!= NULL
) {
468 error
= copyin(uap
->fromlenaddr
, &fromlen
, sizeof (fromlen
));
474 if (uap
->msg_flags
) {
475 error
= copyin(uap
->msg_flags
, &msg_flags
, sizeof (int));
482 auio
.uio_iovcnt
= uap
->iovlen
;
483 auio
.uio_segflg
= UIO_USERSPACE
;
484 auio
.uio_rw
= UIO_READ
;
486 auio
.uio_offset
= 0; /* XXX */
489 for (i
= 0; i
<uap
->iovlen
; i
++, tiov
++) {
490 if ((auio
.uio_resid
+= tiov
->iov_len
) < 0) {
495 len
= auio
.uio_resid
;
496 fromsa
= (struct sockaddr
*)sockbufstore
;
499 if (KTRPOINT(td
, KTR_GENIO
))
500 ktruio
= cloneuio(&auio
);
502 memset(&sinfo
, 0, sizeof(struct sctp_sndrcvinfo
));
503 CURVNET_SET(so
->so_vnet
);
504 error
= sctp_sorecvmsg(so
, &auio
, (struct mbuf
**)NULL
,
505 fromsa
, fromlen
, &msg_flags
,
506 (struct sctp_sndrcvinfo
*)&sinfo
, 1);
509 if (auio
.uio_resid
!= len
&& (error
== ERESTART
||
510 error
== EINTR
|| error
== EWOULDBLOCK
))
514 error
= copyout(&sinfo
, uap
->sinfo
, sizeof (sinfo
));
517 if (ktruio
!= NULL
) {
518 ktruio
->uio_resid
= len
- auio
.uio_resid
;
519 ktrgenio(uap
->sd
, UIO_READ
, ktruio
, error
);
524 td
->td_retval
[0] = len
- auio
.uio_resid
;
526 if (fromlen
&& uap
->from
) {
528 if (len
<= 0 || fromsa
== NULL
)
531 len
= MIN(len
, fromsa
->sa_len
);
532 error
= copyout(fromsa
, uap
->from
, (size_t)len
);
536 error
= copyout(&len
, uap
->fromlenaddr
, sizeof (socklen_t
));
541 if (KTRPOINT(td
, KTR_STRUCT
))
544 if (uap
->msg_flags
) {
545 error
= copyout(&msg_flags
, uap
->msg_flags
, sizeof (int));