*BSD News Article 15944


Return to BSD News archive

Path: sserve!newshost.anu.edu.au!munnari.oz.au!spool.mu.edu!howland.reston.ans.net!zaphod.mps.ohio-state.edu!cs.utexas.edu!uunet!news.univie.ac.at!fstgds15.tu-graz.ac.at!fstgds01.tu-graz.ac.at!not-for-mail
From: chmr@edvz.tu-graz.ac.at (Christoph Robitschko)
Newsgroups: comp.os.386bsd.bugs
Subject: copyout family fixed
Date: 12 May 1993 09:20:57 +0200
Organization: Technical University of Graz, Austria
Lines: 955
Message-ID: <1sq8gpINNnbb@fstgds01.tu-graz.ac.at>
NNTP-Posting-Host: fstgds01.tu-graz.ac.at
X-Newsreader: TIN [version 1.1 PL7]


Description:
	The copyin/copyout and fubyte/subyte functions as they are
	in stock 386bsd do not check for the page protections,
	allowing the user to read/overwrite memory areas where a user
	program should not have access to (kernel memory etc).

	There is some code #ifdef'ed out in the original locore.s file,
	but this code only checks for write permission, and not whether
	the user has permissions to access this memory at all,
	and the code is very buggy.

	There is patch00137 in patchkit 0.2.3, which fixes these problems
	with ptrace, but it does not fix the problems with read, write and
	ioctl(). My patch should fix all of these situations.

	With Testprogram 2, I have had interesting side effects when using
	the original versions of copyin and subyte: When I modify the
	text segment, the changes are paged back to the executable file,
	regardless of write permissions, even if the filesystem is mounted
	read-only !

Repeat-By:
	Testprogram 1: test copyin. Tries to read a kernel memory region.
	    Start with:
		"nm -g /386bsd | awk '/copyright1/ { printf "0x%s\n", $1 }' | xargs ./cpitest"
	    cpitest.c:
		main(argc, argv)
		char    **argv;
		{
		void    *v1;
		
		v1 = strtoul(argv[1], 0, 0);
		
		if (write(1, v1, 20) < 0)
        		perror("copyin");
		}


	Testprogram 2: test copyin/subyte. Tries to write to read-only memory.
	    Start with:
		echo -n no | ./cpotest	# to test copyout
		./cpotest		# type "no^D" to test subyte
	    cpotest.c:
		const char      v1[] = {"hallihallo !"};

		main()
		{
		printf("v1 is %s\n", v1);
		if (read(0, v1, 5) < 0)
        		perror("copyout/subyte");
		printf("v1 is %s\n", v1);
		}
	Testcase 3: use gdb to read/modify a kernel memory region.
		Note that this is fixed when patch00137 is installed.
	    gdbtest.csh:
		#!/bin/csh -f
		set verbose
		set address=`nm -g /386bsd | awk '/copyright1/ { print $1 }'`
		cd /tmp; cat << EOF1 > copyout$$.c
		main() { char *s = (char *)0x$address; }
		EOF1
		cc -g copyout$$.c -o copyout$$
		gdb copyout$$ << EOF2
		b main
		run
		n
		p s
		set (*s)++
		p s
		c
		q
		EOF2
		rm -f copyout$$ copyout$$.c

Fix:
	I have rewritten the routines copyout, copyin, fubyte, fusword,
	fuword, subyte, susword, suword. For performance reasons I have also
	replaced the C versions of copyinstr, copyoutstr and copystr
	in machdep.c with assembler versions (in locore.s).

	Here are context diffs for locore.s (long !), which includes the
	fixed routines, for trap.c which now contains another support
	function for copyin (named trapread), and for machdep.c to
	#ifdef out the C versions on copy[in/out]str.

	All patches are taken from the Patchkit-0.2.3 versions.

=== CUT HERE === locore.s.patch follows ========================================
*** /sys/i386/i386/locore.s.pk023	Wed May 12 07:42:57 1993
--- /sys/i386/i386/locore.s	Wed May 12 07:51:53 1993
***************
*** 551,616 ****
  	cld
  	ret
  
! #ifdef notdef
  	.globl	_copyout
  	ALIGN32
  _copyout:
  	movl	_curpcb, %eax
  	movl	$cpyflt, PCB_ONFAULT(%eax) # in case we page/protection violate
