From: David van Moolenbroek Date: Mon, 2 Nov 2009 22:30:37 +0000 (+0000) Subject: Kernel: add support for indirect grants X-Git-Tag: v3.1.6~226 X-Git-Url: http://zhaoyanbai.com/repos/Bv9ARM.ch06.html?a=commitdiff_plain;h=f814fe41be02a3805f57efb307af9256cb6fb559;p=minix.git Kernel: add support for indirect grants --- diff --git a/kernel/proto.h b/kernel/proto.h index 5223ad903..737a622f6 100755 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -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) ); diff --git a/kernel/system.c b/kernel/system.c index 888170093..bd276dc22 100755 --- a/kernel/system.c +++ b/kernel/system.c @@ -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 * *===========================================================================*/ diff --git a/kernel/system/do_safecopy.c b/kernel/system/do_safecopy.c index 2e7d7f8ee..a518e3600 100644 --- a/kernel/system/do_safecopy.c +++ b/kernel/system/do_safecopy.c @@ -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)) {