Пример #1
2
int
sys_posix_openpt(struct thread *td, struct posix_openpt_args *uap)
{
	int error, fd;
	struct file *fp;

	/*
	 * POSIX states it's unspecified when other flags are passed. We
	 * don't allow this.
	 */
	if (uap->flags & ~(O_RDWR|O_NOCTTY|O_CLOEXEC))
		return (EINVAL);

	error = falloc(td, &fp, &fd, uap->flags);
	if (error)
		return (error);

	/* Allocate the actual pseudo-TTY. */
	error = pts_alloc(FFLAGS(uap->flags & O_ACCMODE), td, fp);
	if (error != 0) {
		fdclose(td, fp, fd);
		fdrop(fp, td);
		return (error);
	}

	/* Pass it back to userspace. */
	td->td_retval[0] = fd;
	fdrop(fp, td);

	return (0);
}
Пример #2
0
struct cfs_kern_file *
kern_file_open(const char * filename, int uflags, int mode, int *err)
{
        struct cfs_kern_file    *fp;
        vnode_t         vp;
        int             error;

        fp = (struct cfs_kern_file *)_MALLOC(sizeof(struct cfs_kern_file), M_TEMP, M_WAITOK);
        if (fp == NULL) {
                if (err != NULL)
                        *err = -ENOMEM;
                return NULL;
        }
        fp->f_flags = FFLAGS(uflags);
        fp->f_ctxt = vfs_context_create(NULL);

        if ((error = vnode_open(filename, fp->f_flags, 
                                mode, 0, &vp, fp->f_ctxt))){
                if (err != NULL)
                        *err = -error;
                _FREE(fp, M_TEMP);
        } else {
                if (err != NULL)
                        *err = 0;
                fp->f_vp = vp;
        }

        return fp;
}
Пример #3
0
/*
 * fp_open:
 *
 *	Open a file as specified.  Use O_* flags for flags.
 *
 *	vn_open() asserts that the cred must match the process's cred.
 *
 *	NOTE! when fp_open() is called from a pure thread, root creds are
 *	used.
 */
int
fp_open(const char *path, int flags, int mode, file_t *fpp)
{
    struct nlookupdata nd;
    struct thread *td;
    struct file *fp;
    int error;

    if ((error = falloc(NULL, fpp, NULL)) != 0)
	return (error);
    fp = *fpp;
    td = curthread;
    if (td->td_proc)
	fsetcred(fp, td->td_proc->p_ucred);
    error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_LOCKVP);
    flags = FFLAGS(flags);
    if (error == 0)
	error = vn_open(&nd, fp, flags, mode);
    nlookup_done(&nd);
    if (error) {
	fdrop(fp);
	*fpp = NULL;
    }
    return(error);
}
Пример #4
0
	cru2x(td->td_ucred, &msg.lm_cred);

	/*
	 * Open the lock fifo.  If for any reason we don't find the fifo, it
	 * means that the lock daemon isn't running.  Translate any missing
	 * file error message for the user, otherwise the application will
	 * complain that the user's file is missing, which isn't the case.
	 * Note that we use proc0's cred, so the fifo is opened as root.
	 *
	 * XXX: Note that this behavior is relative to the root directory
	 * of the current process, and this may result in a variety of
	 * {functional, security} problems in chroot() environments.
	 */
	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, _PATH_LCKFIFO, td);

	fmode = FFLAGS(O_WRONLY);
	error = vn_open_cred(&nd, &fmode, 0, thread0.td_ucred);
	if (error != 0) {
		return (error == ENOENT ? EOPNOTSUPP : error);
	}
	wvp = nd.ni_vp;
	VOP_UNLOCK(wvp, 0, td);		/* vn_open leaves it locked */


	ioflg = IO_UNIT | IO_NOMACCHECK;
	for (;;) {
		VOP_LEASE(wvp, td, thread0.td_ucred, LEASE_WRITE);

		error = vn_rdwr(UIO_WRITE, wvp, (caddr_t)&msg, sizeof(msg), 0,
		    UIO_SYSSPACE, ioflg, thread0.td_ucred, NOCRED, NULL, td);
Пример #5
0
int
xfs_fhopen (d_thread_t *proc,
	    struct xfs_fhandle_t *fhp,
	    int user_flags,
	    register_t *retval)
{
    int error;
    struct vnode *vp;
#ifdef HAVE_FREEBSD_THREAD
    struct ucred *cred = proc->td_proc->p_ucred;
#else
    struct ucred *cred = proc->p_ucred;
#endif
    int flags = FFLAGS(user_flags);
    int index;
    struct file *fp;
    int mode;
    struct xfs_fhandle_t fh;

    NNPFSDEB(XDEBVFOPS, ("xfs_fhopen: flags = %d\n", user_flags));

    error = copyin (fhp, &fh, sizeof(fh));
    if (error)
	return error;

    error = xfs_fhlookup (proc, &fh, &vp);
    NNPFSDEB(XDEBVFOPS, ("xfs_fhlookup returned %d\n", error));
    if (error)
	return error;

    switch (vp->v_type) {
    case VDIR :
    case VREG :
	break;
    case VLNK :
	error = EMLINK;
	goto out;
    default :
	error = EOPNOTSUPP;
	goto out;
    }

    mode = 0;
    if (flags & FWRITE) {
	switch (vp->v_type) {
	case VREG :
	    break;
	case VDIR :
	    error = EISDIR;
	    goto out;
	default :
	    error = EOPNOTSUPP;
	    goto out;
	}

	error = vn_writechk (vp);
	if (error)
	    goto out;

	mode |= VWRITE;
    }
    if (flags & FREAD)
	mode |= VREAD;

    if (mode) {
	error = VOP_ACCESS(vp, mode, cred, proc);
	if (error)
	    goto out;
    }

    error = VOP_OPEN(vp, flags, cred, proc);
    if (error)
	goto out;

    error = falloc(proc, &fp, &index);
    if (error)
	goto out;

    if (flags & FWRITE)
        vp->v_writecount++;

#if defined(__FreeBSD_version) && __FreeBSD_version >= 300000
    if (vp->v_type == VREG) {
#ifdef HAVE_FREEBSD_THREAD
	error = xfs_vfs_object_create(vp, proc, proc->td_proc->p_ucred);
#else
	error = xfs_vfs_object_create(vp, proc, proc->p_ucred);
#endif
	if (error)
	    goto out;
    }
#endif

    fp->f_flag = flags & FMASK;
    fp->f_type = DTYPE_VNODE;
    fp->f_ops  = &vnops;
    fp->f_data = (caddr_t)vp;
    xfs_vfs_unlock(vp, proc);
    *retval = index;
#ifdef FILE_UNUSE
    FILE_UNUSE(fp, proc);
#endif
#ifdef __APPLE__
    *fdflags(proc, index) &= ~UF_RESERVED;
#endif
    return 0;
out:
    NNPFSDEB(XDEBVFOPS, ("xfs_fhopen: error = %d\n", error));
    vput(vp);
    return error;
}
Пример #6
0
/* System calls. */
int
sys_shm_open(struct thread *td, struct shm_open_args *uap)
{
	struct filedesc *fdp;
	struct shmfd *shmfd;
	struct file *fp;
	char *path;
	Fnv32_t fnv;
	mode_t cmode;
	int fd, error;

#ifdef CAPABILITY_MODE
	/*
	 * shm_open(2) is only allowed for anonymous objects.
	 */
	if (IN_CAPABILITY_MODE(td) && (uap->path != SHM_ANON))
		return (ECAPMODE);
#endif

	if ((uap->flags & O_ACCMODE) != O_RDONLY &&
	    (uap->flags & O_ACCMODE) != O_RDWR)
		return (EINVAL);

	if ((uap->flags & ~(O_ACCMODE | O_CREAT | O_EXCL | O_TRUNC)) != 0)
		return (EINVAL);

	fdp = td->td_proc->p_fd;
	cmode = (uap->mode & ~fdp->fd_cmask) & ACCESSPERMS;

	error = falloc(td, &fp, &fd, 0);
	if (error)
		return (error);

	/* A SHM_ANON path pointer creates an anonymous object. */
	if (uap->path == SHM_ANON) {
		/* A read-only anonymous object is pointless. */
		if ((uap->flags & O_ACCMODE) == O_RDONLY) {
			fdclose(fdp, fp, fd, td);
			fdrop(fp, td);
			return (EINVAL);
		}
		shmfd = shm_alloc(td->td_ucred, cmode);
	} else {
		path = malloc(MAXPATHLEN, M_SHMFD, M_WAITOK);
		error = copyinstr(uap->path, path, MAXPATHLEN, NULL);

		/* Require paths to start with a '/' character. */
		if (error == 0 && path[0] != '/')
			error = EINVAL;
		if (error) {
			fdclose(fdp, fp, fd, td);
			fdrop(fp, td);
			free(path, M_SHMFD);
			return (error);
		}

		fnv = fnv_32_str(path, FNV1_32_INIT);
		sx_xlock(&shm_dict_lock);
		shmfd = shm_lookup(path, fnv);
		if (shmfd == NULL) {
			/* Object does not yet exist, create it if requested. */
			if (uap->flags & O_CREAT) {
#ifdef MAC
				error = mac_posixshm_check_create(td->td_ucred,
				    path);
				if (error == 0) {
#endif
					shmfd = shm_alloc(td->td_ucred, cmode);
					shm_insert(path, fnv, shmfd);
#ifdef MAC
				}
#endif
			} else {
				free(path, M_SHMFD);
				error = ENOENT;
			}
		} else {
			/*
			 * Object already exists, obtain a new
			 * reference if requested and permitted.
			 */
			free(path, M_SHMFD);
			if ((uap->flags & (O_CREAT | O_EXCL)) ==
			    (O_CREAT | O_EXCL))
				error = EEXIST;
			else {
#ifdef MAC
				error = mac_posixshm_check_open(td->td_ucred,
				    shmfd, FFLAGS(uap->flags & O_ACCMODE));
				if (error == 0)
#endif
				error = shm_access(shmfd, td->td_ucred,
				    FFLAGS(uap->flags & O_ACCMODE));
			}

			/*
			 * Truncate the file back to zero length if
			 * O_TRUNC was specified and the object was
			 * opened with read/write.
			 */
			if (error == 0 &&
			    (uap->flags & (O_ACCMODE | O_TRUNC)) ==
			    (O_RDWR | O_TRUNC)) {
#ifdef MAC
				error = mac_posixshm_check_truncate(
					td->td_ucred, fp->f_cred, shmfd);
				if (error == 0)
#endif
					shm_dotruncate(shmfd, 0);
			}
			if (error == 0)
				shm_hold(shmfd);
		}
		sx_xunlock(&shm_dict_lock);

		if (error) {
			fdclose(fdp, fp, fd, td);
			fdrop(fp, td);
			return (error);
		}
	}

	finit(fp, FFLAGS(uap->flags & O_ACCMODE), DTYPE_SHM, shmfd, &shm_ops);

	FILEDESC_XLOCK(fdp);
	if (fdp->fd_ofiles[fd] == fp)
		fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
	FILEDESC_XUNLOCK(fdp);
	td->td_retval[0] = fd;
	fdrop(fp, td);

	return (0);
}
Пример #7
0
/*
 * The file control system call.
 */
int
sys_fcntl(struct lwp *l, const struct sys_fcntl_args *uap, register_t *retval)
{
	/* {
		syscallarg(int)		fd;
		syscallarg(int)		cmd;
		syscallarg(void *)	arg;
	} */
	int fd, i, tmp, error, cmd, newmin;
	filedesc_t *fdp;
	file_t *fp;
	struct flock fl;
	bool cloexec = false;

	fd = SCARG(uap, fd);
	cmd = SCARG(uap, cmd);
	fdp = l->l_fd;
	error = 0;

	switch (cmd) {
	case F_CLOSEM:
		if (fd < 0)
			return EBADF;
		while ((i = fdp->fd_lastfile) >= fd) {
			if (fd_getfile(i) == NULL) {
				/* Another thread has updated. */
				continue;
			}
			fd_close(i);
		}
		return 0;

	case F_MAXFD:
		*retval = fdp->fd_lastfile;
		return 0;

	case F_SETLKW:
	case F_SETLK:
	case F_GETLK:
		error = copyin(SCARG(uap, arg), &fl, sizeof(fl));
		if (error)
			return error;
		error = do_fcntl_lock(fd, cmd, &fl);
		if (cmd == F_GETLK && error == 0)
			error = copyout(&fl, SCARG(uap, arg), sizeof(fl));
		return error;

	default:
		/* Handled below */
		break;
	}

	if ((fp = fd_getfile(fd)) == NULL)
		return (EBADF);

	if ((cmd & F_FSCTL)) {
		error = fcntl_forfs(fd, fp, cmd, SCARG(uap, arg));
		fd_putfile(fd);
		return error;
	}

	switch (cmd) {
	case F_DUPFD_CLOEXEC:
		cloexec = true;
		/*FALLTHROUGH*/
	case F_DUPFD:
		newmin = (long)SCARG(uap, arg);
		if ((u_int)newmin >=
		    l->l_proc->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
		    (u_int)newmin >= maxfiles) {
			fd_putfile(fd);
			return EINVAL;
		}
		error = fd_dup(fp, newmin, &i, cloexec);
		*retval = i;
		break;

	case F_GETFD:
		*retval = fdp->fd_dt->dt_ff[fd]->ff_exclose;
		break;

	case F_SETFD:
		fd_set_exclose(l, fd,
		    ((long)SCARG(uap, arg) & FD_CLOEXEC) != 0);
		break;

	case F_GETNOSIGPIPE:
		*retval = (fp->f_flag & FNOSIGPIPE) != 0;
		break;

	case F_SETNOSIGPIPE:
		if (SCARG(uap, arg))
			atomic_or_uint(&fp->f_flag, FNOSIGPIPE);
		else
			atomic_and_uint(&fp->f_flag, ~FNOSIGPIPE);
		*retval = 0;
		break;

	case F_GETFL:
		*retval = OFLAGS(fp->f_flag);
		break;

	case F_SETFL:
		/* XXX not guaranteed to be atomic. */
		tmp = FFLAGS((long)SCARG(uap, arg)) & FCNTLFLAGS;
		error = (*fp->f_ops->fo_fcntl)(fp, F_SETFL, &tmp);
		if (error)
			break;
		i = tmp ^ fp->f_flag;
		if (i & FNONBLOCK) {
			int flgs = tmp & FNONBLOCK;
			error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, &flgs);
			if (error) {
				(*fp->f_ops->fo_fcntl)(fp, F_SETFL,
				    &fp->f_flag);
				break;
			}
		}
		if (i & FASYNC) {
			int flgs = tmp & FASYNC;
			error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, &flgs);
			if (error) {
				if (i & FNONBLOCK) {
					tmp = fp->f_flag & FNONBLOCK;
					(void)(*fp->f_ops->fo_ioctl)(fp,
						FIONBIO, &tmp);
				}
				(*fp->f_ops->fo_fcntl)(fp, F_SETFL,
				    &fp->f_flag);
				break;
			}
		}
		fp->f_flag = (fp->f_flag & ~FCNTLFLAGS) | tmp;
		break;

	case F_GETOWN:
		error = (*fp->f_ops->fo_ioctl)(fp, FIOGETOWN, &tmp);
		*retval = tmp;
		break;

	case F_SETOWN:
		tmp = (int)(uintptr_t) SCARG(uap, arg);
		error = (*fp->f_ops->fo_ioctl)(fp, FIOSETOWN, &tmp);
		break;

	default:
		error = EINVAL;
	}

	fd_putfile(fd);
	return (error);
}
Пример #8
0
/*
 * fp_vpopen():	convert a vnode to a file pointer, call VOP_OPEN() on the
 * the vnode.  The vnode must be refd and locked.
 *
 * On success the vnode's ref is inherited by the file pointer and the caller
 * should not vrele() it, and the vnode is unlocked.
 *
 * On failure the vnode remains locked and refd and the caller is responsible
 * for vput()ing it.
 */
