diff -NurX nopatch linux-2.2.17/arch/i386/kernel/entry.S linux-2.2.17-pax/arch/
i386/kernel/entry.S
--- linux-2.2.17/arch/i386/kernel/entry.S       Mon Sep  4 19:39:16 2000
+++ linux-2.2.17-pax/arch/i386/kernel/entry.S   Sun Nov  5 14:05:19 2000
@@ -280,6 +280,36 @@
        addl $8,%esp
        jmp ret_from_exception
 
+       ALIGN
+error_code_page_fault:
+       pushl %ds
+       pushl %eax
+       xorl %eax,%eax
+       pushl %ebp
+       pushl %edi
+       pushl %esi
+       pushl %edx
+       decl %eax                       # eax = -1
+       pushl %ecx
+       pushl %ebx
+       cld
+       movl %es,%cx
+       xchgl %eax, ORIG_EAX(%esp)      # orig_eax (get the error code. )
+       movl %esp,%edx
+       xchgl %ecx, ES(%esp)            # get the address and save es.
+       pushl %eax                      # push the error code
+       pushl %edx
+       movl $(__KERNEL_DS),%edx
+       movl %dx,%ds
+       movl %dx,%es
+       GET_CURRENT(%ebx)
+       call *%ecx
+       addl $8,%esp
+       test %eax,%eax
+       jz ret_from_exception
+       jmp restore_all
+       
+
 ENTRY(coprocessor_error)
        pushl $0
        pushl $ SYMBOL_NAME(do_coprocessor_error)
@@ -364,7 +394,7 @@
 
 ENTRY(page_fault)
        pushl $ SYMBOL_NAME(do_page_fault)
-       jmp error_code
+       jmp error_code_page_fault
 
 ENTRY(machine_check)
        pushl $0
diff -NurX nopatch linux-2.2.17/arch/i386/kernel/signal.c linux-2.2.17-pax/arch
/i386/kernel/signal.c
--- linux-2.2.17/arch/i386/kernel/signal.c      Tue Jan  4 19:12:11 2000
+++ linux-2.2.17-pax/arch/i386/kernel/signal.c  Mon Oct  9 23:02:47 2000
@@ -399,7 +399,7 @@
                esp = (unsigned long) ka->sa.sa_restorer;
        }
 