! 	pushl	%esi
! 	pushl	%edi
  	pushl	%ebx
  	movl	16(%esp), %esi
  	movl	20(%esp), %edi
  	movl	24(%esp), %ebx
  
!  				/* first, check to see if "write fault" */
! 1:	movl	%edi, %eax
! #ifdef notyet
! 	shrl	$IDXSHIFT, %eax	/* fetch pte associated with address */
! 	andb	$0xfc, %al
! 	movl	_PTmap(%eax), %eax
  
! 	andb	$7, %al		/* if we are the one case that won't trap... */
! 	cmpb	$5, %al
! 	jne	2f
! 				/* ... then simulate the trap! */
! 	pushl	%edi
! 	call	_trapwrite	/* trapwrite(addr) */
  	popl	%edx
  
! 	cmpl	$0, %eax	/* if not ok, return */
! 	jne	cpyflt
! 				/* otherwise, continue with reference */
  2:
! 	movl	%edi, %eax	/* calculate remainder this pass */
! 	andl	$0xfffff000, %eax
! 	movl	$NBPG, %ecx
! 	subl	%eax, %ecx
! 	cmpl	%ecx, %ebx
! 	jle	3f
! 	movl	%ebx, %ecx
! 3:	subl	%ecx, %ebx
! 	movl	%ecx, %edx
! #else
! 	movl	%ebx, %ecx
! 	movl	%ebx, %edx
! #endif
  
! 	shrl	$2,%ecx			/* movem */
  	cld
  	rep
  	movsl
! 	movl	%edx, %ecx		/* don't depend on ecx here! */
! 	andl	$3, %ecx
  	rep
  	movsb
  
- #ifdef notyet
- 	cmpl	$0, %ebx
- 	jl	1b
- #endif
- 
  	popl	%ebx
  	popl	%edi
  	popl	%esi
--- 552,625 ----
  	cld
  	ret
  
! 
! /*
!  * copyout (src, dst, len)
!  *	to is in userspace, so each page must be checked for
!  *	user addressability and write protections.
!  *	first check all pages, then copy it over.
!  * Apr 1993 Christoph Robitschko <chmr@edvz.tu-graz.ac.at>
!  */
  	.globl	_copyout
  	ALIGN32
  _copyout:
  	movl	_curpcb, %eax
  	movl	$cpyflt, PCB_ONFAULT(%eax) # in case we page/protection violate
! 	pushl	%esi		/* Note: The same registers must be */
! 	pushl	%edi		/* pushed/popped in copyout, copyin and copyflt */
  	pushl	%ebx
  	movl	16(%esp), %esi
  	movl	20(%esp), %edi
  	movl	24(%esp), %ebx
  
! 			/* compute number of pages */
! 	movl	%edi, %ecx
! 	andl	$0x0fff, %ecx
! 	addl	%ebx, %ecx
! 	shrl	$12, %ecx	/* IDXSHIFT+2 */
! 	incl	%ecx
  
! 			/* compute PTE offset for start address */
! 	movl	%edi, %edx
! 	shrl	$IDXSHIFT, %edx
! 	andb	$0xfc, %dl
! 
! 1:			/* check PTE for each page */
! 	movb	_PTmap(%edx), %al
! 	andb	$0x07, %al	/* Pages must be VALID + USERACC + WRITABLE */
! 	cmpb	$0x07, %al
! 	je	2f
! 				
! 				/* simulate a trap */
! 	pushl	%edx
! 	pushl	%ecx
! 	shll	$IDXSHIFT, %edx
! 	pushl	%edx
! 	call	_trapwrite	/* XXX trapwrite(addr) */
  	popl	%edx
+ 	popl	%ecx
+ 	popl	%edx
  
! 	orl	%eax, %eax	/* if not ok, return EFAULT */
! 	jnz	cpyflt
! 
  2:
! 	addl	$4, %edx
! 	decl	%ecx
! 	jnz	1b		/* check next page */
  
! do_copyio:			/* now copy it over */
! 				/* bcopy (%esi, %edi, %ebx) */
  	cld
+ 	movl	%ebx, %ecx
+ 	shrl	$2, %ecx
  	rep
  	movsl
