]> Zhao Yanbai Git Server - minix.git/commitdiff
Prepare VFS to support back calls from PFS. For security reasons and to support
authorThomas Veerman <thomas@minix3.org>
Mon, 30 Aug 2010 13:44:07 +0000 (13:44 +0000)
committerThomas Veerman <thomas@minix3.org>
Mon, 30 Aug 2010 13:44:07 +0000 (13:44 +0000)
file descriptor passing, PFS does some back calls to VFS. For example, to
verify the validity of a path provided by a process and to tell VFS it must
copy file descriptors from one process to another.

17 files changed:
servers/vfs/device.c
servers/vfs/exec.c
servers/vfs/filedes.c
servers/vfs/fscall.c
servers/vfs/glo.h
servers/vfs/link.c
servers/vfs/mount.c
servers/vfs/open.c
servers/vfs/path.c
servers/vfs/protect.c
servers/vfs/proto.h
servers/vfs/read.c
servers/vfs/request.c
servers/vfs/stadir.c
servers/vfs/table.c
servers/vfs/time.c
servers/vfs/utility.c

index f9809c17ec906b5e3807580aa625af3527bb0e8f..c304c30b73281771e50819f661e806255e0f91d0 100644 (file)
@@ -621,30 +621,48 @@ message *mess_ptr;                /* pointer to message for task */
 
   int r, proc_e;
 
-  if(task_nr == SYSTEM) printf("VFS: sending %d to SYSTEM\n", mess_ptr->m_type);
+  if(task_nr == SYSTEM) {
+       printf("VFS: sending %d to SYSTEM\n", mess_ptr->m_type);
+  }
 
   proc_e = mess_ptr->IO_ENDPT;
