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