Date:	Mon, 16 Feb 1998 12:40:59 -0800 (PST)
From:	Linus Torvalds <torvalds@transmeta.com>
To:	Alan Cox <alan@lxorguk.ukuu.org.uk>
Subject: Re: How to read-protect a vm_area?



On Mon, 16 Feb 1998, Alan Cox wrote:
>
> > Note that this is an issue only for something that _has_ been accessible
> > and then has turned into PROT_NONE by using mprotect() - because if the
> > pages aren't there at all then the page fault handler will refuse to page
> > them in even when the access is done from kernel space. 
> 
> As is done by Texas, Electric Fence ... It potentially stops ElectricFence
> detecting a syscall into an area that has been read/written to after being
> freed, and I think it means anyone wanting to run the texas persistent object
> store needs to go and download OpenBSD.
> 
> How tricky is it to handle - I agree its not a normal issue..

I would have said that it is impossible to handle cleanly, but I have a
trick that I can play that may make it fairly easy to fix without
introducing any other issues than an even trickier <asm-i386/pgtable.h>.

Essentially, the problem is that currently I use the "present" bit to
imply that the page is in RAM vs paged out. This is the obvious and
straightforward implementation - it's what the hardware does. But I
_could_ use two bits for that, where the pattern would be:

	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx00	- truly not present (ie paged out)
	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx10	- PROT_NONE
	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1	- present

which should work fairly well, and would still match the hardware
behaviour we want. 

Anyway, I haven't even tried compiling this, but this very small patch
(I'd call it trivial if it wasn't so subtle) MAY work. Would somebody like
to test it?

Anyway, I'll just say again that the Linux mm layer is probably the best
in the business - I don't think anybody else could have done this kind of
change without major surgery. Yes sir, we're #1 (even if this patch
doesn't work, I'll bet it is close). 

		Linus

-----
--- v2.1.86/linux/include/asm-i386/pgtable.h	Fri Feb  6 15:32:54 1998
+++ linux/include/asm-i386/pgtable.h	Mon Feb 16 12:37:25 1998
@@ -200,7 +200,8 @@
  * memory. 
  */
 #define _PAGE_PRESENT	0x001
-#define _PAGE_RW	0x002
+#define _PAGE_PROTNONE	0x002		/* If not present */
+#define _PAGE_RW	0x002		/* If present */
 #define _PAGE_USER	0x004
 #define _PAGE_WT	0x008
 #define _PAGE_PCD	0x010
@@ -211,9 +212,9 @@
 
 #define _PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
 #define _KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
-#define _PAGE_CHG_MASK	(PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define _PAGE_CHG_MASK	(PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_PRESENT)
 
-#define PAGE_NONE	__pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
+#define PAGE_NONE	__pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
 #define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
 #define PAGE_COPY	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
 #define PAGE_READONLY	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
@@ -291,7 +292,7 @@
 } while (0)
 
 #define pte_none(x)	(!pte_val(x))
-#define pte_present(x)	(pte_val(x) & _PAGE_PRESENT)
+#define pte_present(x)	(pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE))
 #define pte_clear(xp)	do { pte_val(*(xp)) = 0; } while (0)
 
 #define pmd_none(x)	(!pmd_val(x))
@@ -489,9 +490,9 @@
 {
 }
 
-#define SWP_TYPE(entry) (((entry) >> 1) & 0x7f)
+#define SWP_TYPE(entry) (((entry) >> 2) & 0x3f)
 #define SWP_OFFSET(entry) ((entry) >> 8)
-#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
+#define SWP_ENTRY(type,offset) (((type) << 2) | ((offset) << 8))
 
 #define module_map      vmalloc
 #define module_unmap    vfree



-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu