Beispiel #1
0
int
pipe1(struct lwp *l, register_t *retval, int flags)
{
	file_t		*rf, *wf;
	struct socket	*rso, *wso;
	int		fd, error;
	proc_t		*p;

	if (flags & ~(O_CLOEXEC|O_NONBLOCK|O_NOSIGPIPE))
		return EINVAL;
	p = curproc;
	if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, l, NULL)) != 0)
		return error;
	if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, l, rso)) != 0)
		goto free1;
	/* remember this socket pair implements a pipe */
	wso->so_state |= SS_ISAPIPE;
	rso->so_state |= SS_ISAPIPE;
	if ((error = fd_allocfile(&rf, &fd)) != 0)
		goto free2;
	retval[0] = fd;
	rf->f_flag = FREAD | flags;
	rf->f_type = DTYPE_SOCKET;
	rf->f_ops = &socketops;
	rf->f_socket = rso;
	if ((error = fd_allocfile(&wf, &fd)) != 0)
		goto free3;
	wf->f_flag = FWRITE | flags;
	wf->f_type = DTYPE_SOCKET;
	wf->f_ops = &socketops;
	wf->f_socket = wso;
	retval[1] = fd;
	solock(wso);
	error = unp_connect2(wso, rso);
	sounlock(wso);
	if (error != 0)
		goto free4;
	fd_affix(p, wf, (int)retval[1]);
	fd_affix(p, rf, (int)retval[0]);
	return (0);
 free4:
	fd_abort(p, wf, (int)retval[1]);
 free3:
	fd_abort(p, rf, (int)retval[0]);
 free2:
	(void)soclose(wso);
 free1:
	(void)soclose(rso);
	return error;
}
Beispiel #2
0
/* open the xenevt device; this is where we clone */
int
xenevtopen(dev_t dev, int flags, int mode, struct lwp *l)
{
	struct xenevt_d *d;
	struct file *fp;
	int fd, error;

	switch(minor(dev)) {
	case DEV_EVT:
		/* falloc() will use the descriptor for us. */
		if ((error = fd_allocfile(&fp, &fd)) != 0)
			return error;

		d = malloc(sizeof(*d), M_DEVBUF, M_WAITOK | M_ZERO);
		d->ci = &cpu_info_primary;
		mutex_init(&d->lock, MUTEX_DEFAULT, IPL_HIGH);
		cv_init(&d->cv, "xenevt");
		selinit(&d->sel);
		return fd_clone(fp, fd, flags, &xenevt_fileops, d);
	case DEV_XSD:
		/* no clone for /dev/xsd_kva */
		return (0);
	default:
		break;
	}
	return ENODEV;
}
Beispiel #3
0
static int
makesocket(struct lwp *l, file_t **fp, int *fd, int flags, int type,
    int domain, int proto, struct socket *soo)
{
	struct socket *so;
	int error;

	if ((error = socreate(domain, &so, type, proto, l, soo)) != 0) {
		return error;
	}
	if (flags & SOCK_NONBLOCK) {
		so->so_state |= SS_NBIO;
	}

	if ((error = fd_allocfile(fp, fd)) != 0) {
		soclose(so);
		return error;
	}
	fd_set_exclose(l, *fd, (flags & SOCK_CLOEXEC) != 0);
	(*fp)->f_flag = FREAD|FWRITE|
	    ((flags & SOCK_NONBLOCK) ? FNONBLOCK : 0)|
	    ((flags & SOCK_NOSIGPIPE) ? FNOSIGPIPE : 0);
	(*fp)->f_type = DTYPE_SOCKET;
	(*fp)->f_ops = &socketops;
	(*fp)->f_socket = so;
	return 0;
}
Beispiel #4
0
static int
pty_alloc_slave(struct lwp *l, int *fd, dev_t dev, struct mount *mp)
{
	int error;
	struct file *fp;
	struct vnode *vp;

	/* Grab a filedescriptor for the slave */
	if ((error = fd_allocfile(&fp, fd)) != 0) {
		DPRINTF(("fd_allocfile %d\n", error));
		return error;
	}

	if (ptm == NULL) {
		error = EOPNOTSUPP;
		goto bad;
	}

	if ((error = (*ptm->allocvp)(mp, l, &vp, dev, 't')) != 0)
		goto bad;
	if ((error = pty_vn_open(vp, l)) != 0)
		goto bad;

	fp->f_flag = FREAD|FWRITE;
	fp->f_type = DTYPE_VNODE;
	fp->f_ops = &vnops;
	fp->f_data = vp;
	VOP_UNLOCK(vp);
	fd_affix(curproc, fp, *fd);
	return 0;
bad:
	fd_abort(curproc, fp, *fd);
	return error;
}
Beispiel #5
0
static int
xen_dev_open(dev_t dev, int flags, int mode, struct lwp *l)
{
	const struct xen_dev_info *xdinfo;
	int fd, err;
	struct file *fp;
	void *fdata;

	DPRINTF(("xen devsw: opening minor=%lu\n", (unsigned long)minor(dev)));

        if (minor(dev) < 0 || minor(dev) >= NUM_DEV_INFOS)
		return ENODEV;

	xdinfo = &devs[minor(dev)];

	if (!xdinfo->xd_open)
		return ENODEV;

	err = fd_allocfile(&fp, &fd);
	if (err)
		return err;

	DPRINTF(("%s: opening...\n", xdinfo->path));

	err = xdinfo->xd_open(fp, &fdata);
	if (err) {
		fd_abort(curproc, fp, fd);
		return err;
	}

	DPRINTF(("%s: opened, fd_clone\n", xdinfo->path));

	return fd_clone(fp, fd, flags, xdinfo->fo, fdata);
}
Beispiel #6
0
int sys_tunopen(struct lwp *l, const struct sys_tunopen_args *uap, register_t *retval)
{
	int error;
	struct file* fp;
	int indx;

	error = ChkSpaceBstrR(SCARG(uap, path), 0);
	if ( error < E_OK ) {
		return EFAULT;
	}

	if ((error = fd_allocfile(&fp, &indx)) != 0)
		return (error);

	if ((error = tkn_tun_open(SCARG(uap, path), SCARG(uap, oflag), fp)) != 0) {
		fd_abort(l->l_proc, fp, indx);
		if ((error == EDUPFD || error == EMOVEFD) &&
		    l->l_dupfd >= 0 &&			/* XXX from fdopen */
		    (error =
			fd_dupopen(l->l_dupfd, &indx, SCARG(uap, oflag), error)) == 0) {
			*retval = indx;
			return (0);
		}
		if (error == ERESTART)
			error = EINTR;
		return (error);
	}

	return ENOTSUP;
}
int
rndopen(dev_t dev, int flags, int fmt, struct lwp *l)
{
	bool hard;
	struct file *fp;
	int fd;
	int error;

	switch (minor(dev)) {
	case RND_DEV_URANDOM:
		hard = false;
		break;

	case RND_DEV_RANDOM:
		hard = true;
		break;

	default:
		return ENXIO;
	}

	error = fd_allocfile(&fp, &fd);
	if (error)
		return error;

	/*
	 * Allocate a context, but don't create a CPRNG yet -- do that
	 * lazily because it consumes entropy from the system entropy
	 * pool, which (currently) has the effect of depleting it and
	 * causing readers from /dev/random to block.  If this is
	 * /dev/urandom and the process is about to send only short
	 * reads to it, then we will be using a per-CPU CPRNG anyway.
	 */
	struct rnd_ctx *const ctx = pool_cache_get(rnd_ctx_cache, PR_WAITOK);
	ctx->rc_cprng = NULL;
	ctx->rc_hard = hard;

	error = fd_clone(fp, fd, flags, &rnd_fileops, ctx);
	KASSERT(error == EMOVEFD);

	return error;
}
Beispiel #8
0
static int
tap_dev_cloner(struct lwp *l)
{
	struct tap_softc *sc;
	file_t *fp;
	int error, fd;

	if ((error = fd_allocfile(&fp, &fd)) != 0)
		return (error);

	if ((sc = tap_clone_creator(-1)) == NULL) {
		fd_abort(curproc, fp, fd);
		return (ENXIO);
	}

	sc->sc_flags |= TAP_INUSE;

	return fd_clone(fp, fd, FREAD|FWRITE, &tap_fileops,
	    (void *)(intptr_t)device_unit(sc->sc_dev));
}
Beispiel #9
0
/*
 * dmoverioopen:
 *
 *	Device switch open routine.
 */
