kernel: Allow kernel calls to return ENOTREADY.
This is required to avoid races with safecopy() at live update time. Change-Id: I1f3e22d40f22d94bd2b850915f9b8163a08b5616
This commit is contained in:
		
							parent
							
								
									c8a9900b0c
								
							
						
					
					
						commit
						9e6b1315c3
					
				| @ -87,7 +87,8 @@ void cpf_reload(void); | ||||
| /* Set a process' grant table location and size (in-kernel only). */ | ||||
| #define _K_SET_GRANT_TABLE(rp, ptr, entries)	\ | ||||
| 	priv(rp)->s_grant_table= (ptr);		\ | ||||
| 	priv(rp)->s_grant_entries= (entries); | ||||
| 	priv(rp)->s_grant_entries= (entries);   \ | ||||
| 	priv(rp)->s_grant_endpoint= (rp)->p_endpoint; | ||||
| 
 | ||||
| #endif	/* _MINIX_SAFECOPIES_H */ | ||||
| 
 | ||||
|  | ||||
| @ -30,7 +30,7 @@ int do_sdevio(struct proc * caller, message *m_ptr) | ||||
|   vir_bytes count = m_ptr->m_lsys_krn_sys_sdevio.vec_size; | ||||
|   long port = m_ptr->m_lsys_krn_sys_sdevio.port; | ||||
|   phys_bytes vir_buf; | ||||
|   int i, req_type, req_dir, size, nr_io_range; | ||||
|   int i, r, req_type, req_dir, size, nr_io_range; | ||||
|   struct priv *privp; | ||||
|   struct io_range *iorp; | ||||
|   struct proc *destproc; | ||||
| @ -67,11 +67,12 @@ int do_sdevio(struct proc * caller, message *m_ptr) | ||||
|   /* Check for 'safe' variants. */ | ||||
|   if((m_ptr->m_lsys_krn_sys_sdevio.request & _DIO_SAFEMASK) == _DIO_SAFE) { | ||||
|      /* Map grant address to physical address. */ | ||||
|      if(verify_grant(proc_nr_e, caller->p_endpoint, | ||||
|      if((r=verify_grant(proc_nr_e, caller->p_endpoint, | ||||
| 		m_ptr->m_lsys_krn_sys_sdevio.vec_addr, count, | ||||
| 		req_dir == _DIO_INPUT ? CPF_WRITE : CPF_READ, | ||||
| 		m_ptr->m_lsys_krn_sys_sdevio.offset, &newoffset, &newep, | ||||
| 		NULL) != OK) { | ||||
| 		NULL)) != OK) { | ||||
| 	if(r == ENOTREADY) return r; | ||||
| 	printf("do_sdevio: verify_grant failed\n"); | ||||
| 	return EPERM; | ||||
|     } | ||||
|  | ||||
| @ -60,6 +60,7 @@ struct priv { | ||||
|   int s_irq_tab[NR_IRQ]; | ||||
|   vir_bytes s_grant_table;	/* grant table address of process, or 0 */ | ||||
|   int s_grant_entries;		/* no. of entries, or 0 */ | ||||
|   endpoint_t s_grant_endpoint;  /* the endpoint the grant table belongs to */ | ||||
|   vir_bytes s_state_table;	/* state table address of process, or 0 */ | ||||
|   int s_state_entries;		/* no. of entries, or 0 */ | ||||
| }; | ||||
|  | ||||
| @ -156,6 +156,7 @@ int do_privctl(struct proc * caller, message * m_ptr) | ||||
| 	priv(rp)->s_nr_irq= 0; | ||||
| 	priv(rp)->s_grant_table= 0; | ||||
| 	priv(rp)->s_grant_entries= 0; | ||||
| 	priv(rp)->s_grant_endpoint = rp->p_endpoint; | ||||
| 	priv(rp)->s_state_table= 0; | ||||
| 	priv(rp)->s_state_entries= 0; | ||||
| 	priv(rp)->s_ipcf= 0; | ||||
|  | ||||
| @ -64,6 +64,23 @@ u32_t *flags;			/* CPF_* */ | ||||
| 		} | ||||
| 		granter_proc = proc_addr(proc_nr); | ||||
| 
 | ||||
| 		/* If the granter has a temporary grant table, always allow
 | ||||
| 		 * requests with unspecified access and return ENOTREADY if | ||||
| 		 * no grant table is present or if the grantee's endpoint is not | ||||
| 		 * the endpoint the table belongs to. When ENOTREADY is returned | ||||
| 		 * the same verify_grant() request will be replayed again in a | ||||
| 		 * while until the grant table is final. This is necessary to | ||||
| 		 * avoid races at live update time. | ||||
| 		 */ | ||||
| 		if(priv(granter_proc)->s_grant_endpoint != granter_proc->p_endpoint) { | ||||
| 			if(!access) { | ||||
| 				return OK; | ||||
| 			} | ||||
| 			else if(!HASGRANTTABLE(granter_proc) || grantee != priv(granter_proc)->s_grant_endpoint) { | ||||
| 				return ENOTREADY; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		/* 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. | ||||
| @ -255,14 +272,6 @@ int access;			/* CPF_READ for a copy from granter to grantee, CPF_WRITE | ||||
| 		return EFAULT; | ||||
| 	} | ||||
| 
 | ||||
| 	/* See if there is a reasonable grant table. */ | ||||
| 	if(!(granter_p = endpoint_lookup(granter))) return EINVAL; | ||||
| 	if(!HASGRANTTABLE(granter_p)) { | ||||
| 		printf( | ||||
| 		"safecopy failed: granter %d has no grant table\n", granter); | ||||
| 		return(EPERM); | ||||
| 	} | ||||
| 
 | ||||
| 	/* Decide who is src and who is dst. */ | ||||
| 	if(access & CPF_READ) { | ||||
| 		src = &granter; | ||||
| @ -275,6 +284,7 @@ int access;			/* CPF_READ for a copy from granter to grantee, CPF_WRITE | ||||
| 	/* Verify permission exists. */ | ||||
| 	if((r=verify_grant(granter, grantee, grantid, bytes, access, | ||||
| 	    g_offset, &v_offset, &new_granter, &flags)) != OK) { | ||||
| 		if(r == ENOTREADY) return r; | ||||
| 			printf( | ||||
| 		"grant %d verify to copy %d->%d by %d failed: err %d\n", | ||||
| 				grantid, *src, *dst, grantee, r); | ||||
|  | ||||
| @ -1,9 +1,22 @@ | ||||
| #define _SYSTEM 1 | ||||
| 
 | ||||
| #include <lib.h> | ||||
| #include <minix/syslib.h> | ||||
| #include <minix/sysutil.h> | ||||
| 
 | ||||
| int _kernel_call(int syscallnr, message *msgptr) | ||||
| { | ||||
|   int t, r; | ||||
|   t = 1; | ||||
|   while(1) { | ||||
|       msgptr->m_type = syscallnr; | ||||
|       do_kernel_call(msgptr); | ||||
|   return(msgptr->m_type); | ||||
|       r = msgptr->m_type; | ||||
|       if(r != ENOTREADY) { | ||||
|           break; | ||||
|       } | ||||
|       tickdelay(t++); | ||||
|   } | ||||
|   return r; | ||||
| } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Cristiano Giuffrida
						Cristiano Giuffrida