10dac22d8SPawel Jakub Dawidek /*- 2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 37f2d13d6SPedro F. Giffuni * 40dac22d8SPawel Jakub Dawidek * Copyright (c) 2013 The FreeBSD Foundation 50dac22d8SPawel Jakub Dawidek * 60dac22d8SPawel Jakub Dawidek * This software was developed by Pawel Jakub Dawidek under sponsorship from 70dac22d8SPawel Jakub Dawidek * the FreeBSD Foundation. 80dac22d8SPawel Jakub Dawidek * 90dac22d8SPawel Jakub Dawidek * Redistribution and use in source and binary forms, with or without 100dac22d8SPawel Jakub Dawidek * modification, are permitted provided that the following conditions 110dac22d8SPawel Jakub Dawidek * are met: 120dac22d8SPawel Jakub Dawidek * 1. Redistributions of source code must retain the above copyright 130dac22d8SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer. 140dac22d8SPawel Jakub Dawidek * 2. Redistributions in binary form must reproduce the above copyright 150dac22d8SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer in the 160dac22d8SPawel Jakub Dawidek * documentation and/or other materials provided with the distribution. 170dac22d8SPawel Jakub Dawidek * 180dac22d8SPawel Jakub Dawidek * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 190dac22d8SPawel Jakub Dawidek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 200dac22d8SPawel Jakub Dawidek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 210dac22d8SPawel Jakub Dawidek * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 220dac22d8SPawel Jakub Dawidek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 230dac22d8SPawel Jakub Dawidek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 240dac22d8SPawel Jakub Dawidek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 250dac22d8SPawel Jakub Dawidek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 260dac22d8SPawel Jakub Dawidek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 270dac22d8SPawel Jakub Dawidek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 280dac22d8SPawel Jakub Dawidek * SUCH DAMAGE. 290dac22d8SPawel Jakub Dawidek */ 300dac22d8SPawel Jakub Dawidek 310dac22d8SPawel Jakub Dawidek #include <sys/cdefs.h> 320dac22d8SPawel Jakub Dawidek __FBSDID("$FreeBSD$"); 330dac22d8SPawel Jakub Dawidek 340dac22d8SPawel Jakub Dawidek #include "opt_capsicum.h" 350dac22d8SPawel Jakub Dawidek 360dac22d8SPawel Jakub Dawidek #include <sys/param.h> 374a144410SRobert Watson #include <sys/capsicum.h> 380dac22d8SPawel Jakub Dawidek #include <sys/filedesc.h> 3991898857SMark Johnston #include <sys/limits.h> 400dac22d8SPawel Jakub Dawidek #include <sys/malloc.h> 410dac22d8SPawel Jakub Dawidek #include <sys/proc.h> 420dac22d8SPawel Jakub Dawidek #include <sys/syscallsubr.h> 4332536142SPawel Jakub Dawidek #include <sys/sysproto.h> 440dac22d8SPawel Jakub Dawidek 450dac22d8SPawel Jakub Dawidek #include <security/audit/audit.h> 460dac22d8SPawel Jakub Dawidek 470dac22d8SPawel Jakub Dawidek #include <compat/freebsd32/freebsd32_proto.h> 480dac22d8SPawel Jakub Dawidek 490dac22d8SPawel Jakub Dawidek #ifdef CAPABILITIES 500dac22d8SPawel Jakub Dawidek 510dac22d8SPawel Jakub Dawidek MALLOC_DECLARE(M_FILECAPS); 520dac22d8SPawel Jakub Dawidek 530dac22d8SPawel Jakub Dawidek int 540dac22d8SPawel Jakub Dawidek freebsd32_cap_ioctls_limit(struct thread *td, 550dac22d8SPawel Jakub Dawidek struct freebsd32_cap_ioctls_limit_args *uap) 560dac22d8SPawel Jakub Dawidek { 570dac22d8SPawel Jakub Dawidek u_long *cmds; 580dac22d8SPawel Jakub Dawidek uint32_t *cmds32; 590dac22d8SPawel Jakub Dawidek size_t ncmds; 600dac22d8SPawel Jakub Dawidek u_int i; 610dac22d8SPawel Jakub Dawidek int error; 620dac22d8SPawel Jakub Dawidek 630dac22d8SPawel Jakub Dawidek ncmds = uap->ncmds; 640dac22d8SPawel Jakub Dawidek 650dac22d8SPawel Jakub Dawidek if (ncmds > 256) /* XXX: Is 256 sane? */ 660dac22d8SPawel Jakub Dawidek return (EINVAL); 670dac22d8SPawel Jakub Dawidek 680dac22d8SPawel Jakub Dawidek if (ncmds == 0) { 690dac22d8SPawel Jakub Dawidek cmds = NULL; 700dac22d8SPawel Jakub Dawidek } else { 710dac22d8SPawel Jakub Dawidek cmds32 = malloc(sizeof(cmds32[0]) * ncmds, M_FILECAPS, M_WAITOK); 720dac22d8SPawel Jakub Dawidek error = copyin(uap->cmds, cmds32, sizeof(cmds32[0]) * ncmds); 730dac22d8SPawel Jakub Dawidek if (error != 0) { 740dac22d8SPawel Jakub Dawidek free(cmds32, M_FILECAPS); 750dac22d8SPawel Jakub Dawidek return (error); 760dac22d8SPawel Jakub Dawidek } 770dac22d8SPawel Jakub Dawidek cmds = malloc(sizeof(cmds[0]) * ncmds, M_FILECAPS, M_WAITOK); 780dac22d8SPawel Jakub Dawidek for (i = 0; i < ncmds; i++) 790dac22d8SPawel Jakub Dawidek cmds[i] = cmds32[i]; 800dac22d8SPawel Jakub Dawidek free(cmds32, M_FILECAPS); 810dac22d8SPawel Jakub Dawidek } 820dac22d8SPawel Jakub Dawidek 830dac22d8SPawel Jakub Dawidek return (kern_cap_ioctls_limit(td, uap->fd, cmds, ncmds)); 840dac22d8SPawel Jakub Dawidek } 850dac22d8SPawel Jakub Dawidek 860dac22d8SPawel Jakub Dawidek int 870dac22d8SPawel Jakub Dawidek freebsd32_cap_ioctls_get(struct thread *td, 880dac22d8SPawel Jakub Dawidek struct freebsd32_cap_ioctls_get_args *uap) 890dac22d8SPawel Jakub Dawidek { 900dac22d8SPawel Jakub Dawidek struct filedesc *fdp; 910dac22d8SPawel Jakub Dawidek struct filedescent *fdep; 920dac22d8SPawel Jakub Dawidek uint32_t *cmds32; 930dac22d8SPawel Jakub Dawidek u_long *cmds; 940dac22d8SPawel Jakub Dawidek size_t maxcmds; 950dac22d8SPawel Jakub Dawidek int error, fd; 960dac22d8SPawel Jakub Dawidek u_int i; 970dac22d8SPawel Jakub Dawidek 980dac22d8SPawel Jakub Dawidek fd = uap->fd; 990dac22d8SPawel Jakub Dawidek cmds32 = uap->cmds; 1000dac22d8SPawel Jakub Dawidek maxcmds = uap->maxcmds; 1010dac22d8SPawel Jakub Dawidek 1020dac22d8SPawel Jakub Dawidek AUDIT_ARG_FD(fd); 1030dac22d8SPawel Jakub Dawidek 1040dac22d8SPawel Jakub Dawidek fdp = td->td_proc->p_fd; 1050dac22d8SPawel Jakub Dawidek FILEDESC_SLOCK(fdp); 1060dac22d8SPawel Jakub Dawidek 107f17ef286SMateusz Guzik if (fget_noref(fdp, fd) == NULL) { 1080dac22d8SPawel Jakub Dawidek error = EBADF; 1090dac22d8SPawel Jakub Dawidek goto out; 1100dac22d8SPawel Jakub Dawidek } 1110dac22d8SPawel Jakub Dawidek 1120dac22d8SPawel Jakub Dawidek /* 1130dac22d8SPawel Jakub Dawidek * If all ioctls are allowed (fde_nioctls == -1 && fde_ioctls == NULL) 1140dac22d8SPawel Jakub Dawidek * the only sane thing we can do is to not populate the given array and 1150dac22d8SPawel Jakub Dawidek * return CAP_IOCTLS_ALL (actually, INT_MAX). 1160dac22d8SPawel Jakub Dawidek */ 1170dac22d8SPawel Jakub Dawidek 1180dac22d8SPawel Jakub Dawidek fdep = &fdp->fd_ofiles[fd]; 1190dac22d8SPawel Jakub Dawidek cmds = fdep->fde_ioctls; 1200dac22d8SPawel Jakub Dawidek if (cmds32 != NULL && cmds != NULL) { 1210dac22d8SPawel Jakub Dawidek for (i = 0; i < MIN(fdep->fde_nioctls, maxcmds); i++) { 1220dac22d8SPawel Jakub Dawidek error = suword32(&cmds32[i], cmds[i]); 1230dac22d8SPawel Jakub Dawidek if (error != 0) 1240dac22d8SPawel Jakub Dawidek goto out; 1250dac22d8SPawel Jakub Dawidek } 1260dac22d8SPawel Jakub Dawidek } 1270dac22d8SPawel Jakub Dawidek if (fdep->fde_nioctls == -1) 1280dac22d8SPawel Jakub Dawidek td->td_retval[0] = INT_MAX; 1290dac22d8SPawel Jakub Dawidek else 1300dac22d8SPawel Jakub Dawidek td->td_retval[0] = fdep->fde_nioctls; 1310dac22d8SPawel Jakub Dawidek 1320dac22d8SPawel Jakub Dawidek error = 0; 1330dac22d8SPawel Jakub Dawidek out: 1340dac22d8SPawel Jakub Dawidek FILEDESC_SUNLOCK(fdp); 1350dac22d8SPawel Jakub Dawidek return (error); 1360dac22d8SPawel Jakub Dawidek } 1370dac22d8SPawel Jakub Dawidek 1380dac22d8SPawel Jakub Dawidek #else /* !CAPABILITIES */ 1390dac22d8SPawel Jakub Dawidek 1400dac22d8SPawel Jakub Dawidek int 1410dac22d8SPawel Jakub Dawidek freebsd32_cap_ioctls_limit(struct thread *td, 1420dac22d8SPawel Jakub Dawidek struct freebsd32_cap_ioctls_limit_args *uap) 1430dac22d8SPawel Jakub Dawidek { 1440dac22d8SPawel Jakub Dawidek 1450dac22d8SPawel Jakub Dawidek return (ENOSYS); 1460dac22d8SPawel Jakub Dawidek } 1470dac22d8SPawel Jakub Dawidek 1480dac22d8SPawel Jakub Dawidek int 1490dac22d8SPawel Jakub Dawidek freebsd32_cap_ioctls_get(struct thread *td, 1500dac22d8SPawel Jakub Dawidek struct freebsd32_cap_ioctls_get_args *uap) 1510dac22d8SPawel Jakub Dawidek { 1520dac22d8SPawel Jakub Dawidek 1530dac22d8SPawel Jakub Dawidek return (ENOSYS); 1540dac22d8SPawel Jakub Dawidek } 1550dac22d8SPawel Jakub Dawidek 1560dac22d8SPawel Jakub Dawidek #endif /* CAPABILITIES */ 157