]> Zhao Yanbai Git Server - minix.git/commitdiff
Kernel: add support for indirect grants
authorDavid van Moolenbroek <david@minix3.org>
Mon, 2 Nov 2009 22:30:37 +0000 (22:30 +0000)
committerDavid van Moolenbroek <david@minix3.org>
Mon, 2 Nov 2009 22:30:37 +0000 (22:30 +0000)
kernel/proto.h
kernel/system.c
kernel/system/do_safecopy.c

index 5223ad903bd820664b4f2f2943fef2a6392e8988..737a622f6329adebc9699223cbc875db9d7ec49e 100755 (executable)
@@ -64,7 +64,6 @@ _PROTOTYPE( phys_bytes umap_grant, (struct proc *, cp_grant_id_t,
        vir_bytes));
 _PROTOTYPE( void clear_endpoint, (struct proc *rc)                     );
 _PROTOTYPE( phys_bytes umap_bios, (vir_bytes vir_addr, vir_bytes bytes));
-_PROTOTYPE( phys_bytes umap_verify_grant, (struct proc *rp, endpoint_t grantee,  cp_grant_id_t grant, vir_bytes offset, vir_bytes bytes, int access));
 
 /* system/do_newmap.c */
 _PROTOTYPE( int newmap, (struct proc *rp, struct mem_map *map_ptr)     );
index 888170093a8dac0cb57ebccaec5f776d2d0ef3ce..bd276dc223e0f63087d58d2127bd3dcdac0b0b70 100755 (executable)
@@ -539,37 +539,6 @@ register struct proc *rc;          /* slot of process to clean up */
   }
 }
 
-/*===========================================================================*
- *                              umap_verify_grant                            *
- *===========================================================================*/
-PUBLIC phys_bytes umap_verify_grant(rp, grantee, grant, offset, bytes, access)
-struct proc *rp;                /* pointer to proc table entry for process */
-endpoint_t grantee;             /* who wants to do this */ 
-cp_grant_id_t grant;            /* grant no. */
-vir_bytes offset;               /* offset into grant */
-vir_bytes bytes;                /* size */
-int access;                     /* does grantee want to CPF_READ or _WRITE? */
-{  
-        int proc_nr;
-        vir_bytes v_offset;
-        endpoint_t granter;
-    
-        /* See if the grant in that process is sensible, and
-         * find out the virtual address and (optionally) new
-         * process for that address. 
-         *
-         * Then convert that process to a slot number.
-         */
-        if(verify_grant(rp->p_endpoint, grantee, grant, bytes, access, offset, 
-                &v_offset, &granter) != OK
-           || !isokendpt(granter, &proc_nr)) {
-                return 0;
-        }
-  
-        /* Do the mapping from virtual to physical. */
-        return umap_virtual(proc_addr(proc_nr), D, v_offset, bytes);
-} 
-
 /*===========================================================================*
  *                              vmrestart_check                            *
  *===========================================================================*/
index 2e7d7f8ee35400af66f9540913520e5138fcfa93..a518e36000cf550c9c35fefd820bc962db7e5e3e 100644 (file)
@@ -20,6 +20,8 @@
 #include "../system.h"
 #include "../vm.h"
 
+#define MAX_INDIRECT_DEPTH 5   /* up to how many indirect grants to follow? */
+
 #define MEM_TOP 0xFFFFFFFFUL
 
 FORWARD _PROTOTYPE(int safecopy, (endpoint_t, endpoint_t, cp_grant_id_t, int, int, size_t, vir_bytes, vir_bytes, int));
@@ -43,51 +45,87 @@ endpoint_t *e_granter;              /* new granter (magic grants) */
        static cp_grant_t g;
        static int proc_nr;
        static struct proc *granter_proc;
-       int r;
+       int r, depth = 0;
 