int
dmoverioopen(dev_t dev, int flag, int mode, struct lwp *l)
{
	struct dmio_state *ds;
	struct file *fp;
	int error, fd, s;

	/* falloc() will use the descriptor for us. */
	if ((error = fd_allocfile(&fp, &fd)) != 0)
		return (error);

	s = splsoftclock();
	ds = pool_get(&dmio_state_pool, PR_WAITOK);
	splx(s);

	memset(ds, 0, sizeof(*ds));
	simple_lock_init(&ds->ds_slock);
	TAILQ_INIT(&ds->ds_pending);
	TAILQ_INIT(&ds->ds_complete);
	selinit(&ds->ds_selq);

	return fd_clone(fp, fd, flag, &dmio_fileops, ds);
}
Beispiel #10
0
/*
 * kqueue(2) system call.
 */
static int
kqueue1(struct lwp *l, int flags, register_t *retval)
{
	struct kqueue *kq;
	file_t *fp;
	int fd, error;

	if ((error = fd_allocfile(&fp, &fd)) != 0)
		return error;
	fp->f_flag = FREAD | FWRITE | (flags & (FNONBLOCK|FNOSIGPIPE));
	fp->f_type = DTYPE_KQUEUE;
	fp->f_ops = &kqueueops;
	kq = kmem_zalloc(sizeof(*kq), KM_SLEEP);
	mutex_init(&kq->kq_lock, MUTEX_DEFAULT, IPL_SCHED);
	cv_init(&kq->kq_cv, "kqueue");
	selinit(&kq->kq_sel);
	TAILQ_INIT(&kq->kq_head);
	fp->f_data = kq;
	*retval = fd;
	kq->kq_fdp = curlwp->l_fd;
	fd_set_exclose(l, fd, (flags & O_CLOEXEC) != 0);
	fd_affix(curproc, fp, fd);
	return error;
}
Beispiel #11
0
int
svr4_netopen(dev_t dev, int flag, int mode, struct lwp *l)
{
	int type, protocol;
	int fd;
	file_t *fp;
	struct socket *so;
	int error;
	int family;

	DPRINTF(("netopen("));

	if (curlwp->l_dupfd >= 0)	/* XXX */
		return ENODEV;

	switch (minor(dev)) {
	case dev_udp:
		family = AF_INET;
		type = SOCK_DGRAM;
		protocol = IPPROTO_UDP;
		DPRINTF(("udp, "));
		break;

	case dev_tcp:
		family = AF_INET;
		type = SOCK_STREAM;
		protocol = IPPROTO_TCP;
		DPRINTF(("tcp, "));
		break;

	case dev_ip:
	case dev_rawip:
		family = AF_INET;
		type = SOCK_RAW;
		protocol = IPPROTO_IP;
		DPRINTF(("ip, "));
		break;

	case dev_icmp:
		family = AF_INET;
		type = SOCK_RAW;
		protocol = IPPROTO_ICMP;
		DPRINTF(("icmp, "));
		break;

	case dev_unix_dgram:
		family = AF_LOCAL;
		type = SOCK_DGRAM;
		protocol = 0;
		DPRINTF(("unix-dgram, "));
		break;

	case dev_unix_stream:
	case dev_unix_ord_stream:
		family = AF_LOCAL;
		type = SOCK_STREAM;
		protocol = 0;
		DPRINTF(("unix-stream, "));
		break;

	default:
		DPRINTF(("%d);\n", minor(dev)));
		return EOPNOTSUPP;
	}

	if ((error = fd_allocfile(&fp, &fd)) != 0)
		return error;

	if ((error = socreate(family, &so, type, protocol, l, NULL)) != 0) {
		DPRINTF(("socreate error %d\n", error));
		fd_abort(curproc, fp, fd);
		return error;
	}

	error = fd_clone(fp, fd, flag, &svr4_netops, so);
	fp->f_type = DTYPE_SOCKET;
	(void)svr4_stream_get(fp);

	DPRINTF(("ok);\n"));
	return error;
}
Beispiel #12
0
int
do_sys_accept(struct lwp *l, int sock, struct mbuf **name,
    register_t *new_sock, const sigset_t *mask, int flags, int clrflags)
{
	file_t		*fp, *fp2;
	struct mbuf	*nam;
	int		error, fd;
	struct socket	*so, *so2;
	short		wakeup_state = 0;

	if ((fp = fd_getfile(sock)) == NULL)
		return EBADF;
	if (fp->f_type != DTYPE_SOCKET) {
		fd_putfile(sock);
		return ENOTSOCK;
	}
	if ((error = fd_allocfile(&fp2, &fd)) != 0) {
		fd_putfile(sock);
		return error;
	}
	nam = m_get(M_WAIT, MT_SONAME);
	*new_sock = fd;
	so = fp->f_socket;
	solock(so);

	if (__predict_false(mask))
		sigsuspendsetup(l, mask);

	if (!(so->so_proto->pr_flags & PR_LISTEN)) {
		error = EOPNOTSUPP;
		goto bad;
	}
	if ((so->so_options & SO_ACCEPTCONN) == 0) {
		error = EINVAL;
		goto bad;
	}
	if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
		error = EWOULDBLOCK;
		goto bad;
	}
	while (so->so_qlen == 0 && so->so_error == 0) {
		if (so->so_state & SS_CANTRCVMORE) {
			so->so_error = ECONNABORTED;
			break;
		}
		if (wakeup_state & SS_RESTARTSYS) {
			error = ERESTART;
			goto bad;
		}
		error = sowait(so, true, 0);
		if (error) {
			goto bad;
		}
		wakeup_state = so->so_state;
	}
	if (so->so_error) {
		error = so->so_error;
		so->so_error = 0;
		goto bad;
	}
	/* connection has been removed from the listen queue */
	KNOTE(&so->so_rcv.sb_sel.sel_klist, NOTE_SUBMIT);
	so2 = TAILQ_FIRST(&so->so_q);
	if (soqremque(so2, 1) == 0)
		panic("accept");
	fp2->f_type = DTYPE_SOCKET;
	fp2->f_flag = (fp->f_flag & ~clrflags) |
	    ((flags & SOCK_NONBLOCK) ? FNONBLOCK : 0)|
	    ((flags & SOCK_NOSIGPIPE) ? FNOSIGPIPE : 0);
	fp2->f_ops = &socketops;
	fp2->f_socket = so2;
	if (fp2->f_flag & FNONBLOCK)
		so2->so_state |= SS_NBIO;
	else
		so2->so_state &= ~SS_NBIO;
	error = soaccept(so2, nam);
	so2->so_cred = kauth_cred_dup(so->so_cred);
	sounlock(so);
	if (error) {
		/* an error occurred, free the file descriptor and mbuf */
		m_freem(nam);
		mutex_enter(&fp2->f_lock);
		fp2->f_count++;
		mutex_exit(&fp2->f_lock);
		closef(fp2);
		fd_abort(curproc, NULL, fd);
	} else {
		fd_set_exclose(l, fd, (flags & SOCK_CLOEXEC) != 0);
		fd_affix(curproc, fp2, fd);
		*name = nam;
	}
	fd_putfile(sock);
	if (__predict_false(mask))
		sigsuspendteardown(l);
	return error;
 bad:
	sounlock(so);
	m_freem(nam);
	fd_putfile(sock);
	fd_abort(curproc, fp2, fd);
	if (__predict_false(mask))
		sigsuspendteardown(l);
	return error;
}
Beispiel #13
0
/* ARGSUSED */
int
sys_ktrace(struct lwp *l, const struct sys_ktrace_args *uap, register_t *retval)
{
	/* {
		syscallarg(const char *) fname;
		syscallarg(int) ops;
		syscallarg(int) facs;
		syscallarg(int) pid;
	} */
	struct vnode *vp = NULL;
	file_t *fp = NULL;
	struct pathbuf *pb;
	struct nameidata nd;
	int error = 0;
	int fd;

	if (ktrenter(l))
		return EAGAIN;

	if (KTROP(SCARG(uap, ops)) != KTROP_CLEAR) {
		/*
		 * an operation which requires a file argument.
		 */
		error = pathbuf_copyin(SCARG(uap, fname), &pb);
		if (error) {
			ktrexit(l);
			return (error);
		}
		NDINIT(&nd, LOOKUP, FOLLOW, pb);
		if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) {
			pathbuf_destroy(pb);
			ktrexit(l);
			return (error);
		}
		vp = nd.ni_vp;
		pathbuf_destroy(pb);
		VOP_UNLOCK(vp);
		if (vp->v_type != VREG) {
			vn_close(vp, FREAD|FWRITE, l->l_cred);
			ktrexit(l);
			return (EACCES);
		}
		/*
		 * This uses up a file descriptor slot in the
		 * tracing process for the duration of this syscall.
		 * This is not expected to be a problem.
		 */
		if ((error = fd_allocfile(&fp, &fd)) != 0) {
			vn_close(vp, FWRITE, l->l_cred);
			ktrexit(l);
			return error;
		}
		fp->f_flag = FWRITE;
		fp->f_type = DTYPE_VNODE;
		fp->f_ops = &vnops;
		fp->f_data = (void *)vp;
		vp = NULL;
	}
	error = ktrace_common(l, SCARG(uap, ops), SCARG(uap, facs),
	    SCARG(uap, pid), &fp);
	if (KTROP(SCARG(uap, ops)) != KTROP_CLEAR)
		fd_abort(curproc, fp, fd);
	return (error);
}
Beispiel #14
0
static int
pty_alloc_master(struct lwp *l, int *fd, dev_t *dev, struct mount *mp)
{
	int error;
	struct file *fp;
	struct vnode *vp;
	int md;

	if ((error = fd_allocfile(&fp, fd)) != 0) {
		DPRINTF(("fd_allocfile %d\n", error));
		return error;
	}
retry:
	/* Find and open a free master pty. */
	*dev = pty_getfree();
	md = minor(*dev);
	if ((error = pty_check(md)) != 0) {
		DPRINTF(("pty_check %d\n", error));
		goto bad;
	}
	if (ptm == NULL) {
		DPRINTF(("no ptm\n"));
		error = EOPNOTSUPP;
		goto bad;
	}
	/*
	 * XXX Since PTYFS has now multiple instance support, if we mounted
	 * more than one PTYFS we must check here the ptyfs_used_tbl, to find
	 * out if the ptyfsnode is under the appropriate mount and skip the
	 * node if not, because the pty could has been released, but
	 * ptyfs_reclaim didn't get a chance to release the corresponding
	 * node other mount point yet.
	 *
	 * It's important to have only one mount point's ptyfsnode for each
	 * appropriate device in ptyfs_used_tbl, else we will have a security 
	 * problem, because every entry will have access to this device.
	 *
	 * Also we will not have not efficient vnode and memory usage.
	 * You can test this by changing a_recycle from true to false
	 * in ptyfs_inactive.
	 */
	if ((error = (*ptm->allocvp)(mp, l, &vp, *dev, 'p')) != 0) {
		DPRINTF(("pty_allocvp %d\n", error));
		goto bad;
	}

	if ((error = pty_vn_open(vp, l)) != 0) {
		DPRINTF(("pty_vn_open %d\n", error));
		/*
		 * Check if the master open failed because we lost
		 * the race to grab it.
		 */
		if (error != EIO)
			goto bad;
		error = !pty_isfree(md, 1);
		DPRINTF(("pty_isfree %d\n", error));
		if (error)
			goto retry;
		else
			goto bad;
	}
	fp->f_flag = FREAD|FWRITE;
	fp->f_type = DTYPE_VNODE;
	fp->f_ops = &vnops;
	fp->f_data = vp;
	VOP_UNLOCK(vp);
	fd_affix(curproc, fp, *fd);
	return 0;
bad:
	fd_abort(curproc, fp, *fd);
	return error;
}