int
fp_vpopen(struct vnode *vp, int flags, file_t *fpp)
{
    struct thread *td;
    struct file *fp;
    int vmode;
    int error;

    td = curthread;

    /*
     * Vnode checks (from vn_open())
     */
    if (vp->v_type == VLNK) {
	error = EMLINK;
	goto bad2;
    }
    if (vp->v_type == VSOCK) {
	error = EOPNOTSUPP;
	goto bad2;
    }
    flags = FFLAGS(flags);
    vmode = 0;
    if (flags & (FWRITE | O_TRUNC)) {
	if (vp->v_type == VDIR) {
	    error = EISDIR;
	    goto bad2;
	}
	error = vn_writechk(vp, NULL);
	if (error)
	    goto bad2;
	vmode |= VWRITE;
    }
    if (flags & FREAD)
	vmode |= VREAD;
    if (vmode) {
	error = VOP_ACCESS(vp, vmode, td->td_proc->p_ucred);
	if (error)
	    goto bad2;
    }

    /*
     * File pointer setup
     */
    if ((error = falloc(NULL, fpp, NULL)) != 0)
	goto bad2;
    fp = *fpp;
    if (td->td_proc)
	fsetcred(fp, td->td_proc->p_ucred);

    error = VOP_OPEN(vp, flags, td->td_proc->p_ucred, fp);
    if (error)
	goto bad1;

    vput(vp);
    return (0);
bad1:
    fp->f_ops = &badfileops;	/* open failed, don't close */
    fp->f_data = NULL;
    fdrop(fp);
    /* leave the vnode intact, but fall through and unlock it anyway */
bad2:
    *fpp = NULL;
    return (error);
}