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