Пример #1
0
/*
 * 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);
}
Пример #2
0
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);
}
Пример #3
0
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);
}
Пример #4
0
/*
 * 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);
}
Пример #5
0
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);
}
Пример #6
0
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);
}