From 8bab0dfa2a81c54fb6b415a75440a7308e2c37a1 Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Mon, 29 Jun 2015 00:07:29 +0200 Subject: [PATCH] Kernel: delivermsg improvements . make arch-independent, and local to proc.c, reduce code duplication . make vm_suspend public but unduplicated in proc.c . ask VM for handling once, 2nd time SIGSEGV process . remove debug printfs . test case for bogus sendrec() address argument Change-Id: I3893758910c01de60b8fe3e50edd594296a0b73e --- minix/kernel/arch/earm/memory.c | 58 ----------------------------- minix/kernel/arch/i386/memory.c | 61 ------------------------------- minix/kernel/proc.c | 65 +++++++++++++++++++++++++++++++++ minix/kernel/proc.h | 1 + minix/kernel/proto.h | 4 +- 5 files changed, 69 insertions(+), 120 deletions(-) diff --git a/minix/kernel/arch/earm/memory.c b/minix/kernel/arch/earm/memory.c index e8648897c..743886a33 100644 --- a/minix/kernel/arch/earm/memory.c +++ b/minix/kernel/arch/earm/memory.c @@ -394,35 +394,6 @@ size_t vm_lookup_range(const struct proc *proc, vir_bytes vir_addr, return MIN(bytes, len); } -/*===========================================================================* - * vm_suspend * - *===========================================================================*/ -static void vm_suspend(struct proc *caller, const struct proc *target, - const vir_bytes linaddr, const vir_bytes len, const int type, - const int writeflag) -{ - /* This range is not OK for this process. Set parameters - * of the request and notify VM about the pending request. - */ - assert(!RTS_ISSET(caller, RTS_VMREQUEST)); - assert(!RTS_ISSET(target, RTS_VMREQUEST)); - - RTS_SET(caller, RTS_VMREQUEST); - - caller->p_vmrequest.req_type = VMPTYPE_CHECK; - caller->p_vmrequest.target = target->p_endpoint; - caller->p_vmrequest.params.check.start = linaddr; - caller->p_vmrequest.params.check.length = len; - caller->p_vmrequest.params.check.writeflag = writeflag; - caller->p_vmrequest.type = type; - - /* Connect caller on vmrequest wait queue. */ - if(!(caller->p_vmrequest.nextrequestor = vmrequest)) - if(OK != send_sig(VM_PROC_NR, SIGKMEM)) - panic("send_sig failed"); - vmrequest = caller; -} - /*===========================================================================* * vm_check_range * *===========================================================================*/ @@ -449,35 +420,6 @@ int vm_check_range(struct proc *caller, struct proc *target, return VMSUSPEND; } -/*===========================================================================* - * delivermsg * - *===========================================================================*/ -void delivermsg(struct proc *rp) -{ - int r = OK; - - assert(rp->p_misc_flags & MF_DELIVERMSG); - assert(rp->p_delivermsg.m_source != NONE); - - if (copy_msg_to_user(&rp->p_delivermsg, - (message *) rp->p_delivermsg_vir)) { - printf("WARNING wrong user pointer 0x%08lx from " - "process %s / %d\n", - rp->p_delivermsg_vir, - rp->p_name, - rp->p_endpoint); - r = EFAULT; - } - - /* Indicate message has been delivered; address is 'used'. */ - rp->p_delivermsg.m_source = NONE; - rp->p_misc_flags &= ~MF_DELIVERMSG; - - if(!(rp->p_misc_flags & MF_CONTEXT_SET)) { - rp->p_reg.retreg = r; - } -} - /*===========================================================================* * vmmemset * *===========================================================================*/ diff --git a/minix/kernel/arch/i386/memory.c b/minix/kernel/arch/i386/memory.c index b07d685f4..57ca4ce9c 100644 --- a/minix/kernel/arch/i386/memory.c +++ b/minix/kernel/arch/i386/memory.c @@ -421,37 +421,6 @@ size_t vm_lookup_range(const struct proc *proc, vir_bytes vir_addr, return MIN(bytes, len); } -/*===========================================================================* - * vm_suspend * - *===========================================================================*/ -static void vm_suspend(struct proc *caller, const struct proc *target, - const vir_bytes linaddr, const vir_bytes len, const int type, - const int writeflag) -{ - /* This range is not OK for this process. Set parameters - * of the request and notify VM about the pending request. - */ - assert(!RTS_ISSET(caller, RTS_VMREQUEST)); - assert(!RTS_ISSET(target, RTS_VMREQUEST)); - - RTS_SET(caller, RTS_VMREQUEST); - - assert(caller->p_endpoint != VM_PROC_NR); - - caller->p_vmrequest.req_type = VMPTYPE_CHECK; - caller->p_vmrequest.target = target->p_endpoint; - caller->p_vmrequest.params.check.start = linaddr; - caller->p_vmrequest.params.check.length = len; - caller->p_vmrequest.params.check.writeflag = writeflag; - caller->p_vmrequest.type = type; - - /* Connect caller on vmrequest wait queue. */ - if(!(caller->p_vmrequest.nextrequestor = vmrequest)) - if(OK != send_sig(VM_PROC_NR, SIGKMEM)) - panic("send_sig failed"); - vmrequest = caller; -} - /*===========================================================================* * vm_check_range * *===========================================================================*/ @@ -478,36 +447,6 @@ int vm_check_range(struct proc *caller, struct proc *target, return VMSUSPEND; } -/*===========================================================================* - * delivermsg * - *===========================================================================*/ -void delivermsg(struct proc *rp) -{ - int r = OK; - - assert(rp->p_misc_flags & MF_DELIVERMSG); - assert(rp->p_delivermsg.m_source != NONE); - - if (copy_msg_to_user(&rp->p_delivermsg, - (message *) rp->p_delivermsg_vir)) { - printf("WARNING wrong user pointer 0x%08lx from " - "process %s / %d\n", - rp->p_delivermsg_vir, - rp->p_name, - rp->p_endpoint); - cause_sig(rp->p_nr, SIGSEGV); - r = EFAULT; - } - - /* Indicate message has been delivered; address is 'used'. */ - rp->p_delivermsg.m_source = NONE; - rp->p_misc_flags &= ~MF_DELIVERMSG; - - if(!(rp->p_misc_flags & MF_CONTEXT_SET)) { - rp->p_reg.retreg = r; - } -} - #if 0 static char *flagstr(u32_t e, const int dir) { diff --git a/minix/kernel/proc.c b/minix/kernel/proc.c index bc8458f4c..57864dbe6 100644 --- a/minix/kernel/proc.c +++ b/minix/kernel/proc.c @@ -231,6 +231,71 @@ static void idle(void) */ } +/*===========================================================================* + * vm_suspend * + *===========================================================================*/ +void vm_suspend(struct proc *caller, const struct proc *target, + const vir_bytes linaddr, const vir_bytes len, const int type, + const int writeflag) +{ + /* This range is not OK for this process. Set parameters + * of the request and notify VM about the pending request. + */ + assert(!RTS_ISSET(caller, RTS_VMREQUEST)); + assert(!RTS_ISSET(target, RTS_VMREQUEST)); + + RTS_SET(caller, RTS_VMREQUEST); + + caller->p_vmrequest.req_type = VMPTYPE_CHECK; + caller->p_vmrequest.target = target->p_endpoint; + caller->p_vmrequest.params.check.start = linaddr; + caller->p_vmrequest.params.check.length = len; + caller->p_vmrequest.params.check.writeflag = writeflag; + caller->p_vmrequest.type = type; + + /* Connect caller on vmrequest wait queue. */ + if(!(caller->p_vmrequest.nextrequestor = vmrequest)) + if(OK != send_sig(VM_PROC_NR, SIGKMEM)) + panic("send_sig failed"); + vmrequest = caller; +} + +/*===========================================================================* + * delivermsg * + *===========================================================================*/ +static void delivermsg(struct proc *rp) +{ + assert(!RTS_ISSET(rp, RTS_VMREQUEST)); + assert(rp->p_misc_flags & MF_DELIVERMSG); + assert(rp->p_delivermsg.m_source != NONE); + + if (copy_msg_to_user(&rp->p_delivermsg, + (message *) rp->p_delivermsg_vir)) { + if(rp->p_misc_flags & MF_MSGFAILED) { + /* 2nd consecutive failure means this won't succeed */ + printf("WARNING wrong user pointer 0x%08lx from " + "process %s / %d\n", + rp->p_delivermsg_vir, + rp->p_name, + rp->p_endpoint); + cause_sig(rp->p_nr, SIGSEGV); + } else { + /* 1st failure means we have to ask VM to handle it */ + vm_suspend(rp, rp, rp->p_delivermsg_vir, + sizeof(message), VMSTYPE_DELIVERMSG, 1); + rp->p_misc_flags |= MF_MSGFAILED; + } + } else { + /* Indicate message has been delivered; address is 'used'. */ + rp->p_delivermsg.m_source = NONE; + rp->p_misc_flags &= ~(MF_DELIVERMSG|MF_MSGFAILED); + + if(!(rp->p_misc_flags & MF_CONTEXT_SET)) { + rp->p_reg.retreg = OK; + } + } +} + /*===========================================================================* * switch_to_user * *===========================================================================*/ diff --git a/minix/kernel/proc.h b/minix/kernel/proc.h index 559e35850..3b80630d6 100644 --- a/minix/kernel/proc.h +++ b/minix/kernel/proc.h @@ -255,6 +255,7 @@ struct proc { because of VM modifying the sender's address space*/ #define MF_STEP 0x40000 /* Single-step process */ +#define MF_MSGFAILED 0x80000 /* Magic process table addresses. */ #define BEG_PROC_ADDR (&proc[0]) diff --git a/minix/kernel/proto.h b/minix/kernel/proto.h index e0161879b..cc5d8414a 100644 --- a/minix/kernel/proto.h +++ b/minix/kernel/proto.h @@ -59,6 +59,9 @@ int has_pending_notify(struct proc * caller, int src_p); int has_pending_asend(struct proc * caller, int src_p); void unset_notify_pending(struct proc * caller, int src_p); int mini_notify(const struct proc *src, endpoint_t dst); +void vm_suspend(struct proc *caller, const struct proc *target, + const vir_bytes linaddr, const vir_bytes len, const int type, + const int writeflag); void enqueue(struct proc *rp); void dequeue(struct proc *rp); void switch_to_user(void); @@ -215,7 +218,6 @@ int vm_lookup(const struct proc *proc, vir_bytes virtual, phys_bytes *result, u32_t *ptent); size_t vm_lookup_range(const struct proc *proc, vir_bytes vir_addr, phys_bytes *phys_addr, size_t bytes); -void delivermsg(struct proc *target); void arch_do_syscall(struct proc *proc); int arch_phys_map(int index, phys_bytes *addr, phys_bytes *len, int *flags);