-       return (void *)((esp - frame_size) & -8ul);
+       return (void *)((esp - frame_size) & -16ul);
 }
 
 static void setup_frame(int sig, struct k_sigaction *ka,
Binary files linux-2.2.17/arch/i386/mm/core and linux-2.2.17-pax/arch/i386/mm/c
ore differ
diff -NurX nopatch linux-2.2.17/arch/i386/mm/fault.c linux-2.2.17-pax/arch/i386
/mm/fault.c
--- linux-2.2.17/arch/i386/mm/fault.c   Thu May  4 02:16:31 2000
+++ linux-2.2.17-pax/arch/i386/mm/fault.c       Mon Nov 13 15:56:56 2000
@@ -16,6 +16,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
+#include <linux/unistd.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -108,7 +109,7 @@
  *     bit 1 == 0 means read, 1 means write
  *     bit 2 == 0 means kernel, 1 means user-mode
  */
-asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
+asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long error_code)
 {
        struct task_struct *tsk;
        struct mm_struct *mm;
@@ -117,6 +118,9 @@
        unsigned long page;
        unsigned long fixup;
        int write;
+       pgd_t *pgd;
+       pmd_t *pmd;
+       pte_t *pte;
 
        /* get the address */
        __asm__("movl %%cr2,%0":"=r" (address));
@@ -136,8 +140,79 @@
        vma = find_vma(mm, address);
        if (!vma)
                goto bad_area;
-       if (vma->vm_start <= address)
+       if (vma->vm_start <= address) {
+               if ((error_code & 5) == 5) {
+                       pgd = pgd_offset(vma->vm_mm, address);
+                       pmd = pmd_offset(pgd, address);
+                       pte = pte_offset(pmd, address);
+               } else {
+                       goto good_area;
+               }
+               if ((error_code & 7) == 5 && !pte_exec(*pte)) {
+                       /* read/instruction fetch attempt from a protected page
 in user mode */
+                       unsigned long linear_cseip = regs->eip;
+
+                       if (VM_MASK & regs->eflags) {
+                               linear_cseip = (((regs->xcs)&0xFFFF)<<4) + ((re
gs->eip)&0xFFFF);
+                       } else if (regs->xcs != __USER_CS) { /* hmmm, unknown p
rotected mode code segment... */
+                               printk(KERN_ERR "PAX: wtf, task: %s:%d, CS:EIP:
 %04X:%08lX, SS:ESP: %04X:%08lX\n", tsk->comm, tsk->pid, regs->xcs, regs->eip, 
regs->xss, regs->esp);
+                               goto pax_emu;
+                       } else if (linear_cseip == address) {
+                               if (((regs->eip & 0xF) <= 8) &&
+                                   (*(unsigned short*)(regs->eip) == 0xb858) &
&
+                                   (*(unsigned int*)(regs->eip+2) == __NR_sigr
eturn) &&
+                                   (*(unsigned short*)(regs->eip+6) == 0x80cd)
)
+                               {
+                                       goto pax_emu;
+                               }
+                               if ((((regs->eip-1) & 0xF) <= 8) &&
+                                   (*(unsigned short*)(regs->eip-1) == 0xb858)
 &&
+                                   (*(unsigned int*)(regs->eip+2-1) == __NR_si
greturn) &&
+                                   (*(unsigned short*)(regs->eip+6-1) == 0x80c
d))
+                               {
+                                       goto pax_emu;
+                               }
+                               if ((((regs->eip-1-5) & 0xF) <= 8) &&
+                                   (regs->eax == __NR_sigreturn) &&
+                                   (*(unsigned short*)(regs->eip-1-5) == 0xb85
8) &&
+                                   (*(unsigned int*)(regs->eip+2-1-5) == __NR_
sigreturn) &&
+                                   (*(unsigned short*)(regs->eip+6-1-5) == 0x8
0cd))
+                               {
+                                       goto pax_emu;
+                               }
+
+                               if (((regs->eip & 0xF) <= 8) &&
+                                   (*(unsigned char*)(regs->eip) == 0xb8) &&
+                                   (*(unsigned int*)(regs->eip+1) == __NR_rt_s
igreturn) &&
+                                   (*(unsigned short*)(regs->eip+5) == 0x80cd)
)
+                               {
+                                       goto pax_emu;
+                               }
+                               if ((((regs->eip-5) & 0xF) <= 8) &&
+                                   (regs->eax == __NR_rt_sigreturn) &&
+                                   (*(unsigned char*)(regs->eip-5) == 0xb8) &&
+                                   (*(unsigned int*)(regs->eip+1-5) == __NR_rt
_sigreturn) &&
+                                   (*(unsigned short*)(regs->eip+5-5) == 0x80c
d))
+                               {
+                                       goto pax_emu;
+                               }
+                       }
+                       if (linear_cseip == address) {  /* PAX in action */
+                               up(&mm->mmap_sem);
+                               printk(KERN_ERR "PAX: terminating task: %s:%d, 
EIP: %08lX, ESP: %08lX\n", tsk->comm, tsk->pid, regs->eip, regs->esp);
+                               tsk->tss.cr2 = address;
+                               tsk->tss.error_code = error_code;
+                               tsk->tss.trap_no = 14;
+                               force_sig(SIGKILL,tsk);
+                               return 0;
+                       }
+                       goto pax_emu;
+               } else if ((error_code & 7) == 7 && !pte_exec(*pte) && pte_writ
e(*pte)) {
+                       /* write attempt to a protected page in user mode */
+                       goto pax_emu;
+               }
                goto good_area;
+       }
        if (!(vma->vm_flags & VM_GROWSDOWN))
                goto bad_area;
        if (error_code & 4) {
@@ -200,7 +275,20 @@
                        tsk->tss.screen_bitmap |= 1 << bit;
        }
        up(&mm->mmap_sem);
-       return;
+       return 0;
+
+       /*
+        * PAX: fill DTLB with user rights and retry
+        */
+pax_emu:
+       __asm__ __volatile__ (
+               "invlpg %0\n"
+               "orb $0x4,%1\n"
+               "testb $0,%0\n"
+               "andb $0xFB,%1\n"
+               : : "g" (*(char*)address), "g" (*(char*)pte) : "memory", "cc");
+       up(&mm->mmap_sem);
+       return 1;
 
 /*
  * Something tried to access memory that isn't in our memory map..
@@ -215,7 +303,7 @@
                tsk->tss.error_code = error_code;
                tsk->tss.trap_no = 14;
                force_sig(SIGSEGV, tsk);
-               return;
+               return 0;
        }
 
        /*
@@ -228,7 +316,7 @@
 
                if (nr == 6) {
                        do_invalid_op(regs, 0);
-                       return;
+                       return 0;
                }
        }
 
@@ -236,7 +324,7 @@
        /* Are we prepared to handle this kernel fault?  */
        if ((fixup = search_exception_table(regs->eip)) != 0) {
                regs->eip = fixup;
-               return;
+               return 0;
        }
 
 /*
@@ -255,7 +343,7 @@
                 * CPU state on certain buggy processors.
                 */
                printk("Ok");
-               return;
+               return 0;
        }
 
        if (address < PAGE_SIZE)
@@ -310,7 +398,7 @@
                                tsk->policy |= SCHED_YIELD;
                                schedule();
                        }
