* Convert a user file descriptor to a kernel file entry and check that, if it * is a capability, the correct rights are present. A reference on the file * entry is held upon returning. */
| 4237 | * entry is held upon returning. |
| 4238 | */ |
| 4239 | int |
| 4240 | getvnode(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp) |
| 4241 | { |
| 4242 | struct file *fp; |
| 4243 | int error; |
| 4244 | |
| 4245 | error = fget_unlocked(td->td_proc->p_fd, fd, rightsp, &fp); |
| 4246 | if (error != 0) |
| 4247 | return (error); |
| 4248 | |
| 4249 | /* |
| 4250 | * The file could be not of the vnode type, or it may be not |
| 4251 | * yet fully initialized, in which case the f_vnode pointer |
| 4252 | * may be set, but f_ops is still badfileops. E.g., |
| 4253 | * devfs_open() transiently create such situation to |
| 4254 | * facilitate csw d_fdopen(). |
| 4255 | * |
| 4256 | * Dupfdopen() handling in kern_openat() installs the |
| 4257 | * half-baked file into the process descriptor table, allowing |
| 4258 | * other thread to dereference it. Guard against the race by |
| 4259 | * checking f_ops. |
| 4260 | */ |
| 4261 | if (fp->f_vnode == NULL || fp->f_ops == &badfileops) { |
| 4262 | fdrop(fp, td); |
| 4263 | return (EINVAL); |
| 4264 | } |
| 4265 | *fpp = fp; |
| 4266 | return (0); |
| 4267 | } |
| 4268 | |
| 4269 | /* |
| 4270 | * Get an (NFS) file handle. |
no test coverage detected