diff --git a/minix/kernel/priv.h b/minix/kernel/priv.h index 4efd9e877..4303ac497 100644 --- a/minix/kernel/priv.h +++ b/minix/kernel/priv.h @@ -30,6 +30,7 @@ struct priv { size_t s_asynsize; /* number of elements in table. 0 when not in * use */ + endpoint_t s_asynendpoint; /* the endpoint the asyn table belongs to. */ short s_trap_mask; /* allowed system call traps */ sys_map_t s_ipc_to; /* allowed destination processes */ diff --git a/minix/kernel/proc.c b/minix/kernel/proc.c index 1629b3ca6..bc8458f4c 100644 --- a/minix/kernel/proc.c +++ b/minix/kernel/proc.c @@ -1153,6 +1153,7 @@ int try_deliver_senda(struct proc *caller_ptr, /* Clear table */ privp->s_asyntab = -1; privp->s_asynsize = 0; + privp->s_asynendpoint = caller_ptr->p_endpoint; if (size == 0) return(OK); /* Nothing to do, just return */ @@ -1346,6 +1347,7 @@ static int try_one(endpoint_t receive_e, struct proc *src_ptr, unset_sys_bit(priv(dst_ptr)->s_asyn_pending, privp->s_id); if (size == 0) return(EAGAIN); + if (privp->s_asynendpoint != src_ptr->p_endpoint) return EAGAIN; if (!may_asynsend_to(src_ptr, proc_nr(dst_ptr))) return (ECALLDENIED); caller_ptr = src_ptr; /* Needed for A_ macros later on */ diff --git a/minix/kernel/system/do_privctl.c b/minix/kernel/system/do_privctl.c index 188cea939..1dd19423e 100644 --- a/minix/kernel/system/do_privctl.c +++ b/minix/kernel/system/do_privctl.c @@ -126,6 +126,7 @@ int do_privctl(struct proc * caller, message * m_ptr) reset_kernel_timer(&priv(rp)->s_alarm_timer); /* - alarm */ priv(rp)->s_asyntab= -1; /* - asynsends */ priv(rp)->s_asynsize= 0; + priv(rp)->s_asynendpoint = rp->p_endpoint; priv(rp)->s_diag_sig = FALSE; /* no request for diag sigs */ /* Set defaults for privilege bitmaps. */ diff --git a/minix/kernel/system/do_update.c b/minix/kernel/system/do_update.c index 14792c92e..089037b88 100644 --- a/minix/kernel/system/do_update.c +++ b/minix/kernel/system/do_update.c @@ -23,9 +23,11 @@ static int inherit_priv_irq(struct proc *src_rp, struct proc *dst_rp); static int inherit_priv_io(struct proc *src_rp, struct proc *dst_rp); static int inherit_priv_mem(struct proc *src_rp, struct proc *dst_rp); +static void abort_proc_ipc_send(struct proc *rp); static void adjust_proc_slot(struct proc *rp, struct proc *from_rp); static void adjust_priv_slot(struct priv *privp, struct priv *from_privp); +static void adjust_asyn_table(struct priv *src_privp, struct priv *dst_privp); static void swap_proc_slot_pointer(struct proc **rpp, struct proc *src_rp, struct proc *dst_rp); @@ -38,7 +40,7 @@ int do_update(struct proc * caller, message * m_ptr) * slots. */ endpoint_t src_e, dst_e; - int src_p, dst_p; + int src_p, dst_p, flags; struct proc *src_rp, *dst_rp; struct priv *src_privp, *dst_privp; struct proc orig_src_proc; @@ -48,6 +50,7 @@ int do_update(struct proc * caller, message * m_ptr) int i, r; /* Lookup slots for source and destination process. */ + flags = m_ptr->SYS_UPD_FLAGS; src_e = m_ptr->SYS_UPD_SRC_ENDPT; if(!isokendpt(src_e, &src_p)) { return EINVAL; @@ -112,6 +115,15 @@ int do_update(struct proc * caller, message * m_ptr) orig_dst_proc = *dst_rp; orig_dst_priv = *(priv(dst_rp)); + /* Adjust asyn tables. */ + adjust_asyn_table(priv(src_rp), priv(dst_rp)); + adjust_asyn_table(priv(dst_rp), priv(src_rp)); + + /* Abort any pending send() on rollback. */ + if(flags & SYS_UPD_ROLLBACK) { + abort_proc_ipc_send(src_rp); + } + /* Swap slots. */ *src_rp = orig_dst_proc; *src_privp = orig_dst_priv; @@ -195,6 +207,27 @@ int inherit_priv_mem(struct proc *src_rp, struct proc *dst_rp) return OK; } +/*===========================================================================* + * abort_proc_ipc_send * + *===========================================================================*/ +void abort_proc_ipc_send(struct proc *rp) +{ + if(RTS_ISSET(rp, RTS_SENDING)) { + struct proc **xpp; + RTS_UNSET(rp, RTS_SENDING); + rp->p_misc_flags &= ~MF_SENDING_FROM_KERNEL; + xpp = &(proc_addr(_ENDPOINT_P(rp->p_sendto_e))->p_caller_q); + while (*xpp) { + if(*xpp == rp) { + *xpp = rp->p_q_link; + rp->p_q_link = NULL; + break; + } + xpp = &(*xpp)->p_q_link; + } + } +} + /*===========================================================================* * adjust_proc_slot * *===========================================================================*/ @@ -205,6 +238,7 @@ static void adjust_proc_slot(struct proc *rp, struct proc *from_rp) rp->p_nr = from_rp->p_nr; rp->p_priv = from_rp->p_priv; priv(rp)->s_proc_nr = from_rp->p_nr; + rp->p_caller_q = from_rp->p_caller_q; /* preserve scheduling */ @@ -216,6 +250,27 @@ static void adjust_proc_slot(struct proc *rp, struct proc *from_rp) #endif } +/*===========================================================================* + * adjust_asyn_table * + *===========================================================================*/ +static void adjust_asyn_table(struct priv *src_privp, struct priv *dst_privp) +{ + /* Transfer the asyn table if source's table belongs to the destination. */ + endpoint_t src_e = proc_addr(src_privp->s_proc_nr)->p_endpoint; + endpoint_t dst_e = proc_addr(dst_privp->s_proc_nr)->p_endpoint; + + if(src_privp->s_asynsize > 0 && dst_privp->s_asynsize > 0 && src_privp->s_asynendpoint == dst_e) { + if(data_copy(src_e, src_privp->s_asyntab, dst_e, dst_privp->s_asyntab, + src_privp->s_asynsize*sizeof(asynmsg_t)) != OK) { + printf("Warning: unable to transfer asyn table from ep %d to ep %d\n", + src_e, dst_e); + } + else { + dst_privp->s_asynsize = src_privp->s_asynsize; + } + } +} + /*===========================================================================* * adjust_priv_slot * *===========================================================================*/