! 	movb	%bl, %cl
! 	andb	$3, %cl
  	rep
  	movsb
  
  	popl	%ebx
  	popl	%edi
  	popl	%esi
***************
*** 619,651 ****
  	movl	%eax,PCB_ONFAULT(%edx)
  	ret
  
  	.globl	_copyin
  	ALIGN32
  _copyin:
! 	movl	_curpcb,%eax
! 	movl	$cpyflt,PCB_ONFAULT(%eax) # in case we page/protection violate
  	pushl	%esi
  	pushl	%edi
  	pushl	%ebx
! 	movl	12(%esp),%esi
! 	movl	16(%esp),%edi
! 	movl	20(%esp),%ecx
! 	shrl	$2,%ecx
! 	cld
! 	rep
! 	movsl
! 	movl	20(%esp),%ecx
! 	andl	$3,%ecx
! 	rep
! 	movsb
! 	popl	%ebx
! 	popl	%edi
! 	popl	%esi
! 	xorl	%eax,%eax
! 	movl	_curpcb,%edx
! 	movl	%eax,PCB_ONFAULT(%edx)
! 	ret
  
  	ALIGN32
  cpyflt:
  	popl	%ebx
--- 628,698 ----
  	movl	%eax,PCB_ONFAULT(%edx)
  	ret
  
+ 
+ /*
+  * copyin(src, dst, len)
+  *	src is in user space; check if user-addressable.
+  *	This is the same code as copyout, but here the src is checked,
+  *	and only for READ protection
+  * Apr 1993 Christoph Robitschko <chmr@edvz.tu-graz.ac.at>
+  */
  	.globl	_copyin
  	ALIGN32
  _copyin:
! 	movl	_curpcb, %eax
! 	movl	$cpyflt, PCB_ONFAULT(%eax) # in case we page/protection violate
  	pushl	%esi
  	pushl	%edi
  	pushl	%ebx
! 	movl	16(%esp), %esi
! 	movl	20(%esp), %edi
! 	movl	24(%esp), %ebx
  
+ 			/* compute number of pages */
+ 	movl	%esi, %ecx
+ 	andl	$0x0fff, %ecx
+ 	addl	%ebx, %ecx
+ 	shrl	$12, %ecx
+ 	incl	%ecx
+ 
+ 			/* compute PTE offset for start address */
+ 	movl	%esi, %edx
+ 	shrl	$IDXSHIFT, %edx
+ 	andb	$0xfc, %dl
+ 
+ 1:			/* check PTE for each page */
+ 	movb	_PTmap(%edx), %al
+ 	andb	$0x05, %al	/* Pages must be VALID + USERACC */
+ 	cmpb	$0x05, %al
+ 	je	2f
+ 				
+ 				/* simulate a trap */
+ 	pushl	%edx
+ 	pushl	%ecx
+ 	shll	$IDXSHIFT, %edx
+ 	pushl	%edx
+ 	call	_trapread	/* XXX trapread(addr) */
+ 	popl	%edx
+ 	popl	%ecx
+ 	popl	%edx
+ 
+ 	orl	%eax, %eax	/* if not ok, return EFAULT */
+ 	jnz	cpyflt
+ 
+ 2:
+ 	addl	$4, %edx
+ 	decl	%ecx
+ 	jnz	1b		/* check next page */
+ 
+ 	jmp	do_copyio	/* do the copy operation */
+ 
+ 
+ 	/*
+ 	 * copyflt
+ 	 * is jumped to either directly from copyin/copyout, or when a
+ 	 * protection fault is handled while in copyin/out.
+ 	 * Simply returns EFAULT to the caller of copyin/out.
+ 	 */
  	ALIGN32
  cpyflt:
  	popl	%ebx
***************
*** 655,721 ****
  	movl	$0,PCB_ONFAULT(%edx)
  	movl	$ EFAULT,%eax
  	ret
! #else
! 	.globl	_copyout
  	ALIGN32
! _copyout:
! 	movl	_curpcb,%eax
! 	movl	$cpyflt,PCB_ONFAULT(%eax) # in case we page/protection violate
  	pushl	%esi
  	pushl	%edi
