SOURCES (LINUX_2_6): linux-2.6-grsec_full.patch (NEW) - http://www...

mguevara mguevara at pld-linux.org
Tue May 1 22:27:15 CEST 2007


Author: mguevara                     Date: Tue May  1 20:27:15 2007 GMT
Module: SOURCES                       Tag: LINUX_2_6
---- Log message:
- http://www.grsecurity.net/~spender/grsecurity-2.1.10-2.6.21-200704301822.patch
- more generic name for grsecurity patch
- obsoletes grsecurity-2.1.10-2.6.20.3.patch for LINUX_2_6 (2.6.21)
- needs 3 fixes w/o vs applied - after vs there will be more fixes needed

---- Files affected:
SOURCES:
   linux-2.6-grsec_full.patch (NONE -> 1.1.2.1)  (NEW)

---- Diffs:

================================================================
Index: SOURCES/linux-2.6-grsec_full.patch
diff -u /dev/null SOURCES/linux-2.6-grsec_full.patch:1.1.2.1
--- /dev/null	Tue May  1 22:27:15 2007
+++ SOURCES/linux-2.6-grsec_full.patch	Tue May  1 22:27:10 2007
@@ -0,0 +1,31922 @@
+diff -urNp linux-2.6.21/arch/alpha/kernel/module.c linux-2.6.21/arch/alpha/kernel/module.c
+--- linux-2.6.21/arch/alpha/kernel/module.c	2007-04-25 23:08:32.000000000 -0400
++++ linux-2.6.21/arch/alpha/kernel/module.c	2007-04-30 17:07:41.000000000 -0400
+@@ -177,7 +177,7 @@ apply_relocate_add(Elf64_Shdr *sechdrs, 
+ 
+ 	/* The small sections were sorted to the end of the segment.
+ 	   The following should definitely cover them.  */
+-	gp = (u64)me->module_core + me->core_size - 0x8000;
++	gp = (u64)me->module_core_rw + me->core_size_rw - 0x8000;
+ 	got = sechdrs[me->arch.gotsecindex].sh_addr;
+ 
+ 	for (i = 0; i < n; i++) {
+diff -urNp linux-2.6.21/arch/alpha/kernel/osf_sys.c linux-2.6.21/arch/alpha/kernel/osf_sys.c
+--- linux-2.6.21/arch/alpha/kernel/osf_sys.c	2007-04-25 23:08:32.000000000 -0400
++++ linux-2.6.21/arch/alpha/kernel/osf_sys.c	2007-04-30 17:07:41.000000000 -0400
+@@ -1277,6 +1277,10 @@ arch_get_unmapped_area(struct file *filp
+ 	   merely specific addresses, but regions of memory -- perhaps
+ 	   this feature should be incorporated into all ports?  */
+ 
++#ifdef CONFIG_PAX_RANDMMAP
++	if (!(current->mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
++#endif
++
+ 	if (addr) {
+ 		addr = arch_get_unmapped_area_1 (PAGE_ALIGN(addr), len, limit);
+ 		if (addr != (unsigned long) -ENOMEM)
+@@ -1284,8 +1288,8 @@ arch_get_unmapped_area(struct file *filp
+ 	}
+ 
+ 	/* Next, try allocating at TASK_UNMAPPED_BASE.  */
+-	addr = arch_get_unmapped_area_1 (PAGE_ALIGN(TASK_UNMAPPED_BASE),
+-					 len, limit);
++	addr = arch_get_unmapped_area_1 (PAGE_ALIGN(current->mm->mmap_base), len, limit);
++
+ 	if (addr != (unsigned long) -ENOMEM)
+ 		return addr;
+ 
+diff -urNp linux-2.6.21/arch/alpha/kernel/ptrace.c linux-2.6.21/arch/alpha/kernel/ptrace.c
+--- linux-2.6.21/arch/alpha/kernel/ptrace.c	2007-04-25 23:08:32.000000000 -0400
++++ linux-2.6.21/arch/alpha/kernel/ptrace.c	2007-04-29 22:41:26.000000000 -0400
+@@ -15,6 +15,7 @@
+ #include <linux/slab.h>
+ #include <linux/security.h>
+ #include <linux/signal.h>
++#include <linux/grsecurity.h>
+ 
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -283,6 +284,9 @@ do_sys_ptrace(long request, long pid, lo
+ 		goto out_notsk;
+ 	}
+ 
++	if (gr_handle_ptrace(child, request))
++		goto out;
++
+ 	if (request == PTRACE_ATTACH) {
+ 		ret = ptrace_attach(child);
+ 		goto out;
+diff -urNp linux-2.6.21/arch/alpha/mm/fault.c linux-2.6.21/arch/alpha/mm/fault.c
+--- linux-2.6.21/arch/alpha/mm/fault.c	2007-04-25 23:08:32.000000000 -0400
++++ linux-2.6.21/arch/alpha/mm/fault.c	2007-04-30 17:07:41.000000000 -0400
+@@ -24,6 +24,7 @@
+ #include <linux/smp_lock.h>
+ #include <linux/interrupt.h>
+ #include <linux/module.h>
++#include <linux/binfmts.h>
+ 
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+@@ -55,6 +56,124 @@ __load_new_mm_context(struct mm_struct *
+ 	__reload_thread(pcb);
+ }
+ 
++#ifdef CONFIG_PAX_PAGEEXEC
++/*
++ * PaX: decide what to do with offenders (regs->pc = fault address)
++ *
++ * returns 1 when task should be killed
++ *         2 when patched PLT trampoline was detected
++ *         3 when unpatched PLT trampoline was detected
++ */
++static int pax_handle_fetch_fault(struct pt_regs *regs)
++{
++
++#ifdef CONFIG_PAX_EMUPLT
++	int err;
++
++	do { /* PaX: patched PLT emulation #1 */
++		unsigned int ldah, ldq, jmp;
++
++		err = get_user(ldah, (unsigned int *)regs->pc);
++		err |= get_user(ldq, (unsigned int *)(regs->pc+4));
++		err |= get_user(jmp, (unsigned int *)(regs->pc+8));
++
++		if (err)
++			break;
++
++		if ((ldah & 0xFFFF0000U) == 0x277B0000U &&
++		    (ldq & 0xFFFF0000U) == 0xA77B0000U &&
++		    jmp == 0x6BFB0000U)
++		{
++			unsigned long r27, addr;
++			unsigned long addrh = (ldah | 0xFFFFFFFFFFFF0000UL) << 16;
++			unsigned long addrl = ldq | 0xFFFFFFFFFFFF0000UL;
++
++			addr = regs->r27 + ((addrh ^ 0x80000000UL) + 0x80000000UL) + ((addrl ^ 0x8000UL) + 0x8000UL);
++			err = get_user(r27, (unsigned long*)addr);
++			if (err)
++				break;
++
++			regs->r27 = r27;
++			regs->pc = r27;
++			return 2;
++		}
++	} while (0);
++
++	do { /* PaX: patched PLT emulation #2 */
++		unsigned int ldah, lda, br;
++
++		err = get_user(ldah, (unsigned int *)regs->pc);
++		err |= get_user(lda, (unsigned int *)(regs->pc+4));
++		err |= get_user(br, (unsigned int *)(regs->pc+8));
++
++		if (err)
++			break;
++
++		if ((ldah & 0xFFFF0000U) == 0x277B0000U &&
++		    (lda & 0xFFFF0000U) == 0xA77B0000U &&
++		    (br & 0xFFE00000U) == 0xC3E00000U)
++		{
++			unsigned long addr = br | 0xFFFFFFFFFFE00000UL;
++			unsigned long addrh = (ldah | 0xFFFFFFFFFFFF0000UL) << 16;
++			unsigned long addrl = lda | 0xFFFFFFFFFFFF0000UL;
++
++			regs->r27 += ((addrh ^ 0x80000000UL) + 0x80000000UL) + ((addrl ^ 0x8000UL) + 0x8000UL);
++			regs->pc += 12 + (((addr ^ 0x00100000UL) + 0x00100000UL) << 2);
++			return 2;
++		}
++	} while (0);
++
++	do { /* PaX: unpatched PLT emulation */
++		unsigned int br;
++
++		err = get_user(br, (unsigned int *)regs->pc);
++
++		if (!err && (br & 0xFFE00000U) == 0xC3800000U) {
++			unsigned int br2, ldq, nop, jmp;
++			unsigned long addr = br | 0xFFFFFFFFFFE00000UL, resolver;
++
++			addr = regs->pc + 4 + (((addr ^ 0x00100000UL) + 0x00100000UL) << 2);
++			err = get_user(br2, (unsigned int *)addr);
++			err |= get_user(ldq, (unsigned int *)(addr+4));
++			err |= get_user(nop, (unsigned int *)(addr+8));
++			err |= get_user(jmp, (unsigned int *)(addr+12));
++			err |= get_user(resolver, (unsigned long *)(addr+16));
++
++			if (err)
++				break;
++
++			if (br2 == 0xC3600000U &&
++			    ldq == 0xA77B000CU &&
++			    nop == 0x47FF041FU &&
++			    jmp == 0x6B7B0000U)
++			{
++				regs->r28 = regs->pc+4;
++				regs->r27 = addr+16;
++				regs->pc = resolver;
++				return 3;
++			}
++		}
++	} while (0);
++#endif
++
++	return 1;
++}
++
++void pax_report_insns(void *pc, void *sp)
++{
++	unsigned long i;
++
++	printk(KERN_ERR "PAX: bytes at PC: ");
++	for (i = 0; i < 5; i++) {
++		unsigned int c;
++		if (get_user(c, (unsigned int*)pc+i))
++			printk("???????? ");
++		else
++			printk("%08x ", c);
++	}
++	printk("\n");
++}
++#endif
+ 
+ /*
+  * This routine handles page faults.  It determines the address,
+@@ -132,8 +251,29 @@ do_page_fault(unsigned long address, uns
+  good_area:
+ 	si_code = SEGV_ACCERR;
+ 	if (cause < 0) {
+-		if (!(vma->vm_flags & VM_EXEC))
++		if (!(vma->vm_flags & VM_EXEC)) {
++
++#ifdef CONFIG_PAX_PAGEEXEC
++			if (!(mm->pax_flags & MF_PAX_PAGEEXEC) || address != regs->pc)
++				goto bad_area;
++
++			up_read(&mm->mmap_sem);
++			switch(pax_handle_fetch_fault(regs)) {
++
++#ifdef CONFIG_PAX_EMUPLT
++			case 2:
++			case 3:
++				return;
++#endif
++
++			}
++			pax_report_fault(regs, (void*)regs->pc, (void*)rdusp());
++			do_exit(SIGKILL);
++#else
+ 			goto bad_area;
++#endif
++
++		}
+ 	} else if (!cause) {
+ 		/* Allow reads even for write-only mappings */
+ 		if (!(vma->vm_flags & (VM_READ | VM_WRITE)))
+diff -urNp linux-2.6.21/arch/arm/mm/mmap.c linux-2.6.21/arch/arm/mm/mmap.c
+--- linux-2.6.21/arch/arm/mm/mmap.c	2007-04-25 23:08:32.000000000 -0400
++++ linux-2.6.21/arch/arm/mm/mmap.c	2007-04-30 17:07:41.000000000 -0400
+@@ -61,6 +61,10 @@ arch_get_unmapped_area(struct file *filp
+ 	if (len > TASK_SIZE)
+ 		return -ENOMEM;
+ 
++#ifdef CONFIG_PAX_RANDMMAP
++	if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
++#endif
++
+ 	if (addr) {
+ 		if (do_align)
+ 			addr = COLOUR_ALIGN(addr, pgoff);
+@@ -75,7 +79,7 @@ arch_get_unmapped_area(struct file *filp
+ 	if (len > mm->cached_hole_size) {
+ 	        start_addr = addr = mm->free_area_cache;
+ 	} else {
+-	        start_addr = addr = TASK_UNMAPPED_BASE;
++	        start_addr = addr = mm->mmap_base;
+ 	        mm->cached_hole_size = 0;
+ 	}
+ 
+@@ -92,8 +96,8 @@ full_search:
+ 			 * Start a new search - just in case we missed
+ 			 * some holes.
+ 			 */
+-			if (start_addr != TASK_UNMAPPED_BASE) {
+-				start_addr = addr = TASK_UNMAPPED_BASE;
++			if (start_addr != mm->mmap_base) {
++				start_addr = addr = mm->mmap_base;
+ 				mm->cached_hole_size = 0;
+ 				goto full_search;
+ 			}
+diff -urNp linux-2.6.21/arch/avr32/mm/fault.c linux-2.6.21/arch/avr32/mm/fault.c
+--- linux-2.6.21/arch/avr32/mm/fault.c	2007-04-25 23:08:32.000000000 -0400
++++ linux-2.6.21/arch/avr32/mm/fault.c	2007-04-30 17:07:41.000000000 -0400
+@@ -68,6 +68,23 @@ static inline int notify_page_fault(enum
+ }
+ #endif
+ 
++#ifdef CONFIG_PAX_PAGEEXEC
++void pax_report_insns(void *pc, void *sp)
++{
++	unsigned long i;
++
++	printk(KERN_ERR "PAX: bytes at PC: ");
++	for (i = 0; i < 20; i++) {
++		unsigned char c;
++		if (get_user(c, (unsigned char*)pc+i))
++			printk("???????? ");
++		else
++			printk("%02x ", c);
++	}
++	printk("\n");
++}
++#endif
++
+ /*
+  * This routine handles page faults. It determines the address and the
+  * problem, and then passes it off to one of the appropriate routines.
+@@ -182,6 +199,16 @@ bad_area:
+ 	up_read(&mm->mmap_sem);
+ 
+ 	if (user_mode(regs)) {
++
++#ifdef CONFIG_PAX_PAGEEXEC
++		if (mm->pax_flags & MF_PAX_PAGEEXEC) {
++			if (ecr == ECR_PROTECTION_X || ecr == ECR_TLB_MISS_X) {
++				pax_report_fault(regs, (void*)regs->pc, (void*)regs->sp);
++				do_exit(SIGKILL);
++			}
++		}
++#endif
++
+ 		/* Hmm...we have to pass address and ecr somehow... */
+ 		/* tsk->thread.address = address;
+ 		   tsk->thread.error_code = ecr; */
+diff -urNp linux-2.6.21/arch/i386/boot/setup.S linux-2.6.21/arch/i386/boot/setup.S
+--- linux-2.6.21/arch/i386/boot/setup.S	2007-04-25 23:08:32.000000000 -0400
++++ linux-2.6.21/arch/i386/boot/setup.S	2007-04-30 17:07:41.000000000 -0400
+@@ -869,11 +869,13 @@ startup_32:
+ 	movl %eax, %gs
+ 	movl %eax, %ss
+ 
++	movl 0x00000000, %ecx
+ 	xorl %eax, %eax
+ 1:	incl %eax				# check that A20 really IS enabled
+ 	movl %eax, 0x00000000			# loop forever if it isn't
+ 	cmpl %eax, 0x00100000
+ 	je 1b
++	movl %ecx, 0x00000000
+ 
+ 	# Jump to the 32bit entry point
+ 	jmpl *(code32_start - start + (DELTA_INITSEG << 4))(%esi)
+diff -urNp linux-2.6.21/arch/i386/Kconfig linux-2.6.21/arch/i386/Kconfig
+--- linux-2.6.21/arch/i386/Kconfig	2007-04-25 23:08:32.000000000 -0400
++++ linux-2.6.21/arch/i386/Kconfig	2007-04-30 17:07:41.000000000 -0400
+@@ -892,7 +892,7 @@ config HOTPLUG_CPU
+ 
+ config COMPAT_VDSO
+ 	bool "Compat VDSO support"
+-	default y
++	default n
+ 	help
+ 	  Map the VDSO to the predictable old-style address too.
+ 	---help---
+@@ -1087,7 +1087,7 @@ config PCI
+ choice
+ 	prompt "PCI access mode"
+ 	depends on PCI && !X86_VISWS
+-	default PCI_GOANY
++	default PCI_GODIRECT
+ 	---help---
+ 	  On PCI systems, the BIOS can be used to detect the PCI devices and
+ 	  determine their configuration. However, some old PCI motherboards
+@@ -1119,7 +1119,7 @@ endchoice
+ 
+ config PCI_BIOS
+ 	bool
+-	depends on !X86_VISWS && PCI && (PCI_GOBIOS || PCI_GOANY)
++	depends on !X86_VISWS && PCI && PCI_GOBIOS
+ 	default y
+ 
+ config PCI_DIRECT
+diff -urNp linux-2.6.21/arch/i386/Kconfig.cpu linux-2.6.21/arch/i386/Kconfig.cpu
+--- linux-2.6.21/arch/i386/Kconfig.cpu	2007-04-25 23:08:32.000000000 -0400
++++ linux-2.6.21/arch/i386/Kconfig.cpu	2007-04-30 17:07:41.000000000 -0400
+@@ -262,7 +262,7 @@ config X86_PPRO_FENCE
+ 
+ config X86_F00F_BUG
+ 	bool
+-	depends on M586MMX || M586TSC || M586 || M486 || M386
++	depends on (M586MMX || M586TSC || M586 || M486 || M386) && !PAX_KERNEXEC
+ 	default y
+ 
+ config X86_WP_WORKS_OK
+@@ -292,7 +292,7 @@ config X86_CMPXCHG64
+ 
+ config X86_ALIGNMENT_16
+ 	bool
+-	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
++	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK8 || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
+ 	default y
+ 
+ config X86_GOOD_APIC
+diff -urNp linux-2.6.21/arch/i386/Kconfig.debug linux-2.6.21/arch/i386/Kconfig.debug
+--- linux-2.6.21/arch/i386/Kconfig.debug	2007-04-25 23:08:32.000000000 -0400
++++ linux-2.6.21/arch/i386/Kconfig.debug	2007-04-30 17:07:41.000000000 -0400
+@@ -48,7 +48,7 @@ config DEBUG_PAGEALLOC
+ 
+ config DEBUG_RODATA
+ 	bool "Write protect kernel read-only data structures"
+-	depends on DEBUG_KERNEL
++	depends on DEBUG_KERNEL && !PAX_KERNEXEC
+ 	help
+ 	  Mark the kernel read-only data as write-protected in the pagetables,
+ 	  in order to catch accidental (and incorrect) writes to such const
+diff -urNp linux-2.6.21/arch/i386/kernel/acpi/boot.c linux-2.6.21/arch/i386/kernel/acpi/boot.c
+--- linux-2.6.21/arch/i386/kernel/acpi/boot.c	2007-04-25 23:08:32.000000000 -0400
++++ linux-2.6.21/arch/i386/kernel/acpi/boot.c	2007-04-30 17:07:41.000000000 -0400
+@@ -1116,7 +1116,7 @@ static struct dmi_system_id __initdata a
+ 		     DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
+ 		     },
+ 	 },
+-	{}
++	{ NULL, NULL, {{0, NULL}}, NULL}
+ };
+ 
+ #endif				/* __i386__ */
+diff -urNp linux-2.6.21/arch/i386/kernel/acpi/sleep.c linux-2.6.21/arch/i386/kernel/acpi/sleep.c
+--- linux-2.6.21/arch/i386/kernel/acpi/sleep.c	2007-04-25 23:08:32.000000000 -0400
++++ linux-2.6.21/arch/i386/kernel/acpi/sleep.c	2007-04-30 17:07:41.000000000 -0400
+@@ -94,7 +94,7 @@ static __initdata struct dmi_system_id a
+ 		     DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
+ 		     },
+ 	 },
+-	{}
++	{ NULL, NULL, {{0, NULL}}, NULL}
+ };
+ 
+ static int __init acpisleep_dmi_init(void)
+diff -urNp linux-2.6.21/arch/i386/kernel/acpi/wakeup.S linux-2.6.21/arch/i386/kernel/acpi/wakeup.S
+--- linux-2.6.21/arch/i386/kernel/acpi/wakeup.S	2007-04-25 23:08:32.000000000 -0400
++++ linux-2.6.21/arch/i386/kernel/acpi/wakeup.S	2007-04-30 17:07:41.000000000 -0400
+@@ -205,13 +205,11 @@ wakeup_pmode_return:
+ 	# and restore the stack ... but you need gdt for this to work
+ 	movl	saved_context_esp, %esp
+ 
+-	movl	%cs:saved_magic, %eax
+-	cmpl	$0x12345678, %eax
++	cmpl	$0x12345678, saved_magic
+ 	jne	bogus_magic
+ 
+ 	# jump to place where we left off
+-	movl	saved_eip,%eax
+-	jmp	*%eax
++	jmp	*(saved_eip)
+ 
+ bogus_magic:
+ 	movw	$0x0e00 + 'B', 0xb8018
+diff -urNp linux-2.6.21/arch/i386/kernel/alternative.c linux-2.6.21/arch/i386/kernel/alternative.c
+--- linux-2.6.21/arch/i386/kernel/alternative.c	2007-04-25 23:08:32.000000000 -0400
++++ linux-2.6.21/arch/i386/kernel/alternative.c	2007-04-30 17:07:41.000000000 -0400
+@@ -4,6 +4,7 @@
+ #include <linux/list.h>
+ #include <asm/alternative.h>
+ #include <asm/sections.h>
++#include <asm/desc.h>
+ 
+ static int smp_alt_once      = 0;
+ static int debug_alternative = 0;
+@@ -149,12 +150,18 @@ void apply_alternatives(struct alt_instr
+ 	u8 *instr;
+ 	int diff;
+ 
++#ifdef CONFIG_PAX_KERNEXEC
++	unsigned long cr0;
++
++	pax_open_kernel(cr0);
++#endif
++
+ 	DPRINTK("%s: alt table %p -> %p\n", __FUNCTION__, start, end);
+ 	for (a = start; a < end; a++) {
+ 		BUG_ON(a->replacementlen > a->instrlen);
+ 		if (!boot_cpu_has(a->cpuid))
+ 			continue;
+-		instr = a->instr;
++		instr = a->instr + __KERNEL_TEXT_OFFSET;
+ #ifdef CONFIG_X86_64
+ 		/* vsyscall code is not mapped yet. resolve it manually. */
+ 		if (instr >= (u8 *)VSYSCALL_START && instr < (u8*)VSYSCALL_END) {
+@@ -167,6 +174,11 @@ void apply_alternatives(struct alt_instr
+ 		diff = a->instrlen - a->replacementlen;
+ 		nop_out(instr + a->replacementlen, diff);
+ 	}
++
++#ifdef CONFIG_PAX_KERNEXEC
++	pax_close_kernel(cr0);
++#endif
++
+ }
+ 
+ #ifdef CONFIG_SMP
+@@ -175,49 +187,95 @@ static void alternatives_smp_save(struct
+ {
+ 	struct alt_instr *a;
+ 
++#ifdef CONFIG_PAX_KERNEXEC
++	unsigned long cr0;
++
++	pax_open_kernel(cr0);
++#endif
++
+ 	DPRINTK("%s: alt table %p-%p\n", __FUNCTION__, start, end);
+ 	for (a = start; a < end; a++) {
+ 		memcpy(a->replacement + a->replacementlen,
+-		       a->instr,
++		       a->instr + __KERNEL_TEXT_OFFSET,
+ 		       a->instrlen);
+ 	}
++
++#ifdef CONFIG_PAX_KERNEXEC
++	pax_close_kernel(cr0);
++#endif
++
+ }
+ 
+ static void alternatives_smp_apply(struct alt_instr *start, struct alt_instr *end)
+ {
+ 	struct alt_instr *a;
+ 
++#ifdef CONFIG_PAX_KERNEXEC
++	unsigned long cr0;
++
++	pax_open_kernel(cr0);
++#endif
++
+ 	for (a = start; a < end; a++) {
+-		memcpy(a->instr,
++		memcpy(a->instr + __KERNEL_TEXT_OFFSET,
+ 		       a->replacement + a->replacementlen,
+ 		       a->instrlen);
+ 	}
++
++#ifdef CONFIG_PAX_KERNEXEC
++	pax_close_kernel(cr0);
++#endif
++
+ }
+ 
+ static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end)
+ {
+-	u8 **ptr;
++	u8 *ptr;
+ 
+-	for (ptr = start; ptr < end; ptr++) {
+-		if (*ptr < text)
++#ifdef CONFIG_PAX_KERNEXEC
++	unsigned long cr0;
++
++	pax_open_kernel(cr0);
++#endif
++
++	for (; start < end; start++) {
++		ptr = *start + __KERNEL_TEXT_OFFSET;
++		if (ptr < text)
+ 			continue;
+-		if (*ptr > text_end)
++		if (ptr > text_end)
+ 			continue;
+-		**ptr = 0xf0; /* lock prefix */
++		*ptr = 0xf0; /* lock prefix */
+ 	};
++
++#ifdef CONFIG_PAX_KERNEXEC
++	pax_close_kernel(cr0);
++#endif
++
+ }
+ 
+ static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end)
+ {
+-	u8 **ptr;
++	u8 *ptr;
++
++#ifdef CONFIG_PAX_KERNEXEC
++	unsigned long cr0;
++
++	pax_open_kernel(cr0);
++#endif
+ 
+-	for (ptr = start; ptr < end; ptr++) {
+-		if (*ptr < text)
++	for (; start < end; start++) {
++		ptr = *start + __KERNEL_TEXT_OFFSET;
++		if (ptr < text)
+ 			continue;
+-		if (*ptr > text_end)
++		if (ptr > text_end)
+ 			continue;
+-		nop_out(*ptr, 1);
++		nop_out(ptr, 1);
+ 	};
++
++#ifdef CONFIG_PAX_KERNEXEC
++	pax_close_kernel(cr0);
++#endif
++
+ }
+ 
+ struct smp_alt_module {
+@@ -344,10 +402,17 @@ void apply_paravirt(struct paravirt_patc
+ {
+ 	struct paravirt_patch *p;
+ 
++#ifdef CONFIG_PAX_KERNEXEC
++	unsigned long cr0;
++
++	pax_open_kernel(cr0);
++#endif
++
+ 	for (p = start; p < end; p++) {
+ 		unsigned int used;
++		u8 *instr = p->instr + __KERNEL_TEXT_OFFSET;
+ 
<<Diff was trimmed, longer than 597 lines>>


More information about the pld-cvs-commit mailing list