-  r = sendrec(task_nr, mess_ptr);
-  if(r == OK && mess_ptr->REP_STATUS == ERESTART) r = EDEADEPT;
-  if (r != OK) {
-       if (r == EDEADSRCDST || r == EDEADEPT) {
-               printf("fs: dead driver %d\n", task_nr);
-               dmap_unmap_by_endpt(task_nr);
-               return(r);
+
+  for (;;) {
+
+       r = sendrec(task_nr, mess_ptr);
+       if(r == OK && mess_ptr->REP_STATUS == ERESTART) r = EDEADEPT;
+       if (r != OK) {
+               if (r == EDEADSRCDST || r == EDEADEPT) {
+                       printf("fs: dead driver %d\n", task_nr);
+                       dmap_unmap_by_endpt(task_nr);
+                       return(r);
+               }
+               if (r == ELOCKED) {
+                       printf("fs: ELOCKED talking to %d\n", task_nr);
+                       return(r);
+               }
+               panic("call_task: can't send/receive: %d", r);
        }
-       if (r == ELOCKED) {
-               printf("fs: ELOCKED talking to %d\n", task_nr);
-               return(r);
+
+       /* Did the process we did the sendrec() for get a result? */
+       if (mess_ptr->REP_ENDPT != proc_e && VFS_PROC_NR != proc_e) {
+
+               printf("fs: strange device reply from %d, type = %d, "
+               "proc = %d (not %d) (2) ignored\n", mess_ptr->m_source, 
+               mess_ptr->m_type, proc_e, mess_ptr->REP_ENDPT);
+
+               return(EIO);
        }
-       panic("call_task: can't send/receive: %d", r);
-  }
 
-  /* Did the process we did the sendrec() for get a result? */
-  if (mess_ptr->REP_ENDPT != proc_e) {
-       printf("fs: strange device reply from %d, type = %d, proc = %d "
-              "(not %d) (2) ignored\n", mess_ptr->m_source, mess_ptr->m_type,
-              proc_e, mess_ptr->REP_ENDPT);
-       return(EIO);
+       if (mess_ptr->m_type == TASK_REPLY ||
+               IS_DEV_RS(mess_ptr->m_type) ||
+               mess_ptr->m_type <= 0) {
+
+               break; /* reply */
+       } else {
+
+               nested_dev_call(mess_ptr);
+       }
   }
 
   return(OK);
index 334f1f0979719f8b61a9feffb65dab91476c3d0f..c6fccecadc7c75f2457db0bc07737f374ea241b2 100644 (file)
@@ -115,7 +115,7 @@ vir_bytes *pc;
        progname[PROC_NAME_LEN-1] = '\0';
 
        /* Open executable */
-       if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+       if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
 
        if ((vp->v_mode & I_TYPE) != I_REGULAR) 
                r = ENOEXEC;
index a6c677969bb7eaf782d0b44c2f7c950384a5b78c..65da4bcf6ca9caf8362aad9667ef061f80079248 100644 (file)
@@ -1,14 +1,22 @@
 /* This file contains the procedures that manipulate file descriptors.
  *
  * The entry points into this file are
- *   get_fd:    look for free file descriptor and free filp slots
- *   get_filp:  look up the filp entry for a given file descriptor
- *   find_filp:         find a filp slot that points to a given vnode
- *   inval_filp: invalidate a filp and associated fd's, only let close()
- *               happen on it
+ *   get_fd:       look for free file descriptor and free filp slots
+ *   get_filp:     look up the filp entry for a given file descriptor
+ *   find_filp:            find a filp slot that points to a given vnode
+ *   inval_filp:    invalidate a filp and associated fd's, only let close()
+ *                  happen on it
+ *   do_verify_fd:  verify whether the given file descriptor is valid for 
+ *                  the given endpoint.
+ *   do_set_filp:   marks a filp as in-flight.
+ *   do_copy_filp:  copies a filp to another endpoint.
+ *   do_put_filp:   marks a filp as not in-flight anymore.
+ *   do_cancel_fd:  cancel the transaction when something goes wrong for 
+ *                  the receiver.
  */
 
 #include <sys/select.h>
+#include <minix/callnr.h>
 #include <minix/u64.h>
 #include <assert.h>
 #include "fs.h"
@@ -139,3 +147,205 @@ PUBLIC int invalidate(struct filp *fp)
 
   return(n);   /* Report back how often this filp has been invalidated. */
 }
+
+/*===========================================================================*
+ *                              verify_fd                                    *
+ *===========================================================================*/
+PUBLIC filp_id_t verify_fd(ep, fd)
+endpoint_t ep;
+int fd;
+{
+  /*
+   * verify whether the given file descriptor 'fd' is valid for the
+   * endpoint 'ep'. When the file descriptor is valid verify_fd returns a 
+   * pointer to that filp, else it returns NULL.
+   */
+  int proc;
+
+  if (isokendpt(ep, &proc) != OK) {
+       return NULL;
+  }
+
+  return get_filp2(&fproc[proc], fd);
+}
+
+/*===========================================================================*
+ *                              do_verify_fd                                 *
+ *===========================================================================*/
+PUBLIC int do_verify_fd(void)
+{
+  m_out.ADDRESS = (void *) verify_fd(m_in.IO_ENDPT, m_in.COUNT);
+  return (m_out.ADDRESS != NULL) ? OK : EINVAL;
+}
+
+/*===========================================================================*
+ *                              set_filp                                     *
+ *===========================================================================*/
+PUBLIC int set_filp(sfilp)
+filp_id_t sfilp;
+{
+  if (sfilp == NULL) {
+       return EINVAL;
+  } else {
+       sfilp->filp_count++;
+       return OK;
+  }
+}
+
+/*===========================================================================*
+ *                              do_set_filp                                  *
+ *===========================================================================*/
+PUBLIC int do_set_filp(void)
+{
+  return set_filp((filp_id_t) m_in.ADDRESS);;
+}
+
+/*===========================================================================*
+ *                              copy_filp                                    *
+ *===========================================================================*/
+PUBLIC int copy_filp(to_ep, cfilp)
+endpoint_t to_ep;
+filp_id_t cfilp;
+{
+  int j;
+  int proc;
+
+  if (isokendpt(to_ep, &proc) != OK) {
+       return EINVAL;
+  }
+
+  /* Find an open slot in fp_filp */
+  for (j = 0; j < OPEN_MAX; j++) {
+       if (fproc[proc].fp_filp[j] == NULL && 
+                       !FD_ISSET(j, &fproc[proc].fp_filp_inuse)) {
+
+               /* Found a free slot, add descriptor */
+               FD_SET(j, &fproc[proc].fp_filp_inuse);
+               fproc[proc].fp_filp[j] = cfilp;
+               fproc[proc].fp_filp[j]->filp_count++;
+               return j;
+       }
+  }
+
+  /* File Descriptor Table is Full */
+  return EMFILE;
+}
+
+/*===========================================================================*
+ *                              do_copy_filp                                 *
+ *===========================================================================*/
+PUBLIC int do_copy_filp(void)
+{
+  return copy_filp(m_in.IO_ENDPT, (filp_id_t) m_in.ADDRESS);
+}
+
+/*===========================================================================*
+ *                              put_filp                                     *
+ *===========================================================================*/
+PUBLIC int put_filp(pfilp)
+filp_id_t pfilp;
+{
+  if (pfilp == NULL) {
+       return EINVAL;
+  } else {
+       close_filp(pfilp);
+       return OK;
+  }
+}
+
+/*===========================================================================*
+ *                              do_put_filp                                  *
+ *===========================================================================*/
+PUBLIC int do_put_filp(void)
+{
+  return put_filp((filp_id_t) m_in.ADDRESS);
+}
+
+/*===========================================================================*
+ *                             cancel_fd                                     *
+ *===========================================================================*/
+PUBLIC int cancel_fd(ep, fd)
+endpoint_t ep;
+int fd;
+{
+  int j;
+  int proc;
+
+  if (isokendpt(ep, &proc) != OK) {
+       return EINVAL;
+  }
+
+  /* Check that the input 'fd' is valid */
+  if (verify_fd(ep, fd) != NULL) {
+
+       /* Found a valid descriptor, remove it */
+       FD_CLR(fd, &fproc[proc].fp_filp_inuse);
+       fproc[proc].fp_filp[fd]->filp_count--;
+       fproc[proc].fp_filp[fd] = NULL;
+
+       return fd;
+  }
+
+  /* File descriptor is not valid for the endpoint. */
+  return EINVAL;
+}
+
+/*===========================================================================*
+ *                              do_cancel_fd                                 *
+ *===========================================================================*/
+PUBLIC int do_cancel_fd(void)
+{
+  return cancel_fd(m_in.IO_ENDPT, m_in.COUNT);
+}
+
+/*===========================================================================*
+ *                             close_filp                                   *
+ *===========================================================================*/
+PUBLIC void close_filp(fp)
+struct filp *fp;
+{
+  int mode_word, rw;
+  dev_t dev;
+  struct vnode *vp;
+
+  vp = fp->filp_vno;
+  if (fp->filp_count - 1 == 0 && fp->filp_mode != FILP_CLOSED) {
+       /* Check to see if the file is special. */
+       mode_word = vp->v_mode & I_TYPE;
+       if (mode_word == I_CHAR_SPECIAL || mode_word == I_BLOCK_SPECIAL) {
+               dev = (dev_t) vp->v_sdev;
+               if (mode_word == I_BLOCK_SPECIAL)  {
+                       if (vp->v_bfs_e == ROOT_FS_E) {
+                               /* Invalidate the cache unless the special is
+                                * mounted. Assume that the root filesystem's
+                                * is open only for fsck.
+                                */
+                               req_flush(vp->v_bfs_e, dev);
+                       }
+               }
+               /* Do any special processing on device close. */
+               (void) dev_close(dev, fp-filp);
+               /* Ignore any errors, even SUSPEND. */
+
+               fp->filp_mode = FILP_CLOSED;
+       }
+  }
+
+  /* If the inode being closed is a pipe, release everyone hanging on it. */
+  if (vp->v_pipe == I_PIPE) {
+       rw = (fp->filp_mode & R_BIT ? WRITE : READ);
+       release(vp, rw, NR_PROCS);
+  }
+
+  /* If a write has been done, the inode is already marked as DIRTY. */
+  if (--fp->filp_count == 0) {
+       if (vp->v_pipe == I_PIPE) {
+               /* Last reader or writer is going. Tell PFS about latest
+                * pipe size.
+                */
+               truncate_vnode(vp, vp->v_size);
+       }
+               
+       put_vnode(fp->filp_vno);
+  }
+}
index 9ba3fe7eccf1c23ef672991966948472d7a61643..c6026ef4aa2c1f1667c5f2b2d65b64e12dff8b51 100644 (file)
@@ -3,6 +3,8 @@
  *
  * The entry points into this file are
  *   nested_fs_call    perform a nested call from a file system server
+ *   nested_dev_call   perform a nested call from a device driver server
+ *
  */
 
 #include "fs.h"
@@ -11,6 +13,7 @@
 #include <assert.h>
 #include <minix/callnr.h>
 #include <minix/endpoint.h>
+#include <minix/vfsif.h>
 
 /* maximum nested call stack depth */
 #define MAX_DEPTH 1
@@ -149,3 +152,51 @@ message *m;                                /* request/reply message pointer */
 
   m->m_type = r;
 }
+
+/*===========================================================================*
+ *                             nested_dev_call                              *
+ *===========================================================================*/
+PUBLIC void nested_dev_call(m)
+message *m;                            /* request/reply message pointer */
+{
+/* Handle a nested call from a device driver server.
+ */
+  int r;
+
+  /* Save global variables of the current call */
+  if ((r = push_globals()) != OK) {
+       printf("VFS: error saving globals in call %d from driver %d\n",
+               m->m_type, m->m_source);
+  } else {
+       /* Initialize global variables for the nested call */
+       set_globals(m);
+
+       if (call_nr >= PFS_BASE) {
+               call_nr -= PFS_BASE;
+       }
+
+       /* Perform the nested call */
+       if (call_nr < 0 || call_nr >= PFS_NREQS) {
+
+               printf("VFS: invalid nested call %d from driver %d\n",
+                       call_nr, who_e);
+
+               r = ENOSYS;
+       } else if (who_e == PFS_PROC_NR) {
+
+               r = (*pfs_call_vec[call_nr])();
+       } else {
+
+               printf("VFS: only the PFS device can make nested VFS calls\n");
+
+               r = ENOSYS;
+       }
+
+       /* Store the result, and restore original global variables */
+       *m = m_out;
+
+       pop_globals();
+  }
+
+  m->m_type = r;
+}
index 737f1c93879e408d19d49eb866649a165ef41be6..f6f54b1ca812fe37a23634269cefa73397557d73 100644 (file)
@@ -34,5 +34,6 @@ EXTERN int err_code;          /* temporary storage for error number */
 
 /* Data initialized elsewhere. */
 extern _PROTOTYPE (int (*call_vec[]), (void) ); /* sys call table */
+extern _PROTOTYPE (int (*pfs_call_vec[]), (void) ); /* pfs callback table */
 extern char dot1[2];   /* dot1 (&dot1[0]) and dot2 (&dot2[0]) have a special */
 extern char dot2[3];   /* meaning to search_dir: no access permission check. */
index 3b8a6171f0a4e62d83fcac66a93756604f5b4d31..bb0c148e18d0c507d11f896ed2c8c32edd042b21 100644 (file)
@@ -34,12 +34,12 @@ PUBLIC int do_link()
 
   /* See if 'name1' (file to be linked to) exists. */ 
   if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
-  if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+  if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
 
   /* Does the final directory of 'name2' exist? */
   if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) 
        r = err_code;
