VFS: add dupfrom(2) call

This call copies a file descriptor from a remote process into the
calling process. The call is for the VND driver only, and in the
future, ACLs will prevent any other process from using this call.

Change-Id: Ib16fdd1f1a12cb38a70d7e441dad91bc86898f6d
This commit is contained in:
David van Moolenbroek
2014-03-01 09:04:54 +01:00
committed by sambuc
parent 1f8286c377
commit dba2d1f8b4
10 changed files with 85 additions and 6 deletions
+1 -1
View File
@@ -67,7 +67,7 @@ int (*call_vec[])(void) = {
no_sys, /* 53 = (lstat) */
no_sys, /* 54 = ioctl */
no_sys, /* 55 = fcntl */
no_sys, /* 56 = unused */
no_sys, /* 56 = dupfrom */
no_sys, /* 57 = unused */
no_sys, /* 58 = unused */
do_exec, /* 59 = execve */
+57 -1
View File
@@ -13,6 +13,7 @@
* do_put_filp: marks a filp as not in-flight anymore.
* do_cancel_fd: cancel the transaction when something goes wrong for
* the receiver.
* do_dupfrom: copies a filp from another endpoint.
*/
#include <sys/select.h>
@@ -172,7 +173,7 @@ tll_access_t locktype;
err_code = EIO; /* disallow all use except close(2) */
else if ((filp = rfp->fp_filp[fild]) == NULL)
err_code = EBADF;
else
else if (locktype != VNODE_NONE) /* Only lock the filp if requested */
lock_filp(filp, locktype); /* All is fine */
return(filp); /* may also be NULL */
@@ -614,3 +615,58 @@ struct filp *f;
mutex_unlock(&f->filp_lock);
}
/*===========================================================================*
* do_dupfrom *
*===========================================================================*/
int do_dupfrom(message *UNUSED(m_out))
{
/* Duplicate a file descriptor from another process into the calling process.
* The other process is identified by a magic grant created for it to make the
* initial (IOCTL) request to the calling process. This call has been added
* specifically for the VND driver.
*/
struct fproc *rfp;
struct filp *rfilp;
struct vnode *vp;
endpoint_t endpt;
int r, fd, slot;
/* This should be replaced with an ACL check. */
if (!super_user) return(EPERM);
endpt = (endpoint_t) job_m_in.VFS_DUPFROM_ENDPT;
fd = job_m_in.VFS_DUPFROM_FD;
if (isokendpt(endpt, &slot) != OK) return(EINVAL);
rfp = &fproc[slot];
/* Obtain the filp, but do not lock it yet: we first need to make sure that
* locking it will not result in a deadlock.
*/
if ((rfilp = get_filp2(rfp, fd, VNODE_NONE)) == NULL)
return(err_code);
/* For now, we do not allow remote duplication of device nodes. In practice,
* only a block-special file can cause a deadlock for the caller (currently
* only the VND driver). This would happen if a user process passes in the
* file descriptor to the device node on which it is performing the IOCTL.
* This would cause two VFS threads to deadlock on the same filp. Since the
* VND driver does not allow device nodes to be used anyway, this somewhat
* rudimentary check eliminates such deadlocks. A better solution would be
* to check if the given endpoint holds a lock to the target filp, but we
* currently do not have this information within VFS.
*/
vp = rfilp->filp_vno;
if (S_ISCHR(vp->v_mode) || S_ISBLK(vp->v_mode))
return(EINVAL);
/* Now we can safely lock the filp, copy it, and unlock it again. */
lock_filp(rfilp, VNODE_READ);
r = copy_filp(who_e, (filp_id_t) rfilp);
unlock_filp(rfilp);
return(r);
}
+1
View File
@@ -100,6 +100,7 @@ int do_put_filp(message *m_out);
int cancel_fd(endpoint_t ep, int fd);
int do_cancel_fd(message *m_out);
void close_filp(struct filp *fp);
int do_dupfrom(message *m_out);
/* fscall.c */
void nested_fs_call(message *m);
+1 -1
View File
@@ -70,7 +70,7 @@ int (*call_vec[])(message *m_out) = {
do_lstat, /* 53 = lstat */
do_ioctl, /* 54 = ioctl */
do_fcntl, /* 55 = fcntl */
no_sys, /* 56 = (mpx) */
do_dupfrom, /* 56 = dupfrom */
do_fsready, /* 57 = FS proc ready */
do_pipe2, /* 58 = pipe2 */
no_sys, /* 59 = (execve)*/
+1
View File
@@ -23,6 +23,7 @@ EXTERN struct vnode {
} vnode[NR_VNODES];
/* vnode lock types mapping */
#define VNODE_NONE TLL_NONE /* used only for get_filp2 to avoid locking */
#define VNODE_READ TLL_READ
#define VNODE_OPCL TLL_READSER
#define VNODE_WRITE TLL_WRITE