Subject: bug in uvm_fault_unwire()
To: None <tech-kern@netbsd.org>
From: Jason Thorpe <thorpej@nas.nasa.gov>
List: tech-kern
Date: 06/16/1999 12:25:23
Hi folks...

I think I've discovered a bug in uvm_fault_unwire(), but I think it will
be fairly straight-forward to fix.

Consider the following:

	- User mlock(2)'s a buffer, to guarantee it will never become
	  non-resident while he is using it.

	- User then does physio to that buffer.  Physio calls uvm_vslock()
	  to lock down the pages and ensure that page faults do not happen
	  while the I/O is in progress (possibly in interrupt context).

	- Physio does the I/O.

	- Physio calls uvm_vsunlock().  This calls uvm_fault_unwire().

	  >>> HERE IS WHERE THE PROBLEM OCCURS <<<

	  uvm_fault_unwire() calls pmap_change_wiring(..., FALSE),
	  which now gives the pmap free reign to recycle the mapping
	  information for that page, which is illegal; the mapping is
	  still wired (due to the mlock(2)), but now access of the
	  page could cause a non-protection page fault (disallowed).

	  NOTE: This could eventually lead to a panic when the user
	  subsequently munlock(2)'s the buffer and the mapping info
	  has been recycled for use by another mapping!

I think the fix is fairly simple:  Make uvm_fault_unwire() lookup the
map entry or entries for the region being unwired.  Only call
pmap_change_wiring(..., FALSE) if the entry for the region is not
wired.

This affects the locking protocol for uvm_fault_unwire(), but not
too badly; only uvm_map_pageable*() will be affected in this regard.

        -- Jason R. Thorpe <thorpej@nas.nasa.gov>