This is required to avoid races with safecopy() at live update time.
Change-Id: I1f3e22d40f22d94bd2b850915f9b8163a08b5616
/* 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 */
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;
/* 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;
}
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 */
};
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;
}
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.
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;
/* 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);
+#define _SYSTEM 1
+
#include <lib.h>
#include <minix/syslib.h>
+#include <minix/sysutil.h>
int _kernel_call(int syscallnr, message *msgptr)
{
- msgptr->m_type = syscallnr;
- do_kernel_call(msgptr);
- return(msgptr->m_type);
+ int t, r;
+ t = 1;
+ while(1) {
+ msgptr->m_type = syscallnr;
+ do_kernel_call(msgptr);
+ r = msgptr->m_type;
+ if(r != ENOTREADY) {
+ break;
+ }
+ tickdelay(t++);
+ }
+ return r;
}
+