Subject: Re: nasty powerpc mmap problems (was: Re: Vger broken w.r.t. gdb)

From: Daniel Jacobowitz <[email-masked]>
Date: Sun, 1 Aug 1999 22:45:36 -0400

I think I've found the problem.  access_process_vm() would trigger a
page fault for write if the page was unmapped, but not if it was
already mapped for read.  The attached patch fixed all my problems.

On Fri, Jul 30, 1999 at 03:07:39AM -0400, Daniel Jacobowitz wrote:
> [CC me in replies, I'm not on linux-kernel]
> 
> Background from the thread on linuxppc-dev: with the current vger tree,
> gdb's breakpoints are apparently being set in the wrong copy of a
> shared library, and not properly removed.  After running gdb over any
> program, even with no extra breakpoints set, every dynamically linked
> program run inside or outside of gdb dies with SIGTRAP.  The SIGTRAP
> appears to be in _dl_debug_state or thereabouts in ld.so.

...

> I've found a much simpler test case for this problem.  It seems to me
> to be more than ptrace being broken.  I wrote two test programs; mmap1
> merely opens a file, mmaps it, closes it, prints some debugging info,
> sleeps, and prints a little more.  Notice the permissions:
>   int fd = open("testfile", O_RDONLY);
>   ptr = mmap(0, 0x4000, PROT_READ|PROT_EXEC, MAP_SHARED, fd, 0);
>   close(fd);

Dan

/--------------------------------\  /--------------------------------\
|       Daniel Jacobowitz        |__|        SCS Class of 2002       |
|   Debian GNU/Linux Developer    __    Carnegie Mellon University   |
|         [email-masked]         |  |       [email-masked]      |
\--------------------------------/  \--------------------------------/
Index: ptrace.c
===================================================================
RCS file: /cvs/linux/linux/kernel/ptrace.c,v
retrieving revision 1.2
diff -c -p -r1.2 ptrace.c
*** ptrace.c	1999/07/23 02:04:32	1.2
--- ptrace.c	1999/08/02 02:23:45
*************** repeat:
*** 38,43 ****
--- 38,45 ----
  	pgtable = pte_offset(pgmiddle, addr);
  	if (!pte_present(*pgtable))
  		goto fault_in_page;
+ 	if (write && !pte_write(*pgtable))
+ 		goto fault_in_page;
  	page = pte_page(*pgtable);
  	if (MAP_NR(page) >= max_mapnr)
  		return 0;