-                       return;
+                       return 0;
                }
        }
        goto no_context;
@@ -330,4 +418,5 @@
        /* Kernel mode? Handle exceptions or die */
        if (!(error_code & 4))
                goto no_context;
+       return 0;
 }
diff -NurX nopatch linux-2.2.17/arch/i386/mm/init.c linux-2.2.17-pax/arch/i386/
mm/init.c
--- linux-2.2.17/arch/i386/mm/init.c    Wed Oct 27 02:53:39 1999
+++ linux-2.2.17-pax/arch/i386/mm/init.c        Sat Sep 30 16:13:40 2000
@@ -141,7 +141,7 @@
                             "0" ((long) empty_bad_page),
                             "1" (PAGE_SIZE/4)
                             : "memory");
-       return pte_mkdirty(mk_pte((unsigned long) empty_bad_page, PAGE_SHARED))
;
+       return pte_mkdirty(mk_pte((unsigned long) empty_bad_page, PAGE_SHARED_E
XEC));
 }
 
 void show_mem(void)
@@ -359,7 +359,7 @@
        unsigned long old = pg0[0];
 
        printk("Checking if this processor honours the WP bit even in superviso
r mode... ");
-       pg0[0] = pte_val(mk_pte(PAGE_OFFSET, PAGE_READONLY));
+       pg0[0] = pte_val(mk_pte(PAGE_OFFSET, PAGE_READONLY_EXEC));
        local_flush_tlb();
        current->mm->mmap->vm_start += PAGE_SIZE;
        __asm__ __volatile__(
diff -NurX nopatch linux-2.2.17/drivers/char/bttv.c linux-2.2.17-pax/drivers/ch
ar/bttv.c
--- linux-2.2.17/drivers/char/bttv.c    Mon Sep  4 19:39:17 2000
+++ linux-2.2.17-pax/drivers/char/bttv.c        Thu Nov  9 22:48:58 2000
@@ -2325,7 +2325,7 @@
        while (size > 0) 
        {
                page = kvirt_to_pa(pos);
-               if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))
+               if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED_EXEC))
                        return -EAGAIN;
                start+=PAGE_SIZE;
                pos+=PAGE_SIZE;