-       /* Get granter process slot (if valid), and check range of
-        * grant id.
-        */
-       if(!isokendpt(granter, &proc_nr) || !GRANT_VALID(grant)) {
-               kprintf("grant verify failed: invalid granter or grant\n");
-               return(EINVAL);
-       }
-       granter_proc = proc_addr(proc_nr);
+       do {
+               /* Get granter process slot (if valid), and check range of
+                * grant id.
+                */
+               if(!isokendpt(granter, &proc_nr) || !GRANT_VALID(grant)) {
+                       kprintf(
+                       "grant verify failed: invalid granter or grant\n");
+                       return(EINVAL);
+               }
+               granter_proc = proc_addr(proc_nr);
 
-       /* If there is no priv. structure, or no grant table in the
-        * priv. structure, or the grant table in the priv. structure
-        * is too small for the grant, return EPERM.
-        */
-       if(!HASGRANTTABLE(granter_proc)) return EPERM;
+               /* If there is no priv. structure, or no grant table in the
+                * priv. structure, or the grant table in the priv. structure
+                * is too small for the grant, return EPERM.
+                */
+               if(!HASGRANTTABLE(granter_proc)) return EPERM;
+
+               if(priv(granter_proc)->s_grant_entries <= grant) {
+                               kprintf(
+                               "verify_grant: grant verify failed in ep %d "
+                               "proc %d: grant %d out of range "
+                               "for table size %d\n",
+                                       granter, proc_nr, grant,
+                                       priv(granter_proc)->s_grant_entries);
+                       return(EPERM);
+               }
 
-       if(priv(granter_proc)->s_grant_entries <= grant) {
+               /* Copy the grant entry corresponding to this id to see what it
+                * looks like. If it fails, hide the fact that granter has
+                * (presumably) set an invalid grant table entry by returning
+                * EPERM, just like with an invalid grant id.
+                */
+               if((r=data_copy(granter,
+                       priv(granter_proc)->s_grant_table + sizeof(g)*grant,
+                       SYSTEM, (vir_bytes) &g, sizeof(g))) != OK) {
                        kprintf(
-                       "verify_grant: grant verify failed in ep %d proc %d: "
-                       "grant %d out of range for table size %d\n",
-                               granter, proc_nr, grant,
-                               priv(granter_proc)->s_grant_entries);
-               return(EPERM);
-       }
+                       "verify_grant: grant verify: data_copy failed\n");
+                       return EPERM;
+               }
 
-       /* Copy the grant entry corresponding to this id to see what it
-        * looks like. If it fails, hide the fact that granter has
-        * (presumably) set an invalid grant table entry by returning
-        * EPERM, just like with an invalid grant id.
-        */
-       if((r=data_copy(granter,
-               priv(granter_proc)->s_grant_table + sizeof(g)*grant,
-               SYSTEM, (vir_bytes) &g, sizeof(g))) != OK) {
-               kprintf("verify_grant: grant verify: data_copy failed\n");
-               return EPERM;
-       }
+               /* Check validity. */
+               if((g.cp_flags & (CPF_USED | CPF_VALID)) !=
+                       (CPF_USED | CPF_VALID)) {
+                       kprintf(
+                       "verify_grant: grant failed: invalid (%d flags 0x%lx)\n",
+                               grant, g.cp_flags);
+                       return EPERM;
+               }
 
-       /* Check validity. */
-       if((g.cp_flags & (CPF_USED | CPF_VALID)) != (CPF_USED | CPF_VALID)) {
-               kprintf(
-               "verify_grant: grant failed: invalid (%d flags 0x%lx)\n",
-                       grant, g.cp_flags);
-               return EPERM;
-       }
+               /* The given grant may be an indirect grant, that is, a grant
+                * that provides permission to use a grant given to the
+                * granter (i.e., for which it is the grantee). This can lead
+                * to a chain of indirect grants which must be followed back.
+                */
+               if((g.cp_flags & CPF_INDIRECT)) {
+                       /* Stop after a few iterations. There may be a loop. */
+                       if (depth == MAX_INDIRECT_DEPTH) {
+                               kprintf(
+                                       "verify grant: indirect grant verify "
+                                       "failed: exceeded maximum depth\n");
+                               return ELOOP;
+                       }
+                       depth++;
+
+                       /* Verify actual grantee. */
+                       if(g.cp_u.cp_indirect.cp_who_to != grantee &&
+                               grantee != ANY) {
+                               kprintf(
+                                       "verify_grant: indirect grant verify "
+                                       "failed: bad grantee\n");
+                               return EPERM;
+                       }
+
+                       /* Start over with new granter, grant, and grantee. */
+                       grantee = granter;
+                       granter = g.cp_u.cp_indirect.cp_who_from;
+                       grant = g.cp_u.cp_indirect.cp_grant;
+               }
+       } while(g.cp_flags & CPF_INDIRECT);
 
        /* Check access of grant. */
        if(((g.cp_flags & access) != access)) {