-  else if ((vp_d = last_dir()) == NULL)
+  else if ((vp_d = last_dir(fp)) == NULL)
        r = err_code; 
   if (r != OK) {
          put_vnode(vp);
@@ -76,7 +76,7 @@ PUBLIC int do_unlink()
   
   /* Get the last directory in the path. */
   if(fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
-  if ((vldirp = last_dir()) == NULL) return(err_code);
+  if ((vldirp = last_dir(fp)) == NULL) return(err_code);
 
   /* Make sure that the object is a directory */
   if((vldirp->v_mode & I_TYPE) != I_DIRECTORY) {
@@ -94,7 +94,7 @@ PUBLIC int do_unlink()
      user is allowed to unlink */
   if ((vldirp->v_mode & S_ISVTX) == S_ISVTX) {
        /* Look up inode of file to unlink to retrieve owner */
-       vp = advance(vldirp, PATH_RET_SYMLINK);
+       vp = advance(vldirp, PATH_RET_SYMLINK, fp);
        if (vp != NULL) {
                if(vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID) 
                        r = EPERM;
@@ -129,13 +129,13 @@ PUBLIC int do_rename()
   
   /* See if 'name1' (existing file) exists.  Get dir and file inodes. */
   if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
-  if ((old_dirp = last_dir()) == NULL) return(err_code);
+  if ((old_dirp = last_dir(fp)) == NULL) return(err_code);
 
   /* If the sticky bit is set, only the owner of the file or a privileged
      user is allowed to rename */
   if((old_dirp->v_mode & S_ISVTX) == S_ISVTX) {
        /* Look up inode of file to unlink to retrieve owner */
-       vp = advance(old_dirp, PATH_RET_SYMLINK);
+       vp = advance(old_dirp, PATH_RET_SYMLINK, fp);
        if (vp != NULL) {
                if(vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID) 
                        r = EPERM;
@@ -158,7 +158,7 @@ PUBLIC int do_rename()
   /* See if 'name2' (new name) exists.  Get dir inode */
   if(fetch_name(m_in.name2, m_in.name2_length, M1) != OK) 
        r = err_code;
-  else if ((new_dirp = last_dir()) == NULL)
+  else if ((new_dirp = last_dir(fp)) == NULL)
        r = err_code; 
   if (r != OK) {
        put_vnode(old_dirp);
@@ -198,7 +198,7 @@ PUBLIC int do_truncate()
 
   /* Temporarily open file */
   if (fetch_name(m_in.m2_p1, m_in.m2_i1, M1) != OK) return(err_code);
-  if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+  if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
   
   /* Ask FS to truncate the file */
   if ((r = forbidden(vp, W_BIT)) == OK)
@@ -259,7 +259,7 @@ PUBLIC int do_slink()
   
   /* Get dir inode of 'name2' */
   if(fetch_name(m_in.name2, m_in.name2_length, M1) != OK) return(err_code);
-  if ((vp = last_dir()) == NULL) return(err_code);
+  if ((vp = last_dir(fp)) == NULL) return(err_code);
 
   if ((r = forbidden(vp, W_BIT|X_BIT)) == OK) {
        r = req_slink(vp->v_fs_e, vp->v_inode_nr, user_fullpath, who_e,
@@ -271,6 +271,32 @@ PUBLIC int do_slink()
   return(r);
 }
 
+/*===========================================================================*
+ *                              rdlink_direct                                *
+ *===========================================================================*/
+PUBLIC int rdlink_direct(orig_path, link_path, rfp)
+char *orig_path;
+char *link_path; /* should have length PATH_MAX+1 */
+struct fproc *rfp;
+{
+/* Perform a readlink()-like call from within the VFS */
+  int r;
+  struct vnode *vp;
+
+  /* Temporarily open the file containing the symbolic link */
+  strncpy(user_fullpath, orig_path, PATH_MAX);
+  if ((vp = eat_path(PATH_RET_SYMLINK, rfp)) == NULL) return(err_code);
+
+  /* Make sure this is a symbolic link */
+  if((vp->v_mode & I_TYPE) != I_SYMBOLIC_LINK)
+       r = EINVAL;
+  else
+       r = req_rdlink(vp->v_fs_e, vp->v_inode_nr, (endpoint_t) 0,
+                                               link_path, PATH_MAX+1, 1);
+
+  put_vnode(vp);
+  return r;
+}
 
 /*===========================================================================*
  *                             do_rdlink                                    *
@@ -286,13 +312,14 @@ PUBLIC int do_rdlink()
 
   /* Temporarily open the file containing the symbolic link */
   if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
-  if ((vp = eat_path(PATH_RET_SYMLINK)) == NULL) return(err_code);
+  if ((vp = eat_path(PATH_RET_SYMLINK, fp)) == NULL) return(err_code);
 
   /* Make sure this is a symbolic link */
   if((vp->v_mode & I_TYPE) != I_SYMBOLIC_LINK) 
        r = EINVAL;
   else
-       r = req_rdlink(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, copylen);
+       r = req_rdlink(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2,
+                                                               copylen, 0);
 
   put_vnode(vp);
   return(r);
index 6a731a5cc03beef3edd2725eb3c58610be9237f3..5064be82f2d64305807ecf0ec25ede3211db019c 100644 (file)
@@ -213,7 +213,7 @@ PRIVATE int mount_fs(endpoint_t fs_e)
   
        /* Now get the inode of the file to be mounted on. */
        if (fetch_name(m_in.name2, m_in.name2_length, M1)!=OK) return(err_code);
-       if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+       if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
        if (vp->v_ref_count != 1) {
                put_vnode(vp);
                return(EBUSY);
@@ -254,7 +254,7 @@ PRIVATE int mount_fs(endpoint_t fs_e)
 
   if(!replace_root) {
        /* Get vnode of mountpoint */
-       if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+       if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
 
               if (vp->v_ref_count != 1) {
                       put_vnode(vp);
@@ -451,7 +451,8 @@ PUBLIC int unmount(
        panic("unmount: strange fs endpoint: %d", vmp->m_fs_e);
 
   if ((r = req_unmount(vmp->m_fs_e)) != OK)              /* Not recoverable. */
-       printf("VFS: ignoring failed umount attempt (%d)\n", r);
+       printf("VFS: ignoring failed umount attempt (%d) fs pid: %d\n", r,
+                                               _ENDPOINT_P(vmp->m_fs_e));
 
   if (is_nonedev(vmp->m_dev))
        free_nonedev(vmp->m_dev);
@@ -507,7 +508,7 @@ PRIVATE dev_t name_to_dev(int allow_mountpt)
   struct vnode *vp;
   
   /* Request lookup */
-  if ((vp = eat_path(PATH_NOFLAGS)) == NULL) {
+  if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) {
        return(NO_DEV);
   }
 
index 1ef32ca35880333accd1da60be8a6822a02bd0f1..ae116b252ec0184df7a9333e01c9957df1430fca 100644 (file)
@@ -104,7 +104,7 @@ PRIVATE int common_open(register int oflags, mode_t omode)
                                             flag is set this is an error */
   } else {
        /* Scan path name */
-       if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+       if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
   }
 
   /* Claim the file descriptor and filp slot and fill them in. */
@@ -254,10 +254,10 @@ PRIVATE struct vnode *new_node(int oflags, mode_t bits)
   if (oflags & O_EXCL) flags |= PATH_RET_SYMLINK;
 
   /* See if the path can be opened down to the last directory. */
-  if ((dirp = last_dir()) == NULL) return(NULL);
+  if ((dirp = last_dir(fp)) == NULL) return(NULL);
 
   /* The final directory is accessible. Get final component of the path. */
-  vp = advance(dirp, flags);
+  vp = advance(dirp, flags, fp);
 
   /* The combination of a symlink with absolute path followed by a danglink
    * symlink results in a new path that needs to be re-resolved entirely. */
@@ -280,7 +280,7 @@ PRIVATE struct vnode *new_node(int oflags, mode_t bits)
                        struct vnode *slp, *old_wd;
 
                        /* Resolve path up to symlink */
-                       slp = advance(dirp, PATH_RET_SYMLINK);
+                       slp = advance(dirp, PATH_RET_SYMLINK, fp);
                        if (slp != NULL) {
                                if (S_ISLNK(slp->v_mode)) {
                                        /* Get contents of link */
@@ -291,7 +291,7 @@ PRIVATE struct vnode *new_node(int oflags, mode_t bits)
                                                       slp->v_inode_nr,
                                                       VFS_PROC_NR,
                                                       user_fullpath,
-                                                      max_linklen);
+                                                      max_linklen, 0);
                                        if (r < 0) {
                                                /* Failed to read link */
                                                put_vnode(slp);
@@ -406,7 +406,7 @@ PUBLIC int do_mknod()
 
   /* Open directory that's going to hold the new node. */
   if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
-  if((vp = last_dir()) == NULL) return(err_code);
+  if((vp = last_dir(fp)) == NULL) return(err_code);
 
   /* Make sure that the object is a directory */
   if((vp->v_mode & I_TYPE) != I_DIRECTORY) {
@@ -439,7 +439,7 @@ PUBLIC int do_mkdir()
   bits = I_DIRECTORY | (m_in.mode & RWX_MODES & fp->fp_umask);
 
   /* Request lookup */
-  if((vp = last_dir()) == NULL) return(err_code);
+  if((vp = last_dir(fp)) == NULL) return(err_code);
 
   /* Make sure that the object is a directory */
   if ((vp->v_mode & I_TYPE) != I_DIRECTORY) {
@@ -596,60 +596,6 @@ int fd_nr;
   return(OK);
 }
 
-
-/*===========================================================================*
- *                             close_filp                                   *
- *===========================================================================*/
-PUBLIC void close_filp(fp)
-struct filp *fp;
-{
-  int mode_word, rw;
-  dev_t dev;
-  struct vnode *vp;
-
-  vp = fp->filp_vno;
-  if (fp->filp_count - 1 == 0 && fp->filp_mode != FILP_CLOSED) {
-       /* Check to see if the file is special. */
-       mode_word = vp->v_mode & I_TYPE;
-       if (mode_word == I_CHAR_SPECIAL || mode_word == I_BLOCK_SPECIAL) {
-               dev = (dev_t) vp->v_sdev;
-               if (mode_word == I_BLOCK_SPECIAL)  {
-                       if (vp->v_bfs_e == ROOT_FS_E) {
-                               /* Invalidate the cache unless the special is
-                                * mounted. Assume that the root filesystem's
-                                * is open only for fsck.
-                                */
-                               req_flush(vp->v_bfs_e, dev);
-                       }
-               }
-               /* Do any special processing on device close. */
-               (void) dev_close(dev, fp-filp);
-               /* Ignore any errors, even SUSPEND. */
-
-               fp->filp_mode = FILP_CLOSED;
-       }
-  }
-
-  /* If the inode being closed is a pipe, release everyone hanging on it. */
-  if (vp->v_pipe == I_PIPE) {
-       rw = (fp->filp_mode & R_BIT ? WRITE : READ);
-       release(vp, rw, NR_PROCS);
-  }
-
-  /* If a write has been done, the inode is already marked as DIRTY. */
-  if (--fp->filp_count == 0) {
-       if (vp->v_pipe == I_PIPE) {
-               /* Last reader or writer is going. Tell PFS about latest
-                * pipe size.
-                */
-               truncate_vnode(vp, vp->v_size);
-       }
-               
-       put_vnode(fp->filp_vno);
-  }
-}
-
-
 /*===========================================================================*
  *                             close_reply                                  *
  *===========================================================================*/
index c85af71f7b97a0529cebfc7e7cad732e2e762c24..3bd7f60199f2ab1089caa9c043b14295e4175d4f 100644 (file)
@@ -13,6 +13,9 @@
 #include <unistd.h>
 #include <assert.h>
 #include <minix/vfsif.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <dirent.h>
 #include "fproc.h"
 #include "vmnt.h"
 #include "vnode.h"
 #define DO_POSIX_PATHNAME_RES  0
 
 FORWARD _PROTOTYPE( int lookup, (struct vnode *dirp, int flags,
-                                node_details_t *node)                  );
+                                node_details_t *node, struct fproc *rfp));
 
 /*===========================================================================*
  *                             advance                                      *
  *===========================================================================*/
-PUBLIC struct vnode *advance(dirp, flags)
+PUBLIC struct vnode *advance(dirp, flags, rfp)
 struct vnode *dirp;
 int flags;
+struct fproc *rfp;
 {
 /* Resolve a pathname (in user_fullpath) starting at dirp to a vnode. */
   int r;
@@ -50,7 +54,7 @@ int flags;
   if((new_vp = get_free_vnode()) == NULL) return(NULL);
   
   /* Lookup vnode belonging to the file. */
-  if ((r = lookup(dirp, flags, &res)) != OK) {
+  if ((r = lookup(dirp, flags, &res, rfp)) != OK) {
        err_code = r;
        return(NULL);
   }
@@ -86,21 +90,23 @@ int flags;
 /*===========================================================================*
  *                             eat_path                                     *
  *===========================================================================*/
-PUBLIC struct vnode *eat_path(flags)
+PUBLIC struct vnode *eat_path(flags, rfp)
 int flags;
+struct fproc *rfp;
 {
 /* Resolve 'user_fullpath' to a vnode. advance does the actual work. */
   struct vnode *vp;
 
-  vp = (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
-  return advance(vp, flags);
+  vp = (user_fullpath[0] == '/' ? rfp->fp_rd : rfp->fp_wd);
+  return advance(vp, flags, rfp);
 }
 
 
 /*===========================================================================*
- *                             last_dir                                             *
+ *                             last_dir                                     *
  *===========================================================================*/
-PUBLIC struct vnode *last_dir(void)
+PUBLIC struct vnode *last_dir(rfp)
+struct fproc *rfp;
 {
 /* Parse a path, 'user_fullpath', as far as the last directory, fetch the vnode
  * for the last directory into the vnode table, and return a pointer to the
@@ -117,7 +123,7 @@ PUBLIC struct vnode *last_dir(void)
   struct vnode *vp, *res;
   
   /* Is the path absolute or relative? Initialize 'vp' accordingly. */
-  vp = (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
+  vp = (user_fullpath[0] == '/' ? rfp->fp_rd : rfp->fp_wd);
 
   len = strlen(user_fullpath);
 
@@ -155,7 +161,7 @@ PUBLIC struct vnode *last_dir(void)
          cp--;
   }
 
-  res = advance(vp, PATH_NOFLAGS);
+  res = advance(vp, PATH_NOFLAGS, rfp);
   if (res == NULL) return(NULL);
 
   /* Copy the directory entry back to user_fullpath */
@@ -168,10 +174,11 @@ PUBLIC struct vnode *last_dir(void)
 /*===========================================================================*
  *                             lookup                                       *
  *===========================================================================*/
-PRIVATE int lookup(start_node, flags, node)
+PRIVATE int lookup(start_node, flags, node, rfp)
 struct vnode *start_node;
 int flags;
 node_details_t *node;
+struct fproc *rfp;
 {
 /* Resolve a pathname (in user_fullpath) relative to start_node. */
 
@@ -191,8 +198,8 @@ node_details_t *node;
        return(ENOENT);
   }
 
-  if(!fp->fp_rd || !fp->fp_wd) {
-       printf("VFS: lookup_rel %d: no rd/wd\n", fp->fp_endpoint);
+  if(!rfp->fp_rd || !rfp->fp_wd) {
+       printf("VFS: lookup_rel %d: no rd/wd\n", rfp->fp_endpoint);
        return(ENOENT);
   }
 
@@ -201,19 +208,19 @@ node_details_t *node;
  
   /* Is the process' root directory on the same partition?,
    * if so, set the chroot directory too. */
-  if (fp->fp_rd->v_dev == fp->fp_wd->v_dev)
-       root_ino = fp->fp_rd->v_inode_nr; 
+  if (rfp->fp_rd->v_dev == rfp->fp_wd->v_dev)
+       root_ino = rfp->fp_rd->v_inode_nr; 
   else
        root_ino = 0;
 
   /* Set user and group ids according to the system call */
-  uid = (call_nr == ACCESS ? fp->fp_realuid : fp->fp_effuid); 
-  gid = (call_nr == ACCESS ? fp->fp_realgid : fp->fp_effgid); 
+  uid = (call_nr == ACCESS ? rfp->fp_realuid : rfp->fp_effuid); 
+  gid = (call_nr == ACCESS ? rfp->fp_realgid : rfp->fp_effgid); 
 
   symloop = 0; /* Number of symlinks seen so far */
 
   /* Issue the request */
-  r = req_lookup(fs_e, dir_ino, root_ino, uid, gid, flags, &res);
+  r = req_lookup(fs_e, dir_ino, root_ino, uid, gid, flags, &res, rfp);
 
   if (r != OK && r != EENTERMOUNT && r != ELEAVEMOUNT && r != ESYMLINK)
        return(r); /* i.e., an error occured */
@@ -234,7 +241,7 @@ node_details_t *node;
 
        /* Symlink encountered with absolute path */
        if (r == ESYMLINK) {
-               dir_vp = fp->fp_rd;
+               dir_vp = rfp->fp_rd;
        } else if (r == EENTERMOUNT) {
                /* Entering a new partition */
                dir_vp = 0;
@@ -278,12 +285,12 @@ node_details_t *node;
 
        /* Is the process' root directory on the same partition?,
         * if so, set the chroot directory too. */
-       if(dir_vp->v_dev == fp->fp_rd->v_dev)
-               root_ino = fp->fp_rd->v_inode_nr; 
+       if(dir_vp->v_dev == rfp->fp_rd->v_dev)
+               root_ino = rfp->fp_rd->v_inode_nr; 
        else
                root_ino = 0;
 
-       r = req_lookup(fs_e, dir_ino, root_ino, uid, gid, flags, &res);
+       r = req_lookup(fs_e, dir_ino, root_ino, uid, gid, flags, &res, rfp);
 
        if(r != OK && r != EENTERMOUNT && r != ELEAVEMOUNT && r != ESYMLINK)
                return(r);
@@ -300,3 +307,229 @@ node_details_t *node;
   
   return(r);
 }
+
+/*===========================================================================*
+ *                             get_name                                     *
+ *===========================================================================*/
+PUBLIC int get_name(dirp, entry, ename)
+struct vnode *dirp;
+struct vnode *entry;
+char ename[NAME_MAX + 1];
+{
+  u64_t pos = {0, 0}, new_pos;
+  int r, consumed, totalbytes;
+  char buf[(sizeof(struct dirent) + NAME_MAX) * 8];
+  struct dirent *cur;
+
+  if ((dirp->v_mode & I_TYPE) != I_DIRECTORY) {
+       return(EBADF);
+  }
+
+  do {
+       r = req_getdents(dirp->v_fs_e, dirp->v_inode_nr, pos, 
+                                               buf, sizeof(buf), &new_pos, 1);
+
+       if (r == 0) {
+               return(ENOENT); /* end of entries -- matching inode !found */
+       } else if (r < 0) {
+               return(r); /* error */
+       }
+
+       consumed = 0; /* bytes consumed */
+       totalbytes = r; /* number of bytes to consume */
+
+       do {
+               cur = (struct dirent *) (buf + consumed);
+               if (entry->v_inode_nr == cur->d_ino) {
+                       /* found the entry we were looking for */
+                       strncpy(ename, cur->d_name, NAME_MAX);
+                       ename[NAME_MAX] = '\0';
+                       return(OK);
+               }
+
+               /* not a match -- move on to the next dirent */
+               consumed += cur->d_reclen;
+       } while (consumed < totalbytes);
+
+       pos = new_pos;
+  } while (1);
+}
+
+/*===========================================================================*
+ *                             canonical_path                               *
+ *===========================================================================*/
+PUBLIC int canonical_path(orig_path, canon_path, rfp)
+char *orig_path;
+char *canon_path; /* should have length PATH_MAX+1 */
+struct fproc *rfp;
+{
+  int len = 0;
+  int r, symloop = 0;
+  struct vnode *dir_vp, *parent_dir;
+  char component[NAME_MAX+1];
+  char link_path[PATH_MAX+1];
+
+  dir_vp = NULL;
+  strncpy(user_fullpath, orig_path, PATH_MAX);
+
+  do {
+       if (dir_vp) put_vnode(dir_vp);
+
+       /* Resolve to the last directory holding the socket file */
+       if ((dir_vp = last_dir(rfp)) == NULL) {
+               return(err_code);
+       }
+
+       /* dir_vp points to dir and user_fullpath now contains only the
+        * filename.
+        */
+       strcpy(canon_path, user_fullpath); /* Store file name */
+
+       /* check if the file is a symlink, if so resolve it */
+       r = rdlink_direct(canon_path, link_path, rfp);
+       if (r <= 0) {
+               strcpy(user_fullpath, canon_path);
+               break;
+       }
+
+       /* encountered a symlink -- loop again */
+       strcpy(user_fullpath, link_path);
+
+       symloop++;
+  } while (symloop < SYMLOOP_MAX);
+
+  if (symloop >= SYMLOOP_MAX) {
+       if (dir_vp) put_vnode(dir_vp);
+       return ELOOP;
+  }
+
+  while(dir_vp != rfp->fp_rd) {
+
+       strcpy(user_fullpath, "..");
+
+       /* check if we're at the root node of the file system */
+       if (dir_vp->v_vmnt->m_root_node == dir_vp) {
+               put_vnode(dir_vp);
+               dir_vp = dir_vp->v_vmnt->m_mounted_on;
+               dup_vnode(dir_vp);
+       }
+
+       if ((parent_dir = advance(dir_vp, PATH_NOFLAGS, rfp)) == NULL) {
+               put_vnode(dir_vp);
+               return(err_code);
+       }
+
+       /* now we have to retrieve the name of the parent directory */
+       if (get_name(parent_dir, dir_vp, component) != OK) {
+               put_vnode(dir_vp);
+               put_vnode(parent_dir);
+               return(ENOENT);
+       }
+
+       len += strlen(component) + 1;
+       if (len > PATH_MAX) {
+               /* adding the component to canon_path would exceed PATH_MAX */
+               put_vnode(dir_vp);
+               put_vnode(parent_dir);
+               return(ENOMEM);
+       }
+
+       /* store result of component in canon_path */
+
+       /* first make space by moving the contents of canon_path to
+        * the right. Move strlen + 1 bytes to include the terminating '\0'.
+        */
+       memmove(canon_path+strlen(component)+1, canon_path, 
+                                               strlen(canon_path) + 1);
+
+       /* Copy component into canon_path */
+       memmove(canon_path, component, strlen(component));
+
+       /* Put slash into place */
+       canon_path[strlen(component)] = '/';
+
+       /* Store parent_dir result, and continue the loop once more */
+       put_vnode(dir_vp);
+       dir_vp = parent_dir;
+  }
+
+  put_vnode(dir_vp);
+
+  /* add the leading slash */
+  if (strlen(canon_path) >= PATH_MAX) return(ENAMETOOLONG);
+  memmove(canon_path+1, canon_path, strlen(canon_path));
+  canon_path[0] = '/';
+
+  return(OK);
+}
+
+/*===========================================================================*
+ *                             check_perms                                  *
+ *===========================================================================*/
+PUBLIC int check_perms(ep, io_gr, pathlen)
+endpoint_t ep;
+cp_grant_id_t io_gr;
+int pathlen;
+{
+  int r, i;
+  struct vnode *vp;
+  struct fproc *rfp;
+  char orig_path[PATH_MAX+1];
+  char canon_path[PATH_MAX+1];
+
+  i = _ENDPOINT_P(ep);
+  if (pathlen < UNIX_PATH_MAX || pathlen > PATH_MAX || i < 0 || i >= NR_PROCS) {
+       return EINVAL;
+  }
+  rfp = &(fproc[i]);
+
+  memset(canon_path, '\0', PATH_MAX+1);
+
+  r = sys_safecopyfrom(PFS_PROC_NR, io_gr, (vir_bytes) 0,
+                               (vir_bytes) &user_fullpath, pathlen, D);
+  if (r != OK) {
+       return r;
+  }
+  user_fullpath[pathlen] = '\0';
+
+  /* save path from pfs before permissions checking modifies it */
+  memcpy(orig_path, user_fullpath, PATH_MAX+1);
+
+  /* get the canonical path to the socket file */
+  r = canonical_path(orig_path, canon_path, rfp);
+  if (r != OK) {
+       return r;
+  }
+
+  if (strlen(canon_path) >= pathlen) {
+       return ENAMETOOLONG;
+  }
+
+  /* copy canon_path back to PFS */
+  r = sys_safecopyto(PFS_PROC_NR, (cp_grant_id_t) io_gr, (vir_bytes) 0, 
+                               (vir_bytes) canon_path, strlen(canon_path)+1,
+                               D);
+  if (r != OK) {
+       return r;
+  }
+
+  /* reload user_fullpath for permissions checking */
+  memcpy(user_fullpath, orig_path, PATH_MAX+1);
+  if ((vp = eat_path(PATH_NOFLAGS, rfp)) == NULL) {
+       return(err_code);
+  }
+
+  /* check permissions */
+  r = forbidden(vp, (R_BIT | W_BIT));
+
+  put_vnode(vp);
+  return(r);
+}
+
+/*===========================================================================*
+ *                             do_check_perms                               *
+ *===========================================================================*/
+PUBLIC int do_check_perms(void)
+{
+  return check_perms(m_in.IO_ENDPT, (cp_grant_id_t) m_in.IO_GRANT, m_in.COUNT);
+}
index 83b116944ca5634cd7bb381cb35b044999da7fbd..558cf4f90c5cba50cb8c2cdbf423f549a8629d2c 100644 (file)
@@ -18,8 +18,6 @@
 #include "vnode.h"
 #include "vmnt.h"
 
-FORWARD _PROTOTYPE( int in_group, (gid_t grp)                          );
-
 /*===========================================================================*
  *                             do_chmod                                     *
  *===========================================================================*/
@@ -35,7 +33,7 @@ PUBLIC int do_chmod()
   if (call_nr == CHMOD) {
        /* Temporarily open the file */
        if(fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
-       if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+       if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
   } else {     /* call_nr == FCHMOD */
        /* File is already opened; get a pointer to vnode from filp. */
        if (!(flp = get_filp(m_in.fd))) return(err_code);
@@ -85,7 +83,7 @@ PUBLIC int do_chown()
   if (call_nr == CHOWN) {
        /* Temporarily open the file. */
       if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
-      if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+      if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
   } else {     /* call_nr == FCHOWN */
        /* File is already opened; get a pointer to the vnode from filp. */
       if (!(flp = get_filp(m_in.fd))) return(err_code);
@@ -152,7 +150,7 @@ PUBLIC int do_access()
 
   /* Temporarily open the file. */
   if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
-  if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+  if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
 
   r = forbidden(vp, m_in.mode);
   put_vnode(vp);
@@ -196,7 +194,7 @@ PUBLIC int forbidden(struct vnode *vp, mode_t access_desired)
   } else {
        if (uid == vp->v_uid) shift = 6;                /* owner */
        else if (gid == vp->v_gid) shift = 3;           /* group */
-       else if (in_group(vp->v_gid) == OK) shift = 3;  /* suppl. groups */
+       else if (in_group(fp, vp->v_gid) == OK) shift = 3; /* suppl. groups */
        else shift = 0;                                 /* other */
        perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT);
   }
@@ -215,22 +213,6 @@ PUBLIC int forbidden(struct vnode *vp, mode_t access_desired)
   return(r);
 }
 
-
-/*===========================================================================*
- *                             in_group                                     *
- *===========================================================================*/
-PRIVATE int in_group(gid_t grp)
-{
-  int i;
-
-  for (i = 0; i < fp->fp_ngroups; i++)
-       if (fp->fp_sgroups[i] == grp)
-               return(OK);
-       
-  return(EINVAL);
-}
-
-
 /*===========================================================================*
  *                             read_only                                    *
  *===========================================================================*/
index 10fd861940d083ba571135925215230e5ce4d512..1cb17b9ca385e87507b9fe0f0593f3428b86c572 100644 (file)
@@ -10,6 +10,8 @@ struct fproc;
 struct vmnt;
 struct vnode;
 
+typedef struct filp * filp_id_t;
+
 /* device.c */
 _PROTOTYPE( int dev_open, (dev_t dev, int proc, int flags)             );
 _PROTOTYPE( int dev_reopen, (dev_t dev, int filp_no, int flags)                );
@@ -54,9 +56,21 @@ _PROTOTYPE( int get_fd, (int start, mode_t bits, int *k,
 _PROTOTYPE( struct filp *get_filp, (int fild)                          );
 _PROTOTYPE( struct filp *get_filp2, (struct fproc *rfp, int fild)      );
 _PROTOTYPE( int invalidate, (struct filp *)                            );
+_PROTOTYPE( filp_id_t verify_fd, (endpoint_t ep, int fd)               );
+_PROTOTYPE( int do_verify_fd, (void)                                   );
+_PROTOTYPE( int set_filp, (filp_id_t sfilp)                            );
+_PROTOTYPE( int do_set_filp, (void)                                    );
+_PROTOTYPE( int copy_filp, (endpoint_t to_ep, filp_id_t cfilp)         );
+_PROTOTYPE( int do_copy_filp, (void)                                   );
+_PROTOTYPE( int put_filp, (filp_id_t pfilp)                            );
+_PROTOTYPE( int do_put_filp, (void)                                    );
+_PROTOTYPE( int cancel_fd, (endpoint_t ep, int fd)                     );
+_PROTOTYPE( int do_cancel_fd, (void)                                   );
+_PROTOTYPE( void close_filp, (struct filp *fp)                         );
 
 /* fscall.c */
 _PROTOTYPE( void nested_fs_call, (message *m)                          );
+_PROTOTYPE( void nested_dev_call, (message *m)                         );
 
 /* link.c */
 _PROTOTYPE( int do_link, (void)                                                );
@@ -64,7 +78,9 @@ _PROTOTYPE( int do_unlink, (void)                                     );
 _PROTOTYPE( int do_rename, (void)                                      );
 _PROTOTYPE( int do_truncate, (void)                                    );
 _PROTOTYPE( int do_ftruncate, (void)                                   );
-_PROTOTYPE( int truncate_vnode, (struct vnode *vp, off_t newsize)              );
+_PROTOTYPE( int truncate_vnode, (struct vnode *vp, off_t newsize)      );
+_PROTOTYPE( int rdlink_direct, (char *orig_path, char *link_path,
+                                               struct fproc *rfp)      );
 
 /* lock.c */
 _PROTOTYPE( int lock_op, (struct filp *f, int req)                     );
@@ -99,7 +115,6 @@ _PROTOTYPE( int unmount, (dev_t dev, char *label)                    );
 /* open.c */
 _PROTOTYPE( int do_close, (void)                                       );
 _PROTOTYPE( int close_fd, (struct fproc *rfp, int fd_nr)               );
-_PROTOTYPE( void close_filp, (struct filp *fp)                         );
 _PROTOTYPE( void close_reply, (void)                                   );
 _PROTOTYPE( int do_creat, (void)                                       );
 _PROTOTYPE( int do_lseek, (void)                                       );
@@ -112,9 +127,17 @@ _PROTOTYPE( int do_vm_open, (void)                                 );
 _PROTOTYPE( int do_vm_close, (void)                                    );
 
 /* path.c */
-_PROTOTYPE( struct vnode *advance, (struct vnode *dirp, int flags)     );
-_PROTOTYPE( struct vnode *eat_path, (int flags)                                );
-_PROTOTYPE( struct vnode *last_dir, (void)                             );
+_PROTOTYPE( struct vnode *advance, (struct vnode *dirp, int flags,
+                                               struct fproc *rfp)      );
+_PROTOTYPE( struct vnode *eat_path, (int flags, struct fproc *rfp)     );
+_PROTOTYPE( struct vnode *last_dir, (struct fproc *rfp)                        );
+_PROTOTYPE( int get_name, (struct vnode *dirp, struct vnode *entry,
+                                                       char *_name)    );
+_PROTOTYPE( int canonical_path, (char *orig_path, char *canon_path,
+                                               struct fproc *rfp)      );
+_PROTOTYPE( int check_perms, (endpoint_t ep, cp_grant_id_t gid,
+                                                       int strlen)     );
+_PROTOTYPE( int do_check_perms, (void)                                 );
 
 /* pipe.c */
 _PROTOTYPE( int do_pipe, (void)                                                );
@@ -168,14 +191,15 @@ _PROTOTYPE( int req_fstatfs, (int fs_e, int who_e, char *buf)             );
 _PROTOTYPE( int req_statvfs, (int fs_e, int who_e, char *buf)          );
 _PROTOTYPE( int req_ftrunc, (endpoint_t fs_e, ino_t inode_nr,
                                                off_t start, off_t end) );
-_PROTOTYPE( int req_getdents, (endpoint_t fs_e, ino_t inode_nr, u64_t pos,
-                        char *buf, size_t size, u64_t *new_pos)        );
+_PROTOTYPE( int req_getdents, (endpoint_t fs_e, ino_t inode_nr,
+                       u64_t pos, char *buf, size_t size,
+                       u64_t *new_pos, int direct)                     );
 _PROTOTYPE( int req_inhibread, (endpoint_t fs_e, ino_t inode_nr)       );
 _PROTOTYPE( int req_link, (endpoint_t fs_e, ino_t link_parent,
                                        char *lastc, ino_t linked_file) );
 _PROTOTYPE( int req_lookup, (endpoint_t fs_e, ino_t dir_ino, ino_t root_ino,
                             uid_t uid, gid_t gid, int flags,
-                            lookup_res_t *res)                         );
+                            lookup_res_t *res, struct fproc *rfp)      );
 _PROTOTYPE( int req_mkdir, (endpoint_t fs_e, ino_t inode_nr,
        char *lastc, uid_t uid, gid_t gid, mode_t dmode)                );
 _PROTOTYPE( int req_mknod, (endpoint_t fs_e, ino_t inode_nr,
@@ -187,7 +211,8 @@ _PROTOTYPE( int req_newnode, (endpoint_t fs_e, uid_t uid,
                                dev_t dev, struct node_details *res)    );
 _PROTOTYPE( int req_putnode, (int fs_e, ino_t inode_nr, int count)     );
 _PROTOTYPE( int req_rdlink, (endpoint_t fs_e, ino_t inode_nr,
-                       endpoint_t who_e, char *buf, size_t len)        );
+                               endpoint_t who_e, char *buf, size_t len, 
+                               int direct)                             );
 _PROTOTYPE( int req_readsuper, (endpoint_t fs_e, char *driver_name,
                                dev_t dev, int readonly, int isroot,
                                struct node_details *res_nodep)         );
@@ -236,6 +261,7 @@ _PROTOTYPE( long conv4, (int norm, long x)                          );
 _PROTOTYPE( int fetch_name, (char *path, int len, int flag)            );
 _PROTOTYPE( int no_sys, (void)                                         );
 _PROTOTYPE( int isokendpt_f, (char *f, int l, endpoint_t e, int *p, int ft));
+_PROTOTYPE( int in_group, (struct fproc *rfp, gid_t grp)               );
 
 #define okendpt(e, p) isokendpt_f(__FILE__, __LINE__, (e), (p), 1)
 #define isokendpt(e, p) isokendpt_f(__FILE__, __LINE__, (e), (p), 0)
index 9b6853ac39d2ac966866fc4614826e500e00a57d..06bf6dcf27c99b73c86a954b7bea74f6336af243 100644 (file)
@@ -168,7 +168,7 @@ PUBLIC int do_getdents()
        panic("do_getdents: should handle large offsets");
        
   r = req_getdents(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr, 
-                  rfilp->filp_pos, m_in.buffer, m_in.nbytes, &new_pos);
+                  rfilp->filp_pos, m_in.buffer, m_in.nbytes, &new_pos, 0);
 
   if (r > 0)
        rfilp->filp_pos = new_pos;
index cdd208da4fc38155072b799de33996d18c06b0cf..ecc01ee89305739f2528c907cd3894f6246fc4dc 100644 (file)
@@ -283,16 +283,25 @@ PUBLIC int req_getdents(
   u64_t pos,
   char *buf,
   size_t size,
-  u64_t *new_pos
+  u64_t *new_pos,
+  int direct
 )
 {
   int r;
   message m;
   cp_grant_id_t grant_id;
-  
-  grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, size, CPF_WRITE);
+
+  if (direct) {
+       grant_id = cpf_grant_direct(fs_e, (vir_bytes) buf, size,
+                                                               CPF_WRITE);
+  } else {
+       grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, size,
+                                                               CPF_WRITE);
+  }
+
   if (grant_id < 0)
-       panic("req_getdents: cpf_grant_magic failed: %d", grant_id);
+       panic("req_getdents: cpf_grant_direct/cpf_grant_magic failed: %d",
+                                                               grant_id);
 
   m.m_type = REQ_GETDENTS;
   m.REQ_INODE_NR = inode_nr;
@@ -312,7 +321,6 @@ PUBLIC int req_getdents(
   return(r);
 }
 
-
 /*===========================================================================*
  *                             req_inhibread                                *
  *===========================================================================*/
@@ -373,7 +381,8 @@ PUBLIC int req_lookup(
   uid_t uid,
   gid_t gid,
   int flags,
-  lookup_res_t *res
+  lookup_res_t *res,
+  struct fproc *rfp
 )
 {
   int r;
@@ -396,16 +405,16 @@ PUBLIC int req_lookup(
   m.REQ_DIR_INO        = dir_ino;
   m.REQ_ROOT_INO       = root_ino;
 
-  if(fp->fp_ngroups > 0) { /* Is the process member of multiple groups? */
+  if(rfp->fp_ngroups > 0) { /* Is the process member of multiple groups? */
        /* In that case the FS has to copy the uid/gid credentials */
        int i;
 
        /* Set credentials */
-       credentials.vu_uid = fp->fp_effuid;
-       credentials.vu_gid = fp->fp_effgid;
-       credentials.vu_ngroups = fp->fp_ngroups;
-       for (i = 0; i < fp->fp_ngroups; i++) 
-               credentials.vu_sgroups[i] = fp->fp_sgroups[i];
+       credentials.vu_uid = rfp->fp_effuid;
+       credentials.vu_gid = rfp->fp_effgid;
+       credentials.vu_ngroups = rfp->fp_ngroups;
+       for (i = 0; i < rfp->fp_ngroups; i++) 
+               credentials.vu_sgroups[i] = rfp->fp_sgroups[i];
 
        grant_id2 = cpf_grant_direct(fs_e, (vir_bytes) &credentials,
                                     sizeof(credentials), CPF_READ);
@@ -427,7 +436,7 @@ PUBLIC int req_lookup(
   /* Send/rec request */
   r = fs_sendrec(fs_e, &m);
   cpf_revoke(grant_id);
-  if(fp->fp_ngroups > 0) cpf_revoke(grant_id2); 
+  if(rfp->fp_ngroups > 0) cpf_revoke(grant_id2); 
 
   /* Fill in response according to the return value */
   res->fs_e = m.m_source;
@@ -653,18 +662,24 @@ int count;
 /*===========================================================================*
  *                             req_rdlink                                   *
  *===========================================================================*/
-PUBLIC int req_rdlink(fs_e, inode_nr, who_e, buf, len)
+PUBLIC int req_rdlink(fs_e, inode_nr, who_e, buf, len, direct)
 endpoint_t fs_e;
 ino_t inode_nr;
 endpoint_t who_e;
 char *buf;
 size_t len;
+int direct; /* set to 1 to use direct grants instead of magic grants */
 {
   message m;
   int r;
   cp_grant_id_t grant_id;
 
-  grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, len, CPF_WRITE);
+  if (direct) {
+       grant_id = cpf_grant_direct(fs_e, (vir_bytes) buf, len, CPF_WRITE);
+  } else {
+       grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, len,
+                                                               CPF_WRITE);
+  }
   if(grant_id == -1)
          panic("req_rdlink: cpf_grant_magic failed");
 
index 3805f63db82f2311c52d53d0f84d784aea01c7c2..55d80c290f74748c6ca54f5bf2cced16bd2812ec 100644 (file)
@@ -80,7 +80,7 @@ int len;                      /* length of the directory name string */
 
   /* Try to open the directory */
   if (fetch_name(name_ptr, len, M3) != OK) return(err_code);
-  if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+  if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
   return change_into(iip, vp);
 }
 
@@ -123,7 +123,7 @@ PUBLIC int do_stat()
   struct vnode *vp;
 
   if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
-  if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+  if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
   r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0);
 
   put_vnode(vp);
@@ -181,7 +181,7 @@ PUBLIC int do_statvfs()
   struct vnode *vp;
 
   if (fetch_name(m_in.STATVFS_NAME, m_in.STATVFS_LEN, M1) != OK) return(err_code);
-  if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+  if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
   r = req_statvfs(vp->v_fs_e, who_e, m_in.STATVFS_BUF);
 
   put_vnode(vp);
@@ -214,7 +214,7 @@ PUBLIC int do_lstat()
   int r;
 
   if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
-  if ((vp = eat_path(PATH_RET_SYMLINK)) == NULL) return(err_code);
+  if ((vp = eat_path(PATH_RET_SYMLINK, fp)) == NULL) return(err_code);
   r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0);
 
   put_vnode(vp);
index 2c7c3e413c6d4b78206ea27a20bffca56e07cb58..c46a04cca592001ffe9380468e717a80c3636802 100644 (file)
@@ -133,3 +133,13 @@ PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = {
 /* This should not fail with "array size is negative": */
 extern int dummy[sizeof(call_vec) == NCALLS * sizeof(call_vec[0]) ? 1 : -1];
 
+PUBLIC _PROTOTYPE (int (*pfs_call_vec[]), (void) ) = {
+
+       no_sys,         /* 0 */
+       do_check_perms, /* 1 */
+       do_verify_fd,   /* 2 */ 
+       do_set_filp,    /* 3 */
+       do_copy_filp,   /* 4 */
+       do_put_filp,    /* 5 */
+       do_cancel_fd    /* 6 */
+};
index cf279ddacf30fe1bfb132fc2922a789ad5771bb6..749581cba91f5ba6e3d8b1a976c4b4b8df5e931f 100644 (file)
@@ -32,7 +32,7 @@ PUBLIC int do_utime()
 
   /* Temporarily open the file */
   if (fetch_name(m_in.utime_file, len, M1) != OK) return(err_code);
-  if ((vp = eat_path(PATH_NOFLAGS)) == NULL) return(err_code);
+  if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
 
   /* Only the owner of a file or the super user can change its name. */  
   r = OK;
index 296fe1beeee6f23919760d3d0469947f52342758..0c99b8ef03bfefef2b38b7d8274edc4755946675 100644 (file)
@@ -8,6 +8,7 @@
  *   panic:       something awful has occurred;  MINIX cannot continue
  *   conv2:      do byte swapping on a 16-bit int
  *   conv4:      do byte swapping on a 32-bit long
+ *   in_group:    determines if group 'grp' is in rfp->fp_sgroups[]
  */
 
 #include "fs.h"
@@ -140,3 +141,19 @@ PUBLIC time_t clock_time()
   return( (time_t) (boottime + (uptime/system_hz)));
 }
 
+/*===========================================================================*
+ *                              in_group                                     *
+ *===========================================================================*/
+PUBLIC int in_group(struct fproc *rfp, gid_t grp)
+{
+  int i;
+
+  for (i = 0; i < rfp->fp_ngroups; i++) {
+       if (rfp->fp_sgroups[i] == grp) {
+               return(OK);
+       }
+  }
+
+  return(EINVAL);
+}
+