diff -NurX nopatch linux-2.2.17/drivers/char/buz.c linux-2.2.17-pax/drivers/cha
r/buz.c
--- linux-2.2.17/drivers/char/buz.c     Thu May  4 02:16:33 2000
+++ linux-2.2.17-pax/drivers/char/buz.c Thu Nov  9 22:49:12 2000
@@ -2989,7 +2989,7 @@
                                        todo = fraglen;
                                pos = (unsigned long) zr->jpg_gbuf[i].frag_tab[
2 * j];
                                page = virt_to_phys(bus_to_virt(pos));  /* shou
ld just be pos on i386 */
-                               if (remap_page_range(start, page, todo, PAGE_SH
ARED)) {
+                               if (remap_page_range(start, page, todo, PAGE_SH
ARED_EXEC)) {
                                        printk(KERN_ERR "%s: zoran_mmap(V4L): r
emap_page_range failed\n", zr->name);
                                        return -EAGAIN;
                                }
@@ -3016,7 +3016,7 @@
                                todo = v4l_bufsize;
                        page = zr->v4l_gbuf[i].fbuffer_phys;
                        DEBUG(printk("V4L remap page range %d 0x%x %d to 0x%x\n
", i, page, todo, start));
-                       if (remap_page_range(start, page, todo, PAGE_SHARED)) {
+                       if (remap_page_range(start, page, todo, PAGE_SHARED_EXE
C)) {
                                printk(KERN_ERR "%s: zoran_mmap(V4L): remap_pag
e_range failed\n", zr->name);
                                return -EAGAIN;
                        }
diff -NurX nopatch linux-2.2.17/drivers/char/cpia.c linux-2.2.17-pax/drivers/ch
ar/cpia.c
--- linux-2.2.17/drivers/char/cpia.c    Wed Jun  7 23:26:42 2000
+++ linux-2.2.17-pax/drivers/char/cpia.c        Thu Nov  9 22:49:24 2000
@@ -3065,7 +3065,7 @@
        pos = (unsigned long)(cam->frame_buf);
        while (size > 0) {
                page = kvirt_to_phys(pos);
-               if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) {
+               if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED_EXEC))
 {
                        up(&cam->busy_lock);
                        return -EAGAIN;
                }
diff -NurX nopatch linux-2.2.17/drivers/char/mem.c linux-2.2.17-pax/drivers/cha
r/mem.c
--- linux-2.2.17/drivers/char/mem.c     Tue Jan  4 19:12:14 2000
+++ linux-2.2.17-pax/drivers/char/mem.c Thu Nov  9 22:49:59 2000
@@ -353,7 +353,11 @@
 
                flush_cache_range(mm, addr, addr + count);
                zap_page_range(mm, addr, count);
-               zeromap_page_range(addr, count, PAGE_COPY);
+               if (vma->vm_flags & VM_EXEC) {
+                       zeromap_page_range(addr, count, PAGE_COPY_EXEC);
+               } else {
+                       zeromap_page_range(addr, count, PAGE_COPY_NOEXEC);
+               }
                flush_tlb_range(mm, addr, addr + count);
 
                size -= count;
diff -NurX nopatch linux-2.2.17/drivers/char/planb.c linux-2.2.17-pax/drivers/c
har/planb.c
--- linux-2.2.17/drivers/char/planb.c   Thu Aug 26 02:29:47 1999
+++ linux-2.2.17-pax/drivers/char/planb.c       Thu Nov  9 22:50:25 2000
@@ -2085,7 +2085,7 @@
        while (size > 0) 
        {
                page = vmalloc_to_phys(pos);
-               if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))
+               if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED_EXEC))
                        return -EAGAIN;
                start+=PAGE_SIZE;
                pos+=PAGE_SIZE;
diff -NurX nopatch linux-2.2.17/fs/binfmt_aout.c linux-2.2.17-pax/fs/binfmt_aou
t.c
--- linux-2.2.17/fs/binfmt_aout.c       Tue Jan  4 19:12:22 2000
+++ linux-2.2.17-pax/fs/binfmt_aout.c   Mon Nov  6 19:08:14 2000
@@ -50,7 +50,7 @@
        if (end <= start)
                return;
        do_mmap(NULL, start, end - start,
-               PROT_READ | PROT_WRITE | PROT_EXEC,
+               PROT_READ | PROT_WRITE,
                MAP_FIXED | MAP_PRIVATE, 0);
 }
 
@@ -441,7 +441,7 @@
                }
 
                error = do_mmap(file, N_DATADDR(ex), ex.a_data,
-                               PROT_READ | PROT_WRITE | PROT_EXEC,
+                               PROT_READ | PROT_WRITE,
                                MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_E
XECUTABLE,
                                fd_offset + ex.a_text);
                fput(file);
@@ -560,7 +560,7 @@
        bss = ex.a_text + ex.a_data + ex.a_bss;
        if (bss > len) {
                error = do_mmap(NULL, start_addr + len, bss - len,
-                               PROT_READ | PROT_WRITE | PROT_EXEC,
+                               PROT_READ | PROT_WRITE,
                                MAP_PRIVATE | MAP_FIXED, 0);
                retval = error;
                if (error != start_addr + len)
diff -NurX nopatch linux-2.2.17/fs/binfmt_elf.c linux-2.2.17-pax/fs/binfmt_elf.
c
--- linux-2.2.17/fs/binfmt_elf.c        Wed Jun  7 23:26:43 2000
+++ linux-2.2.17-pax/fs/binfmt_elf.c    Mon Nov  6 19:18:36 2000
@@ -78,7 +78,7 @@
        if (end <= start)
                return;
        do_mmap(NULL, start, end - start,
-               PROT_READ | PROT_WRITE | PROT_EXEC,
+               PROT_READ | PROT_WRITE,
                MAP_FIXED | MAP_PRIVATE, 0);
 }
 
