int sys_cap_ioctls_limit(struct thread *td, struct cap_ioctls_limit_args *uap) { struct filedesc *fdp; u_long *cmds, *ocmds; size_t ncmds; int error, fd; fd = uap->fd; ncmds = uap->ncmds; AUDIT_ARG_FD(fd); if (ncmds > 256) /* XXX: Is 256 sane? */ return (EINVAL); if (ncmds == 0) { cmds = NULL; } else { cmds = malloc(sizeof(cmds[0]) * ncmds, M_TEMP, M_WAITOK); error = copyin(uap->cmds, cmds, sizeof(cmds[0]) * ncmds); if (error != 0) { free(cmds, M_TEMP); return (error); } } fdp = td->td_proc->p_fd; FILEDESC_XLOCK(fdp); if (fget_locked(fdp, fd) == NULL) { error = EBADF; goto out; } error = cap_ioctl_limit_check(fdp, fd, cmds, ncmds); if (error != 0) goto out; ocmds = fdp->fd_ofiles[fd].fde_ioctls; fdp->fd_ofiles[fd].fde_ioctls = cmds; fdp->fd_ofiles[fd].fde_nioctls = ncmds; cmds = ocmds; error = 0; out: FILEDESC_XUNLOCK(fdp); free(cmds, M_TEMP); return (error); }
int kern_cap_ioctls_limit(struct thread *td, int fd, u_long *cmds, size_t ncmds) { struct filedesc *fdp; struct filedescent *fdep; u_long *ocmds; int error; AUDIT_ARG_FD(fd); if (ncmds > IOCTLS_MAX_COUNT) { error = EINVAL; goto out_free; } fdp = td->td_proc->p_fd; FILEDESC_XLOCK(fdp); fdep = fdeget_locked(fdp, fd); if (fdep == NULL) { error = EBADF; goto out; } error = cap_ioctl_limit_check(fdep, cmds, ncmds); if (error != 0) goto out; ocmds = fdep->fde_ioctls; fdep->fde_ioctls = cmds; fdep->fde_nioctls = ncmds; cmds = ocmds; error = 0; out: FILEDESC_XUNLOCK(fdp); out_free: free(cmds, M_FILECAPS); return (error); }