Re: How to read-protect a vm_area?

Linus Torvalds (torvalds@transmeta.com)
Mon, 16 Feb 1998 12:40:59 -0800 (PST)


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