[S390] Remove data execution protection
Martin Schwidefsky [Mon, 23 May 2011 08:24:23 +0000 (10:24 +0200)]
The noexec support on s390 does not rely on a bit in the page table
entry but utilizes the secondary space mode to distinguish between
memory accesses for instructions vs. data. The noexec code relies
on the assumption that the cpu will always use the secondary space
page table for data accesses while it is running in the secondary
space mode. Up to the z9-109 class machines this has been the case.
Unfortunately this is not true anymore with z10 and later machines.
The load-relative-long instructions lrl, lgrl and lgfrl access the
memory operand using the same addressing-space mode that has been
used to fetch the instruction.
This breaks the noexec mode for all user space binaries compiled
with march=z10 or later. The only option is to remove the current
noexec support.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

14 files changed:
arch/s390/Kconfig
arch/s390/include/asm/elf.h
arch/s390/include/asm/hugetlb.h
arch/s390/include/asm/lowcore.h
arch/s390/include/asm/mmu.h
arch/s390/include/asm/mmu_context.h
arch/s390/include/asm/pgalloc.h
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/tlbflush.h
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/setup.c
arch/s390/mm/fault.c
arch/s390/mm/hugetlbpage.c
arch/s390/mm/pgtable.c

index 4a7f140..ff2d237 100644 (file)
@@ -230,17 +230,6 @@ config SYSVIPC_COMPAT
 config AUDIT_ARCH
        def_bool y
 
-config S390_EXEC_PROTECT
-       def_bool y
-       prompt "Data execute protection"
-       help
-         This option allows to enable a buffer overflow protection for user
-         space programs and it also selects the addressing mode option above.
-         The kernel parameter noexec=on will enable this feature and also
-         switch the addressing modes, default is disabled. Enabling this (via
-         kernel parameter) on machines earlier than IBM System z9 this will
-         reduce system performance.
-
 comment "Code generation options"
 
 choice
index 10c029c..64b61bf 100644 (file)
@@ -196,18 +196,6 @@ do {                                                               \
 } while (0)
 #endif /* __s390x__ */
 
-/*
- * An executable for which elf_read_implies_exec() returns TRUE will
- * have the READ_IMPLIES_EXEC personality flag set automatically.
- */
-#define elf_read_implies_exec(ex, executable_stack)    \
-({                                                     \
-       if (current->mm->context.noexec &&              \
-           executable_stack != EXSTACK_DISABLE_X)      \
-               disable_noexec(current->mm, current);   \
-       current->mm->context.noexec == 0;               \
-})
-
 #define STACK_RND_MASK 0x7ffUL
 
 #define ARCH_DLINFO                                                        \
