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 * 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. 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$"); 33 34 #include "opt_capsicum.h" 35 #include "opt_inet.h" 36 #include "opt_inet6.h" 37 #include "opt_sctp.h" 38 #include "opt_ktrace.h" 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/capsicum.h> 43 #include <sys/kernel.h> 44 #include <sys/lock.h> 45 #include <sys/mutex.h> 46 #include <sys/sysproto.h> 47 #include <sys/malloc.h> 48 #include <sys/filedesc.h> 49 #include <sys/event.h> 50 #include <sys/proc.h> 51 #include <sys/fcntl.h> 52 #include <sys/file.h> 53 #include <sys/filio.h> 54 #include <sys/jail.h> 55 #include <sys/mount.h> 56 #include <sys/mbuf.h> 57 #include <sys/protosw.h> 58 #include <sys/sf_buf.h> 59 #include <sys/sysent.h> 60 #include <sys/socket.h> 61 #include <sys/socketvar.h> 62 #include <sys/signalvar.h> 63 #include <sys/syscall.h> 64 #include <sys/syscallsubr.h> 65 #include <sys/sysctl.h> 66 #include <sys/uio.h> 67 #include <sys/vnode.h> 68 #ifdef KTRACE 69 #include <sys/ktrace.h> 70 #endif 71 #ifdef COMPAT_FREEBSD32 72 #include <compat/freebsd32/freebsd32_util.h> 73 #endif 74 75 #include <net/vnet.h> 76 77 #include <security/audit/audit.h> 78 #include <security/mac/mac_framework.h> 79 80 #include <netinet/sctp.h> 81 #include <netinet/sctp_peeloff.h> 82 83 static struct syscall_helper_data sctp_syscalls[] = { 84 SYSCALL_INIT_HELPER_F(sctp_peeloff, SYF_CAPENABLED), 85 SYSCALL_INIT_HELPER_F(sctp_generic_sendmsg, SYF_CAPENABLED), 86 SYSCALL_INIT_HELPER_F(sctp_generic_sendmsg_iov, SYF_CAPENABLED), 87 SYSCALL_INIT_HELPER_F(sctp_generic_recvmsg, SYF_CAPENABLED), 88 SYSCALL_INIT_LAST 89 }; 90 91 static void 92 sctp_syscalls_init(void *unused __unused) 93 { 94 int error __unused; 95 96 error = syscall_helper_register(sctp_syscalls, SY_THR_STATIC); 97 KASSERT((error == 0), 98 ("%s: syscall_helper_register failed for sctp syscalls", __func__)); 99 #ifdef COMPAT_FREEBSD32 100 error = syscall32_helper_register(sctp_syscalls, SY_THR_STATIC); 101 KASSERT((error == 0), 102 ("%s: syscall32_helper_register failed for sctp syscalls", 103 __func__)); 104 #endif 105 } 106 SYSINIT(sctp_syscalls, SI_SUB_SYSCALLS, SI_ORDER_ANY, sctp_syscalls_init, NULL); 107 108 /* 109 * SCTP syscalls. 110 * Functionality only compiled in if SCTP is defined in the kernel Makefile, 111 * otherwise all return EOPNOTSUPP. 112 * XXX: We should make this loadable one day. 113 */ 114 int 115 sys_sctp_peeloff(td, uap) 116 struct thread *td; 117 struct sctp_peeloff_args /* { 118 int sd; 119 caddr_t name; 120 } */ *uap; 121 { 122 #if (defined(INET) || defined(INET6)) && defined(SCTP) 123 struct file *headfp, *nfp = NULL; 124 struct socket *head, *so; 125 cap_rights_t rights; 126 u_int fflag; 127 int error, fd; 128 129 AUDIT_ARG_FD(uap->sd); 130 error = getsock_cap(td, uap->sd, cap_rights_init(&rights, CAP_PEELOFF), 131 &headfp, &fflag, NULL); 132 if (error != 0) 133 goto done2; 134 head = headfp->f_data; 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 = sopeeloff(head); 155 if (so == NULL) { 156 error = ENOMEM; 157 goto noconnection; 158 } 159 finit(nfp, fflag, DTYPE_SOCKET, so, &socketops); 160 error = sctp_do_peeloff(head, so, (sctp_assoc_t)uap->name); 161 if (error != 0) 162 goto noconnection; 163 if (head->so_sigio != NULL) 164 fsetown(fgetown(&head->so_sigio), &so->so_sigio); 165 166 noconnection: 167 /* 168 * close the new descriptor, assuming someone hasn't ripped it 169 * out from under us. 170 */ 171 if (error != 0) 172 fdclose(td, nfp, fd); 173 174 /* 175 * Release explicitly held references before returning. 176 */ 177 CURVNET_RESTORE(); 178 done: 179 if (nfp != NULL) 180 fdrop(nfp, td); 181 fdrop(headfp, td); 182 done2: 183 return (error); 184 #else /* SCTP */ 185 return (EOPNOTSUPP); 186 #endif /* SCTP */ 187 } 188 189 int 190 sys_sctp_generic_sendmsg (td, uap) 191 struct thread *td; 192 struct sctp_generic_sendmsg_args /* { 193 int sd, 194 caddr_t msg, 195 int mlen, 196 caddr_t to, 197 __socklen_t tolen, 198 struct sctp_sndrcvinfo *sinfo, 199 int flags 200 } */ *uap; 201 { 202 #if (defined(INET) || defined(INET6)) && defined(SCTP) 203 struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL; 204 struct socket *so; 205 struct file *fp = NULL; 206 struct sockaddr *to = NULL; 207 #ifdef KTRACE 208 struct uio *ktruio = NULL; 209 #endif 210 struct uio auio; 211 struct iovec iov[1]; 212 cap_rights_t rights; 213 int error = 0, len; 214 215 if (uap->sinfo != NULL) { 216 error = copyin(uap->sinfo, &sinfo, sizeof (sinfo)); 217 if (error != 0) 218 return (error); 219 u_sinfo = &sinfo; 220 } 221 222 cap_rights_init_one(&rights, CAP_SEND); 223 if (uap->tolen != 0) { 224 error = getsockaddr(&to, uap->to, uap->tolen); 225 if (error != 0) { 226 to = NULL; 227 goto sctp_bad2; 228 } 229 cap_rights_set_one(&rights, CAP_CONNECT); 230 } 231 232 AUDIT_ARG_FD(uap->sd); 233 error = getsock_cap(td, uap->sd, &rights, &fp, NULL, NULL); 234 if (error != 0) 235 goto sctp_bad; 236 #ifdef KTRACE 237 if (to && (KTRPOINT(td, KTR_STRUCT))) 238 ktrsockaddr(to); 239 #endif 240 241 iov[0].iov_base = uap->msg; 242 iov[0].iov_len = uap->mlen; 243 244 so = (struct socket *)fp->f_data; 245 if (so->so_proto->pr_protocol != IPPROTO_SCTP) { 246 error = EOPNOTSUPP; 247 goto sctp_bad; 248 } 249 #ifdef MAC 250 error = mac_socket_check_send(td->td_ucred, so); 251 if (error != 0) 252 goto sctp_bad; 253 #endif /* MAC */ 254 255 auio.uio_iov = iov; 256 auio.uio_iovcnt = 1; 257 auio.uio_segflg = UIO_USERSPACE; 258 auio.uio_rw = UIO_WRITE; 259 auio.uio_td = td; 260 auio.uio_offset = 0; /* XXX */ 261 auio.uio_resid = 0; 262 #ifdef KTRACE 263 if (KTRPOINT(td, KTR_GENIO)) 264 ktruio = cloneuio(&auio); 265 #endif /* KTRACE */ 266 len = auio.uio_resid = uap->mlen; 267 CURVNET_SET(so->so_vnet); 268 error = sctp_lower_sosend(so, to, &auio, (struct mbuf *)NULL, 269 (struct mbuf *)NULL, uap->flags, u_sinfo, td); 270 CURVNET_RESTORE(); 271 if (error != 0) { 272 if (auio.uio_resid != len && (error == ERESTART || 273 error == EINTR || error == EWOULDBLOCK)) 274 error = 0; 275 /* Generation of SIGPIPE can be controlled per socket. */ 276 if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) && 277 !(uap->flags & MSG_NOSIGNAL)) { 278 PROC_LOCK(td->td_proc); 279 tdsignal(td, SIGPIPE); 280 PROC_UNLOCK(td->td_proc); 281 } 282 } 283 if (error == 0) 284 td->td_retval[0] = len - auio.uio_resid; 285 #ifdef KTRACE 286 if (ktruio != NULL) { 287 ktruio->uio_resid = td->td_retval[0]; 288 ktrgenio(uap->sd, UIO_WRITE, ktruio, error); 289 } 290 #endif /* KTRACE */ 291 sctp_bad: 292 if (fp != NULL) 293 fdrop(fp, td); 294 sctp_bad2: 295 free(to, M_SONAME); 296 return (error); 297 #else /* SCTP */ 298 return (EOPNOTSUPP); 299 #endif /* SCTP */ 300 } 301 302 int 303 sys_sctp_generic_sendmsg_iov(td, uap) 304 struct thread *td; 305 struct sctp_generic_sendmsg_iov_args /* { 306 int sd, 307 struct iovec *iov, 308 int iovlen, 309 caddr_t to, 310 __socklen_t tolen, 311 struct sctp_sndrcvinfo *sinfo, 312 int flags 313 } */ *uap; 314 { 315 #if (defined(INET) || defined(INET6)) && defined(SCTP) 316 struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL; 317 struct socket *so; 318 struct file *fp = NULL; 319 struct sockaddr *to = NULL; 320 #ifdef KTRACE 321 struct uio *ktruio = NULL; 322 #endif 323 struct uio auio; 324 struct iovec *iov, *tiov; 325 cap_rights_t rights; 326 ssize_t len; 327 int error, i; 328 329 if (uap->sinfo != NULL) { 330 error = copyin(uap->sinfo, &sinfo, sizeof (sinfo)); 331 if (error != 0) 332 return (error); 333 u_sinfo = &sinfo; 334 } 335 cap_rights_init_one(&rights, CAP_SEND); 336 if (uap->tolen != 0) { 337 error = getsockaddr(&to, uap->to, uap->tolen); 338 if (error != 0) { 339 to = NULL; 340 goto sctp_bad2; 341 } 342 cap_rights_set_one(&rights, CAP_CONNECT); 343 } 344 345 AUDIT_ARG_FD(uap->sd); 346 error = getsock_cap(td, uap->sd, &rights, &fp, NULL, NULL); 347 if (error != 0) 348 goto sctp_bad1; 349 350 #ifdef COMPAT_FREEBSD32 351 if (SV_CURPROC_FLAG(SV_ILP32)) 352 error = freebsd32_copyiniov((struct iovec32 *)uap->iov, 353 uap->iovlen, &iov, EMSGSIZE); 354 else 355 #endif 356 error = copyiniov(uap->iov, uap->iovlen, &iov, EMSGSIZE); 357 if (error != 0) 358 goto sctp_bad1; 359 #ifdef KTRACE 360 if (to && (KTRPOINT(td, KTR_STRUCT))) 361 ktrsockaddr(to); 362 #endif 363 364 so = (struct socket *)fp->f_data; 365 if (so->so_proto->pr_protocol != IPPROTO_SCTP) { 366 error = EOPNOTSUPP; 367 goto sctp_bad; 368 } 369 #ifdef MAC 370 error = mac_socket_check_send(td->td_ucred, so); 371 if (error != 0) 372 goto sctp_bad; 373 #endif /* MAC */ 374 375 auio.uio_iov = iov; 376 auio.uio_iovcnt = uap->iovlen; 377 auio.uio_segflg = UIO_USERSPACE; 378 auio.uio_rw = UIO_WRITE; 379 auio.uio_td = td; 380 auio.uio_offset = 0; /* XXX */ 381 auio.uio_resid = 0; 382 tiov = iov; 383 for (i = 0; i <uap->iovlen; i++, tiov++) { 384 if ((auio.uio_resid += tiov->iov_len) < 0) { 385 error = EINVAL; 386 goto sctp_bad; 387 } 388 } 389 #ifdef KTRACE 390 if (KTRPOINT(td, KTR_GENIO)) 391 ktruio = cloneuio(&auio); 392 #endif /* KTRACE */ 393 len = auio.uio_resid; 394 CURVNET_SET(so->so_vnet); 395 error = sctp_lower_sosend(so, to, &auio, 396 (struct mbuf *)NULL, (struct mbuf *)NULL, 397 uap->flags, u_sinfo, td); 398 CURVNET_RESTORE(); 399 if (error != 0) { 400 if (auio.uio_resid != len && (error == ERESTART || 401 error == EINTR || error == EWOULDBLOCK)) 402 error = 0; 403 /* Generation of SIGPIPE can be controlled per socket */ 404 if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) && 405 !(uap->flags & MSG_NOSIGNAL)) { 406 PROC_LOCK(td->td_proc); 407 tdsignal(td, SIGPIPE); 408 PROC_UNLOCK(td->td_proc); 409 } 410 } 411 if (error == 0) 412 td->td_retval[0] = len - auio.uio_resid; 413 #ifdef KTRACE 414 if (ktruio != NULL) { 415 ktruio->uio_resid = td->td_retval[0]; 416 ktrgenio(uap->sd, UIO_WRITE, ktruio, error); 417 } 418 #endif /* KTRACE */ 419 sctp_bad: 420 free(iov, M_IOV); 421 sctp_bad1: 422 if (fp != NULL) 423 fdrop(fp, td); 424 sctp_bad2: 425 free(to, M_SONAME); 426 return (error); 427 #else /* SCTP */ 428 return (EOPNOTSUPP); 429 #endif /* SCTP */ 430 } 431 432 int 433 sys_sctp_generic_recvmsg(td, uap) 434 struct thread *td; 435 struct sctp_generic_recvmsg_args /* { 436 int sd, 437 struct iovec *iov, 438 int iovlen, 439 struct sockaddr *from, 440 __socklen_t *fromlenaddr, 441 struct sctp_sndrcvinfo *sinfo, 442 int *msg_flags 443 } */ *uap; 444 { 445 #if (defined(INET) || defined(INET6)) && defined(SCTP) 446 uint8_t sockbufstore[256]; 447 struct uio auio; 448 struct iovec *iov, *tiov; 449 struct sctp_sndrcvinfo sinfo; 450 struct socket *so; 451 struct file *fp = NULL; 452 struct sockaddr *fromsa; 453 cap_rights_t rights; 454 #ifdef KTRACE 455 struct uio *ktruio = NULL; 456 #endif 457 ssize_t len; 458 int error, fromlen, i, msg_flags; 459 460 AUDIT_ARG_FD(uap->sd); 461 error = getsock_cap(td, uap->sd, cap_rights_init(&rights, CAP_RECV), 462 &fp, NULL, NULL); 463 if (error != 0) 464 return (error); 465 #ifdef COMPAT_FREEBSD32 466 if (SV_CURPROC_FLAG(SV_ILP32)) 467 error = freebsd32_copyiniov((struct iovec32 *)uap->iov, 468 uap->iovlen, &iov, EMSGSIZE); 469 else 470 #endif 471 error = copyiniov(uap->iov, uap->iovlen, &iov, EMSGSIZE); 472 if (error != 0) 473 goto out1; 474 475 so = fp->f_data; 476 if (so->so_proto->pr_protocol != IPPROTO_SCTP) { 477 error = EOPNOTSUPP; 478 goto out; 479 } 480 #ifdef MAC 481 error = mac_socket_check_receive(td->td_ucred, so); 482 if (error != 0) 483 goto out; 484 #endif /* MAC */ 485 486 if (uap->fromlenaddr != NULL) { 487 error = copyin(uap->fromlenaddr, &fromlen, sizeof (fromlen)); 488 if (error != 0) 489 goto out; 490 } else { 491 fromlen = 0; 492 } 493 if (uap->msg_flags) { 494 error = copyin(uap->msg_flags, &msg_flags, sizeof (int)); 495 if (error != 0) 496 goto out; 497 } else { 498 msg_flags = 0; 499 } 500 auio.uio_iov = iov; 501 auio.uio_iovcnt = uap->iovlen; 502 auio.uio_segflg = UIO_USERSPACE; 503 auio.uio_rw = UIO_READ; 504 auio.uio_td = td; 505 auio.uio_offset = 0; /* XXX */ 506 auio.uio_resid = 0; 507 tiov = iov; 508 for (i = 0; i <uap->iovlen; i++, tiov++) { 509 if ((auio.uio_resid += tiov->iov_len) < 0) { 510 error = EINVAL; 511 goto out; 512 } 513 } 514 len = auio.uio_resid; 515 fromsa = (struct sockaddr *)sockbufstore; 516 517 #ifdef KTRACE 518 if (KTRPOINT(td, KTR_GENIO)) 519 ktruio = cloneuio(&auio); 520 #endif /* KTRACE */ 521 memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo)); 522 CURVNET_SET(so->so_vnet); 523 error = sctp_sorecvmsg(so, &auio, (struct mbuf **)NULL, 524 fromsa, fromlen, &msg_flags, 525 (struct sctp_sndrcvinfo *)&sinfo, 1); 526 CURVNET_RESTORE(); 527 if (error != 0) { 528 if (auio.uio_resid != len && (error == ERESTART || 529 error == EINTR || error == EWOULDBLOCK)) 530 error = 0; 531 } else { 532 if (uap->sinfo) 533 error = copyout(&sinfo, uap->sinfo, sizeof (sinfo)); 534 } 535 #ifdef KTRACE 536 if (ktruio != NULL) { 537 ktruio->uio_resid = len - auio.uio_resid; 538 ktrgenio(uap->sd, UIO_READ, ktruio, error); 539 } 540 #endif /* KTRACE */ 541 if (error != 0) 542 goto out; 543 td->td_retval[0] = len - auio.uio_resid; 544 545 if (fromlen && uap->from) { 546 len = fromlen; 547 if (len <= 0 || fromsa == NULL) 548 len = 0; 549 else { 550 len = MIN(len, fromsa->sa_len); 551 error = copyout(fromsa, uap->from, (size_t)len); 552 if (error != 0) 553 goto out; 554 } 555 error = copyout(&len, uap->fromlenaddr, sizeof (socklen_t)); 556 if (error != 0) 557 goto out; 558 } 559 #ifdef KTRACE 560 if (KTRPOINT(td, KTR_STRUCT)) 561 ktrsockaddr(fromsa); 562 #endif 563 if (uap->msg_flags) { 564 error = copyout(&msg_flags, uap->msg_flags, sizeof (int)); 565 if (error != 0) 566 goto out; 567 } 568 out: 569 free(iov, M_IOV); 570 out1: 571 if (fp != NULL) 572 fdrop(fp, td); 573 574 return (error); 575 #else /* SCTP */ 576 return (EOPNOTSUPP); 577 #endif /* SCTP */ 578 } 579