Kernel: add support for indirect grants

This commit is contained in:
David van Moolenbroek 2009-11-02 22:30:37 +00:00
parent 769bed22c8
commit f814fe41be
3 changed files with 79 additions and 73 deletions

View file

@ -64,7 +64,6 @@ _PROTOTYPE( phys_bytes umap_grant, (struct proc *, cp_grant_id_t,
vir_bytes)); vir_bytes));
_PROTOTYPE( void clear_endpoint, (struct proc *rc) ); _PROTOTYPE( void clear_endpoint, (struct proc *rc) );
_PROTOTYPE( phys_bytes umap_bios, (vir_bytes vir_addr, vir_bytes bytes)); _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 */ /* system/do_newmap.c */
_PROTOTYPE( int newmap, (struct proc *rp, struct mem_map *map_ptr) ); _PROTOTYPE( int newmap, (struct proc *rp, struct mem_map *map_ptr) );

View file

@ -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 * * vmrestart_check *
*===========================================================================*/ *===========================================================================*/

View file

@ -20,6 +20,8 @@
#include "../system.h" #include "../system.h"
#include "../vm.h" #include "../vm.h"
#define MAX_INDIRECT_DEPTH 5 /* up to how many indirect grants to follow? */
#define MEM_TOP 0xFFFFFFFFUL #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)); 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 cp_grant_t g;
static int proc_nr; static int proc_nr;
static struct proc *granter_proc; static struct proc *granter_proc;
int r; int r, depth = 0;
/* Get granter process slot (if valid), and check range of do {
* grant id. /* 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"); if(!isokendpt(granter, &proc_nr) || !GRANT_VALID(grant)) {
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(priv(granter_proc)->s_grant_entries <= grant) {
kprintf( kprintf(
"verify_grant: grant verify failed in ep %d proc %d: " "grant verify failed: invalid granter or grant\n");
"grant %d out of range for table size %d\n", return(EINVAL);
granter, proc_nr, grant, }
priv(granter_proc)->s_grant_entries); granter_proc = proc_addr(proc_nr);
return(EPERM);
}
/* Copy the grant entry corresponding to this id to see what it /* If there is no priv. structure, or no grant table in the
* looks like. If it fails, hide the fact that granter has * priv. structure, or the grant table in the priv. structure
* (presumably) set an invalid grant table entry by returning * is too small for the grant, return EPERM.
* EPERM, just like with an invalid grant id. */
*/ if(!HASGRANTTABLE(granter_proc)) return EPERM;
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(priv(granter_proc)->s_grant_entries <= grant) {
if((g.cp_flags & (CPF_USED | CPF_VALID)) != (CPF_USED | CPF_VALID)) { kprintf(
kprintf( "verify_grant: grant verify failed in ep %d "
"verify_grant: grant failed: invalid (%d flags 0x%lx)\n", "proc %d: grant %d out of range "
grant, g.cp_flags); "for table size %d\n",
return EPERM; granter, proc_nr, grant,
} priv(granter_proc)->s_grant_entries);
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;
}
/* 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. */ /* Check access of grant. */
if(((g.cp_flags & access) != access)) { if(((g.cp_flags & access) != access)) {