! 	movl	12(%esp),%esi
! 	movl	16(%esp),%edi
! 	movl	20(%esp),%ecx
! 	shrl	$2,%ecx
! 	cld
! 	rep
! 	movsl
! 	movl	20(%esp),%ecx
! 	andl	$3,%ecx
! 	rep
! 	movsb
  	popl	%edi
! 	popl	%esi
! 	xorl	%eax,%eax
! 	movl	_curpcb,%edx
! 	movl	%eax,PCB_ONFAULT(%edx)
! 	ret
  
! 	.globl	_copyin
  	ALIGN32
! _copyin:
! 	movl	_curpcb,%eax
! 	movl	$cpyflt,PCB_ONFAULT(%eax) # in case we page/protection violate
  	pushl	%esi
  	pushl	%edi
! 	movl	12(%esp),%esi
! 	movl	16(%esp),%edi
! 	movl	20(%esp),%ecx
! 	shrl	$2,%ecx
! 	cld
! 	rep
! 	movsl
! 	movl	20(%esp),%ecx
! 	andl	$3,%ecx
! 	rep
! 	movsb
  	popl	%edi
  	popl	%esi
- 	xorl	%eax,%eax
- 	movl	_curpcb,%edx
- 	movl	%eax,PCB_ONFAULT(%edx)
  	ret
  
! 	ALIGN32
! cpyflt: popl	%edi
! 	popl	%esi
! 	movl	_curpcb,%edx
! 	movl	$0,PCB_ONFAULT(%edx)
! 	movl	$ EFAULT,%eax
  	ret
  
- #endif
  
  	# insb(port,addr,cnt)
  	.globl	_insb
  	ALIGN32
--- 702,903 ----
  	movl	$0,PCB_ONFAULT(%edx)
  	movl	$ EFAULT,%eax
  	ret
! 
! /*
!  * copyoutstr(from, to, maxlen, int *lencopied)
!  *	copy a string from from to to, stop when a 0 character is reached.
!  *	return ENAMETOOLONG if string is longer than maxlen, and
!  *	EFAULT on protection violations. If lencopied is non-zero,
!  *	return the actual length in *lencopied.
!  * May 93 Christoph Robitschko <chmr@edvz.tu-graz.ac.at>
!  */
! 	.globl	_copyoutstr
  	ALIGN32
! _copyoutstr:
  	pushl	%esi
  	pushl	%edi
! 	pushl	%ebx
! 	movl	_curpcb, %ecx
! 	movl	$cpystrflt, PCB_ONFAULT(%ecx)
! 
! 	movl	16(%esp), %esi			# %esi = from
! 	movl	20(%esp), %edi			# %edi = to
! 	movl	24(%esp), %ebx			# %ebx = maxlen
! 1:
! 	movl	%edi, %edx
! 	shrl	$IDXSHIFT, %edx
! 	andb	$0xfc, %dl
! 	movb	_PTmap(%edx), %al
! 	andb	$7, %al
! 	cmpb	$7, %al
! 	je	2f
! 
! 			/* simulate trap */
! 	pushl	%edi
! 	call	_trapwrite
  	popl	%edi
! 	orl	%eax, %eax
! 	jnz	cpystrflt
  
! 2:			/* copy up to end of this page */
! 	movl	%edi, %eax
! 	andl	$0x0fff, %eax
! 	movl	$NBPG, %ecx
! 	subl	%eax, %ecx	/* ecx = NBPG - (src % NBPG) */
! 	cmpl	%ecx, %ebx
! 	jge	3f
! 	movl	%ebx, %ecx	/* ecx = min (ecx, ebx) */
! 3:
! 	orl	%ecx, %ecx
! 	jz	4f
! 	decl	%ecx
! 	decl	%ebx
! 	movb	0(%esi), %al
! 	movb	%al, 0(%edi)
! 	incl	%esi
! 	incl	%edi
! 	orb	%al, %al
! 	jnz	3b
! 
! 			/* Success -- 0 byte reached */
! 	xorl	%eax, %eax
! 	jmp	6f
! 
! 4:			/* next page */
! 	orl	%ebx, %ebx
! 	jnz	1b
! 			/* ebx is zero -- return ENAMETOOLONG */
! 	movl	$ENAMETOOLONG, %eax
! 	jmp	6f
! 
! 
! /*
!  * copyinstr(from, to, maxlen, int *lencopied)
!  *	copy a string from from to to, stop when a 0 character is reached.
!  *	return ENAMETOOLONG if string is longer than maxlen, and
!  *	EFAULT on protection violations. If lencopied is non-zero,
!  *	return the actual length in *lencopied.
!  * May 93 Christoph Robitschko <chmr@edvz.tu-graz.ac.at>
!  */
! 	.globl	_copyinstr
  	ALIGN32
