]> Zhao Yanbai Git Server - minix.git/commitdiff
VFS: add dupfrom(2) call 87/987/2
authorDavid van Moolenbroek <david@minix3.org>
Wed, 18 Sep 2013 11:55:15 +0000 (13:55 +0200)
committerLionel Sambuc <lionel@minix3.org>
Sat, 1 Mar 2014 08:04:54 +0000 (09:04 +0100)
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

include/lib.h
include/minix/callnr.h
include/minix/com.h
lib/libminlib/Makefile
lib/libminlib/dupfrom.c [new file with mode: 0644]
servers/pm/table.c
servers/vfs/filedes.c
servers/vfs/proto.h
servers/vfs/table.c
servers/vfs/vnode.h

index 512714f66a1ea352c75fd11037c0a9ce79868bc5..92cf2a5fb56c329192e5d1578c48f45d1afcb1b8 100644 (file)
@@ -44,6 +44,7 @@ int mapdriver(char *label, int major, int style, int flags);
 pid_t getnpid(endpoint_t proc_ep);
 uid_t getnuid(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 pwrite64(int fd, const void *buf, size_t count, u64_t where);
 
index 340e6d6196c2e41551574adebff64c98aaec48de..ed220aba56dacb31e52e9b597ac23ade825ad6ab 100644 (file)
@@ -47,6 +47,7 @@
 #define FSTAT            52
 #define LSTAT            53
 #define IOCTL            54
+#define DUPFROM                  56
 #define FS_READY         57
 #define PIPE2            58
 #define EXEC             59
index 3847825f701b25fdd63ebc5f13b2fc1ebc6b40ad..e0985618f14a901c27d2ab4435d83a17d9a7756c 100644 (file)
 #define VFS_PFS_FD             m2_i3
 #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 */
 #define RU_ENDPT       m1_i1   /* indicates a process for sys_getrusage */
 #define RU_WHO         m1_i1   /* who argument in getrusage call */
index af025661c844556689e906d8e7d16f24eaff1de8..5d5092d52e5a891c43ab9c2895c9d36675c7f5a5 100644 (file)
@@ -30,9 +30,10 @@ SRCS+= servxcheck.c
 # queryparam
 SRCS+= paramvalue.c
 
-# Minix servers/drivers syscall.
-SRCS+=         getngid.c getnpid.c getnprocnr.c getnucred.c getnuid.c getprocnr.c \
-       mapdriver.c vm_memctl.c vm_set_priv.c vm_query_exit.c vm_update.c
+# Minix servers/drivers syscall. FIXME: these should be moved into libsys.
+SRCS+=         dupfrom.c getngid.c getnpid.c getnprocnr.c getnucred.c getnuid.c \
+       getprocnr.c mapdriver.c vm_memctl.c vm_set_priv.c vm_query_exit.c \
+       vm_update.c
 
 SRCS+= oneC_sum.c
 
diff --git a/lib/libminlib/dupfrom.c b/lib/libminlib/dupfrom.c
new file mode 100644 (file)
index 0000000..b244fbb
--- /dev/null
@@ -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);
+}
index 6290a4ccebaed953ae6ea53fdd24d48f8b037da7..2150f0bf6f7d5a9ca083f66a0744b080a8d1b664 100644 (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  */
index 3167fc01ae2c7d895d25868205f37a2449cdd12b..a285625d1af834397b34bfcf659feff6458cc3cf 100644 (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);
+}
index 25df2dce45ed131a84fc91bc055dbe70359ed657..8da3eef1ebc1e1dfc9eeee7ca2881527a94f8e38 100644 (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);
index 2329aac075f50d0ed7b81fd770c78ce427653fe2..982d96c590088ff5c34947809d3542d328693a18 100644 (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)*/
index e9f7cdc5ea1e1104890c4b518ebb8c67aef80e63..068053f898fc56ffe3cc0b41e45c821699073018 100644 (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