Kernel: add support for indirect grants
This commit is contained in:
parent
769bed22c8
commit
f814fe41be
3 changed files with 79 additions and 73 deletions
|
@ -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) );
|
||||||
|
|
|
@ -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 *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
|
|
@ -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,13 +45,15 @@ 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;
|
||||||
|
|
||||||
|
do {
|
||||||
/* Get granter process slot (if valid), and check range of
|
/* Get granter process slot (if valid), and check range of
|
||||||
* grant id.
|
* grant id.
|
||||||
*/
|
*/
|
||||||
if(!isokendpt(granter, &proc_nr) || !GRANT_VALID(grant)) {
|
if(!isokendpt(granter, &proc_nr) || !GRANT_VALID(grant)) {
|
||||||
kprintf("grant verify failed: invalid granter or grant\n");
|
kprintf(
|
||||||
|
"grant verify failed: invalid granter or grant\n");
|
||||||
return(EINVAL);
|
return(EINVAL);
|
||||||
}
|
}
|
||||||
granter_proc = proc_addr(proc_nr);
|
granter_proc = proc_addr(proc_nr);
|
||||||
|
@ -62,8 +66,9 @@ endpoint_t *e_granter; /* new granter (magic grants) */
|
||||||
|
|
||||||
if(priv(granter_proc)->s_grant_entries <= grant) {
|
if(priv(granter_proc)->s_grant_entries <= grant) {
|
||||||
kprintf(
|
kprintf(
|
||||||
"verify_grant: grant verify failed in ep %d proc %d: "
|
"verify_grant: grant verify failed in ep %d "
|
||||||
"grant %d out of range for table size %d\n",
|
"proc %d: grant %d out of range "
|
||||||
|
"for table size %d\n",
|
||||||
granter, proc_nr, grant,
|
granter, proc_nr, grant,
|
||||||
priv(granter_proc)->s_grant_entries);
|
priv(granter_proc)->s_grant_entries);
|
||||||
return(EPERM);
|
return(EPERM);
|
||||||
|
@ -77,18 +82,51 @@ endpoint_t *e_granter; /* new granter (magic grants) */
|
||||||
if((r=data_copy(granter,
|
if((r=data_copy(granter,
|
||||||
priv(granter_proc)->s_grant_table + sizeof(g)*grant,
|
priv(granter_proc)->s_grant_table + sizeof(g)*grant,
|
||||||
SYSTEM, (vir_bytes) &g, sizeof(g))) != OK) {
|
SYSTEM, (vir_bytes) &g, sizeof(g))) != OK) {
|
||||||
kprintf("verify_grant: grant verify: data_copy failed\n");
|
kprintf(
|
||||||
|
"verify_grant: grant verify: data_copy failed\n");
|
||||||
return EPERM;
|
return EPERM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check validity. */
|
/* Check validity. */
|
||||||
if((g.cp_flags & (CPF_USED | CPF_VALID)) != (CPF_USED | CPF_VALID)) {
|
if((g.cp_flags & (CPF_USED | CPF_VALID)) !=
|
||||||
|
(CPF_USED | CPF_VALID)) {
|
||||||
kprintf(
|
kprintf(
|
||||||
"verify_grant: grant failed: invalid (%d flags 0x%lx)\n",
|
"verify_grant: grant failed: invalid (%d flags 0x%lx)\n",
|
||||||
grant, g.cp_flags);
|
grant, g.cp_flags);
|
||||||
return EPERM;
|
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)) {
|
||||||
kprintf(
|
kprintf(
|
||||||
|
|
Loading…
Reference in a new issue