! _copyinstr:
  	pushl	%esi
  	pushl	%edi
! 	pushl	%ebx
! 	movl	_curpcb, %ecx
! 	movl	$cpystrflt, PCB_ONFAULT(%ecx)
! 
! 	movl	16(%esp), %esi			# %esi = from
! 	movl	20(%esp), %edi			# %edi = to
! 	movl	24(%esp), %ebx			# %ebx = maxlen
! 1:
! 	movl	%esi, %edx
! 	shrl	$IDXSHIFT, %edx
! 	andb	$0xfc, %dl
! 	movb	_PTmap(%edx), %al
! 	andb	$5, %al
! 	cmpb	$5, %al
! 	je	2f
! 
! 			/* simulate trap */
! 	pushl	%esi
! 	call	_trapread
! 	popl	%esi
! 	orl	%eax, %eax
! 	jnz	cpystrflt
! 
! 2:			/* copy up to end of this page */
! 	movl	%esi, %eax
! 	andl	$0x0fff, %eax
! 	movl	$NBPG, %ecx
! 	subl	%eax, %ecx	/* ecx = NBPG - (src % NBPG) */
! 	cmpl	%ecx, %ebx
! 	jge	3f
! 	movl	%ebx, %ecx	/* ecx = min (ecx, ebx) */
! 3:
! 	orl	%ecx, %ecx
! 	jz	4f
! 	decl	%ecx
! 	decl	%ebx
! 	movb	0(%esi), %al
! 	movb	%al, 0(%edi)
! 	incl	%esi
! 	incl	%edi
! 	orb	%al, %al
! 	jnz	3b
! 
! 			/* Success -- 0 byte reached */
! 	xorl	%eax, %eax
! 	jmp	6f
! 
! 4:			/* next page */
! 	orl	%ebx, %ebx
! 	jnz	1b
! 			/* ebx is zero -- return ENAMETOOLONG */
! 	movl	$ENAMETOOLONG, %eax
! 	jmp	6f
! 
! cpystrflt:
! 	movl	$EFAULT, %eax
! 6:			/* set *lencopied and return %eax */
! 	movl	_curpcb, %ecx
! 	movl	$0, PCB_ONFAULT(%ecx)
! 	movl	28(%esp), %edx
! 	orl	%edx, %edx
! 	jz	7f
! 	movl	24(%esp), %ecx
! 	subl	%ebx, %ecx
! 	movl	%ecx, 0(%edx)
! 7:
! 	popl	%ebx
  	popl	%edi
  	popl	%esi
  	ret
  
! 
! /*
!  * copystr(from, to, maxlen, int *lencopied)
!  */
!  	.globl	_copystr
!  	ALIGN32
!  _copystr:
! 	pushl	%ebx
! 
! 	movl	8(%esp), %edx			# %edx = from
! 	movl	12(%esp), %ecx			# %ecx = to
! 	movl	16(%esp), %ebx			# %ebx = maxlen
! 1:
! 	orl	%ebx, %ebx
! 	jz	4f
! 	decl	%ebx
! 	movb	0(%edx), %al
! 	movb	%al, 0(%ecx)
! 	incl	%edx
! 	incl	%ecx
! 	orb	%al, %al
! 	jnz	1b
! 
! 			/* Success -- 0 byte reached */
! 	xorl	%eax, %eax
! 	jmp	6f
! 
! 4:			/* ebx is zero -- return ENAMETOOLONG */
! 	movl	$ENAMETOOLONG, %eax
! 
! 6:			/* set *lencopied and return %eax */
! 	movl	20(%esp), %edx
! 	orl	%edx, %edx
! 	jz	7f
! 	movl	16(%esp), %ecx
! 	subl	%ebx, %ecx
! 	movl	%ecx, 0(%edx)
! 7:
! 	popl	%ebx
  	ret
  
  
