Index: head/sys/amd64/amd64/pmap.c =================================================================== --- head/sys/amd64/amd64/pmap.c +++ head/sys/amd64/amd64/pmap.c @@ -1422,22 +1422,22 @@ * * This function operates on 2M pages, since we map the kernel space that * way. - * - * Note that this doesn't currently provide any protection for modules. */ static inline pt_entry_t bootaddr_rwx(vm_paddr_t pa) { /* - * Everything in the same 2M page as the start of the kernel - * should be static. On the other hand, things in the same 2M - * page as the end of the kernel could be read-write/executable, - * as the kernel image is not guaranteed to end on a 2M boundary. + * The kernel is loaded at a 2MB-aligned address, and memory below that + * need not be executable. The .bss section is padded to a 2MB + * boundary, so memory following the kernel need not be executable + * either. Preloaded kernel modules have their mapping permissions + * fixed up by the linker. */ if (pa < trunc_2mpage(btext - KERNBASE) || - pa >= trunc_2mpage(_end - KERNBASE)) - return (X86_PG_RW); + pa >= trunc_2mpage(_end - KERNBASE)) + return (X86_PG_RW | pg_nx); + /* * The linker should ensure that the read-only and read-write * portions don't share the same 2M page, so this shouldn't @@ -1446,6 +1446,7 @@ */ if (pa >= trunc_2mpage(brwsection - KERNBASE)) return (X86_PG_RW | pg_nx); + /* * Mark any 2M page containing kernel text as read-only. Mark * other pages with read-only data as read-only and not executable. Index: head/sys/conf/ldscript.amd64 =================================================================== --- head/sys/conf/ldscript.amd64 +++ head/sys/conf/ldscript.amd64 @@ -45,12 +45,6 @@ .rela.got : { *(.rela.got) } .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } - .rel.ldata : { *(.rel.ldata .rel.ldata.* .rel.gnu.linkonce.l.*) } - .rela.ldata : { *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*) } - .rel.lbss : { *(.rel.lbss .rel.lbss.* .rel.gnu.linkonce.lb.*) } - .rela.lbss : { *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*) } - .rel.lrodata : { *(.rel.lrodata .rel.lrodata.* .rel.gnu.linkonce.lr.*) } - .rela.lrodata : { *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*) } .rel.plt : { *(.rel.plt) } .rela.plt : { *(.rela.plt) } .init : @@ -179,30 +173,10 @@ *(.dynbss) *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) - /* Align here to ensure that the .bss section occupies space up to - _end. Align after .bss to ensure correct alignment even if the - .bss section disappears because there are no input sections. - FIXME: Why do we need it? When there is no .bss section, we don't - pad the .data section. */ - . = ALIGN(. != 0 ? 64 / 8 : 1); + /* Ensure that the .bss section ends at a superpage boundary. + This way it can be mapped using non-executable large pages. */ + . = ALIGN(0x200000); } - .lbss : - { - *(.dynlbss) - *(.lbss .lbss.* .gnu.linkonce.lb.*) - *(LARGE_COMMON) - } - . = ALIGN(64 / 8); - .lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : - { - *(.lrodata .lrodata.* .gnu.linkonce.lr.*) - } - .ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : - { - *(.ldata .ldata.* .gnu.linkonce.l.*) - . = ALIGN(. != 0 ? 64 / 8 : 1); - } - . = ALIGN(64 / 8); _end = .; PROVIDE (end = .); . = DATA_SEGMENT_END (.); /* Stabs debugging sections. */