copy_msg_from_user() and copy_msg_to_user()
- copies a mesage from/to userspace without need of translating addresses - the assumption is that the address space is installed, i.e. ldt and cr3 are loaded correctly - if a pagefault or a general protection occurs while copying from userland to kernel (or vice versa) and error is returned which gives the caller a chance to respond in a proper way - error happens _only_ because of a wrong user pointer if the function is used correctly - if the prerequisites of the function do no hold, the function will most likely fail as the user address becomes random
This commit is contained in:
		
							parent
							
								
									ad9ba944d1
								
							
						
					
					
						commit
						5e57818431
					
				@ -142,6 +142,33 @@ PUBLIC void exception_handler(int is_nested, struct exception_frame * frame)
 | 
				
			|||||||
	return;
 | 
						return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*
 | 
				
			||||||
 | 
					   * handle special cases for nested problems as they might be tricky or filter
 | 
				
			||||||
 | 
					   * them out quickly if the traps are not nested
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  if (is_nested) {
 | 
				
			||||||
 | 
						  /*
 | 
				
			||||||
 | 
						   * if a problem occured while copying a message from userspace because
 | 
				
			||||||
 | 
						   * of a wrong pointer supplied by userland, handle it the only way we
 | 
				
			||||||
 | 
						   * can handle it ...
 | 
				
			||||||
 | 
						   */
 | 
				
			||||||
 | 
						  if (((void*)frame->eip >= copy_msg_to_user &&
 | 
				
			||||||
 | 
								  (void*)frame->eip <= __copy_msg_to_user_end) ||
 | 
				
			||||||
 | 
								  ((void*)frame->eip >= copy_msg_from_user &&
 | 
				
			||||||
 | 
								  (void*)frame->eip <= __copy_msg_from_user_end)) {
 | 
				
			||||||
 | 
							  switch(frame->vector) {
 | 
				
			||||||
 | 
							  /* these error are expected */
 | 
				
			||||||
 | 
							  case PAGE_FAULT_VECTOR:
 | 
				
			||||||
 | 
							  case PROTECTION_VECTOR:
 | 
				
			||||||
 | 
								  frame->eip = (reg_t) __user_copy_msg_pointer_failure;
 | 
				
			||||||
 | 
								  return;
 | 
				
			||||||
 | 
							  default:
 | 
				
			||||||
 | 
								  minix_panic("Copy involving a user pointer "
 | 
				
			||||||
 | 
										  "failed unexpectedly!", NO_NUM);
 | 
				
			||||||
 | 
							  }
 | 
				
			||||||
 | 
						  }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if(frame->vector == PAGE_FAULT_VECTOR) {
 | 
					  if(frame->vector == PAGE_FAULT_VECTOR) {
 | 
				
			||||||
	pagefault(saved_proc, frame, is_nested);
 | 
						pagefault(saved_proc, frame, is_nested);
 | 
				
			||||||
	return;
 | 
						return;
 | 
				
			||||||
 | 
				
			|||||||
@ -386,6 +386,137 @@ phys_copy_fault_in_kernel:			/* kernel can send us here */
 | 
				
			|||||||
	mov	%cr2, %eax
 | 
						mov	%cr2, %eax
 | 
				
			||||||
	ret
 | 
						ret
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*===========================================================================*/
 | 
				
			||||||
 | 
					/*				copy_msg_from_user			     */
 | 
				
			||||||
 | 
					/*===========================================================================*/
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * int copy_msg_from_user(struct proc * p, message * user_mbuf, message * dst);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copies a message of 36 bytes from user process space to a kernel buffer. This
 | 
				
			||||||
 | 
					 * function assumes that the process address space is installed (cr3 loaded) and
 | 
				
			||||||
 | 
					 * the local descriptor table of this process is loaded too.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The %gs segment register is used to access the userspace memory. We load the
 | 
				
			||||||
 | 
					 * process' data segment in this register.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function from the callers point of view either succeeds or returns an
 | 
				
			||||||
 | 
					 * error which gives the caller a chance to respond accordingly. In fact it
 | 
				
			||||||
 | 
					 * either succeeds or if it generates a pagefault, general protection or other
 | 
				
			||||||
 | 
					 * exception, the trap handler has to redirect the execution to
 | 
				
			||||||
 | 
					 * __user_copy_msg_pointer_failure where the error is reported to the caller
 | 
				
			||||||
 | 
					 * without resolving the pagefault. It is not kernel's problem to deal with
 | 
				
			||||||
 | 
					 * wrong pointers from userspace and the caller should return an error to
 | 
				
			||||||
 | 
					 * userspace as if wrong values or request were passed to the kernel
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.balign 16
 | 
				
			||||||
 | 
					.globl copy_msg_from_user
 | 
				
			||||||
 | 
					copy_msg_from_user:
 | 
				
			||||||
 | 
						push	%gs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mov	8(%esp), %eax
 | 
				
			||||||
 | 
						movw	DSREG(%eax), %gs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* load the source pointer */
 | 
				
			||||||
 | 
						mov	12(%esp), %ecx
 | 
				
			||||||
 | 
						/* load the destination pointer */
 | 
				
			||||||
 | 
						mov	16(%esp), %edx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mov	%gs:0*4(%ecx), %eax
 | 
				
			||||||
 | 
						mov	%eax, 0*4(%edx)
 | 
				
			||||||
 | 
						mov	%gs:1*4(%ecx), %eax
 | 
				
			||||||
 | 
						mov	%eax, 1*4(%edx)
 | 
				
			||||||
 | 
						mov	%gs:2*4(%ecx), %eax
 | 
				
			||||||
 | 
						mov	%eax, 2*4(%edx)
 | 
				
			||||||
 | 
						mov	%gs:3*4(%ecx), %eax
 | 
				
			||||||
 | 
						mov	%eax, 3*4(%edx)
 | 
				
			||||||
 | 
						mov	%gs:4*4(%ecx), %eax
 | 
				
			||||||
 | 
						mov	%eax, 4*4(%edx)
 | 
				
			||||||
 | 
						mov	%gs:5*4(%ecx), %eax
 | 
				
			||||||
 | 
						mov	%eax, 5*4(%edx)
 | 
				
			||||||
 | 
						mov	%gs:6*4(%ecx), %eax
 | 
				
			||||||
 | 
						mov	%eax, 6*4(%edx)
 | 
				
			||||||
 | 
						mov	%gs:7*4(%ecx), %eax
 | 
				
			||||||
 | 
						mov	%eax, 7*4(%edx)
 | 
				
			||||||
 | 
						mov	%gs:8*4(%ecx), %eax
 | 
				
			||||||
 | 
						mov	%eax, 8*4(%edx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.globl __copy_msg_from_user_end
 | 
				
			||||||
 | 
					__copy_msg_from_user_end:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pop	%gs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						movl	$0, %eax
 | 
				
			||||||
 | 
						ret
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*===========================================================================*/
 | 
				
			||||||
 | 
					/*				copy_msg_to_user			     */
 | 
				
			||||||
 | 
					/*===========================================================================*/
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * void copy_msg_to_user(struct proc * p, message * src, message * user_mbuf);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copies a message of 36 bytes to user process space from a kernel buffer. This
 | 
				
			||||||
 | 
					 * function assumes that the process address space is installed (cr3 loaded) and
 | 
				
			||||||
 | 
					 * the local descriptor table of this process is loaded too.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All the other copy_msg_from_user() comments apply here as well!
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.balign 16
 | 
				
			||||||
 | 
					.globl copy_msg_to_user
 | 
				
			||||||
 | 
					copy_msg_to_user:
 | 
				
			||||||
 | 
						push	%gs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mov	8(%esp), %eax
 | 
				
			||||||
 | 
						movw	DSREG(%eax), %gs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* load the source pointer */
 | 
				
			||||||
 | 
						mov	12(%esp), %ecx
 | 
				
			||||||
 | 
						/* load the destination pointer */
 | 
				
			||||||
 | 
						mov	16(%esp), %edx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mov	0*4(%ecx), %eax
 | 
				
			||||||
 | 
						mov	%eax, %gs:0*4(%edx)
 | 
				
			||||||
 | 
						mov	1*4(%ecx), %eax
 | 
				
			||||||
 | 
						mov	%eax, %gs:1*4(%edx)
 | 
				
			||||||
 | 
						mov	2*4(%ecx), %eax
 | 
				
			||||||
 | 
						mov	%eax, %gs:2*4(%edx)
 | 
				
			||||||
 | 
						mov	3*4(%ecx), %eax
 | 
				
			||||||
 | 
						mov	%eax, %gs:3*4(%edx)
 | 
				
			||||||
 | 
						mov	4*4(%ecx), %eax
 | 
				
			||||||
 | 
						mov	%eax, %gs:4*4(%edx)
 | 
				
			||||||
 | 
						mov	5*4(%ecx), %eax
 | 
				
			||||||
 | 
						mov	%eax, %gs:5*4(%edx)
 | 
				
			||||||
 | 
						mov	6*4(%ecx), %eax
 | 
				
			||||||
 | 
						mov	%eax, %gs:6*4(%edx)
 | 
				
			||||||
 | 
						mov	7*4(%ecx), %eax
 | 
				
			||||||
 | 
						mov	%eax, %gs:7*4(%edx)
 | 
				
			||||||
 | 
						mov	8*4(%ecx), %eax
 | 
				
			||||||
 | 
						mov	%eax, %gs:8*4(%edx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.globl __copy_msg_to_user_end
 | 
				
			||||||
 | 
					__copy_msg_to_user_end:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pop	%gs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						movl	$0, %eax
 | 
				
			||||||
 | 
						ret
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * if a function from a selected set of copies from or to userspace fails, it is
 | 
				
			||||||
 | 
					 * because of a wrong pointer supplied by the userspace. We have to clean up and
 | 
				
			||||||
 | 
					 * and return -1 to indicated that something wrong has happend. The place it was
 | 
				
			||||||
 | 
					 * called from has to handle this situation. The exception handler redirect us
 | 
				
			||||||
 | 
					 * here to continue, clean up and report the error
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					.balign 16
 | 
				
			||||||
 | 
					.globl __user_copy_msg_pointer_failure
 | 
				
			||||||
 | 
					__user_copy_msg_pointer_failure:
 | 
				
			||||||
 | 
						pop	%gs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						movl	$-1, %eax
 | 
				
			||||||
 | 
						ret
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*===========================================================================*/
 | 
					/*===========================================================================*/
 | 
				
			||||||
/*				phys_memset				     */
 | 
					/*				phys_memset				     */
 | 
				
			||||||
/*===========================================================================*/
 | 
					/*===========================================================================*/
 | 
				
			||||||
 | 
				
			|||||||
@ -44,6 +44,7 @@ void                              _PROTOTYPE( simd_exception, (void) );
 | 
				
			|||||||
/* Software interrupt handlers, in numerical order. */
 | 
					/* Software interrupt handlers, in numerical order. */
 | 
				
			||||||
_PROTOTYPE( void trp, (void) );
 | 
					_PROTOTYPE( void trp, (void) );
 | 
				
			||||||
_PROTOTYPE( void ipc_entry, (void) );
 | 
					_PROTOTYPE( void ipc_entry, (void) );
 | 
				
			||||||
 | 
					_PROTOTYPE( void kernel_call_entry, (void) );
 | 
				
			||||||
_PROTOTYPE( void level0_call, (void) );
 | 
					_PROTOTYPE( void level0_call, (void) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* memory.c */
 | 
					/* memory.c */
 | 
				
			||||||
@ -153,6 +154,10 @@ EXTERN void * k_boot_stktop;
 | 
				
			|||||||
_PROTOTYPE( void int_gate, (unsigned vec_nr, vir_bytes offset,
 | 
					_PROTOTYPE( void int_gate, (unsigned vec_nr, vir_bytes offset,
 | 
				
			||||||
		unsigned dpl_type) );
 | 
							unsigned dpl_type) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_PROTOTYPE(void __copy_msg_from_user_end, (void));
 | 
				
			||||||
 | 
					_PROTOTYPE(void __copy_msg_to_user_end, (void));
 | 
				
			||||||
 | 
					_PROTOTYPE(void __user_copy_msg_pointer_failure, (void));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* functions defined in architecture-independent kernel source. */
 | 
					/* functions defined in architecture-independent kernel source. */
 | 
				
			||||||
#include "../../proto.h"
 | 
					#include "../../proto.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -171,5 +171,9 @@ _PROTOTYPE( int arch_phys_map, (int index, phys_bytes *addr,
 | 
				
			|||||||
_PROTOTYPE( int arch_phys_map_reply, (int index, vir_bytes addr));
 | 
					_PROTOTYPE( int arch_phys_map_reply, (int index, vir_bytes addr));
 | 
				
			||||||
_PROTOTYPE( int arch_enable_paging, (void));
 | 
					_PROTOTYPE( int arch_enable_paging, (void));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_PROTOTYPE( int copy_msg_from_user, (struct proc * p, message * user_mbuf,
 | 
				
			||||||
 | 
												message * dst));
 | 
				
			||||||
 | 
					_PROTOTYPE( int copy_msg_to_user, (struct proc * p, message * src,
 | 
				
			||||||
 | 
												message * user_mbuf));
 | 
				
			||||||
_PROTOTYPE(void switch_address_space, (struct proc * p));
 | 
					_PROTOTYPE(void switch_address_space, (struct proc * p));
 | 
				
			||||||
#endif /* PROTO_H */
 | 
					#endif /* PROTO_H */
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user