Re: [PATCH 1/2] No-exec support for ppc64
On Wed, 16 Mar 2005 17:10:57 +1100 Paul Mackerras <[EMAIL PROTECTED]> wrote: > Jake Moilanen writes: > > > It does not work w/o the sys_mprotect. It will hang in one of the first > > few binaries. > > Hmmm, what distro is this with? I just tried a kernel with the patch > below on a SLES9 install and a Debian install and it came up and ran > just fine in both cases. I'm not sure that the patch you sent is actually doing protection correctly. To test I commented out this line: > +#define elf_read_implies_exec(ex, have_pt_gnu_stack) (!(have_pt_gnu_stack)) and then ran a non-pt_gnu_stack binary which should have executed on a non-exec segment, it did not segfault. > + * > + * Note due to the way vm flags are laid out, the bits are XWR > */ > #define __P000 PAGE_NONE > -#define __P001 PAGE_READONLY_X > +#define __P001 PAGE_READONLY > #define __P010 PAGE_COPY > #define __P011 PAGE_COPY_X > #define __P100 PAGE_READONLY > #define __P101 PAGE_READONLY_X > -#define __P110 PAGE_COPY > +#define __P110 PAGE_COPY_X > #define __P111 PAGE_COPY_X I think the problem was this hunk. __P011 should be PAGE_COPY and __P100 should be PAGE_READONLY_X. Here is a patch ontop of the last patch you sent to fix this problem and take another crack at doing the sys_mprotect less hackish. Signed-off-by: Jake Moilanen <[EMAIL PROTECTED]> --- linux-2.6.11.4-paulus-moilanen/fs/binfmt_elf.c | 18 + linux-2.6.11.4-paulus-moilanen/include/asm-ppc64/pgtable.h |4 +- 2 files changed, 15 insertions(+), 7 deletions(-) diff -puN fs/binfmt_elf.c~more-nx fs/binfmt_elf.c --- linux-2.6.11.4-paulus/fs/binfmt_elf.c~more-nx 2005-03-16 09:35:28 -06:00 +++ linux-2.6.11.4-paulus-moilanen/fs/binfmt_elf.c 2005-03-16 11:03:15 -06:00 @@ -88,7 +88,7 @@ static struct linux_binfmt elf_format = #define BAD_ADDR(x)((unsigned long)(x) > TASK_SIZE) -static int set_brk(unsigned long start, unsigned long end) +static int set_brk(unsigned long start, unsigned long end, int prot) { start = ELF_PAGEALIGN(start); end = ELF_PAGEALIGN(end); @@ -99,6 +99,9 @@ static int set_brk(unsigned long start, up_write(¤t->mm->mmap_sem); if (BAD_ADDR(addr)) return addr; + + sys_mprotect(start, end-start, prot); + } current->mm->start_brk = current->mm->brk = end; return 0; @@ -529,6 +532,7 @@ static int load_elf_binary(struct linux_ struct files_struct *files; int have_pt_gnu_stack, executable_stack = EXSTACK_DEFAULT; unsigned long def_flags = 0; + int bss_prot = 0; struct { struct elfhdr elf_ex; struct elfhdr interp_elf_ex; @@ -811,7 +815,7 @@ static int load_elf_binary(struct linux_ before this one. Map anonymous pages, if needed, and clear the area. */ retval = set_brk (elf_bss + load_bias, - elf_brk + load_bias); + elf_brk + load_bias, bss_prot); if (retval) { send_sig(SIGKILL, current, 0); goto out_free_dentry; @@ -883,15 +887,19 @@ static int load_elf_binary(struct linux_ k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; - if (k > elf_bss) + if (k > elf_bss) { elf_bss = k; + bss_prot = elf_prot; + } if ((elf_ppnt->p_flags & PF_X) && end_code < k) end_code = k; if (end_data < k) end_data = k; k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz; - if (k > elf_brk) + if (k > elf_brk) { elf_brk = k; + bss_prot = elf_prot; + } } loc->elf_ex.e_entry += load_bias; @@ -907,7 +915,7 @@ static int load_elf_binary(struct linux_ * mapping in the interpreter, to make sure it doesn't wind * up getting placed where the bss needs to go. */ - retval = set_brk(elf_bss, elf_brk); + retval = set_brk(elf_bss, elf_brk, bss_prot); if (retval) { send_sig(SIGKILL, current, 0); goto out_free_dentry; diff -puN include/asm-ppc64/pgtable.h~more-nx include/asm-ppc64/pgtable.h --- linux-2.6.11.4-paulus/include/asm-ppc64/pgtable.h~more-nx 2005-03-16 09:35:44 -06:00 +++ linux-2.6.11.4-paulus-moilanen/include/asm-ppc64/pgtable.h 2005-03-16 09:35:53 -06:00 @@ -137,8 +137,8 @@ #define __P000 PAGE_NONE #define __P001 PAGE_READONLY #define __P010 PAGE_COPY -#define __P011 PAGE_COPY_X -#define __P100 PAGE_READONLY +#define __P011 PAGE_COPY +#define __P100 PAGE_READONLY_X #define __P101 PAGE
Re: [PATCH 1/2] No-exec support for ppc64
Jake Moilanen writes: > It does not work w/o the sys_mprotect. It will hang in one of the first > few binaries. Hmmm, what distro is this with? I just tried a kernel with the patch below on a SLES9 install and a Debian install and it came up and ran just fine in both cases. Paul. diff -urN linux-2.5/arch/ppc64/kernel/head.S test/arch/ppc64/kernel/head.S --- linux-2.5/arch/ppc64/kernel/head.S 2005-03-07 10:46:38.0 +1100 +++ test/arch/ppc64/kernel/head.S 2005-03-15 17:14:44.0 +1100 @@ -950,11 +950,12 @@ * accessing a userspace segment (even from the kernel). We assume * kernel addresses always have the high bit set. */ - rlwinm r4,r4,32-23,29,29 /* DSISR_STORE -> _PAGE_RW */ + rlwinm r4,r4,32-25+9,31-9,31-9 /* DSISR_STORE -> _PAGE_RW */ rotldi r0,r3,15/* Move high bit into MSR_PR posn */ orc r0,r12,r0 /* MSR_PR | ~high_bit */ rlwimi r4,r0,32-13,30,30 /* becomes _PAGE_USER access bit */ ori r4,r4,1 /* add _PAGE_PRESENT */ + rlwimi r4,r5,22+2,31-2,31-2/* Set _PAGE_EXEC if trap is 0x400 */ /* * On iSeries, we soft-disable interrupts here, then diff -urN linux-2.5/arch/ppc64/kernel/iSeries_htab.c test/arch/ppc64/kernel/iSeries_htab.c --- linux-2.5/arch/ppc64/kernel/iSeries_htab.c 2004-09-21 17:22:33.0 +1000 +++ test/arch/ppc64/kernel/iSeries_htab.c 2005-03-15 17:15:36.0 +1100 @@ -144,6 +144,10 @@ HvCallHpt_get(&hpte, slot); if ((hpte.dw0.dw0.avpn == avpn) && (hpte.dw0.dw0.v)) { + /* +* Hypervisor expects bits as NPPP, which is +* different from how they are mapped in our PP. +*/ HvCallHpt_setPp(slot, (newpp & 0x3) | ((newpp & 0x4) << 1)); iSeries_hunlock(slot); return 0; diff -urN linux-2.5/arch/ppc64/kernel/iSeries_setup.c test/arch/ppc64/kernel/iSeries_setup.c --- linux-2.5/arch/ppc64/kernel/iSeries_setup.c 2005-03-07 10:46:38.0 +1100 +++ test/arch/ppc64/kernel/iSeries_setup.c 2005-03-15 16:55:05.0 +1100 @@ -633,6 +633,10 @@ unsigned long vpn = va >> PAGE_SHIFT; unsigned long slot = HvCallHpt_findValid(&hpte, vpn); + /* Make non-kernel text non-executable */ + if (!in_kernel_text(ea)) + mode_rw |= HW_NO_EXEC; + if (hpte.dw0.dw0.v) { /* HPTE exists, so just bolt it */ HvCallHpt_setSwBits(slot, 0x10, 0); diff -urN linux-2.5/arch/ppc64/kernel/module.c test/arch/ppc64/kernel/module.c --- linux-2.5/arch/ppc64/kernel/module.c2004-05-10 21:25:58.0 +1000 +++ test/arch/ppc64/kernel/module.c 2005-03-15 16:55:05.0 +1100 @@ -102,7 +102,8 @@ { if (size == 0) return NULL; - return vmalloc(size); + + return vmalloc_exec(size); } /* Free memory returned from module_alloc */ diff -urN linux-2.5/arch/ppc64/kernel/pSeries_lpar.c test/arch/ppc64/kernel/pSeries_lpar.c --- linux-2.5/arch/ppc64/kernel/pSeries_lpar.c 2005-03-07 10:46:38.0 +1100 +++ test/arch/ppc64/kernel/pSeries_lpar.c 2005-03-15 16:55:02.0 +1100 @@ -470,7 +470,7 @@ slot = pSeries_lpar_hpte_find(vpn); BUG_ON(slot == -1); - flags = newpp & 3; + flags = newpp & 7; lpar_rc = plpar_pte_protect(flags, slot, 0); BUG_ON(lpar_rc != H_Success); diff -urN linux-2.5/arch/ppc64/mm/fault.c test/arch/ppc64/mm/fault.c --- linux-2.5/arch/ppc64/mm/fault.c 2005-01-04 10:49:20.0 +1100 +++ test/arch/ppc64/mm/fault.c 2005-03-15 17:13:05.0 +1100 @@ -91,8 +91,9 @@ struct mm_struct *mm = current->mm; siginfo_t info; unsigned long code = SEGV_MAPERR; - unsigned long is_write = error_code & 0x0200; + unsigned long is_write = error_code & DSISR_ISSTORE; unsigned long trap = TRAP(regs); + unsigned long is_exec = trap == 0x400; BUG_ON((trap == 0x380) || (trap == 0x480)); @@ -109,7 +110,7 @@ if (!user_mode(regs) && (address >= TASK_SIZE)) return SIGSEGV; - if (error_code & 0x0040) { + if (error_code & DSISR_DABRMATCH) { if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code, 11, SIGSEGV) == NOTIFY_STOP) return 0; @@ -199,16 +200,19 @@ good_area: code = SEGV_ACCERR; + if (is_exec) { + /* protection fault */ + if (error_code & DSISR_PROTFAULT) + goto bad_area; + if (!(vma->vm_flags & VM_EXEC)) + goto bad_area; /* a write */ - if (is_write) { + } else if (is_write) { if (!(vma->vm_flags & VM_WR
Re: [PATCH 1/2] No-exec support for ppc64
On Wed, 16 Mar 2005 09:18:36 +1030 Alan Modra <[EMAIL PROTECTED]> wrote: > On Tue, Mar 15, 2005 at 03:51:35PM -0600, Jake Moilanen wrote: > > I believe the problem is that the last PT_LOAD entry does not have the > > correct size, and we only mmap up to the sbss. The .sbss, .plt, and > > .bss do not get mmapped with the section. > > Huh? .sbss, .plt and .bss have no file contents, so of course p_filesz > doesn't cover them. Your right, those shouldn't be mmapped. set_brk() call is called on sbss, plt and bss. There needs to be some method to set execute permission, on those pieces as well. Currently it has no concept of what permission should be set. Jake - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/2] No-exec support for ppc64
On Tue, Mar 15, 2005 at 03:51:35PM -0600, Jake Moilanen wrote: > I believe the problem is that the last PT_LOAD entry does not have the > correct size, and we only mmap up to the sbss. The .sbss, .plt, and > .bss do not get mmapped with the section. Huh? .sbss, .plt and .bss have no file contents, so of course p_filesz doesn't cover them. -- Alan Modra IBM OzLabs - Linux Technology Centre - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/2] No-exec support for ppc64
On Tue, 15 Mar 2005 09:18:04 +1100 Paul Mackerras <[EMAIL PROTECTED]> wrote: > Jake Moilanen writes: > > > > I don't think I can push that upstream. What happens if you leave > > > that out? > > > > The bss and the plt are in the same segment, and plt obviously needs to > > be executable. > > Yes... what I was asking was "do things actually break if you leave > that out, or does the binfmt_elf loader honour the 'x' permission on > the PT_LOAD entry for the data/bss region, meaning that it all just > works anyway?" It does not work w/o the sys_mprotect. It will hang in one of the first few binaries. I believe the problem is that the last PT_LOAD entry does not have the correct size, and we only mmap up to the sbss. The .sbss, .plt, and .bss do not get mmapped with the section. Here is /bin/bash on SLES 9: Section Headers: [Nr] Name TypeAddr OffSize ES Flg Lk Inf Al [ 0] NULL 00 00 00 0 0 0 [ 1] .interp PROGBITS1174 000174 0d 00 A 0 0 1 ... ... [19] .data PROGBITS1008ca80 07ca80 001b34 00 WA 0 0 4 [20] .eh_frame PROGBITS1008e5b4 07e5b4 b4 00 A 0 0 4 [21] .got2 PROGBITS1008e668 07e668 10 00 WA 0 0 1 [22] .dynamic DYNAMIC 1008e678 07e678 e8 08 WA 6 0 4 [23] .ctorsPROGBITS1008e760 07e760 08 00 WA 0 0 4 [24] .dtorsPROGBITS1008e768 07e768 08 00 WA 0 0 4 [25] .jcr PROGBITS1008e770 07e770 04 00 WA 0 0 4 [26] .got PROGBITS1008e774 07e774 14 04 WAX 0 0 4 [27] .sdataPROGBITS1008e788 07e788 d4 00 WA 0 0 4 [28] .sbss NOBITS 1008e860 07e860 000704 00 WA 0 0 8 [29] .plt NOBITS 1008ef64 07e860 000aa4 00 WAX 0 0 4 [30] .bss NOBITS 1008fa10 07e868 0062f0 00 WA 0 0 16 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x34 0x1034 0x1034 0x00120 0x00120 R E 0x4 INTERP 0x000174 0x1174 0x1174 0xd 0xd R 0x1 [Requesting program interpreter: /lib/ld.so.1] LOAD 0x00 0x1000 0x1000 0x7ca80 0x7ca80 R E 0x1 LOAD 0x07ca80 0x1008ca80 0x1008ca80 0x01ddc 0x09280 RWE 0x1 DYNAMIC0x07e678 0x1008e678 0x1008e678 0x000e8 0x000e8 RW 0x4 NOTE 0x000184 0x1184 0x1184 0x00020 0x00020 R 0x4 NOTE 0x0001a4 0x11a4 0x11a4 0x00018 0x00018 R 0x4 GNU_EH_FRAME 0x07ca54 0x1007ca54 0x1007ca54 0x0002c 0x0002c R 0x4 STACK 0x00 0x 0x 0x0 0x0 RW 0x4 Section to Segment mapping: Segment Sections... 00 01 .interp 02 .interp .note.ABI-tag .note.SuSE .hash .dynsym .dynstr .gnu.version .g nu.version_r .rela.dyn .rela.plt .init .text text.unlikely text.hot .fini .rodat a .eh_frame_hdr 03 .data .eh_frame .got2 .dynamic .ctors .dtors .jcr .got .sdata .sbss .p lt .bss 04 .dynamic 05 .note.ABI-tag 06 .note.SuSE 07 .eh_frame_hdr 08 In the program headers section, the FileSiz for the last PT_LOAD is 0x1ddc. If we go back to the Section Headers and look at .data it is at 0x1008ca80. So the segment should end at 0x1008e85c. We round up for alignment and we get 0x1008e860 or .sbss. The sbss, plt, and bss are not mmapped. So the sys_mprotect is used to pick it up. Did I miss something to explain this? Can you think of another way to fix it? Jake - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/2] No-exec support for ppc64
Jake Moilanen writes: > > I don't think I can push that upstream. What happens if you leave > > that out? > > The bss and the plt are in the same segment, and plt obviously needs to > be executable. Yes... what I was asking was "do things actually break if you leave that out, or does the binfmt_elf loader honour the 'x' permission on the PT_LOAD entry for the data/bss region, meaning that it all just works anyway?" I did an objdump -p on some random 32-bit binaries, and they all have "rwx" flags on the data/bss segment (the second PT_LOAD entry). And when I look in /proc//maps, it seems that the heap is in fact marked executable (this is without your patch). So why do we need the hack in binfmt_elf.c? Paul. - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/2] No-exec support for ppc64
On Mon, 14 Mar 2005 21:13:36 +1100 Paul Mackerras <[EMAIL PROTECTED]> wrote: > Jake Moilanen writes: > > > diff -puN fs/binfmt_elf.c~nx-user-ppc64 fs/binfmt_elf.c > > --- linux-2.6-bk/fs/binfmt_elf.c~nx-user-ppc64 2005-03-08 16:08:54 > > -06:00 > > +++ linux-2.6-bk-moilanen/fs/binfmt_elf.c 2005-03-08 16:08:54 -06:00 > > @@ -99,6 +99,8 @@ static int set_brk(unsigned long start, > > up_write(¤t->mm->mmap_sem); > > if (BAD_ADDR(addr)) > > return addr; > > + > > + sys_mprotect(start, end-start, PROT_READ|PROT_WRITE|PROT_EXEC); > > I don't think I can push that upstream. What happens if you leave > that out? The bss and the plt are in the same segment, and plt obviously needs to be executable. Section Headers: [Nr] Name TypeAddr OffSize ES Flg Lk Inf Al [ 0] NULL 00 00 00 0 0 0 [ 1] .interp PROGBITS1154 000154 0d 00 A 0 0 1 ... ... [26] .plt NOBITS 10013c5c 003c34 000210 00 WAX 0 0 4 [27] .bss NOBITS 10013e6c 003c34 000128 00 WA 0 0 4 Segment Sections... 00 01 .interp 02 .interp .note.ABI-tag .note.SuSE .hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .text .fini .rodata 03 .data .eh_frame .got2 .dynamic .ctors .dtors .jcr .got .sdata .sbss .plt .bss 04 .dynamic 05 .note.ABI-tag 06 .note.SuSE 07 Anton mentioned that Alan was considering putting plt into a new segment. > More generally, we are making a user-visible change, even for programs > that aren't marked as having non-executable stack or heap, because we > are now enforcing that the program can't execute from mappings that > don't have PROT_EXEC. Perhaps we should enforce the requirement for > execute permission only on those programs that indicate somehow that > they can handle it? Unless a program is compiled w/ pt_gnu_stacks we will set the READ_IMPLIES_EXEC personality and those applications should still work as normal. Jake - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/2] No-exec support for ppc64
Jake Moilanen writes: > diff -puN fs/binfmt_elf.c~nx-user-ppc64 fs/binfmt_elf.c > --- linux-2.6-bk/fs/binfmt_elf.c~nx-user-ppc642005-03-08 16:08:54 > -06:00 > +++ linux-2.6-bk-moilanen/fs/binfmt_elf.c 2005-03-08 16:08:54 -06:00 > @@ -99,6 +99,8 @@ static int set_brk(unsigned long start, > up_write(¤t->mm->mmap_sem); > if (BAD_ADDR(addr)) > return addr; > + > + sys_mprotect(start, end-start, PROT_READ|PROT_WRITE|PROT_EXEC); I don't think I can push that upstream. What happens if you leave that out? More generally, we are making a user-visible change, even for programs that aren't marked as having non-executable stack or heap, because we are now enforcing that the program can't execute from mappings that don't have PROT_EXEC. Perhaps we should enforce the requirement for execute permission only on those programs that indicate somehow that they can handle it? Paul. - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/2] No-exec support for ppc64
On Wed, 9 Mar 2005 21:22:13 -0600 [EMAIL PROTECTED] (Olof Johansson) wrote: > On Tue, Mar 08, 2005 at 05:08:26PM -0600, Jake Moilanen wrote: > > No-exec base and user space support for PPC64. > > Hi, a couple of comments below. > Here's the revised user & base support for no-exec on ppc64 with Olof and Ben's comments. Signed-off-by: Jake Moilanen <[EMAIL PROTECTED]> --- linux-2.6-bk-moilanen/arch/ppc64/kernel/head.S |5 + linux-2.6-bk-moilanen/arch/ppc64/kernel/iSeries_htab.c |4 + linux-2.6-bk-moilanen/arch/ppc64/kernel/pSeries_lpar.c |2 linux-2.6-bk-moilanen/arch/ppc64/mm/fault.c| 14 +++-- linux-2.6-bk-moilanen/arch/ppc64/mm/hash_low.S | 12 ++-- linux-2.6-bk-moilanen/arch/ppc64/mm/hugetlbpage.c | 10 +++ linux-2.6-bk-moilanen/fs/binfmt_elf.c |2 linux-2.6-bk-moilanen/include/asm-ppc64/elf.h |7 ++ linux-2.6-bk-moilanen/include/asm-ppc64/page.h | 19 ++- linux-2.6-bk-moilanen/include/asm-ppc64/pgtable.h | 46 + 10 files changed, 85 insertions(+), 36 deletions(-) diff -puN arch/ppc64/kernel/head.S~nx-user-ppc64 arch/ppc64/kernel/head.S --- linux-2.6-bk/arch/ppc64/kernel/head.S~nx-user-ppc64 2005-03-08 16:08:54 -06:00 +++ linux-2.6-bk-moilanen/arch/ppc64/kernel/head.S 2005-03-08 16:08:54 -06:00 @@ -36,6 +36,7 @@ #include #include #include +#include #include #ifdef CONFIG_PPC_ISERIES @@ -950,11 +951,11 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB) * accessing a userspace segment (even from the kernel). We assume * kernel addresses always have the high bit set. */ - rlwinm r4,r4,32-23,29,29 /* DSISR_STORE -> _PAGE_RW */ + rlwinm r4,r4,32-25+9,31-9,31-9 /* DSISR_STORE -> _PAGE_RW */ rotldi r0,r3,15/* Move high bit into MSR_PR posn */ orc r0,r12,r0 /* MSR_PR | ~high_bit */ rlwimi r4,r0,32-13,30,30 /* becomes _PAGE_USER access bit */ - ori r4,r4,1 /* add _PAGE_PRESENT */ + rlwimi r4,r5,22+2,31-2,31-2/* Set _PAGE_EXEC if trap is 0x400 */ /* * On iSeries, we soft-disable interrupts here, then diff -puN arch/ppc64/kernel/iSeries_htab.c~nx-user-ppc64 arch/ppc64/kernel/iSeries_htab.c --- linux-2.6-bk/arch/ppc64/kernel/iSeries_htab.c~nx-user-ppc64 2005-03-08 16:08:54 -06:00 +++ linux-2.6-bk-moilanen/arch/ppc64/kernel/iSeries_htab.c 2005-03-08 16:08:54 -06:00 @@ -144,6 +144,10 @@ static long iSeries_hpte_updatepp(unsign HvCallHpt_get(&hpte, slot); if ((hpte.dw0.dw0.avpn == avpn) && (hpte.dw0.dw0.v)) { + /* +* Hypervisor expects bit's as NPPP, which is +* different from how they are mapped in our PP. +*/ HvCallHpt_setPp(slot, (newpp & 0x3) | ((newpp & 0x4) << 1)); iSeries_hunlock(slot); return 0; diff -puN arch/ppc64/kernel/pSeries_lpar.c~nx-user-ppc64 arch/ppc64/kernel/pSeries_lpar.c --- linux-2.6-bk/arch/ppc64/kernel/pSeries_lpar.c~nx-user-ppc64 2005-03-08 16:08:54 -06:00 +++ linux-2.6-bk-moilanen/arch/ppc64/kernel/pSeries_lpar.c 2005-03-08 16:08:54 -06:00 @@ -470,7 +470,7 @@ static void pSeries_lpar_hpte_updatebolt slot = pSeries_lpar_hpte_find(vpn); BUG_ON(slot == -1); - flags = newpp & 3; + flags = newpp & 7; lpar_rc = plpar_pte_protect(flags, slot, 0); BUG_ON(lpar_rc != H_Success); diff -puN arch/ppc64/mm/fault.c~nx-user-ppc64 arch/ppc64/mm/fault.c --- linux-2.6-bk/arch/ppc64/mm/fault.c~nx-user-ppc642005-03-08 16:08:54 -06:00 +++ linux-2.6-bk-moilanen/arch/ppc64/mm/fault.c 2005-03-10 16:14:45 -06:00 @@ -93,6 +93,7 @@ int do_page_fault(struct pt_regs *regs, unsigned long code = SEGV_MAPERR; unsigned long is_write = error_code & 0x0200; unsigned long trap = TRAP(regs); + unsigned long is_exec = trap == 0x400; BUG_ON((trap == 0x380) || (trap == 0x480)); @@ -199,16 +200,19 @@ int do_page_fault(struct pt_regs *regs, good_area: code = SEGV_ACCERR; + if (is_exec) { + /* protection fault */ + if (error_code & 0x0800) + goto bad_area; + if (!(vma->vm_flags & VM_EXEC)) + goto bad_area; /* a write */ - if (is_write) { + } else if (is_write) { if (!(vma->vm_flags & VM_WRITE)) goto bad_area; /* a read */ } else { - /* protection fault */ - if (error_code & 0x0800) - goto bad_area; - if (!(vma->vm_flags & (VM_READ | VM_EXEC))) + if (!(vma->vm_flags & VM_READ)) goto bad_area; } diff -puN arch/ppc64/mm/hash_low.S~nx-user-ppc64 arch/ppc64/mm/hash_low.S --- linux-2.6-bk/arch/
Re: [PATCH 1/2] No-exec support for ppc64
On Tue, Mar 08, 2005 at 05:08:26PM -0600, Jake Moilanen wrote: > No-exec base and user space support for PPC64. Hi, a couple of comments below. -Olof > @@ -786,6 +786,7 @@ int hash_huge_page(struct mm_struct *mm, > pte_t old_pte, new_pte; > unsigned long hpteflags, prpn; > long slot; > + int is_exec; > int err = 1; > > spin_lock(&mm->page_table_lock); > @@ -796,6 +797,10 @@ int hash_huge_page(struct mm_struct *mm, > va = (vsid << 28) | (ea & 0x0fff); > vpn = va >> HPAGE_SHIFT; > > + is_exec = access & _PAGE_EXEC; > + if (unlikely(is_exec && !(pte_val(*ptep) & _PAGE_EXEC))) > + goto out; You only use is_exec this one time, you can probably skip it and just add the mask in the if statement. > @@ -898,6 +908,7 @@ repeat: > err = 0; > > out: > + > spin_unlock(&mm->page_table_lock); Whitespace change > diff -puN include/asm-ppc64/pgtable.h~nx-user-ppc64 > include/asm-ppc64/pgtable.h > --- linux-2.6-bk/include/asm-ppc64/pgtable.h~nx-user-ppc642005-03-08 > 16:08:54 -06:00 > +++ linux-2.6-bk-moilanen/include/asm-ppc64/pgtable.h 2005-03-08 16:08:54 > -06:00 > @@ -82,14 +82,14 @@ > #define _PAGE_PRESENT0x0001 /* software: pte contains a translation > */ > #define _PAGE_USER 0x0002 /* matches one of the PP bits */ > #define _PAGE_FILE 0x0002 /* (!present only) software: pte holds file > offset */ > -#define _PAGE_RW 0x0004 /* software: user write access allowed */ > +#define _PAGE_EXEC 0x0004 /* No execute on POWER4 and newer (we invert) */ Good to see the comment there, I remember we talked about that earlier. It can be somewhat confusing. :-) > #define _PAGE_GUARDED0x0008 > #define _PAGE_COHERENT 0x0010 /* M: enforce memory coherence (SMP > systems) */ > #define _PAGE_NO_CACHE 0x0020 /* I: cache inhibit */ > #define _PAGE_WRITETHRU 0x0040 /* W: cache write-through */ > #define _PAGE_DIRTY 0x0080 /* C: page changed */ > #define _PAGE_ACCESSED 0x0100 /* R: page referenced */ > -#define _PAGE_EXEC 0x0200 /* software: i-cache coherence required */ > +#define _PAGE_RW 0x0200 /* software: user write access allowed */ > #define _PAGE_HASHPTE0x0400 /* software: pte has an associated HPTE > */ > #define _PAGE_BUSY 0x0800 /* software: PTE & hash are busy */ > #define _PAGE_SECONDARY 0x8000 /* software: HPTE is in secondary group */ > @@ -100,7 +100,7 @@ > /* PAGE_MASK gives the right answer below, but only by accident */ > /* It should be preserving the high 48 bits and then specifically */ > /* preserving _PAGE_SECONDARY | _PAGE_GROUP_IX */ > -#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | > _PAGE_HPTEFLAGS) > +#define _PAGE_CHG_MASK (_PAGE_GUARDED | _PAGE_COHERENT | _PAGE_NO_CACHE | > _PAGE_WRITETHRU | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_HPTEFLAGS | PAGE_MASK) Can you break it into 80 columns with \ ? - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/2] No-exec support for ppc64
No-exec base and user space support for PPC64. This will prohibit user space apps that a compile w/ PT_GNU_STACK from executing in segments that are non-executable. Non-PT_GNU_STACK compiled apps will work as well, but will not be able to take advantage of the no-exec feature. Signed-off-by: Jake Moilanen <[EMAIL PROTECTED]> --- linux-2.6-bk-moilanen/arch/ppc64/kernel/head.S |5 + linux-2.6-bk-moilanen/arch/ppc64/kernel/iSeries_htab.c |4 + linux-2.6-bk-moilanen/arch/ppc64/kernel/pSeries_lpar.c |2 linux-2.6-bk-moilanen/arch/ppc64/mm/fault.c| 14 +++-- linux-2.6-bk-moilanen/arch/ppc64/mm/hash_low.S | 12 ++-- linux-2.6-bk-moilanen/arch/ppc64/mm/hugetlbpage.c | 13 linux-2.6-bk-moilanen/fs/binfmt_elf.c |2 linux-2.6-bk-moilanen/include/asm-ppc64/elf.h |7 ++ linux-2.6-bk-moilanen/include/asm-ppc64/page.h | 19 ++- linux-2.6-bk-moilanen/include/asm-ppc64/pgtable.h | 45 + 10 files changed, 87 insertions(+), 36 deletions(-) diff -puN arch/ppc64/kernel/head.S~nx-user-ppc64 arch/ppc64/kernel/head.S --- linux-2.6-bk/arch/ppc64/kernel/head.S~nx-user-ppc64 2005-03-08 16:08:54 -06:00 +++ linux-2.6-bk-moilanen/arch/ppc64/kernel/head.S 2005-03-08 16:08:54 -06:00 @@ -36,6 +36,7 @@ #include #include #include +#include #include #ifdef CONFIG_PPC_ISERIES @@ -950,11 +951,11 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB) * accessing a userspace segment (even from the kernel). We assume * kernel addresses always have the high bit set. */ - rlwinm r4,r4,32-23,29,29 /* DSISR_STORE -> _PAGE_RW */ + rlwinm r4,r4,32-25+9,31-9,31-9 /* DSISR_STORE -> _PAGE_RW */ rotldi r0,r3,15/* Move high bit into MSR_PR posn */ orc r0,r12,r0 /* MSR_PR | ~high_bit */ rlwimi r4,r0,32-13,30,30 /* becomes _PAGE_USER access bit */ - ori r4,r4,1 /* add _PAGE_PRESENT */ + rlwimi r4,r5,22+2,31-2,31-2/* Set _PAGE_EXEC if trap is 0x400 */ /* * On iSeries, we soft-disable interrupts here, then diff -puN arch/ppc64/kernel/iSeries_htab.c~nx-user-ppc64 arch/ppc64/kernel/iSeries_htab.c --- linux-2.6-bk/arch/ppc64/kernel/iSeries_htab.c~nx-user-ppc64 2005-03-08 16:08:54 -06:00 +++ linux-2.6-bk-moilanen/arch/ppc64/kernel/iSeries_htab.c 2005-03-08 16:08:54 -06:00 @@ -144,6 +144,10 @@ static long iSeries_hpte_updatepp(unsign HvCallHpt_get(&hpte, slot); if ((hpte.dw0.dw0.avpn == avpn) && (hpte.dw0.dw0.v)) { + /* +* Hypervisor expects bit's as NPPP, which is +* different from how they are mapped in our PP. +*/ HvCallHpt_setPp(slot, (newpp & 0x3) | ((newpp & 0x4) << 1)); iSeries_hunlock(slot); return 0; diff -puN arch/ppc64/kernel/pSeries_lpar.c~nx-user-ppc64 arch/ppc64/kernel/pSeries_lpar.c --- linux-2.6-bk/arch/ppc64/kernel/pSeries_lpar.c~nx-user-ppc64 2005-03-08 16:08:54 -06:00 +++ linux-2.6-bk-moilanen/arch/ppc64/kernel/pSeries_lpar.c 2005-03-08 16:08:54 -06:00 @@ -470,7 +470,7 @@ static void pSeries_lpar_hpte_updatebolt slot = pSeries_lpar_hpte_find(vpn); BUG_ON(slot == -1); - flags = newpp & 3; + flags = newpp & 7; lpar_rc = plpar_pte_protect(flags, slot, 0); BUG_ON(lpar_rc != H_Success); diff -puN arch/ppc64/mm/fault.c~nx-user-ppc64 arch/ppc64/mm/fault.c --- linux-2.6-bk/arch/ppc64/mm/fault.c~nx-user-ppc642005-03-08 16:08:54 -06:00 +++ linux-2.6-bk-moilanen/arch/ppc64/mm/fault.c 2005-03-08 16:08:54 -06:00 @@ -93,6 +93,7 @@ int do_page_fault(struct pt_regs *regs, unsigned long code = SEGV_MAPERR; unsigned long is_write = error_code & 0x0200; unsigned long trap = TRAP(regs); + unsigned long is_exec = trap == 0x400; BUG_ON((trap == 0x380) || (trap == 0x480)); @@ -199,16 +200,19 @@ int do_page_fault(struct pt_regs *regs, good_area: code = SEGV_ACCERR; + if (is_exec) { + /* protection fault */ + if (error_code & 0x0800) + goto bad_area; + if (!(vma->vm_flags & VM_EXEC)) + goto bad_area; /* a write */ - if (is_write) { + } else if (is_write) { if (!(vma->vm_flags & VM_WRITE)) goto bad_area; /* a read */ } else { - /* protection fault */ - if (error_code & 0x0800) - goto bad_area; - if (!(vma->vm_flags & (VM_READ | VM_EXEC))) + if (!(vma->vm_flags & VM_READ)) goto bad_area; } diff -puN arch/ppc64/mm/hash_low.S~nx-user-ppc64 arch/ppc64/mm/hash_low.S --- linux-2.6-bk/arch/ppc64/mm/hash_low.S~nx-user-ppc64 2005-03-0