+ 
  	# insb(port,addr,cnt)
  	.globl	_insb
  	ALIGN32
***************
*** 918,1056 ****
  	popl	%ebx
  	ret
  
  /*
!  * {fu,su},{byte,word}
   */
  	ALIGN32
! ALTENTRY(fuiword)
! ENTRY(fuword)
! 	movl	_curpcb,%ecx
! 	movl	$fusufault,PCB_ONFAULT(%ecx)
! 	movl	4(%esp),%edx
! 	.byte	0x65		# use gs
! 	movl	0(%edx),%eax
! 	movl	$0,PCB_ONFAULT(%ecx)
! 	ret
! 	
  	ALIGN32
! ENTRY(fusword)
! 	movl	_curpcb,%ecx
! 	movl	$fusufault,PCB_ONFAULT(%ecx) #in case we page/protection violate
! 	movl	4(%esp),%edx
! 	.byte	0x65		# use gs
! 	movzwl	0(%edx),%eax
! 	movl	$0,PCB_ONFAULT(%ecx)
! 	ret
! 	
  	ALIGN32
! ALTENTRY(fuibyte)
! ENTRY(fubyte)
! 	movl	_curpcb,%ecx
! 	movl	$fusufault,PCB_ONFAULT(%ecx) #in case we page/protection violate
! 	movl	4(%esp),%edx
! 	.byte	0x65		# use gs
! 	movzbl	0(%edx),%eax
! 	movl	$0,PCB_ONFAULT(%ecx)
  	ret
! 	
! 	ALIGN32
! fusufault:
! 	movl	_curpcb,%ecx
! 	xorl	%eax,%eax
! 	movl	%eax,PCB_ONFAULT(%ecx) #in case we page/protection violate
  	decl	%eax
  	ret
  
- 	ALIGN32
- ALTENTRY(suiword)
- ENTRY(suword)
- 	movl	_curpcb,%ecx
- 	movl	$fusufault,PCB_ONFAULT(%ecx) #in case we page/protection violate
- 	movl	4(%esp),%edx
- 	movl	8(%esp),%eax
  
! #ifdef notdef
! 	shrl	$IDXSHIFT, %edx	/* fetch pte associated with address */
  	andb	$0xfc, %dl
! 	movl	_PTmap(%edx), %edx
! 
! 	andb	$7, %dl		/* if we are the one case that won't trap... */
! 	cmpb	$5 , %edx
! 	jne	1f
! 				/* ... then simulate the trap! */
! 	pushl	%edi
! 	call	_trapwrite	/* trapwrite(addr) */
  	popl	%edx
! 	cmpl	$0, %eax	/* if not ok, return */
! 	jne	fusufault
! 	movl	8(%esp),%eax	/* otherwise, continue with reference */
  1:
! 	movl	4(%esp),%edx
! #endif
! 	.byte	0x65		# use gs
! 	movl	%eax,0(%edx)
! 	xorl	%eax,%eax
! 	movl	%eax,PCB_ONFAULT(%ecx) #in case we page/protection violate
  	ret
! 	
  	ALIGN32
! ENTRY(susword)
! 	movl	_curpcb,%ecx
! 	movl	$fusufault,PCB_ONFAULT(%ecx) #in case we page/protection violate
! 	movl	4(%esp),%edx
! 	movl	8(%esp),%eax
! #ifdef notdef
! shrl	$IDXSHIFT, %edx	/* calculate pte address */
! andb	$0xfc, %dl
! movl	_PTmap(%edx), %edx
! andb	$7, %edx	/* if we are the one case that won't trap... */
! cmpb	$5 , %edx
! jne	1f
! /* ..., then simulate the trap! */
! 	pushl	%edi
! 	call	_trapwrite	/* trapwrite(addr) */
  	popl	%edx
! movl	_curpcb, %ecx	# restore trashed registers
! cmpl	$0, %eax	/* if not ok, return */
! jne	fusufault
! movl	8(%esp),%eax
! 1: movl	4(%esp),%edx
! #endif
! 	.byte	0x65		# use gs
! 	movw	%ax,0(%edx)
! 	xorl	%eax,%eax
! 	movl	%eax,PCB_ONFAULT(%ecx) #in case we page/protection violate
  	ret
  
  	ALIGN32
