/* * The close() system call uses it's own audit call to capture the path/vnode * information because those pieces are not easily obtained within the system * call itself. */ void audit_sysclose(struct thread *td, int fd) { struct kaudit_record *ar; struct vnode *vp; struct file *fp; int vfslocked; KASSERT(td != NULL, ("audit_sysclose: td == NULL")); ar = currecord(); if (ar == NULL) return; audit_arg_fd(fd); if (getvnode(td->td_proc->p_fd, fd, &fp) != 0) return; vp = fp->f_vnode; vfslocked = VFS_LOCK_GIANT(vp->v_mount); vn_lock(vp, LK_SHARED | LK_RETRY); audit_arg_vnode1(vp); VOP_UNLOCK(vp, 0); VFS_UNLOCK_GIANT(vfslocked); fdrop(fp, td); }
static int fdesc_setattr(struct vop_setattr_args *ap) { struct vattr *vap = ap->a_vap; struct vnode *vp; struct mount *mp; struct file *fp; struct thread *td = curthread; cap_rights_t rights; unsigned fd; int error; /* * Can't mess with the root vnode */ if (VTOFDESC(ap->a_vp)->fd_type == Froot) return (EACCES); fd = VTOFDESC(ap->a_vp)->fd_fd; /* * Allow setattr where there is an underlying vnode. */ error = getvnode(td, fd, cap_rights_init(&rights, CAP_EXTATTR_SET), &fp); if (error) { /* * getvnode() returns EINVAL if the file descriptor is not * backed by a vnode. Silently drop all changes except * chflags(2) in this case. */ if (error == EINVAL) { if (vap->va_flags != VNOVAL) error = EOPNOTSUPP; else error = 0; } return (error); } vp = fp->f_vnode; if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) == 0) { vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); error = VOP_SETATTR(vp, ap->a_vap, ap->a_cred); VOP_UNLOCK(vp, 0); vn_finished_write(mp); } fdrop(fp, td); return (error); }
static int linux_getdents_error(struct thread *td, int fd, int err) { struct vnode *vp; struct file *fp; int error; /* Linux return ENOTDIR in case when fd is not a directory. */ error = getvnode(td, fd, &cap_read_rights, &fp); if (error != 0) return (error); vp = fp->f_vnode; if (vp->v_type != VDIR) { fdrop(fp, td); return (ENOTDIR); } fdrop(fp, td); return (err); }
/* * Given a file descriptor, check an ACL for it. */ int sys___acl_aclcheck_fd(struct proc *p, void *v, register_t *retval) { struct sys___acl_aclcheck_fd_args *uap = v; struct vnode *vp; struct file *fp; int error; error = getvnode(p->p_fd, SCARG(uap, filedes), &fp); if (error) return (error); vp = (struct vnode *)fp->f_data; vref(vp); /* vn_acl_check() will drop the reference. */ error = vn_acl_check(p, vp, SCARG(uap, type), SCARG(uap, aclp)); FRELE(fp); return (error); }
int sys_mquery(struct proc *p, void *v, register_t *retval) { struct sys_mquery_args /* { syscallarg(void *) addr; syscallarg(size_t) len; syscallarg(int) prot; syscallarg(int) flags; syscallarg(int) fd; syscallarg(long) pad; syscallarg(off_t) pos; } */ *uap = v; struct file *fp; struct uvm_object *uobj; voff_t uoff; int error; vaddr_t vaddr; int flags = 0; vsize_t size; vm_prot_t prot; int fd; vaddr = (vaddr_t) SCARG(uap, addr); prot = SCARG(uap, prot); size = (vsize_t) SCARG(uap, len); fd = SCARG(uap, fd); if ((prot & VM_PROT_ALL) != prot) return (EINVAL); if (SCARG(uap, flags) & MAP_FIXED) flags |= UVM_FLAG_FIXED; if (fd >= 0) { if ((error = getvnode(p->p_fd, fd, &fp)) != 0) return (error); uobj = &((struct vnode *)fp->f_data)->v_uvm.u_obj; uoff = SCARG(uap, pos); } else { fp = NULL; uobj = NULL; uoff = 0; } if (vaddr == 0) vaddr = uvm_map_hint(p, prot); /* prevent a user requested address from falling in heap space */ if ((vaddr + size > (vaddr_t)p->p_vmspace->vm_daddr) && (vaddr < (vaddr_t)p->p_vmspace->vm_daddr + MAXDSIZ)) { if (flags & UVM_FLAG_FIXED) { error = EINVAL; goto done; } vaddr = round_page((vaddr_t)p->p_vmspace->vm_daddr + MAXDSIZ); } vm_map_lock(&p->p_vmspace->vm_map); again: if (uvm_map_findspace(&p->p_vmspace->vm_map, vaddr, size, &vaddr, uobj, uoff, 0, flags) == NULL) { if (flags & UVM_FLAG_FIXED) error = EINVAL; else error = ENOMEM; } else { /* prevent a returned address from falling in heap space */ if ((vaddr + size > (vaddr_t)p->p_vmspace->vm_daddr) && (vaddr < (vaddr_t)p->p_vmspace->vm_daddr + MAXDSIZ)) { vaddr = round_page((vaddr_t)p->p_vmspace->vm_daddr + MAXDSIZ); goto again; } error = 0; *retval = (register_t)(vaddr); } vm_map_unlock(&p->p_vmspace->vm_map); done: if (fp != NULL) FRELE(fp); return (error); }
int diskmapioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { struct dk_diskmap *dm; struct nameidata ndp; struct filedesc *fdp; struct file *fp = NULL; struct vnode *vp = NULL, *ovp; char *devname; int fd, error = EINVAL; if (cmd != DIOCMAP) return EINVAL; /* * Map a request for a disk to the correct device. We should be * supplied with either a diskname or a disklabel UID. */ dm = (struct dk_diskmap *)addr; fd = dm->fd; devname = malloc(PATH_MAX, M_DEVBUF, M_WAITOK); if (copyinstr(dm->device, devname, PATH_MAX, NULL)) goto invalid; if (disk_map(devname, devname, PATH_MAX, dm->flags) == 0) if (copyoutstr(devname, dm->device, PATH_MAX, NULL)) goto invalid; /* Attempt to open actual device. */ fdp = p->p_fd; fdplock(fdp); if ((error = getvnode(fdp, fd, &fp)) != 0) goto bad; ndp.ni_segflg = UIO_SYSSPACE; ndp.ni_dirfd = AT_FDCWD; ndp.ni_dirp = devname; ndp.ni_cnd.cn_proc = p; if ((error = vn_open(&ndp, fp->f_flag, 0)) != 0) goto bad; vp = ndp.ni_vp; /* Close the original vnode. */ ovp = (struct vnode *)fp->f_data; if (fp->f_flag & FWRITE) ovp->v_writecount--; if (ovp->v_writecount == 0) { vn_lock(ovp, LK_EXCLUSIVE | LK_RETRY, p); VOP_CLOSE(ovp, fp->f_flag, p->p_ucred); vput(ovp); } fp->f_type = DTYPE_VNODE; fp->f_ops = &vnops; fp->f_data = (caddr_t)vp; fp->f_offset = 0; fp->f_rxfer = 0; fp->f_wxfer = 0; fp->f_seek = 0; fp->f_rbytes = 0; fp->f_wbytes = 0; VOP_UNLOCK(vp, 0); FRELE(fp, p); fdpunlock(fdp); free(devname, M_DEVBUF, 0); return 0; bad: if (vp) vput(vp); if (fp) FRELE(fp, p); fdpunlock(fdp); invalid: free(devname, M_DEVBUF, 0); return (error); }