index b56403c..799ed0f 100644 (file)
@@ -111,21 +111,10 @@ static inline void huge_ptep_invalidate(struct mm_struct *mm,
 {
        pmd_t *pmdp = (pmd_t *) ptep;
 
-       if (!MACHINE_HAS_IDTE) {
-               __pmd_csp(pmdp);
-               if (mm->context.noexec) {
-                       pmdp = get_shadow_table(pmdp);
-                       __pmd_csp(pmdp);
-               }
-               return;
-       }
-
-       __pmd_idte(address, pmdp);
-       if (mm->context.noexec) {
-               pmdp = get_shadow_table(pmdp);
+       if (MACHINE_HAS_IDTE)
                __pmd_idte(address, pmdp);
-       }
-       return;
+       else
+               __pmd_csp(pmdp);
 }
 
 #define huge_ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \
index 65e172f..b8624d5 100644 (file)
@@ -124,7 +124,7 @@ struct _lowcore {
        /* Address space pointer. */
        __u32   kernel_asce;                    /* 0x02ac */
        __u32   user_asce;                      /* 0x02b0 */
-       __u32   user_exec_asce;                 /* 0x02b4 */
+       __u8    pad_0x02b4[0x02b8-0x02b4];      /* 0x02b4 */
 
        /* SMP info area */
        __u32   cpu_nr;                         /* 0x02b8 */
@@ -255,7 +255,7 @@ struct _lowcore {
        /* Address space pointer. */
        __u64   kernel_asce;                    /* 0x0310 */
        __u64   user_asce;                      /* 0x0318 */
-       __u64   user_exec_asce;                 /* 0x0320 */
+       __u8    pad_0x0320[0x0328-0x0320];      /* 0x0320 */
 
        /* SMP info area */
        __u32   cpu_nr;                         /* 0x0328 */
index 78522cd..818e829 100644 (file)
@@ -5,19 +5,16 @@ typedef struct {
        atomic_t attach_count;
        unsigned int flush_mm;
        spinlock_t list_lock;
-       struct list_head crst_list;
        struct list_head pgtable_list;
        unsigned long asce_bits;
        unsigned long asce_limit;
        unsigned long vdso_base;
-       int noexec;
        int has_pgste;   /* The mmu context has extended page tables */
        int alloc_pgste; /* cloned contexts will have extended page tables */
 } mm_context_t;
 
 #define INIT_MM_CONTEXT(name)                                                \
        .context.list_lock    = __SPIN_LOCK_UNLOCKED(name.context.list_lock), \
-       .context.crst_list    = LIST_HEAD_INIT(name.context.crst_list),       \
        .context.pgtable_list = LIST_HEAD_INIT(name.context.pgtable_list),
 
 #endif
index 8c277ca..5682f16 100644 (file)
@@ -35,11 +35,9 @@ static inline int init_new_context(struct task_struct *tsk,
                 * and if has_pgste is set, it will create extended page
                 * tables.
                 */
-               mm->context.noexec = 0;
                mm->context.has_pgste = 1;
                mm->context.alloc_pgste = 1;
        } else {
-               mm->context.noexec = (user_mode == SECONDARY_SPACE_MODE);
                mm->context.has_pgste = 0;
                mm->context.alloc_pgste = 0;
        }
@@ -63,10 +61,8 @@ static inline void update_mm(struct mm_struct *mm, struct task_struct *tsk)
        S390_lowcore.user_asce = mm->context.asce_bits | __pa(pgd);
        if (user_mode != HOME_SPACE_MODE) {
                /* Load primary space page table origin. */
-               pgd = mm->context.noexec ? get_shadow_table(pgd) : pgd;
-               S390_lowcore.user_exec_asce = mm->context.asce_bits | __pa(pgd);
                asm volatile(LCTL_OPCODE" 1,1,%0\n"
-                            : : "m" (S390_lowcore.user_exec_asce) );
+                            : : "m" (S390_lowcore.user_asce) );
        } else
                /* Load home space page table origin. */
                asm volatile(LCTL_OPCODE" 13,13,%0"
index 082eb4e..739ff9e 100644 (file)
 
 #define check_pgt_cache()      do {} while (0)
 
-unsigned long *crst_table_alloc(struct mm_struct *, int);
+unsigned long *crst_table_alloc(struct mm_struct *);
 void crst_table_free(struct mm_struct *, unsigned long *);
 void crst_table_free_rcu(struct mm_struct *, unsigned long *);
 
 unsigned long *page_table_alloc(struct mm_struct *);
 void page_table_free(struct mm_struct *, unsigned long *);
 void page_table_free_rcu(struct mm_struct *, unsigned long *);
-void disable_noexec(struct mm_struct *, struct task_struct *);
 
 static inline void clear_table(unsigned long *s, unsigned long val, size_t n)
 {
@@ -50,9 +49,6 @@ static inline void clear_table(unsigned long *s, unsigned long val, size_t n)
 static inline void crst_table_init(unsigned long *crst, unsigned long entry)
 {
        clear_table(crst, entry, sizeof(unsigned long)*2048);
-       crst = get_shadow_table(crst);
-       if (crst)
-               clear_table(crst, entry, sizeof(unsigned long)*2048);
 }
 
 #ifndef __s390x__
@@ -90,7 +86,7 @@ void crst_table_downgrade(struct mm_struct *, unsigned long limit);
 
 static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address)
 {
-       unsigned long *table = crst_table_alloc(mm, mm->context.noexec);
+       unsigned long *table = crst_table_alloc(mm);
        if (table)
                crst_table_init(table, _REGION3_ENTRY_EMPTY);
        return (pud_t *) table;
@@ -99,7 +95,7 @@ static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address)
 
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
 {
-       unsigned long *table = crst_table_alloc(mm, mm->context.noexec);
+       unsigned long *table = crst_table_alloc(mm);
        if (table)
                crst_table_init(table, _SEGMENT_ENTRY_EMPTY);
        return (pmd_t *) table;
@@ -115,11 +111,6 @@ static inline void pgd_populate_kernel(struct mm_struct *mm,
 static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
 {
        pgd_populate_kernel(mm, pgd, pud);
-       if (mm->context.noexec) {
-               pgd = get_shadow_table(pgd);
-               pud = get_shadow_table(pud);
-               pgd_populate_kernel(mm, pgd, pud);
-       }
 }
 
 static inline void pud_populate_kernel(struct mm_struct *mm,
@@ -131,11 +122,6 @@ static inline void pud_populate_kernel(struct mm_struct *mm,
 static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
 {
        pud_populate_kernel(mm, pud, pmd);
-       if (mm->context.noexec) {
-               pud = get_shadow_table(pud);
-               pmd = get_shadow_table(pmd);
-               pud_populate_kernel(mm, pud, pmd);
-       }
 }
 
 #endif /* __s390x__ */
@@ -143,10 +129,8 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
 static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 {
        spin_lock_init(&mm->context.list_lock);
-       INIT_LIST_HEAD(&mm->context.crst_list);
        INIT_LIST_HEAD(&mm->context.pgtable_list);
-       return (pgd_t *)
-               crst_table_alloc(mm, user_mode == SECONDARY_SPACE_MODE);
+       return (pgd_t *) crst_table_alloc(mm);
 }
 #define pgd_free(mm, pgd) crst_table_free(mm, (unsigned long *) pgd)
 
@@ -160,10 +144,6 @@ static inline void pmd_populate(struct mm_struct *mm,
                                pmd_t *pmd, pgtable_t pte)
 {
        pmd_populate_kernel(mm, pmd, pte);
-       if (mm->context.noexec) {
-               pmd = get_shadow_table(pmd);
-               pmd_populate_kernel(mm, pmd, pte + PTRS_PER_PTE);
-       }
 }
 
 #define pmd_pgtable(pmd) \
index 02ace34..763620e 100644 (file)
@@ -256,8 +256,6 @@ extern unsigned long VMALLOC_START;
 #define _PAGE_TYPE_FILE                0x601   /* bit 0x002 is used for offset !! */
 #define _PAGE_TYPE_RO          0x200
 #define _PAGE_TYPE_RW          0x000
-#define _PAGE_TYPE_EX_RO       0x202
-#define _PAGE_TYPE_EX_RW       0x002
 
 /*
  * Only four types for huge pages, using the invalid bit and protection bit
@@ -287,8 +285,6 @@ extern unsigned long VMALLOC_START;
  * _PAGE_TYPE_FILE     11?1   ->   11?1
  * _PAGE_TYPE_RO       0100   ->   1100
  * _PAGE_TYPE_RW       0000   ->   1000
- * _PAGE_TYPE_EX_RO    0110   ->   1110
- * _PAGE_TYPE_EX_RW    0010   ->   1010
  *
  * pte_none is true for bits combinations 1000, 1010, 1100, 1110
  * pte_present is true for bits combinations 0000, 0010, 0100, 0110, 1001
@@ -387,55 +383,33 @@ extern unsigned long VMALLOC_START;
 #define PAGE_NONE      __pgprot(_PAGE_TYPE_NONE)
 #define PAGE_RO                __pgprot(_PAGE_TYPE_RO)
 #define PAGE_RW                __pgprot(_PAGE_TYPE_RW)
-#define PAGE_EX_RO     __pgprot(_PAGE_TYPE_EX_RO)
-#define PAGE_EX_RW     __pgprot(_PAGE_TYPE_EX_RW)
 
 #define PAGE_KERNEL    PAGE_RW
 #define PAGE_COPY      PAGE_RO
 
 /*
- * Dependent on the EXEC_PROTECT option s390 can do execute protection.
- * Write permission always implies read permission. In theory with a
- * primary/secondary page table execute only can be implemented but
- * it would cost an additional bit in the pte to distinguish all the
- * different pte types. To avoid that execute permission currently
- * implies read permission as well.
+ * On s390 the page table entry has an invalid bit and a read-only bit.
+ * Read permission implies execute permission and write permission
+ * implies read permission.
  */
          /*xwr*/
 #define __P000 PAGE_NONE
 #define __P001 PAGE_RO
 #define __P010 PAGE_RO
 #define __P011 PAGE_RO
-#define __P100 PAGE_EX_RO
-#define __P101 PAGE_EX_RO
-#define __P110 PAGE_EX_RO
-#define __P111 PAGE_EX_RO
+#define __P100 PAGE_RO
+#define __P101 PAGE_RO
+#define __P110 PAGE_RO
+#define __P111 PAGE_RO
 
 #define __S000 PAGE_NONE
 #define __S001 PAGE_RO
 #define __S010 PAGE_RW
 #define __S011 PAGE_RW
-#define __S100 PAGE_EX_RO
-#define __S101 PAGE_EX_RO
-#define __S110 PAGE_EX_RW
-#define __S111 PAGE_EX_RW
-
-#ifndef __s390x__
-# define PxD_SHADOW_SHIFT      1
-#else /* __s390x__ */
-# define PxD_SHADOW_SHIFT      2
-#endif /* __s390x__ */
-
-static inline void *get_shadow_table(void *table)
-{
-       unsigned long addr, offset;
-       struct page *page;
-
-       addr = (unsigned long) table;
-       offset = addr & ((PAGE_SIZE << PxD_SHADOW_SHIFT) - 1);
-       page = virt_to_page((void *)(addr ^ offset));
-       return (void *)(addr_t)(page->index ? (page->index | offset) : 0UL);
-}
+#define __S100 PAGE_RO
+#define __S101 PAGE_RO
+#define __S110 PAGE_RW
+#define __S111 PAGE_RW
 
 /*
  * Certain architectures need to do special things when PTEs
@@ -446,14 +420,6 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
                              pte_t *ptep, pte_t entry)
 {
        *ptep = entry;
-       if (mm->context.noexec) {
-               if (!(pte_val(entry) & _PAGE_INVALID) &&
-                   (pte_val(entry) & _PAGE_SWX))
-                       pte_val(entry) |= _PAGE_RO;
-               else
-                       pte_val(entry) = _PAGE_TYPE_EMPTY;
-               ptep[PTRS_PER_PTE] = entry;
-       }
 }
 
 /*
@@ -662,11 +628,7 @@ static inline void pgd_clear_kernel(pgd_t * pgd)
 
 static inline void pgd_clear(pgd_t * pgd)
 {
-       pgd_t *shadow = get_shadow_table(pgd);
-
        pgd_clear_kernel(pgd);
-       if (shadow)
-               pgd_clear_kernel(shadow);
 }
 
 static inline void pud_clear_kernel(pud_t *pud)
@@ -677,13 +639,8 @@ static inline void pud_clear_kernel(pud_t *pud)
 
 static inline void pud_clear(pud_t *pud)
 {
-       pud_t *shadow = get_shadow_table(pud);
-
        pud_clear_kernel(pud);
-       if (shadow)
-               pud_clear_kernel(shadow);
 }
-
 #endif /* __s390x__ */
 
 static inline void pmd_clear_kernel(pmd_t * pmdp)
@@ -693,18 +650,12 @@ static inline void pmd_clear_kernel(pmd_t * pmdp)
 
 static inline void pmd_clear(pmd_t *pmd)
 {
-       pmd_t *shadow = get_shadow_table(pmd);
-
        pmd_clear_kernel(pmd);
-       if (shadow)
-               pmd_clear_kernel(shadow);
 }
 
 static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
        pte_val(*ptep) = _PAGE_TYPE_EMPTY;
-       if (mm->context.noexec)
-               pte_val(ptep[PTRS_PER_PTE]) = _PAGE_TYPE_EMPTY;
 }
 
 /*
@@ -903,10 +854,6 @@ static inline void ptep_invalidate(struct mm_struct *mm,
        }
        __ptep_ipte(address, ptep);
        pte_val(*ptep) = _PAGE_TYPE_EMPTY;
-       if (mm->context.noexec) {
-               __ptep_ipte(address, ptep + PTRS_PER_PTE);
-               pte_val(*(ptep + PTRS_PER_PTE)) = _PAGE_TYPE_EMPTY;
-       }
 }
 
 /*
index 29d5d6d..4fdcefc 100644 (file)
@@ -80,16 +80,11 @@ static inline void __tlb_flush_mm(struct mm_struct * mm)
         * on all cpus instead of doing a local flush if the mm
         * only ran on the local cpu.
         */
-       if (MACHINE_HAS_IDTE) {
-               if (mm->context.noexec)
-                       __tlb_flush_idte((unsigned long)
-                                        get_shadow_table(mm->pgd) |
-                                        mm->context.asce_bits);
+       if (MACHINE_HAS_IDTE)
                __tlb_flush_idte((unsigned long) mm->pgd |
                                 mm->context.asce_bits);
-               return;
-       }
-       __tlb_flush_full(mm);
+       else
+               __tlb_flush_full(mm);
 }
 
 static inline void __tlb_flush_mm_cond(struct mm_struct * mm)
index fe03c14..ef45556 100644 (file)
@@ -128,9 +128,6 @@ int main(void)
        DEFINE(__LC_KERNEL_STACK, offsetof(struct _lowcore, kernel_stack));
        DEFINE(__LC_ASYNC_STACK, offsetof(struct _lowcore, async_stack));
        DEFINE(__LC_PANIC_STACK, offsetof(struct _lowcore, panic_stack));
-       DEFINE(__LC_KERNEL_ASCE, offsetof(struct _lowcore, kernel_asce));
-       DEFINE(__LC_USER_ASCE, offsetof(struct _lowcore, user_asce));
-       DEFINE(__LC_USER_EXEC_ASCE, offsetof(struct _lowcore, user_exec_asce));
        DEFINE(__LC_INT_CLOCK, offsetof(struct _lowcore, int_clock));
        DEFINE(__LC_MCCK_CLOCK, offsetof(struct _lowcore, mcck_clock));
        DEFINE(__LC_MACHINE_FLAGS, offsetof(struct _lowcore, machine_flags));
index f5434d1..0c35dee 100644 (file)
@@ -305,8 +305,7 @@ static int set_amode_and_uaccess(unsigned long user_amode,
  */
 static int __init early_parse_switch_amode(char *p)
 {
-       if (user_mode != SECONDARY_SPACE_MODE)
-               user_mode = PRIMARY_SPACE_MODE;
+       user_mode = PRIMARY_SPACE_MODE;
        return 0;
 }
 early_param("switch_amode", early_parse_switch_amode);
@@ -315,10 +314,6 @@ static int __init early_parse_user_mode(char *p)
 {
        if (p && strcmp(p, "primary") == 0)
                user_mode = PRIMARY_SPACE_MODE;
-#ifdef CONFIG_S390_EXEC_PROTECT
-       else if (p && strcmp(p, "secondary") == 0)
-               user_mode = SECONDARY_SPACE_MODE;
-#endif
        else if (!p || strcmp(p, "home") == 0)
                user_mode = HOME_SPACE_MODE;
        else
@@ -327,31 +322,9 @@ static int __init early_parse_user_mode(char *p)
 }
 early_param("user_mode", early_parse_user_mode);
 
-#ifdef CONFIG_S390_EXEC_PROTECT
-/*
- * Enable execute protection?
- */
-static int __init early_parse_noexec(char *p)
-{
-       if (!strncmp(p, "off", 3))
-               return 0;
-       user_mode = SECONDARY_SPACE_MODE;
-       return 0;
-}
-early_param("noexec", early_parse_noexec);
-#endif /* CONFIG_S390_EXEC_PROTECT */
-
 static void setup_addressing_mode(void)
 {
-       if (user_mode == SECONDARY_SPACE_MODE) {
-               if (set_amode_and_uaccess(PSW_ASC_SECONDARY,
-                                         PSW32_ASC_SECONDARY))
-                       pr_info("Execute protection active, "
-                               "mvcos available\n");
-               else
-                       pr_info("Execute protection active, "
-                               "mvcos not available\n");
-       } else if (user_mode == PRIMARY_SPACE_MODE) {
+       if (user_mode == PRIMARY_SPACE_MODE) {
                if (set_amode_and_uaccess(PSW_ASC_PRIMARY, PSW32_ASC_PRIMARY))
                        pr_info("Address spaces switched, "
                                "mvcos available\n");
index ab98813..177745c 100644 (file)
@@ -225,33 +225,6 @@ static noinline void do_sigbus(struct pt_regs *regs, long int_code,
        force_sig_info(SIGBUS, &si, tsk);
 }
 
-#ifdef CONFIG_S390_EXEC_PROTECT
-static noinline int signal_return(struct pt_regs *regs, long int_code,
-                                 unsigned long trans_exc_code)
-{
-       u16 instruction;
-       int rc;
-
-       rc = __get_user(instruction, (u16 __user *) regs->psw.addr);
-
-       if (!rc && instruction == 0x0a77) {
-               clear_tsk_thread_flag(current, TIF_PER_TRAP);
-               if (is_compat_task())
-                       sys32_sigreturn();
-               else
-                       sys_sigreturn();
-       } else if (!rc && instruction == 0x0aad) {
-               clear_tsk_thread_flag(current, TIF_PER_TRAP);
-               if (is_compat_task())
-                       sys32_rt_sigreturn();
-               else
-                       sys_rt_sigreturn();
-       } else
-               do_sigsegv(regs, int_code, SEGV_MAPERR, trans_exc_code);
-       return 0;
-}
-#endif /* CONFIG_S390_EXEC_PROTECT */
-
 static noinline void do_fault_error(struct pt_regs *regs, long int_code,
                                    unsigned long trans_exc_code, int fault)
 {
@@ -259,13 +232,6 @@ static noinline void do_fault_error(struct pt_regs *regs, long int_code,
 
        switch (fault) {
        case VM_FAULT_BADACCESS:
-#ifdef CONFIG_S390_EXEC_PROTECT
-               if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_SECONDARY &&
-                   (trans_exc_code & 3) == 0) {
-                       signal_return(regs, int_code, trans_exc_code);
-                       break;
-               }
-#endif /* CONFIG_S390_EXEC_PROTECT */
        case VM_FAULT_BADMAP:
                /* Bad memory access. Check if it is kernel or user space. */
                if (regs->psw.mask & PSW_MASK_PSTATE) {
@@ -414,11 +380,6 @@ void __kprobes do_dat_exception(struct pt_regs *regs, long pgm_int_code,
        int access, fault;
 
        access = VM_READ | VM_EXEC | VM_WRITE;
-#ifdef CONFIG_S390_EXEC_PROTECT
-       if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_SECONDARY &&
-           (trans_exc_code & 3) == 0)
-               access = VM_EXEC;
-#endif
        fault = do_exception(regs, access, trans_exc_code);
        if (unlikely(fault))
                do_fault_error(regs, pgm_int_code & 255, trans_exc_code, fault);
index 639cd21..a4d856d 100644 (file)
@@ -13,7 +13,6 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
                                   pte_t *pteptr, pte_t pteval)
 {
        pmd_t *pmdp = (pmd_t *) pteptr;
-       pte_t shadow_pteval = pteval;
        unsigned long mask;
 
        if (!MACHINE_HAS_HPAGE) {
@@ -21,18 +20,9 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
                mask = pte_val(pteval) &
                                (_SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO);
                pte_val(pteval) = (_SEGMENT_ENTRY + __pa(pteptr)) | mask;
-               if (mm->context.noexec) {
-                       pteptr += PTRS_PER_PTE;
-                       pte_val(shadow_pteval) =
-                                       (_SEGMENT_ENTRY + __pa(pteptr)) | mask;
-               }
        }
 
        pmd_val(*pmdp) = pte_val(pteval);
-       if (mm->context.noexec) {
-               pmdp = get_shadow_table(pmdp);
-               pmd_val(*pmdp) = pte_val(shadow_pteval);
-       }
 }
 
 int arch_prepare_hugepage(struct page *page)
index e1850c2..8d43306 100644 (file)
@@ -40,7 +40,6 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 static DEFINE_PER_CPU(struct rcu_table_freelist *, rcu_table_freelist);
 
 static void __page_table_free(struct mm_struct *mm, unsigned long *table);
-static void __crst_table_free(struct mm_struct *mm, unsigned long *table);
 
 static struct rcu_table_freelist *rcu_table_freelist_get(struct mm_struct *mm)
 {
@@ -67,7 +66,7 @@ static void rcu_table_freelist_callback(struct rcu_head *head)
        while (batch->pgt_index > 0)
                __page_table_free(batch->mm, batch->table[--batch->pgt_index]);
        while (batch->crst_index < RCU_FREELIST_SIZE)
-               __crst_table_free(batch->mm, batch->table[batch->crst_index++]);
+               crst_table_free(batch->mm, batch->table[batch->crst_index++]);
        free_page((unsigned long) batch);
 }
 
@@ -125,63 +124,33 @@ static int __init parse_vmalloc(char *arg)
 }
 early_param("vmalloc", parse_vmalloc);
 
-unsigned long *crst_table_alloc(struct mm_struct *mm, int noexec)
+unsigned long *crst_table_alloc(struct mm_struct *mm)
 {
        struct page *page = alloc_pages(GFP_KERNEL, ALLOC_ORDER);
 
        if (!page)
                return NULL;
-       page->index = 0;
-       if (noexec) {
-               struct page *shadow = alloc_pages(GFP_KERNEL, ALLOC_ORDER);
-               if (!shadow) {
-                       __free_pages(page, ALLOC_ORDER);
-                       return NULL;
-               }
-               page->index = page_to_phys(shadow);
-       }
-       spin_lock_bh(&mm->context.list_lock);
-       list_add(&page->lru, &mm->context.crst_list);
-       spin_unlock_bh(&mm->context.list_lock);
        return (unsigned long *) page_to_phys(page);
 }
 
-static void __crst_table_free(struct mm_struct *mm, unsigned long *table)
-{
-       unsigned long *shadow = get_shadow_table(table);
-
-       if (shadow)
-               free_pages((unsigned long) shadow, ALLOC_ORDER);
-       free_pages((unsigned long) table, ALLOC_ORDER);
-}
-
 void crst_table_free(struct mm_struct *mm, unsigned long *table)
 {
-       struct page *page = virt_to_page(table);
-
-       spin_lock_bh(&mm->context.list_lock);
-       list_del(&page->lru);
-       spin_unlock_bh(&mm->context.list_lock);
-       __crst_table_free(mm, table);
+       free_pages((unsigned long) table, ALLOC_ORDER);
 }
 
 void crst_table_free_rcu(struct mm_struct *mm, unsigned long *table)
 {
        struct rcu_table_freelist *batch;
-       struct page *page = virt_to_page(table);
 
-       spin_lock_bh(&mm->context.list_lock);
-       list_del(&page->lru);
-       spin_unlock_bh(&mm->context.list_lock);
        if (atomic_read(&mm->mm_users) < 2 &&
            cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) {
-               __crst_table_free(mm, table);
+               crst_table_free(mm, table);
                return;
        }
        batch = rcu_table_freelist_get(mm);
        if (!batch) {
                smp_call_function(smp_sync, NULL, 1);
-               __crst_table_free(mm, table);
+               crst_table_free(mm, table);
                return;
        }
        batch->table[--batch->crst_index] = table;
@@ -197,7 +166,7 @@ int crst_table_upgrade(struct mm_struct *mm, unsigned long limit)
 
        BUG_ON(limit > (1UL << 53));
 repeat:
-       table = crst_table_alloc(mm, mm->context.noexec);
+       table = crst_table_alloc(mm);
        if (!table)
                return -ENOMEM;
        spin_lock_bh(&mm->page_table_lock);
@@ -273,7 +242,7 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
        unsigned long *table;
        unsigned long bits;
 
-       bits = (mm->context.noexec || mm->context.has_pgste) ? 3UL : 1UL;
+       bits = (mm->context.has_pgste) ? 3UL : 1UL;
        spin_lock_bh(&mm->context.list_lock);
        page = NULL;
        if (!list_empty(&mm->context.pgtable_list)) {
@@ -329,7 +298,7 @@ void page_table_free(struct mm_struct *mm, unsigned long *table)
        struct page *page;
        unsigned long bits;
 
-       bits = (mm->context.noexec || mm->context.has_pgste) ? 3UL : 1UL;
+       bits = (mm->context.has_pgste) ? 3UL : 1UL;
        bits <<= (__pa(table) & (PAGE_SIZE - 1)) / 256 / sizeof(unsigned long);
        page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
        spin_lock_bh(&mm->context.list_lock);
@@ -366,7 +335,7 @@ void page_table_free_rcu(struct mm_struct *mm, unsigned long *table)
                page_table_free(mm, table);
                return;
        }
-       bits = (mm->context.noexec || mm->context.has_pgste) ? 3UL : 1UL;
+       bits = (mm->context.has_pgste) ? 3UL : 1UL;
        bits <<= (__pa(table) & (PAGE_SIZE - 1)) / 256 / sizeof(unsigned long);
        page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
        spin_lock_bh(&mm->context.list_lock);
@@ -379,25 +348,6 @@ void page_table_free_rcu(struct mm_struct *mm, unsigned long *table)
                rcu_table_freelist_finish();
 }
 
-void disable_noexec(struct mm_struct *mm, struct task_struct *tsk)
-{
-       struct page *page;
-
-       spin_lock_bh(&mm->context.list_lock);
-       /* Free shadow region and segment tables. */
-       list_for_each_entry(page, &mm->context.crst_list, lru)
-               if (page->index) {
-                       free_pages((unsigned long) page->index, ALLOC_ORDER);
-                       page->index = 0;
-               }
-       /* "Free" second halves of page tables. */
-       list_for_each_entry(page, &mm->context.pgtable_list, lru)
-               page->flags &= ~SECOND_HALVES;
-       spin_unlock_bh(&mm->context.list_lock);
-       mm->context.noexec = 0;
-       update_mm(mm, tsk);
-}
-
 /*
  * switch on pgstes for its userspace process (for kvm)
  */