! ALTENTRY(suibyte)
! ENTRY(subyte)
! 	movl	_curpcb,%ecx
! 	movl	$fusufault,PCB_ONFAULT(%ecx) #in case we page/protection violate
! 	movl	4(%esp),%edx
! 	movl	8(%esp),%eax
! #ifdef notdef
! shrl	$IDXSHIFT, %edx	/* calculate pte address */
! andb	$0xfc, %dl
! movl	_PTmap(%edx), %edx
! andb	$7, %edx	/* if we are the one case that won't trap... */
! cmpb	$5 , %edx
! jne	1f
! /* ..., then simulate the trap! */
! 	pushl	%edi
! 	call	_trapwrite	/* trapwrite(addr) */
  	popl	%edx
! movl	_curpcb, %ecx	# restore trashed registers
! cmpl	$0, %eax	/* if not ok, return */
! jne	fusufault
! movl	8(%esp),%eax
! 1: movl	4(%esp),%edx
! #endif
! 	.byte	0x65		# use gs
! 	movb	%eax,0(%edx)
! 	xorl	%eax,%eax
! 	movl	%eax,PCB_ONFAULT(%ecx) #in case we page/protection violate
  	ret
  
  	ALIGN32
  	ENTRY(setjmp)
--- 1100,1253 ----
  	popl	%ebx
  	ret
  
+ 
  /*
!  * fubyte family: get a byte/word from userspace.
!  * May 1993 Christoph Robitschko <chmr@edvz.tu-graz.ac.at>
   */
  	ALIGN32
! 	.globl	_fubyte, _fuibyte
! _fubyte:
! _fuibyte:
! 	movl	_curpcb, %ecx
! 	movl	$fusufault, PCB_ONFAULT(%ecx)
! 	movl	4(%esp), %edx
! 	movzbl	0(%edx), %eax
! 	jmp	fu_checkpte
! 
  	ALIGN32
! 	.globl	_fusword
! _fusword:
! 	movl	_curpcb, %ecx
! 	movl	$fusufault, PCB_ONFAULT(%ecx)
! 	movl	4(%esp), %edx
! 	movzwl	0(%edx), %eax
! 	jmp	fu_checkpte
! 
  	ALIGN32
! 	.globl	_fuword, _fuiword
! _fuword:
! _fuiword:
! 	movl	_curpcb, %ecx
! 	movl	$fusufault, PCB_ONFAULT(%ecx)
! 	movl	4(%esp), %edx
! 	movl	0(%edx), %eax
! 
! fu_checkpte:
! 	shrl	$IDXSHIFT, %edx		/* check PTE of address */
! 	andb	$0xfc, %dl
! 	movb	_PTmap(%edx), %dl
! 	andb	$0x5, %dl		/* Page must be VALID + USERACC */
! 	cmpb	$0x5, %dl
! 	jne	1f
! 	movl	$0, PCB_ONFAULT(%ecx)
  	ret
! 
! 1:
! 	/* should we call trapread here ? */
! fusufault:	
! 	xorl	%eax, %eax
! 	movl	_curpcb, %ecx
! 	movl	%eax, PCB_ONFAULT(%ecx)
  	decl	%eax
  	ret
  
  
! /*
!  * subyte family: write a byte/word to userspace.
!  * These routines differ only in one instruction (the data move).
!  * May 1993 Christoph Robitschko <chmr@edvz.tu-graz.ac.at>
!  */
! 	ALIGN32
! 	.globl	_subyte, _suibyte
! _subyte:
! _suibyte:
! 	movl	_curpcb, %ecx
! 	movl	$fusufault, PCB_ONFAULT(%ecx)
! 	movl	4(%esp), %edx
! 	movl	%edx, %ecx
! 	shrl	$IDXSHIFT, %edx
  	andb	$0xfc, %dl
! 	movb	_PTmap(%edx), %dl
! 	andb	$0x7, %dl		/* must be VALID + USERACC + WRITE */
! 	cmpb	$0x7, %dl
! 	je	1f
! 					/* simulate a trap */
! 	pushl	%ecx
! 	call	_trapwrite
  	popl	%edx
