| 230 | } |
| 231 | |
| 232 | int |
| 233 | kern_cap_rights_limit(struct thread *td, int fd, cap_rights_t *rights) |
| 234 | { |
| 235 | struct filedesc *fdp; |
| 236 | struct filedescent *fdep; |
| 237 | u_long *ioctls; |
| 238 | int error; |
| 239 | |
| 240 | fdp = td->td_proc->p_fd; |
| 241 | FILEDESC_XLOCK(fdp); |
| 242 | fdep = fdeget_locked(fdp, fd); |
| 243 | if (fdep == NULL) { |
| 244 | FILEDESC_XUNLOCK(fdp); |
| 245 | return (EBADF); |
| 246 | } |
| 247 | ioctls = NULL; |
| 248 | error = _cap_check(cap_rights(fdp, fd), rights, CAPFAIL_INCREASE); |
| 249 | if (error == 0) { |
| 250 | seqc_write_begin(&fdep->fde_seqc); |
| 251 | fdep->fde_rights = *rights; |
| 252 | if (!cap_rights_is_set(rights, CAP_IOCTL)) { |
| 253 | ioctls = fdep->fde_ioctls; |
| 254 | fdep->fde_ioctls = NULL; |
| 255 | fdep->fde_nioctls = 0; |
| 256 | } |
| 257 | if (!cap_rights_is_set(rights, CAP_FCNTL)) |
| 258 | fdep->fde_fcntls = 0; |
| 259 | seqc_write_end(&fdep->fde_seqc); |
| 260 | } |
| 261 | FILEDESC_XUNLOCK(fdp); |
| 262 | free(ioctls, M_FILECAPS); |
| 263 | return (error); |
| 264 | } |
| 265 | |
| 266 | /* |
| 267 | * System call to limit rights of the given capability. |
no test coverage detected