@@ -330,7 +330,7 @@
        /* Map the last of the bss segment */
        if (last_bss > elf_bss)
                do_mmap(NULL, elf_bss, last_bss - elf_bss,
-                       PROT_READ|PROT_WRITE|PROT_EXEC,
+                       PROT_READ|PROT_WRITE,
                        MAP_FIXED|MAP_PRIVATE, 0);
 
        *interp_load_addr = load_addr;
@@ -389,7 +389,7 @@
 
        do_mmap(NULL, ELF_PAGESTART(text_data + ELF_EXEC_PAGESIZE - 1),
                interp_ex->a_bss,
-               PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE, 0);
+               PROT_READ|PROT_WRITE, MAP_FIXED|MAP_PRIVATE, 0);
        elf_entry = interp_ex->a_entry;
 
 out:
@@ -907,7 +907,7 @@
        bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
        if (bss > len)
                do_mmap(NULL, len, bss - len,
-                       PROT_READ|PROT_WRITE|PROT_EXEC,
+                       PROT_READ|PROT_WRITE,
                        MAP_FIXED|MAP_PRIVATE, 0);
        error = 0;
 
diff -NurX nopatch linux-2.2.17/fs/exec.c linux-2.2.17-pax/fs/exec.c
--- linux-2.2.17/fs/exec.c      Mon Sep  4 19:39:22 2000
+++ linux-2.2.17-pax/fs/exec.c  Mon Nov  6 19:12:17 2000
@@ -314,7 +314,7 @@
                mpnt->vm_mm = current->mm;
                mpnt->vm_start = PAGE_MASK & (unsigned long) p;
                mpnt->vm_end = STACK_TOP;
-               mpnt->vm_page_prot = PAGE_COPY;
+               mpnt->vm_page_prot = PAGE_COPY_NOEXEC;
                mpnt->vm_flags = VM_STACK_FLAGS;
                mpnt->vm_ops = NULL;
                mpnt->vm_offset = 0;
diff -NurX nopatch linux-2.2.17/include/asm-i386/pgtable.h linux-2.2.17-pax/inc
lude/asm-i386/pgtable.h
--- linux-2.2.17/include/asm-i386/pgtable.h     Sun Oct  1 22:10:25 2000
+++ linux-2.2.17-pax/include/asm-i386/pgtable.h Sat Oct 21 22:52:15 2000
@@ -235,33 +235,37 @@
 #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
 
 #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)
+#define PAGE_SHARED_EXEC       __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER 
| _PAGE_ACCESSED)
+#define PAGE_COPY_EXEC         __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACC
ESSED)
+#define PAGE_READONLY_EXEC     __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACC
ESSED)
 #define PAGE_KERNEL    __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE
_ACCESSED)
 #define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_DIRTY | _PAGE_ACCESSED)
 
+#define PAGE_SHARED_NOEXEC     __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCES
SED)
+#define PAGE_COPY_NOEXEC       __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
+#define PAGE_READONLY_NOEXEC   __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
+
 /*
  * The i386 can't do page protection for execute, and considers that the same 
are read.
  * Also, write permissions imply read permissions. This is the closest we can 
get..
  */
 #define __P000 PAGE_NONE
-#define __P001 PAGE_READONLY
-#define __P010 PAGE_COPY
-#define __P011 PAGE_COPY
-#define __P100 PAGE_READONLY
-#define __P101 PAGE_READONLY
-#define __P110 PAGE_COPY
-#define __P111 PAGE_COPY
+#define __P001 PAGE_READONLY_NOEXEC
+#define __P010 PAGE_COPY_NOEXEC
+#define __P011 PAGE_COPY_NOEXEC
+#define __P100 PAGE_READONLY_EXEC
+#define __P101 PAGE_READONLY_EXEC
+#define __P110 PAGE_COPY_EXEC
+#define __P111 PAGE_COPY_EXEC
 
 #define __S000 PAGE_NONE
