Kernel: add support for indirect grants
This commit is contained in:
		
							parent
							
								
									769bed22c8
								
							
						
					
					
						commit
						f814fe41be
					
				| @ -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)	); | ||||
|  | ||||
| @ -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                            * | ||||
|  *===========================================================================*/ | ||||
|  | ||||
| @ -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); | ||||
| 
 | ||||
| 	/* 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) { | ||||
| 	do { | ||||
| 		/* Get granter process slot (if valid), and check range of
 | ||||
| 		 * grant id. | ||||
| 		 */ | ||||
| 		if(!isokendpt(granter, &proc_nr) || !GRANT_VALID(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); | ||||
| 	} | ||||
| 			"grant verify failed: invalid granter or grant\n"); | ||||
| 			return(EINVAL); | ||||
| 		} | ||||
| 		granter_proc = proc_addr(proc_nr); | ||||
| 
 | ||||
| 	/* 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; | ||||
| 	} | ||||
| 		/* 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; | ||||
| 
 | ||||
| 	/* 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; | ||||
| 	} | ||||
| 		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); | ||||
| 		} | ||||
| 
 | ||||
| 		/* 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. */ | ||||
| 	if(((g.cp_flags & access) != access)) { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 David van Moolenbroek
						David van Moolenbroek