! 	orl	%eax, %eax
! 	jnz	fusufault
  1:
! 	movl	4(%esp), %edx
! 	movl	8(%esp), %eax
! 	movb	%al, 0(%edx)
! 	xorl	%eax, %eax
! 	movl	_curpcb, %ecx
! 	movl	%eax, PCB_ONFAULT(%ecx)
  	ret
! 
! 
! 
  	ALIGN32
! 	.globl	_susword
! _susword:
! 	movl	_curpcb, %ecx
! 	movl	$fusufault, PCB_ONFAULT(%ecx)
! 	movl	4(%esp), %edx
! 	movl	%edx, %ecx
! 	shrl	$IDXSHIFT, %edx
! 	andb	$0xfc, %dl
! 	movb	_PTmap(%edx), %dl
! 	andb	$0x7, %dl		/* must be VALID + USERACC + WRITE */
! 	cmpb	$0x7, %dl
! 	je	1f
! 					/* simulate a trap */
! 	pushl	%ecx
! 	call	_trapwrite
  	popl	%edx
! 	orl	%eax, %eax
! 	jnz	fusufault
! 1:
! 	movl	4(%esp), %edx
! 	movl	8(%esp), %eax
! 	movw	%ax, 0(%edx)
! 	xorl	%eax, %eax
! 	movl	_curpcb, %ecx
! 	movl	%eax, PCB_ONFAULT(%ecx)
  	ret
  
+ 
+ 
  	ALIGN32
! 	.globl	_suword, _suiword
! _suword:
! _suiword:
! 	movl	_curpcb, %ecx
! 	movl	$fusufault, PCB_ONFAULT(%ecx)
! 	movl	4(%esp), %edx
! 	movl	%edx, %ecx
! 	shrl	$IDXSHIFT, %edx
! 	andb	$0xfc, %dl
! 	movb	_PTmap(%edx), %dl
! 	andb	$0x7, %dl		/* must be VALID + USERACC + WRITE */
! 	cmpb	$0x7, %dl
! 	je	1f
! 					/* simulate a trap */
! 	pushl	%ecx
! 	call	_trapwrite
  	popl	%edx
! 	orl	%eax, %eax
! 	jnz	fusufault
! 1:
! 	movl	4(%esp), %edx
! 	movl	8(%esp), %eax
! 	movl	%eax, 0(%edx)
! 	xorl	%eax, %eax
! 	movl	_curpcb, %ecx
! 	movl	%eax, PCB_ONFAULT(%ecx)
  	ret
+ 
  
  	ALIGN32
  	ENTRY(setjmp)
=== CUT HERE === trap.c.patch follows ==========================================
*** /sys/i386/i386/trap.c.pk023	Wed May 12 07:42:58 1993
--- /sys/i386/i386/trap.c	Wed May 12 07:59:53 1993
***************
*** 410,415 ****
--- 410,427 ----
  	else return(1);
  }
  
+ int trapread(unsigned addr) {
+ 	int rv;
+ 	vm_offset_t va;
+ 
+ 	va = trunc_page((vm_offset_t)addr);
+ 	if (va > VM_MAXUSER_ADDRESS) return(1);
+ 	rv = vm_fault(&curproc->p_vmspace->vm_map, va,
+ 		VM_PROT_READ, FALSE);
+ 	if (rv == KERN_SUCCESS) return(0);
+ 	else return(1);
+ }
+ 
  /*
   * syscall(frame):
   *	System call request from POSIX system call gate interface to kernel.
=== CUT HERE === machdep.c.patch follows =======================================
*** /sys/i386/i386/machdep.c.pk023	Wed May 12 07:42:57 1993
--- /sys/i386/i386/machdep.c	Wed May 12 07:56:27 1993
***************
*** 1059,1064 ****
--- 1059,1066 ----
  
  vmunaccess() {}
  
+ #ifdef notanymore
+ /* assembler versions now in locore.s */
  /*
   * Below written in C to allow access to debugging code
   */
***************
*** 1119,1121 ****
--- 1121,1124 ----
  	if(lencopied) *lencopied = tally;
  	return(ENAMETOOLONG);
  }
+ #endif
=== CUT HERE === End of patches ================================================