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:
parent
1f8286c377
commit
dba2d1f8b4
@ -44,6 +44,7 @@ int mapdriver(char *label, int major, int style, int flags);
|
|||||||
pid_t getnpid(endpoint_t proc_ep);
|
pid_t getnpid(endpoint_t proc_ep);
|
||||||
uid_t getnuid(endpoint_t proc_ep);
|
uid_t getnuid(endpoint_t proc_ep);
|
||||||
gid_t getngid(endpoint_t proc_ep);
|
gid_t getngid(endpoint_t proc_ep);
|
||||||
|
int dupfrom(endpoint_t endpt, int fd);
|
||||||
ssize_t pread64(int fd, void *buf, size_t count, u64_t where);
|
ssize_t pread64(int fd, void *buf, size_t count, u64_t where);
|
||||||
ssize_t pwrite64(int fd, const void *buf, size_t count, u64_t where);
|
ssize_t pwrite64(int fd, const void *buf, size_t count, u64_t where);
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
#define FSTAT 52
|
#define FSTAT 52
|
||||||
#define LSTAT 53
|
#define LSTAT 53
|
||||||
#define IOCTL 54
|
#define IOCTL 54
|
||||||
|
#define DUPFROM 56
|
||||||
#define FS_READY 57
|
#define FS_READY 57
|
||||||
#define PIPE2 58
|
#define PIPE2 58
|
||||||
#define EXEC 59
|
#define EXEC 59
|
||||||
|
@ -887,6 +887,10 @@
|
|||||||
#define VFS_PFS_FD m2_i3
|
#define VFS_PFS_FD m2_i3
|
||||||
#define VFS_PFS_FILP m2_p1
|
#define VFS_PFS_FILP m2_p1
|
||||||
|
|
||||||
|
/* Field names for the dupfrom(2) call. */
|
||||||
|
#define VFS_DUPFROM_ENDPT m1_i1
|
||||||
|
#define VFS_DUPFROM_FD m1_i2
|
||||||
|
|
||||||
/* Field names for GETRUSAGE related calls */
|
/* Field names for GETRUSAGE related calls */
|
||||||
#define RU_ENDPT m1_i1 /* indicates a process for sys_getrusage */
|
#define RU_ENDPT m1_i1 /* indicates a process for sys_getrusage */
|
||||||
#define RU_WHO m1_i1 /* who argument in getrusage call */
|
#define RU_WHO m1_i1 /* who argument in getrusage call */
|
||||||
|
@ -30,9 +30,10 @@ SRCS+= servxcheck.c
|
|||||||
# queryparam
|
# queryparam
|
||||||
SRCS+= paramvalue.c
|
SRCS+= paramvalue.c
|
||||||
|
|
||||||
# Minix servers/drivers syscall.
|
# Minix servers/drivers syscall. FIXME: these should be moved into libsys.
|
||||||
SRCS+= getngid.c getnpid.c getnprocnr.c getnucred.c getnuid.c getprocnr.c \
|
SRCS+= dupfrom.c getngid.c getnpid.c getnprocnr.c getnucred.c getnuid.c \
|
||||||
mapdriver.c vm_memctl.c vm_set_priv.c vm_query_exit.c vm_update.c
|
getprocnr.c mapdriver.c vm_memctl.c vm_set_priv.c vm_query_exit.c \
|
||||||
|
vm_update.c
|
||||||
|
|
||||||
SRCS+= oneC_sum.c
|
SRCS+= oneC_sum.c
|
||||||
|
|
||||||
|
14
lib/libminlib/dupfrom.c
Normal file
14
lib/libminlib/dupfrom.c
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#include <lib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
dupfrom(endpoint_t endpt, int fd)
|
||||||
|
{
|
||||||
|
message m;
|
||||||
|
|
||||||
|
memset(&m, 0, sizeof(m));
|
||||||
|
m.VFS_DUPFROM_ENDPT = endpt;
|
||||||
|
m.VFS_DUPFROM_FD = fd;
|
||||||
|
|
||||||
|
return _syscall(VFS_PROC_NR, DUPFROM, &m);
|
||||||
|
}
|
@ -67,7 +67,7 @@ int (*call_vec[])(void) = {
|
|||||||
no_sys, /* 53 = (lstat) */
|
no_sys, /* 53 = (lstat) */
|
||||||
no_sys, /* 54 = ioctl */
|
no_sys, /* 54 = ioctl */
|
||||||
no_sys, /* 55 = fcntl */
|
no_sys, /* 55 = fcntl */
|
||||||
no_sys, /* 56 = unused */
|
no_sys, /* 56 = dupfrom */
|
||||||
no_sys, /* 57 = unused */
|
no_sys, /* 57 = unused */
|
||||||
no_sys, /* 58 = unused */
|
no_sys, /* 58 = unused */
|
||||||
do_exec, /* 59 = execve */
|
do_exec, /* 59 = execve */
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
* do_put_filp: marks a filp as not in-flight anymore.
|
* do_put_filp: marks a filp as not in-flight anymore.
|
||||||
* do_cancel_fd: cancel the transaction when something goes wrong for
|
* do_cancel_fd: cancel the transaction when something goes wrong for
|
||||||
* the receiver.
|
* the receiver.
|
||||||
|
* do_dupfrom: copies a filp from another endpoint.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
@ -172,7 +173,7 @@ tll_access_t locktype;
|
|||||||
err_code = EIO; /* disallow all use except close(2) */
|
err_code = EIO; /* disallow all use except close(2) */
|
||||||
else if ((filp = rfp->fp_filp[fild]) == NULL)
|
else if ((filp = rfp->fp_filp[fild]) == NULL)
|
||||||
err_code = EBADF;
|
err_code = EBADF;
|
||||||
else
|
else if (locktype != VNODE_NONE) /* Only lock the filp if requested */
|
||||||
lock_filp(filp, locktype); /* All is fine */
|
lock_filp(filp, locktype); /* All is fine */
|
||||||
|
|
||||||
return(filp); /* may also be NULL */
|
return(filp); /* may also be NULL */
|
||||||
@ -614,3 +615,58 @@ struct filp *f;
|
|||||||
|
|
||||||
mutex_unlock(&f->filp_lock);
|
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);
|
||||||
|
}
|
||||||
|
@ -100,6 +100,7 @@ int do_put_filp(message *m_out);
|
|||||||
int cancel_fd(endpoint_t ep, int fd);
|
int cancel_fd(endpoint_t ep, int fd);
|
||||||
int do_cancel_fd(message *m_out);
|
int do_cancel_fd(message *m_out);
|
||||||
void close_filp(struct filp *fp);
|
void close_filp(struct filp *fp);
|
||||||
|
int do_dupfrom(message *m_out);
|
||||||
|
|
||||||
/* fscall.c */
|
/* fscall.c */
|
||||||
void nested_fs_call(message *m);
|
void nested_fs_call(message *m);
|
||||||
|
@ -70,7 +70,7 @@ int (*call_vec[])(message *m_out) = {
|
|||||||
do_lstat, /* 53 = lstat */
|
do_lstat, /* 53 = lstat */
|
||||||
do_ioctl, /* 54 = ioctl */
|
do_ioctl, /* 54 = ioctl */
|
||||||
do_fcntl, /* 55 = fcntl */
|
do_fcntl, /* 55 = fcntl */
|
||||||
no_sys, /* 56 = (mpx) */
|
do_dupfrom, /* 56 = dupfrom */
|
||||||
do_fsready, /* 57 = FS proc ready */
|
do_fsready, /* 57 = FS proc ready */
|
||||||
do_pipe2, /* 58 = pipe2 */
|
do_pipe2, /* 58 = pipe2 */
|
||||||
no_sys, /* 59 = (execve)*/
|
no_sys, /* 59 = (execve)*/
|
||||||
|
@ -23,6 +23,7 @@ EXTERN struct vnode {
|
|||||||
} vnode[NR_VNODES];
|
} vnode[NR_VNODES];
|
||||||
|
|
||||||
/* vnode lock types mapping */
|
/* vnode lock types mapping */
|
||||||
|
#define VNODE_NONE TLL_NONE /* used only for get_filp2 to avoid locking */
|
||||||
#define VNODE_READ TLL_READ
|
#define VNODE_READ TLL_READ
|
||||||
#define VNODE_OPCL TLL_READSER
|
#define VNODE_OPCL TLL_READSER
|
||||||
#define VNODE_WRITE TLL_WRITE
|
#define VNODE_WRITE TLL_WRITE
|
||||||
|
Loading…
x
Reference in New Issue
Block a user