-#define __S001 PAGE_READONLY
-#define __S010 PAGE_SHARED
-#define __S011 PAGE_SHARED
-#define __S100 PAGE_READONLY
-#define __S101 PAGE_READONLY
-#define __S110 PAGE_SHARED
-#define __S111 PAGE_SHARED
+#define __S001 PAGE_READONLY_NOEXEC
+#define __S010 PAGE_SHARED_NOEXEC
+#define __S011 PAGE_SHARED_NOEXEC
+#define __S100 PAGE_READONLY_EXEC
+#define __S101 PAGE_READONLY_EXEC
+#define __S110 PAGE_SHARED_EXEC
+#define __S111 PAGE_SHARED_EXEC
 
 /*
  * Define this if things work differently on an i386 and an i486:
diff -NurX nopatch linux-2.2.17/include/asm-i386/processor.h linux-2.2.17-pax/i
nclude/asm-i386/processor.h
--- linux-2.2.17/include/asm-i386/processor.h   Mon Sep  4 19:39:28 2000
+++ linux-2.2.17-pax/include/asm-i386/processor.h       Sat Oct 21 22:52:15 200
0
@@ -247,7 +247,7 @@
 };
 
 #define INIT_MMAP \
-{ &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NU
LL }
+{ &init_mm, 0, 0, NULL, PAGE_SHARED_EXEC, VM_READ | VM_WRITE | VM_EXEC, 1, NUL
L, NULL }
 
 #define INIT_TSS  {                                            \
        0,0, /* back_link, __blh */                             \
diff -NurX nopatch linux-2.2.17/include/linux/mm.h linux-2.2.17-pax/include/lin
ux/mm.h
--- linux-2.2.17/include/linux/mm.h     Sun Oct  1 22:10:25 2000
+++ linux-2.2.17-pax/include/linux/mm.h Sat Oct 21 22:52:15 2000
@@ -81,7 +81,7 @@
 #define VM_LOCKED      0x2000
 #define VM_IO           0x4000  /* Memory mapped I/O or similar */
 
-#define VM_STACK_FLAGS 0x0177
+#define VM_STACK_FLAGS 0x0133  /* PAX */ 
 
 /*
  * mapping from the currently active vm_flags protection bits (the
diff -NurX nopatch linux-2.2.17/ipc/shm.c linux-2.2.17-pax/ipc/shm.c
--- linux-2.2.17/ipc/shm.c      Wed Jun  7 23:26:44 2000
+++ linux-2.2.17-pax/ipc/shm.c  Sun Nov  5 13:41:39 2000
@@ -509,9 +509,9 @@
        shmd->vm_start = addr;
        shmd->vm_end = addr + shp->shm_npages * PAGE_SIZE;
        shmd->vm_mm = current->mm;
-       shmd->vm_page_prot = (shmflg & SHM_RDONLY) ? PAGE_READONLY : PAGE_SHARE
D;
+       shmd->vm_page_prot = (shmflg & SHM_RDONLY) ? PAGE_READONLY_NOEXEC : PAG
E_SHARED_NOEXEC;
        shmd->vm_flags = VM_SHM | VM_MAYSHARE | VM_SHARED
-                        | VM_MAYREAD | VM_MAYEXEC | VM_READ | VM_EXEC
+                        | VM_MAYREAD | VM_READ
                         | ((shmflg & SHM_RDONLY) ? 0 : VM_MAYWRITE | VM_WRITE)
;
        shmd->vm_file = NULL;
        shmd->vm_offset = 0;
@@ -667,7 +667,7 @@
                        shm_swp--;
                }
                shm_rss++;
-               pte = pte_mkdirty(mk_pte(page, PAGE_SHARED));
+               pte = pte_mkdirty(mk_pte(page, PAGE_SHARED_NOEXEC));
                shp->shm_pages[idx] = pte_val(pte);
        } else
                --current->maj_flt;  /* was incremented in do_no_page */
@@ -748,7 +748,7 @@
 {
        pte_t pte;
 
-       pte = pte_mkdirty(mk_pte(page, PAGE_SHARED));
+       pte = pte_mkdirty(mk_pte(page, PAGE_SHARED_NOEXEC));
        shp->shm_pages[idx] = pte_val(pte);
        atomic_inc(&mem_map[MAP_NR(page)].count);
        shm_rss++;
diff -NurX nopatch linux-2.2.17/mm/memory.c linux-2.2.17-pax/mm/memory.c
--- linux-2.2.17/mm/memory.c    Tue Jan  4 19:12:26 2000
+++ linux-2.2.17-pax/mm/memory.c        Sat Sep 30 16:10:36 2000
@@ -583,7 +583,7 @@
                return 0;
        }
        flush_page_to_ram(page);
