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
			
			
This commit is contained in:
		
							parent
							
								
									36f477c20e
								
							
						
					
					
						commit
						8bab0dfa2a
					
				@ -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                                  *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
@ -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				     * 
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
 | 
			
		||||
@ -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])
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user