1 Index: linux-2.6.10/arch/i386/kernel/asm-offsets.c
2 ===================================================================
3 --- linux-2.6.10.orig/arch/i386/kernel/asm-offsets.c 2004-12-25 05:34:31.000000000 +0800
4 +++ linux-2.6.10/arch/i386/kernel/asm-offsets.c 2005-04-05 16:34:18.173220992 +0800
6 OFFSET(TI_preempt_count, thread_info, preempt_count);
7 OFFSET(TI_addr_limit, thread_info, addr_limit);
8 OFFSET(TI_restart_block, thread_info, restart_block);
9 + OFFSET(TI_sysenter_return, thread_info, sysenter_return);
12 OFFSET(EXEC_DOMAIN_handler, exec_domain, handler);
13 Index: linux-2.6.10/arch/i386/kernel/cpu/common.c
14 ===================================================================
15 --- linux-2.6.10.orig/arch/i386/kernel/cpu/common.c 2004-12-25 05:33:50.000000000 +0800
16 +++ linux-2.6.10/arch/i386/kernel/cpu/common.c 2005-04-05 16:34:18.174220840 +0800
19 clear_bit(X86_FEATURE_PSE, c->x86_capability);
21 + /* hack: disable SEP for non-NX cpus; SEP breaks Execshield. */
22 + #ifdef CONFIG_HIGHMEM64G
23 + if (!test_bit(X86_FEATURE_NX, c->x86_capability))
25 + clear_bit(X86_FEATURE_SEP, c->x86_capability);
27 /* If the model name is still unset, do table lookup. */
28 if ( !c->x86_model_id[0] ) {
30 Index: linux-2.6.10/arch/i386/kernel/entry.S
31 ===================================================================
32 --- linux-2.6.10.orig/arch/i386/kernel/entry.S 2005-04-05 16:29:30.192000792 +0800
33 +++ linux-2.6.10/arch/i386/kernel/entry.S 2005-04-05 16:34:18.167221904 +0800
38 - pushl $SYSENTER_RETURN
41 + * Push current_thread_info()->sysenter_return to the stack.
42 + * A tiny bit of offset fixup is necessary - 4*4 means the 4 words
43 + * pushed above, and the word being pushed now:
45 + pushl (TI_sysenter_return-THREAD_SIZE+4*4)(%esp)
47 * Load the potential sixth argument from user stack.
48 * Careful about security.
49 Index: linux-2.6.10/arch/i386/kernel/process.c
50 ===================================================================
51 --- linux-2.6.10.orig/arch/i386/kernel/process.c 2004-12-25 05:33:47.000000000 +0800
52 +++ linux-2.6.10/arch/i386/kernel/process.c 2005-04-05 16:34:18.173220992 +0800
54 #include <linux/module.h>
55 #include <linux/kallsyms.h>
56 #include <linux/ptrace.h>
57 +#include <linux/mman.h>
58 +#include <linux/random.h>
60 #include <asm/uaccess.h>
61 #include <asm/pgtable.h>
63 /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
67 + load_user_cs_desc(cpu, next_p->mm);
70 * Reload esp0, LDT and the page table pointer:
76 +unsigned long arch_align_stack(unsigned long sp)
78 + if (current->flags & PF_RELOCEXEC)
79 + sp -= ((get_random_int() % 65536) << 4);
84 +void arch_add_exec_range(struct mm_struct *mm, unsigned long limit)
86 + if (limit > mm->context.exec_limit) {
87 + mm->context.exec_limit = limit;
88 + set_user_cs(&mm->context.user_cs, limit);
89 + if (mm == current->mm)
90 + load_user_cs_desc(smp_processor_id(), mm);
94 +void arch_remove_exec_range(struct mm_struct *mm, unsigned long old_end)
96 + struct vm_area_struct *vma;
97 + unsigned long limit = 0;
99 + if (old_end == mm->context.exec_limit) {
100 + for (vma = mm->mmap; vma; vma = vma->vm_next)
101 + if ((vma->vm_flags & VM_EXEC) && (vma->vm_end > limit))
102 + limit = vma->vm_end;
104 + mm->context.exec_limit = limit;
105 + set_user_cs(&mm->context.user_cs, limit);
106 + if (mm == current->mm)
107 + load_user_cs_desc(smp_processor_id(), mm);
111 +void arch_flush_exec_range(struct mm_struct *mm)
113 + mm->context.exec_limit = 0;
114 + set_user_cs(&mm->context.user_cs, 0);
118 + * Generate random brk address between 128MB and 196MB. (if the layout
121 +void randomize_brk(unsigned long old_brk)
123 + unsigned long new_brk, range_start, range_end;
125 + range_start = 0x08000000;
126 + if (current->mm->brk >= range_start)
127 + range_start = current->mm->brk;
128 + range_end = range_start + 0x02000000;
129 + new_brk = randomize_range(range_start, range_end, 0);
131 + current->mm->brk = new_brk;
134 Index: linux-2.6.10/arch/i386/kernel/signal.c
135 ===================================================================
136 --- linux-2.6.10.orig/arch/i386/kernel/signal.c 2005-04-05 16:29:23.290050048 +0800
137 +++ linux-2.6.10/arch/i386/kernel/signal.c 2005-04-05 16:34:18.170221448 +0800
142 - restorer = &__kernel_sigreturn;
143 + restorer = current->mm->context.vdso + (long)&__kernel_sigreturn;
144 if (ka->sa.sa_flags & SA_RESTORER)
145 restorer = ka->sa.sa_restorer;
150 /* Set up to return from userspace. */
151 - restorer = &__kernel_rt_sigreturn;
152 + restorer = current->mm->context.vdso + (long)&__kernel_rt_sigreturn;
153 if (ka->sa.sa_flags & SA_RESTORER)
154 restorer = ka->sa.sa_restorer;
156 err |= __put_user(restorer, &frame->pretcode);
159 Index: linux-2.6.10/arch/i386/kernel/smp.c
160 ===================================================================
161 --- linux-2.6.10.orig/arch/i386/kernel/smp.c 2005-04-05 16:29:30.198999728 +0800
162 +++ linux-2.6.10/arch/i386/kernel/smp.c 2005-04-05 16:34:18.172221144 +0800
165 #include <asm/mtrr.h>
166 #include <asm/tlbflush.h>
167 +#include <asm/desc.h>
168 #include <mach_apic.h>
175 + if (current->active_mm)
176 + load_user_cs_desc(cpu, current->active_mm);
178 if (!cpu_isset(cpu, flush_cpumask))
180 Index: linux-2.6.10/arch/i386/kernel/sysenter.c
181 ===================================================================
182 --- linux-2.6.10.orig/arch/i386/kernel/sysenter.c 2004-12-25 05:35:40.000000000 +0800
183 +++ linux-2.6.10/arch/i386/kernel/sysenter.c 2005-04-05 16:34:18.171221296 +0800
185 #include <linux/gfp.h>
186 #include <linux/string.h>
187 #include <linux/elf.h>
188 +#include <linux/mman.h>
190 #include <asm/cpufeature.h>
193 extern const char vsyscall_int80_start, vsyscall_int80_end;
194 extern const char vsyscall_sysenter_start, vsyscall_sysenter_end;
196 +struct page *sysenter_page;
198 static int __init sysenter_setup(void)
200 void *page = (void *)get_zeroed_page(GFP_ATOMIC);
202 - __set_fixmap(FIX_VSYSCALL, __pa(page), PAGE_READONLY_EXEC);
203 + __set_fixmap(FIX_VSYSCALL, __pa(page), PAGE_KERNEL_RO);
204 + sysenter_page = virt_to_page(page);
206 if (!boot_cpu_has(X86_FEATURE_SEP)) {
209 &vsyscall_sysenter_end - &vsyscall_sysenter_start);
211 on_each_cpu(enable_sep_cpu, NULL, 1, 1);
216 __initcall(sysenter_setup);
218 +extern void SYSENTER_RETURN_OFFSET;
220 +unsigned int vdso_enabled = 0;
222 +void map_vsyscall(void)
224 + struct thread_info *ti = current_thread_info();
225 + struct vm_area_struct *vma;
226 + unsigned long addr;
228 + if (unlikely(!vdso_enabled)) {
229 + current->mm->context.vdso = NULL;
234 + * Map the vDSO (it will be randomized):
236 + down_write(¤t->mm->mmap_sem);
237 + addr = do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC, MAP_PRIVATE, 0);
238 + current->mm->context.vdso = (void *)addr;
239 + ti->sysenter_return = (void *)addr + (long)&SYSENTER_RETURN_OFFSET;
241 + vma = find_vma(current->mm, addr);
243 + pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW;
244 + get_page(sysenter_page);
245 + install_page(current->mm, vma, addr,
246 + sysenter_page, vma->vm_page_prot);
250 + up_write(¤t->mm->mmap_sem);
253 +static int __init vdso_setup(char *str)
255 + vdso_enabled = simple_strtoul(str, NULL, 0);
258 +__setup("vdso=", vdso_setup);
260 Index: linux-2.6.10/arch/i386/kernel/traps.c
261 ===================================================================
262 --- linux-2.6.10.orig/arch/i386/kernel/traps.c 2005-04-05 16:29:30.193000640 +0800
263 +++ linux-2.6.10/arch/i386/kernel/traps.c 2005-04-05 16:43:17.073295728 +0800
265 DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
266 DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
269 + * the original non-exec stack patch was written by
270 + * Solar Designer <solar at openwall.com>. Thanks!
272 fastcall void do_general_protection(struct pt_regs * regs, long error_code)
276 if (!(regs->xcs & 3))
280 + * lazy-check for CS validity on exec-shield binaries:
283 + int cpu = smp_processor_id();
284 + struct desc_struct *desc1, *desc2;
285 + struct vm_area_struct *vma;
286 + unsigned long limit = 0;
288 + spin_lock(¤t->mm->page_table_lock);
289 + for (vma = current->mm->mmap; vma; vma = vma->vm_next)
290 + if ((vma->vm_flags & VM_EXEC) && (vma->vm_end > limit))
291 + limit = vma->vm_end;
292 + spin_unlock(¤t->mm->page_table_lock);
294 + current->mm->context.exec_limit = limit;
295 + set_user_cs(¤t->mm->context.user_cs, limit);
297 + desc1 = ¤t->mm->context.user_cs;
298 + desc2 = per_cpu(cpu_gdt_table, cpu) + GDT_ENTRY_DEFAULT_USER_CS;
301 + * The CS was not in sync - reload it and retry the
302 + * instruction. If the instruction still faults then
303 + * we wont hit this branch next time around.
305 + if (desc1->a != desc2->a || desc1->b != desc2->b) {
306 + if (print_fatal_signals >= 2) {
307 + printk("#GPF fixup (%ld[seg:%lx]) at %08lx, CPU#%d.\n", error_code, error_code/8, regs->eip, smp_processor_id());
308 + printk(" exec_limit: %08lx, user_cs: %08lx/%08lx, CPU_cs: %08lx/%08lx.\n", current->mm->context.exec_limit, desc1->a, desc1->b, desc2->a, desc2->b);
310 + load_user_cs_desc(cpu, current->mm);
314 + if (print_fatal_signals) {
315 + printk("#GPF(%ld[seg:%lx]) at %08lx, CPU#%d.\n", error_code, error_code/8, regs->eip, smp_processor_id());
316 + printk(" exec_limit: %08lx, user_cs: %08lx/%08lx.\n", current->mm->context.exec_limit, current->mm->context.user_cs.a, current->mm->context.user_cs.b);
319 current->thread.error_code = error_code;
320 current->thread.trap_no = 13;
321 force_sig(SIGSEGV, current);
322 Index: linux-2.6.10/arch/i386/kernel/vsyscall.lds.S
323 ===================================================================
324 --- linux-2.6.10.orig/arch/i386/kernel/vsyscall.lds.S 2004-12-25 05:34:31.000000000 +0800
325 +++ linux-2.6.10/arch/i386/kernel/vsyscall.lds.S 2005-04-05 16:34:18.169221600 +0800
330 - . = VSYSCALL_BASE + SIZEOF_HEADERS;
331 + . = SIZEOF_HEADERS;
333 .hash : { *(.hash) } :text
334 .dynsym : { *(.dynsym) }
336 For the layouts to match, we need to skip more than enough
337 space for the dynamic symbol table et al. If this amount
338 is insufficient, ld -shared will barf. Just increase it here. */
339 - . = VSYSCALL_BASE + 0x400;
342 .text : { *(.text) } :text =0x90909090
344 Index: linux-2.6.10/arch/i386/kernel/vsyscall-sysenter.S
345 ===================================================================
346 --- linux-2.6.10.orig/arch/i386/kernel/vsyscall-sysenter.S 2004-12-25 05:34:32.000000000 +0800
347 +++ linux-2.6.10/arch/i386/kernel/vsyscall-sysenter.S 2005-04-05 16:34:18.170221448 +0800
349 /* 7: align return point with nop's to make disassembly easier */
352 - /* 14: System call restart point is here! (SYSENTER_RETURN - 2) */
353 + /* 14: System call restart point is here! (SYSENTER_RETURN_OFFSET-2) */
355 /* 16: System call normal return point is here! */
356 - .globl SYSENTER_RETURN /* Symbol used by entry.S. */
358 + .globl SYSENTER_RETURN_OFFSET /* Symbol used by sysenter.c */
359 +SYSENTER_RETURN_OFFSET:
363 Index: linux-2.6.10/arch/i386/mm/init.c
364 ===================================================================
365 --- linux-2.6.10.orig/arch/i386/mm/init.c 2005-04-05 16:29:28.016331544 +0800
366 +++ linux-2.6.10/arch/i386/mm/init.c 2005-04-05 16:34:18.167221904 +0800
370 printk("NX (Execute Disable) protection: active\n");
374 + printk("Using x86 segment limits to approximate NX protection\n");
378 Index: linux-2.6.10/arch/i386/mm/mmap.c
379 ===================================================================
380 --- linux-2.6.10.orig/arch/i386/mm/mmap.c 2004-12-25 05:34:33.000000000 +0800
381 +++ linux-2.6.10/arch/i386/mm/mmap.c 2005-04-05 16:43:44.365146736 +0800
384 #include <linux/personality.h>
385 #include <linux/mm.h>
386 +#include <linux/random.h>
389 * Top of mmap area (just below the process stack).
391 static inline unsigned long mmap_base(struct mm_struct *mm)
393 unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur;
394 + unsigned long random_factor = 0;
396 + if (current->flags & PF_RELOCEXEC)
397 + random_factor = get_random_int() % (1024*1024);
401 else if (gap > MAX_GAP)
404 - return TASK_SIZE - (gap & PAGE_MASK);
405 + return PAGE_ALIGN(TASK_SIZE - gap - random_factor);
410 * Fall back to the standard layout if the personality
411 * bit is set, or if the expected stack growth is unlimited:
413 - if (sysctl_legacy_va_layout ||
414 + if ((exec_shield != 2) && (sysctl_legacy_va_layout ||
415 (current->personality & ADDR_COMPAT_LAYOUT) ||
416 - current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) {
417 + current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY)){
418 mm->mmap_base = TASK_UNMAPPED_BASE;
419 mm->get_unmapped_area = arch_get_unmapped_area;
420 mm->unmap_area = arch_unmap_area;
422 mm->mmap_base = mmap_base(mm);
423 mm->get_unmapped_area = arch_get_unmapped_area_topdown;
424 + if (current->flags & PF_RELOCEXEC)
425 + mm->get_unmapped_exec_area = arch_get_unmapped_exec_area;
426 mm->unmap_area = arch_unmap_area_topdown;
429 Index: linux-2.6.10/arch/ia64/ia32/binfmt_elf32.c
430 ===================================================================
431 --- linux-2.6.10.orig/arch/ia64/ia32/binfmt_elf32.c 2004-12-25 05:35:28.000000000 +0800
432 +++ linux-2.6.10/arch/ia64/ia32/binfmt_elf32.c 2005-04-05 16:34:18.174220840 +0800
437 -elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type)
438 +elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type, unsigned long unused)
440 unsigned long pgoff = (eppnt->p_vaddr) & ~IA32_PAGE_MASK;
442 Index: linux-2.6.10/arch/x86_64/ia32/ia32_binfmt.c
443 ===================================================================
444 --- linux-2.6.10.orig/arch/x86_64/ia32/ia32_binfmt.c 2004-12-25 05:33:49.000000000 +0800
445 +++ linux-2.6.10/arch/x86_64/ia32/ia32_binfmt.c 2005-04-05 16:34:18.175220688 +0800
450 -elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type)
451 +elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type, unsigned long unused)
453 unsigned long map_addr;
454 struct task_struct *me = current;
455 Index: linux-2.6.10/drivers/char/random.c
456 ===================================================================
457 --- linux-2.6.10.orig/drivers/char/random.c 2005-04-05 16:29:24.214909448 +0800
458 +++ linux-2.6.10/drivers/char/random.c 2005-04-05 16:34:18.197217344 +0800
459 @@ -2469,3 +2469,37 @@
462 #endif /* CONFIG_INET */
465 + * Get a random word:
467 +unsigned int get_random_int(void)
469 + unsigned int val = 0;
471 + if (!exec_shield_randomize)
474 +#ifdef CONFIG_X86_HAS_TSC
477 + val += current->pid + jiffies + (int)val;
480 + * Use IP's RNG. It suits our purpose perfectly: it re-keys itself
481 + * every second, from the entropy pool (and thus creates a limited
482 + * drain on it), and uses halfMD4Transform within the second. We
483 + * also spice it with the TSC (if available), jiffies, PID and the
486 + return secure_ip_id(val);
489 +unsigned long randomize_range(unsigned long start, unsigned long end, unsigned long len)
491 + unsigned long range = end - len - start;
492 + if (end <= start + len)
494 + return PAGE_ALIGN(get_random_int() % range + start);
497 Index: linux-2.6.10/fs/binfmt_elf.c
498 ===================================================================
499 --- linux-2.6.10.orig/fs/binfmt_elf.c 2005-04-05 16:29:24.353888320 +0800
500 +++ linux-2.6.10/fs/binfmt_elf.c 2005-04-05 16:39:25.042569760 +0800
502 unsigned long reloc_func_desc = 0;
503 char passed_fileno[6];
504 struct files_struct *files;
505 - int have_pt_gnu_stack, executable_stack = EXSTACK_DEFAULT;
506 + int have_pt_gnu_stack, relocexec, executable_stack = EXSTACK_DEFAULT;
507 unsigned long def_flags = 0;
509 struct elfhdr elf_ex;
512 have_pt_gnu_stack = (i < loc->elf_ex.e_phnum);
516 + if (current->personality == PER_LINUX)
517 + switch (exec_shield) {
519 + if (executable_stack == EXSTACK_DISABLE_X) {
520 + current->flags |= PF_RELOCEXEC;
521 + relocexec = PF_RELOCEXEC;
526 + executable_stack = EXSTACK_DISABLE_X;
527 + current->flags |= PF_RELOCEXEC;
528 + relocexec = PF_RELOCEXEC;
532 /* Some simple consistency checks for the interpreter */
533 if (elf_interpreter) {
534 interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
537 goto out_free_dentry;
539 + current->flags |= relocexec;
542 + * Turn off the CS limit completely if exec-shield disabled or
545 + if (!exec_shield || executable_stack != EXSTACK_DISABLE_X || nx_enabled)
546 + arch_add_exec_range(current->mm, -1);
548 /* Discard our unneeded old files struct */
552 /* Do this immediately, since STACK_TOP as used in setup_arg_pages
553 may depend on the personality. */
554 SET_PERSONALITY(loc->elf_ex, ibcs2_interpreter);
555 - if (elf_read_implies_exec(loc->elf_ex, have_pt_gnu_stack))
556 + if (exec_shield != 2 &&
557 + elf_read_implies_exec(loc->elf_ex, have_pt_gnu_stack))
558 current->personality |= READ_IMPLIES_EXEC;
560 arch_pick_mmap_layout(current->mm);
563 set_binfmt(&elf_format);
566 + * Map the vsyscall trampoline. This address is then passed via
569 +#ifdef __HAVE_ARCH_VSYSCALL
574 current->flags &= ~PF_FORKNOEXEC;
575 create_elf_tables(bprm, &loc->elf_ex, (interpreter_type == INTERPRETER_AOUT),
576 Index: linux-2.6.10/fs/exec.c
577 ===================================================================
578 --- linux-2.6.10.orig/fs/exec.c 2005-04-05 16:29:30.270988784 +0800
579 +++ linux-2.6.10/fs/exec.c 2005-04-05 16:34:18.177220384 +0800
581 while (i < MAX_ARG_PAGES)
582 bprm->page[i++] = NULL;
584 +#ifdef __HAVE_ARCH_ALIGN_STACK
585 + stack_base = arch_align_stack(STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE);
586 + stack_base = PAGE_ALIGN(stack_base);
588 stack_base = STACK_TOP - MAX_ARG_PAGES * PAGE_SIZE;
590 bprm->p += stack_base;
591 mm->arg_start = bprm->p;
592 arg_size = STACK_TOP - (PAGE_MASK & (unsigned long) mm->arg_start);
595 set_task_comm(current, tcomm);
597 + current->flags &= ~PF_RELOCEXEC;
600 if (bprm->e_uid != current->euid || bprm->e_gid != current->egid ||
601 Index: linux-2.6.10/fs/proc/array.c
602 ===================================================================
603 --- linux-2.6.10.orig/fs/proc/array.c 2004-12-25 05:35:00.000000000 +0800
604 +++ linux-2.6.10/fs/proc/array.c 2005-04-05 16:34:18.180219928 +0800
606 ppid = pid_alive(task) ? task->group_leader->real_parent->tgid : 0;
607 read_unlock(&tasklist_lock);
609 - if (!whole || num_threads<2)
610 - wchan = get_wchan(task);
611 + if (!whole || num_threads<2) {
613 + if (current->uid == task->uid || current->euid == task->uid ||
614 + capable(CAP_SYS_NICE))
615 + wchan = get_wchan(task);
618 min_flt = task->min_flt;
619 maj_flt = task->maj_flt;
620 Index: linux-2.6.10/fs/proc/base.c
621 ===================================================================
622 --- linux-2.6.10.orig/fs/proc/base.c 2005-04-05 16:29:24.361887104 +0800
623 +++ linux-2.6.10/fs/proc/base.c 2005-04-05 16:34:18.179220080 +0800
625 E(PROC_TGID_CMDLINE, "cmdline", S_IFREG|S_IRUGO),
626 E(PROC_TGID_STAT, "stat", S_IFREG|S_IRUGO),
627 E(PROC_TGID_STATM, "statm", S_IFREG|S_IRUGO),
628 - E(PROC_TGID_MAPS, "maps", S_IFREG|S_IRUGO),
629 + E(PROC_TGID_MAPS, "maps", S_IFREG|S_IRUSR),
630 E(PROC_TGID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR),
631 E(PROC_TGID_CWD, "cwd", S_IFLNK|S_IRWXUGO),
632 E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO),
634 E(PROC_TID_CMDLINE, "cmdline", S_IFREG|S_IRUGO),
635 E(PROC_TID_STAT, "stat", S_IFREG|S_IRUGO),
636 E(PROC_TID_STATM, "statm", S_IFREG|S_IRUGO),
637 - E(PROC_TID_MAPS, "maps", S_IFREG|S_IRUGO),
638 + E(PROC_TID_MAPS, "maps", S_IFREG|S_IRUSR),
639 E(PROC_TID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR),
640 E(PROC_TID_CWD, "cwd", S_IFLNK|S_IRWXUGO),
641 E(PROC_TID_ROOT, "root", S_IFLNK|S_IRWXUGO),
642 Index: linux-2.6.10/fs/proc/task_mmu.c
643 ===================================================================
644 --- linux-2.6.10.orig/fs/proc/task_mmu.c 2004-12-25 05:34:01.000000000 +0800
645 +++ linux-2.6.10/fs/proc/task_mmu.c 2005-04-05 16:41:11.796340720 +0800
647 buffer += sprintf(buffer,
650 - "VmRSS:\t%8lu kB\n"
651 - "VmData:\t%8lu kB\n"
652 - "VmStk:\t%8lu kB\n"
653 - "VmExe:\t%8lu kB\n"
654 - "VmLib:\t%8lu kB\n"
655 - "VmPTE:\t%8lu kB\n",
656 - (mm->total_vm - mm->reserved_vm) << (PAGE_SHIFT-10),
657 - mm->locked_vm << (PAGE_SHIFT-10),
658 - mm->rss << (PAGE_SHIFT-10),
659 - data << (PAGE_SHIFT-10),
660 - mm->stack_vm << (PAGE_SHIFT-10), text, lib,
661 - (PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10);
663 + "VmData:\t%8lu kB\n"
664 + "VmStk:\t%8lu kB\n"
665 + "VmExe:\t%8lu kB\n"
666 + "VmLib:\t%8lu kB\n"
667 + "VmPTE:\t%8lu kB\n"
668 + "StaBrk:\t%08lx kB\n"
670 + "StaStk:\t%08lx kB\n" ,
671 + (mm->total_vm - mm->reserved_vm) << (PAGE_SHIFT-10),
672 + mm->locked_vm << (PAGE_SHIFT-10),
673 + mm->rss << (PAGE_SHIFT-10),
674 + data << (PAGE_SHIFT-10),
675 + mm->stack_vm << (PAGE_SHIFT-10), text, lib,
676 + (PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10,
677 + mm->start_brk, mm->brk, mm->start_stack);
680 + buffer += sprintf(buffer,
681 + "ExecLim:\t%08lx\n", mm->context.exec_limit);
686 unsigned long task_vsize(struct mm_struct *mm)
689 static int show_map(struct seq_file *m, void *v)
692 + struct task_struct *task = m->private;
694 struct vm_area_struct *map = v;
695 struct file *file = map->vm_file;
696 int flags = map->vm_flags;
699 flags & VM_READ ? 'r' : '-',
700 flags & VM_WRITE ? 'w' : '-',
701 - flags & VM_EXEC ? 'x' : '-',
705 + (map->vm_start < task->mm->context.exec_limit))
709 flags & VM_MAYSHARE ? 's' : 'p',
710 map->vm_pgoff << PAGE_SHIFT,
711 MAJOR(dev), MINOR(dev), ino, &len);
712 Index: linux-2.6.10/include/asm-i386/desc.h
713 ===================================================================
714 --- linux-2.6.10.orig/include/asm-i386/desc.h 2005-04-05 16:29:30.129010368 +0800
715 +++ linux-2.6.10/include/asm-i386/desc.h 2005-04-05 16:34:18.188218712 +0800
717 extern int __modify_ldt(struct mm_struct * mm, int func, void __user *ptr,
718 unsigned long bytecount);
720 +static inline void set_user_cs(struct desc_struct *desc, unsigned long limit)
722 + limit = (limit - 1) / PAGE_SIZE;
723 + desc->a = limit & 0xffff;
724 + desc->b = (limit & 0xf0000) | 0x00c0fb00;
727 +#define load_user_cs_desc(cpu, mm) \
728 + per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_DEFAULT_USER_CS] = (mm)->context.user_cs
730 +extern void arch_add_exec_range(struct mm_struct *mm, unsigned long limit);
731 +extern void arch_remove_exec_range(struct mm_struct *mm, unsigned long limit);
732 +extern void arch_flush_exec_range(struct mm_struct *mm);
734 #endif /* !__ASSEMBLY__ */
737 Index: linux-2.6.10/include/asm-i386/elf.h
738 ===================================================================
739 --- linux-2.6.10.orig/include/asm-i386/elf.h 2004-12-25 05:35:15.000000000 +0800
740 +++ linux-2.6.10/include/asm-i386/elf.h 2005-04-05 16:34:18.188218712 +0800
742 #include <asm/user.h>
743 #include <asm/processor.h>
744 #include <asm/system.h> /* for savesegment */
745 +#include <asm/desc.h>
747 #include <linux/utsname.h>
749 @@ -133,15 +134,22 @@
750 #define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs)
751 #define ELF_CORE_COPY_XFPREGS(tsk, elf_xfpregs) dump_task_extended_fpu(tsk, elf_xfpregs)
753 -#define VSYSCALL_BASE (__fix_to_virt(FIX_VSYSCALL))
754 -#define VSYSCALL_EHDR ((const struct elfhdr *) VSYSCALL_BASE)
755 -#define VSYSCALL_ENTRY ((unsigned long) &__kernel_vsyscall)
756 extern void __kernel_vsyscall;
757 +#define VSYSCALL_BASE ((unsigned long)current->mm->context.vdso)
758 +#define VSYSCALL_EHDR ((const struct elfhdr *) VSYSCALL_BASE)
759 +#define VSYSCALL_OFFSET ((unsigned long) &__kernel_vsyscall)
760 +#define VSYSCALL_ENTRY (VSYSCALL_BASE + VSYSCALL_OFFSET)
762 -#define ARCH_DLINFO \
764 - NEW_AUX_ENT(AT_SYSINFO, VSYSCALL_ENTRY); \
765 - NEW_AUX_ENT(AT_SYSINFO_EHDR, VSYSCALL_BASE); \
766 +/* kernel-internal fixmap address: */
767 +#define __VSYSCALL_BASE (__fix_to_virt(FIX_VSYSCALL))
768 +#define __VSYSCALL_EHDR ((const struct elfhdr *) __VSYSCALL_BASE)
770 +#define ARCH_DLINFO \
772 + if (VSYSCALL_BASE) { \
773 + NEW_AUX_ENT(AT_SYSINFO, VSYSCALL_ENTRY); \
774 + NEW_AUX_ENT(AT_SYSINFO_EHDR, VSYSCALL_BASE); \
779 @@ -152,15 +160,15 @@
780 * Dumping its extra ELF program headers includes all the other information
781 * a debugger needs to easily find how the vsyscall DSO was being used.
783 -#define ELF_CORE_EXTRA_PHDRS (VSYSCALL_EHDR->e_phnum)
784 +#define ELF_CORE_EXTRA_PHDRS (__VSYSCALL_EHDR->e_phnum)
785 #define ELF_CORE_WRITE_EXTRA_PHDRS \
787 const struct elf_phdr *const vsyscall_phdrs = \
788 - (const struct elf_phdr *) (VSYSCALL_BASE \
789 - + VSYSCALL_EHDR->e_phoff); \
790 + (const struct elf_phdr *) (__VSYSCALL_BASE \
791 + + __VSYSCALL_EHDR->e_phoff); \
794 - for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) { \
795 + for (i = 0; i < __VSYSCALL_EHDR->e_phnum; ++i) { \
796 struct elf_phdr phdr = vsyscall_phdrs[i]; \
797 if (phdr.p_type == PT_LOAD) { \
799 @@ -178,10 +186,10 @@
800 #define ELF_CORE_WRITE_EXTRA_DATA \
802 const struct elf_phdr *const vsyscall_phdrs = \
803 - (const struct elf_phdr *) (VSYSCALL_BASE \
804 - + VSYSCALL_EHDR->e_phoff); \
805 + (const struct elf_phdr *) (__VSYSCALL_BASE \
806 + + __VSYSCALL_EHDR->e_phoff); \
808 - for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) { \
809 + for (i = 0; i < __VSYSCALL_EHDR->e_phnum; ++i) { \
810 if (vsyscall_phdrs[i].p_type == PT_LOAD) \
811 DUMP_WRITE((void *) vsyscall_phdrs[i].p_vaddr, \
812 PAGE_ALIGN(vsyscall_phdrs[i].p_memsz)); \
817 +#define __HAVE_ARCH_RANDOMIZE_BRK
818 +extern void randomize_brk(unsigned long old_brk);
820 +#define __HAVE_ARCH_VSYSCALL
821 +extern void map_vsyscall(void);
824 Index: linux-2.6.10/include/asm-i386/mmu.h
825 ===================================================================
826 --- linux-2.6.10.orig/include/asm-i386/mmu.h 2004-12-25 05:35:00.000000000 +0800
827 +++ linux-2.6.10/include/asm-i386/mmu.h 2005-04-05 16:34:18.189218560 +0800
829 * we put the segment information here.
831 * cpu_vm_mask is used to optimize ldt flushing.
833 + * exec_limit is used to track the range PROT_EXEC
838 struct semaphore sem;
840 + struct desc_struct user_cs;
841 + unsigned long exec_limit;
846 Index: linux-2.6.10/include/asm-i386/pgalloc.h
847 ===================================================================
848 --- linux-2.6.10.orig/include/asm-i386/pgalloc.h 2004-12-25 05:33:50.000000000 +0800
849 +++ linux-2.6.10/include/asm-i386/pgalloc.h 2005-04-05 16:34:18.190218408 +0800
851 #include <linux/config.h>
852 #include <asm/processor.h>
853 #include <asm/fixmap.h>
854 +#include <asm/desc.h>
855 #include <linux/threads.h>
856 #include <linux/mm.h> /* for struct page */
858 Index: linux-2.6.10/include/asm-i386/processor.h
859 ===================================================================
860 --- linux-2.6.10.orig/include/asm-i386/processor.h 2004-12-25 05:33:50.000000000 +0800
861 +++ linux-2.6.10/include/asm-i386/processor.h 2005-04-05 16:34:18.189218560 +0800
863 /* This decides where the kernel will search for a free chunk of vm
864 * space during mmap's.
866 -#define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3))
867 +#define TASK_UNMAPPED_BASE PAGE_ALIGN(TASK_SIZE/3)
869 +#define __HAVE_ARCH_ALIGN_STACK
870 +extern unsigned long arch_align_stack(unsigned long sp);
872 #define HAVE_ARCH_PICK_MMAP_LAYOUT
875 regs->xcs = __USER_CS; \
876 regs->eip = new_eip; \
877 regs->esp = new_esp; \
878 + load_user_cs_desc(smp_processor_id(), current->mm); \
881 /* Forward declaration, a strange C thing */
882 Index: linux-2.6.10/include/asm-i386/thread_info.h
883 ===================================================================
884 --- linux-2.6.10.orig/include/asm-i386/thread_info.h 2005-04-05 16:29:30.127010672 +0800
885 +++ linux-2.6.10/include/asm-i386/thread_info.h 2005-04-05 16:34:18.190218408 +0800
887 0-0xBFFFFFFF for user-thead
888 0-0xFFFFFFFF for kernel-thread
890 + void *sysenter_return;
891 struct restart_block restart_block;
893 unsigned long previous_esp; /* ESP of the previous stack in case
894 Index: linux-2.6.10/include/asm-ia64/pgalloc.h
895 ===================================================================
896 --- linux-2.6.10.orig/include/asm-ia64/pgalloc.h 2004-12-25 05:33:49.000000000 +0800
897 +++ linux-2.6.10/include/asm-ia64/pgalloc.h 2005-04-05 16:34:18.184219320 +0800
899 #include <asm/mmu_context.h>
900 #include <asm/processor.h>
902 +#define arch_add_exec_range(mm, limit) do { ; } while (0)
903 +#define arch_flush_exec_range(mm) do { ; } while (0)
904 +#define arch_remove_exec_range(mm, limit) do { ; } while (0)
907 * Very stupidly, we used to get new pgd's and pmd's, init their contents
908 * to point to the NULL versions of the next level page table, later on
909 Index: linux-2.6.10/include/asm-ppc64/pgalloc.h
910 ===================================================================
911 --- linux-2.6.10.orig/include/asm-ppc64/pgalloc.h 2004-12-25 05:33:50.000000000 +0800
912 +++ linux-2.6.10/include/asm-ppc64/pgalloc.h 2005-04-05 16:34:18.185219168 +0800
915 extern kmem_cache_t *zero_cache;
917 +/* Dummy functions since we don't support execshield on ppc */
918 +#define arch_add_exec_range(mm, limit) do { ; } while (0)
919 +#define arch_flush_exec_range(mm) do { ; } while (0)
920 +#define arch_remove_exec_range(mm, limit) do { ; } while (0)
923 * This program is free software; you can redistribute it and/or
924 * modify it under the terms of the GNU General Public License
925 Index: linux-2.6.10/include/asm-ppc/pgalloc.h
926 ===================================================================
927 --- linux-2.6.10.orig/include/asm-ppc/pgalloc.h 2004-12-25 05:33:48.000000000 +0800
928 +++ linux-2.6.10/include/asm-ppc/pgalloc.h 2005-04-05 16:34:18.183219472 +0800
931 #define check_pgt_cache() do { } while (0)
933 +#define arch_add_exec_range(mm, limit) do { ; } while (0)
934 +#define arch_flush_exec_range(mm) do { ; } while (0)
935 +#define arch_remove_exec_range(mm, limit) do { ; } while (0)
938 #endif /* _PPC_PGALLOC_H */
939 #endif /* __KERNEL__ */
940 Index: linux-2.6.10/include/asm-s390/pgalloc.h
941 ===================================================================
942 --- linux-2.6.10.orig/include/asm-s390/pgalloc.h 2004-12-25 05:35:00.000000000 +0800
943 +++ linux-2.6.10/include/asm-s390/pgalloc.h 2005-04-05 16:34:18.186219016 +0800
945 #include <linux/gfp.h>
946 #include <linux/mm.h>
948 +#define arch_add_exec_range(mm, limit) do { ; } while (0)
949 +#define arch_flush_exec_range(mm) do { ; } while (0)
950 +#define arch_remove_exec_range(mm, limit) do { ; } while (0)
952 #define check_pgt_cache() do {} while (0)
954 extern void diag10(unsigned long addr);
955 Index: linux-2.6.10/include/asm-sparc64/pgalloc.h
956 ===================================================================
957 --- linux-2.6.10.orig/include/asm-sparc64/pgalloc.h 2004-12-25 05:35:29.000000000 +0800
958 +++ linux-2.6.10/include/asm-sparc64/pgalloc.h 2005-04-05 16:34:18.187218864 +0800
960 #define pgd_free(pgd) free_pgd_fast(pgd)
961 #define pgd_alloc(mm) get_pgd_fast()
963 +#define arch_add_exec_range(mm, limit) do { ; } while (0)
964 +#define arch_flush_exec_range(mm) do { ; } while (0)
965 +#define arch_remove_exec_range(mm, limit) do { ; } while (0)
967 #endif /* _SPARC64_PGALLOC_H */
968 Index: linux-2.6.10/include/asm-sparc/pgalloc.h
969 ===================================================================
970 --- linux-2.6.10.orig/include/asm-sparc/pgalloc.h 2004-12-25 05:33:51.000000000 +0800
971 +++ linux-2.6.10/include/asm-sparc/pgalloc.h 2005-04-05 16:34:18.191218256 +0800
973 #define pte_free(pte) BTFIXUP_CALL(pte_free)(pte)
974 #define __pte_free_tlb(tlb, pte) pte_free(pte)
976 +#define arch_add_exec_range(mm, limit) do { ; } while (0)
977 +#define arch_flush_exec_range(mm) do { ; } while (0)
978 +#define arch_remove_exec_range(mm, limit) do { ; } while (0)
980 #endif /* _SPARC_PGALLOC_H */
981 Index: linux-2.6.10/include/asm-x86_64/pgalloc.h
982 ===================================================================
983 --- linux-2.6.10.orig/include/asm-x86_64/pgalloc.h 2004-12-25 05:34:57.000000000 +0800
984 +++ linux-2.6.10/include/asm-x86_64/pgalloc.h 2005-04-05 16:34:18.185219168 +0800
986 #include <linux/threads.h>
987 #include <linux/mm.h>
989 +#define arch_add_exec_range(mm, limit) do { ; } while (0)
990 +#define arch_flush_exec_range(mm) do { ; } while (0)
991 +#define arch_remove_exec_range(mm, limit) do { ; } while (0)
994 #define pmd_populate_kernel(mm, pmd, pte) \
995 set_pmd(pmd, __pmd(_PAGE_TABLE | __pa(pte)))
996 #define pgd_populate(mm, pgd, pmd) \
997 Index: linux-2.6.10/include/linux/mm.h
998 ===================================================================
999 --- linux-2.6.10.orig/include/linux/mm.h 2005-04-05 16:29:30.250991824 +0800
1000 +++ linux-2.6.10/include/linux/mm.h 2005-04-05 16:43:44.366146584 +0800
1001 @@ -685,7 +685,14 @@
1002 unsigned long addr, unsigned long len, pgoff_t pgoff);
1003 extern void exit_mmap(struct mm_struct *);
1005 -extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
1006 +extern unsigned long get_unmapped_area_prot(struct file *, unsigned long, unsigned long, unsigned long, unsigned long, int);
1009 +static inline unsigned long get_unmapped_area(struct file * file, unsigned long addr,
1010 + unsigned long len, unsigned long pgoff, unsigned long flags)
1012 + return get_unmapped_area_prot(file, addr, len, pgoff, flags, 0);
1015 extern unsigned long __do_mmap_pgoff(struct mm_struct *mm, struct file *file,
1016 unsigned long addr, unsigned long len,
1017 Index: linux-2.6.10/include/linux/random.h
1018 ===================================================================
1019 --- linux-2.6.10.orig/include/linux/random.h 2004-12-25 05:35:40.000000000 +0800
1020 +++ linux-2.6.10/include/linux/random.h 2005-04-05 16:34:18.183219472 +0800
1022 extern struct file_operations random_fops, urandom_fops;
1025 +unsigned int get_random_int(void);
1026 +unsigned long randomize_range(unsigned long start, unsigned long end, unsigned long len);
1028 #endif /* __KERNEL___ */
1030 #endif /* _LINUX_RANDOM_H */
1031 Index: linux-2.6.10/include/linux/resource.h
1032 ===================================================================
1033 --- linux-2.6.10.orig/include/linux/resource.h 2004-12-25 05:33:52.000000000 +0800
1034 +++ linux-2.6.10/include/linux/resource.h 2005-04-05 16:34:18.182219624 +0800
1037 * Limit the stack by to some sane default: root can always
1038 * increase this limit if needed.. 8MB seems reasonable.
1040 + * (2MB more to cover randomization effects.)
1042 -#define _STK_LIM (8*1024*1024)
1043 +#define _STK_LIM (10*1024*1024)
1044 +#define EXEC_STACK_BIAS (2*1024*1024)
1047 * GPG wants 32kB of mlocked memory, to make sure pass phrases
1048 Index: linux-2.6.10/include/linux/sched.h
1049 ===================================================================
1050 --- linux-2.6.10.orig/include/linux/sched.h 2005-04-05 16:29:27.971338384 +0800
1051 +++ linux-2.6.10/include/linux/sched.h 2005-04-05 16:43:44.367146432 +0800
1053 #include <linux/topology.h>
1056 +extern int exec_shield;
1057 +extern int exec_shield_randomize;
1058 +extern int print_fatal_signals;
1062 @@ -193,6 +196,10 @@
1063 extern unsigned long
1064 arch_get_unmapped_area(struct file *, unsigned long, unsigned long,
1065 unsigned long, unsigned long);
1067 +extern unsigned long
1068 +arch_get_unmapped_exec_area(struct file *, unsigned long, unsigned long,
1069 + unsigned long, unsigned long);
1070 extern unsigned long
1071 arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
1072 unsigned long len, unsigned long pgoff,
1074 unsigned long (*get_unmapped_area) (struct file *filp,
1075 unsigned long addr, unsigned long len,
1076 unsigned long pgoff, unsigned long flags);
1077 + unsigned long (*get_unmapped_exec_area) (struct file *filp,
1078 + unsigned long addr, unsigned long len,
1079 + unsigned long pgoff, unsigned long flags);
1080 void (*unmap_area) (struct vm_area_struct *area);
1081 unsigned long mmap_base; /* base of mmap area */
1082 unsigned long free_area_cache; /* first hole */
1084 #define PF_LESS_THROTTLE 0x00100000 /* Throttle me less: I clean memory */
1085 #define PF_SYNCWRITE 0x00200000 /* I am doing a sync write */
1086 #define PF_BORROWED_MM 0x00400000 /* I am a kthread doing use_mm */
1087 +#define PF_RELOCEXEC 0x00800000 /* relocate shared libraries */
1090 extern int set_cpus_allowed(task_t *p, cpumask_t new_mask);
1091 Index: linux-2.6.10/kernel/signal.c
1092 ===================================================================
1093 --- linux-2.6.10.orig/kernel/signal.c 2005-04-05 16:29:27.951341424 +0800
1094 +++ linux-2.6.10/kernel/signal.c 2005-04-05 16:43:17.077295120 +0800
1095 @@ -1608,6 +1608,35 @@
1096 spin_unlock_irq(¤t->sighand->siglock);
1099 +int print_fatal_signals = 0;
1101 +static void print_fatal_signal(struct pt_regs *regs, int signr)
1104 + unsigned char insn;
1105 + printk("%s/%d: potentially unexpected fatal signal %d.\n",
1106 + current->comm, current->pid, signr);
1109 + printk("code at %08lx: ", regs->eip);
1110 + for (i = 0; i < 16; i++) {
1111 + __get_user(insn, (unsigned char *)(regs->eip + i));
1112 + printk("%02x ", insn);
1119 +static int __init setup_print_fatal_signals(char *str)
1121 + get_option (&str, &print_fatal_signals);
1126 +__setup("print-fatal-signals=", setup_print_fatal_signals);
1128 #ifndef HAVE_ARCH_GET_SIGNAL_TO_DELIVER
1131 @@ -1808,6 +1837,12 @@
1133 break; /* will return 0 */
1135 + if ((signr == SIGSEGV) && print_fatal_signals) {
1136 + spin_unlock_irq(¤t->sighand->siglock);
1137 + print_fatal_signal(regs, signr);
1138 + spin_lock_irq(¤t->sighand->siglock);
1141 if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
1142 ptrace_signal_deliver(regs, cookie);
1144 @@ -1904,6 +1939,8 @@
1145 * Anything else is fatal, maybe with a core dump.
1147 current->flags |= PF_SIGNALED;
1148 + if (print_fatal_signals)
1149 + print_fatal_signal(regs, signr);
1150 if (sig_kernel_coredump(signr)) {
1152 * If it was able to dump core, this kills all
1153 Index: linux-2.6.10/kernel/sysctl.c
1154 ===================================================================
1155 --- linux-2.6.10.orig/kernel/sysctl.c 2005-04-05 16:29:24.394882088 +0800
1156 +++ linux-2.6.10/kernel/sysctl.c 2005-04-05 16:43:17.078294968 +0800
1158 void __user *, size_t *, loff_t *);
1161 +extern unsigned int vdso_enabled;
1163 +int exec_shield = 1;
1164 +int exec_shield_randomize = 1;
1166 +static int __init setup_exec_shield(char *str)
1168 + get_option (&str, &exec_shield);
1173 +__setup("exec-shield=", setup_exec_shield);
1175 +static int __init setup_exec_shield_randomize(char *str)
1177 + get_option (&str, &exec_shield_randomize);
1182 +__setup("exec-shield-randomize=", setup_exec_shield_randomize);
1184 /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
1185 static int maxolduid = 65535;
1186 static int minolduid;
1187 @@ -276,6 +299,40 @@
1188 .proc_handler = &proc_dointvec,
1191 + .ctl_name = KERN_PANIC,
1192 + .procname = "exec-shield",
1193 + .data = &exec_shield,
1194 + .maxlen = sizeof(int),
1196 + .proc_handler = &proc_dointvec,
1199 + .ctl_name = KERN_PANIC,
1200 + .procname = "exec-shield-randomize",
1201 + .data = &exec_shield_randomize,
1202 + .maxlen = sizeof(int),
1204 + .proc_handler = &proc_dointvec,
1207 + .ctl_name = KERN_PANIC,
1208 + .procname = "print-fatal-signals",
1209 + .data = &print_fatal_signals,
1210 + .maxlen = sizeof(int),
1212 + .proc_handler = &proc_dointvec,
1216 + .ctl_name = KERN_PANIC,
1217 + .procname = "vdso",
1218 + .data = &vdso_enabled,
1219 + .maxlen = sizeof(int),
1221 + .proc_handler = &proc_dointvec,
1225 .ctl_name = KERN_CORE_USES_PID,
1226 .procname = "core_uses_pid",
1227 .data = &core_uses_pid,
1228 Index: linux-2.6.10/mm/mmap.c
1229 ===================================================================
1230 --- linux-2.6.10.orig/mm/mmap.c 2005-04-05 16:29:30.134009608 +0800
1231 +++ linux-2.6.10/mm/mmap.c 2005-04-05 16:43:44.369146128 +0800
1233 #include <linux/mount.h>
1234 #include <linux/mempolicy.h>
1235 #include <linux/rmap.h>
1236 +#include <linux/random.h>
1238 #include <asm/uaccess.h>
1239 #include <asm/cacheflush.h>
1241 __vma_link_list(struct mm_struct *mm, struct vm_area_struct *vma,
1242 struct vm_area_struct *prev, struct rb_node *rb_parent)
1244 + if (vma->vm_flags & VM_EXEC)
1245 + arch_add_exec_range(mm, vma->vm_end);
1247 vma->vm_next = prev->vm_next;
1248 prev->vm_next = vma;
1250 rb_erase(&vma->vm_rb, &mm->mm_rb);
1251 if (mm->mmap_cache == vma)
1252 mm->mmap_cache = prev;
1253 + if (vma->vm_flags & VM_EXEC)
1254 + arch_remove_exec_range(mm, vma->vm_end);
1259 } else /* cases 2, 5, 7 */
1260 vma_adjust(prev, prev->vm_start,
1261 end, prev->vm_pgoff, NULL);
1262 + if (prev->vm_flags & VM_EXEC)
1263 + arch_add_exec_range(mm, prev->vm_end);
1268 /* Obtain the address to map to. we verify (or select) it and ensure
1269 * that it represents a valid section of the address space.
1271 - addr = get_unmapped_area(file, addr, len, pgoff, flags);
1272 + addr = get_unmapped_area_prot(file, addr, len, pgoff, flags, prot & PROT_EXEC);
1273 if (addr & ~PAGE_MASK)
1276 @@ -1207,9 +1214,10 @@
1277 area->vm_mm->free_area_cache = area->vm_end;
1282 -get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
1283 - unsigned long pgoff, unsigned long flags)
1284 +get_unmapped_area_prot(struct file *file, unsigned long addr, unsigned long len,
1285 + unsigned long pgoff, unsigned long flags, int exec)
1287 if (flags & MAP_FIXED) {
1289 @@ -1241,10 +1249,80 @@
1290 return file->f_op->get_unmapped_area(file, addr, len,
1293 - return current->mm->get_unmapped_area(file, addr, len, pgoff, flags);
1294 + if (exec && current->mm->get_unmapped_exec_area)
1295 + return current->mm->get_unmapped_exec_area(file, addr, len, pgoff, flags);
1297 + return current->mm->get_unmapped_area(file, addr, len, pgoff, flags);
1300 -EXPORT_SYMBOL(get_unmapped_area);
1301 +EXPORT_SYMBOL(get_unmapped_area_prot);
1304 +#define SHLIB_BASE 0x00111000
1306 +unsigned long arch_get_unmapped_exec_area(struct file *filp, unsigned long addr0,
1307 + unsigned long len0, unsigned long pgoff, unsigned long flags)
1309 + unsigned long addr = addr0, len = len0;
1310 + struct mm_struct *mm = current->mm;
1311 + struct vm_area_struct *vma;
1312 + unsigned long tmp;
1314 + if (len > TASK_SIZE)
1317 + if (!addr && !(flags & MAP_FIXED))
1318 + addr = randomize_range(SHLIB_BASE, 0x01000000, len);
1321 + addr = PAGE_ALIGN(addr);
1322 + vma = find_vma(mm, addr);
1323 + if (TASK_SIZE - len >= addr &&
1324 + (!vma || addr + len <= vma->vm_start)) {
1329 + addr = SHLIB_BASE;
1331 + for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
1332 + /* At this point: (!vma || addr < vma->vm_end). */
1333 + if (TASK_SIZE - len < addr) {
1336 + if (!vma || addr + len <= vma->vm_start) {
1338 + * Must not let a PROT_EXEC mapping get into the
1341 + if (addr + len > mm->brk)
1345 + * Up until the brk area we randomize addresses
1346 + * as much as possible:
1348 + if (addr >= 0x01000000) {
1349 + tmp = randomize_range(0x01000000, mm->brk, len);
1350 + vma = find_vma(mm, tmp);
1351 + if (TASK_SIZE - len >= tmp &&
1352 + (!vma || tmp + len <= vma->vm_start))
1356 + * Ok, randomization didnt work out - return
1357 + * the result of the linear search:
1361 + addr = vma->vm_end;
1365 + return current->mm->get_unmapped_area(filp, addr0, len0, pgoff, flags);
1370 /* Look up the first VMA which satisfies addr < vm_end, NULL if none. */
1371 struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr)
1372 @@ -1319,6 +1397,14 @@
1373 return prev ? prev->vm_next : vma;
1377 +static int over_stack_limit(unsigned long sz)
1379 + if (sz < EXEC_STACK_BIAS)
1381 + return (sz - EXEC_STACK_BIAS) > current->signal->rlim[RLIMIT_STACK].rlim_cur;
1384 #ifdef CONFIG_STACK_GROWSUP
1386 * vma is the first one with address > vma->vm_end. Have to extend vma.
1387 @@ -1358,7 +1444,7 @@
1391 - if (address - vma->vm_start > current->signal->rlim[RLIMIT_STACK].rlim_cur ||
1392 + if (over_stack_limit(address - vma->vm_start) ||
1393 ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) >
1394 current->signal->rlim[RLIMIT_AS].rlim_cur) {
1395 anon_vma_unlock(vma);
1396 @@ -1432,7 +1518,7 @@
1400 - if (vma->vm_end - address > current->signal->rlim[RLIMIT_STACK].rlim_cur ||
1401 + if (over_stack_limit(vma->vm_end - address) ||
1402 ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) >
1403 current->signal->rlim[RLIMIT_AS].rlim_cur) {
1404 anon_vma_unlock(vma);
1405 @@ -1668,10 +1754,14 @@
1406 if (new->vm_ops && new->vm_ops->open)
1407 new->vm_ops->open(new);
1411 + unsigned long old_end = vma->vm_end;
1413 vma_adjust(vma, addr, vma->vm_end, vma->vm_pgoff +
1414 ((addr - new->vm_start) >> PAGE_SHIFT), new);
1416 + if (vma->vm_flags & VM_EXEC)
1417 + arch_remove_exec_range(mm, old_end);
1419 vma_adjust(vma, vma->vm_start, addr, vma->vm_pgoff, new);
1422 @@ -1890,6 +1980,7 @@
1426 + arch_flush_exec_range(mm);
1428 spin_unlock(&mm->page_table_lock);
1430 Index: linux-2.6.10/mm/mprotect.c
1431 ===================================================================
1432 --- linux-2.6.10.orig/mm/mprotect.c 2005-04-05 16:29:30.135009456 +0800
1433 +++ linux-2.6.10/mm/mprotect.c 2005-04-05 16:34:18.193217952 +0800
1436 #include <asm/uaccess.h>
1437 #include <asm/pgtable.h>
1438 +#include <asm/pgalloc.h>
1439 #include <asm/cacheflush.h>
1440 #include <asm/tlbflush.h>
1443 struct mm_struct * mm = vma->vm_mm;
1444 unsigned long oldflags = vma->vm_flags;
1445 long nrpages = (end - start) >> PAGE_SHIFT;
1446 - unsigned long charged = 0;
1447 + unsigned long charged = 0, old_end = vma->vm_end;
1451 @@ -179,8 +180,11 @@
1452 * vm_flags and vm_page_prot are protected by the mmap_sem
1453 * held in write mode.
1455 + oldflags = vma->vm_flags;
1456 vma->vm_flags = newflags;
1457 vma->vm_page_prot = newprot;
1458 + if (oldflags & VM_EXEC)
1459 + arch_remove_exec_range(current->mm, old_end);
1460 change_protection(vma, start, end, newprot);
1461 __vm_stat_account(mm, oldflags, vma->vm_file, -nrpages);
1462 __vm_stat_account(mm, newflags, vma->vm_file, nrpages);
1463 Index: linux-2.6.10/mm/mremap.c
1464 ===================================================================
1465 --- linux-2.6.10.orig/mm/mremap.c 2004-12-25 05:34:58.000000000 +0800
1466 +++ linux-2.6.10/mm/mremap.c 2005-04-05 16:43:44.370145976 +0800
1468 if (vma->vm_flags & VM_MAYSHARE)
1469 map_flags |= MAP_SHARED;
1471 - new_addr = get_unmapped_area(vma->vm_file, 0, new_len,
1472 - vma->vm_pgoff, map_flags);
1473 + new_addr = get_unmapped_area_prot(vma->vm_file, 0, new_len,
1474 + vma->vm_pgoff, map_flags, vma->vm_flags & VM_EXEC);
1476 if (new_addr & ~PAGE_MASK)