-       set_pte(pte, pte_mkwrite(pte_mkdirty(mk_pte(page, PAGE_COPY))));
+       set_pte(pte, pte_mkwrite(pte_mkdirty(mk_pte(page, PAGE_COPY_NOEXEC))));
 /* no need for flush_tlb */
        return page;
 }
diff -NurX nopatch linux-2.2.17/mm/mmap.c linux-2.2.17-pax/mm/mmap.c
--- linux-2.2.17/mm/mmap.c      Wed Jun  7 23:26:44 2000
+++ linux-2.2.17-pax/mm/mmap.c  Mon Nov  6 19:54:17 2000
@@ -135,7 +135,7 @@
 
        /* Ok, looks good - let it rip. */
        if (do_mmap(NULL, oldbrk, newbrk-oldbrk,
-                  PROT_READ|PROT_WRITE|PROT_EXEC,
+                  PROT_READ|PROT_WRITE,
                   MAP_FIXED|MAP_PRIVATE, 0) != oldbrk)
                goto out;
 set_brk:
@@ -161,6 +161,10 @@
                _trans(prot, PROT_READ, VM_READ) |
                _trans(prot, PROT_WRITE, VM_WRITE) |
                _trans(prot, PROT_EXEC, VM_EXEC);
+       prot_bits |=
+               _trans(prot, PROT_READ, VM_MAYREAD) |
+               _trans(prot, PROT_WRITE, VM_MAYWRITE) |
+               _trans(prot, PROT_EXEC, VM_MAYEXEC);
        flag_bits =
                _trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN) |
                _trans(flags, MAP_DENYWRITE, VM_DENYWRITE) |
@@ -260,8 +264,17 @@
        vma->vm_flags = vm_flags(prot,flags) | mm->def_flags;
 
        if (file) {
-               if (file->f_mode & 1)
-                       vma->vm_flags |= VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
+               /* PaX: grant write access to executable mappings, even if it w
asn't
+                  explicitly requested (hint: relocation). mprotect() will rem
ove
+                  VM_MAYWRITE after the first request for PROT_WRITE (after wh
ich
+                  the loader is expected to remove PROT_WRITE for good).
+               */
+               if (file->f_mode & 1) {
+                       if (prot & PROT_EXEC)
+                               vma->vm_flags |= VM_MAYWRITE;
+               } else {
+                       vma->vm_flags &= ~(VM_MAYREAD | VM_MAYWRITE | VM_MAYEXE
C);
+               }
                if (flags & MAP_SHARED) {
                        vma->vm_flags |= VM_SHARED | VM_MAYSHARE;
 
@@ -277,8 +290,7 @@
                        if (!(file->f_mode & 2))
                                vma->vm_flags &= ~(VM_MAYWRITE | VM_SHARED);
                }
-       } else
-               vma->vm_flags |= VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
+       }
        vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
        vma->vm_ops = NULL;
        vma->vm_offset = off;
@@ -325,6 +337,14 @@
                        file->f_dentry->d_inode->i_writecount++;
                if (error)
                        goto unmap_and_free_vma;
+               /* if it turns out to be device memory (eg. video RAM), don't a
pply PaX */
+               if ((vma->vm_flags & VM_IO) && !(vma->vm_flags & VM_EXEC)) {
+                       vma->vm_flags |= VM_EXEC | VM_MAYEXEC;
+                       vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f
];
+                       error = remap_page_range(vma->vm_start, vma->vm_offset,
 vma->vm_end-vma->vm_start, vma->vm_page_prot);
+                       if (error)
+                               goto unmap_and_free_vma;
+               }
                vma->vm_file = file;
                file->f_count++;
        }
diff -NurX nopatch linux-2.2.17/mm/mprotect.c linux-2.2.17-pax/mm/mprotect.c
--- linux-2.2.17/mm/mprotect.c  Fri Nov 20 20:43:19 1998
+++ linux-2.2.17-pax/mm/mprotect.c      Sat Nov 11 19:43:01 2000
@@ -229,6 +229,10 @@
                        error = -EACCES;
                        break;
                }
+               /* PaX: disallow write access after relocs are done, hopefully 
noone else needs it... */
+               if ((prot & PROT_WRITE) && (vma->vm_flags & VM_MAYEXEC)) {
+                       newflags &= ~VM_MAYWRITE;
+               }
 
                if (vma->vm_end >= end) {
                        error = mprotect_fixup(vma, nstart, end, newflags);

