diff -urPX nopatch linux-2.4.21/Documentation/Configure.help linux/Documentation/Configure.help --- linux-2.4.21/Documentation/Configure.help Fri Jun 13 14:51:29 2003 +++ linux/Documentation/Configure.help Sun Jun 15 15:56:24 2003 @@ -26648,6 +26652,31 @@ IPMI Watchdog Timer CONFIG_IPMI_WATCHDOG This enables the IPMI watchdog timer. + +Non-executable user stack area +CONFIG_HARDEN_STACK + Most buffer overflow exploits are based on overwriting a function's + return address on the stack to point to some arbitrary code, which is + also put onto the stack. If the stack area is non-executable, buffer + overflow vulnerabilities become harder to exploit. However, a few + programs depend on the stack being executable, and might stop working + unless you also enable GCC trampolines autodetection and emulation + below, or enable the stack area execution permission for every such + program separately using chstk.c. If you don't know what all this is + about, or don't care about security that much, say N. + +Autodetect and emulate GCC trampolines +CONFIG_HARDEN_STACK_SMART + GCC generates trampolines on the stack to correctly pass control to + nested functions when calling from outside. Normally, this requires + the stack being executable. When this option is enabled, the kernel + will trap faults resulting from trampoline calls, and will emulate the + trampolines. However, in some cases this autodetection can be fooled + in a buffer overflow exploit, so, if you've got no programs that use + GCC trampolines, it is more secure to disable this option. If you're + too lazy to find that out, answer Y. Note: if you're using glibc 2.0 + (and not libc 5 or glibc 2.1+), you have to say Y here, or the system + won't even boot. # # A couple of things I keep forgetting: diff -urPX nopatch linux-2.4.21/arch/i386/config.in linux/arch/i386/config.in --- linux-2.4.21/arch/i386/config.in Fri Jun 13 14:51:29 2003 +++ linux/arch/i386/config.in Sun Jun 15 15:51:12 2003 @@ -467,6 +470,16 @@ source drivers/usb/Config.in source net/bluetooth/Config.in + +mainmenu_option next_comment +comment 'Security options' + +bool 'Non-executable user stack area' CONFIG_HARDEN_STACK +if [ "$CONFIG_HARDEN_STACK" = "y" ]; then + bool ' Autodetect and emulate GCC trampolines' CONFIG_HARDEN_STACK_SMART +fi + +endmenu mainmenu_option next_comment comment 'Kernel hacking' diff -urPX nopatch linux-2.4.21/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S --- linux-2.4.21/arch/i386/kernel/head.S Fri Jun 13 14:51:29 2003 +++ linux/arch/i386/kernel/head.S Sun Jun 15 15:51:12 2003 @@ -433,7 +433,11 @@ .quad 0x0000000000000000 /* not used */ .quad 0x00cf9a000000ffff /* 0x10 kernel 4GB code at 0x00000000 */ .quad 0x00cf92000000ffff /* 0x18 kernel 4GB data at 0x00000000 */ +#ifdef CONFIG_HARDEN_STACK + .quad 0x00cbfa000000f7ff /* 0x23 user 3GB-8MB code at 0 */ +#else .quad 0x00cffa000000ffff /* 0x23 user 4GB code at 0x00000000 */ +#endif .quad 0x00cff2000000ffff /* 0x2b user 4GB data at 0x00000000 */ .quad 0x0000000000000000 /* not used */ .quad 0x0000000000000000 /* not used */ diff -urPX nopatch linux-2.4.21/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c --- linux-2.4.21/arch/i386/kernel/signal.c Sat Aug 3 00:39:42 2002 +++ linux/arch/i386/kernel/signal.c Sun Jun 15 15:51:12 2003 @@ -421,11 +421,15 @@ if (ka->sa.sa_flags & SA_RESTORER) { err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); } else { +#ifdef CONFIG_HARDEN_STACK + err |= __put_user(MAGIC_SIGRETURN, &frame->pretcode); +#else err |= __put_user(frame->retcode, &frame->pretcode); /* This is popl %eax ; movl $,%eax ; int $0x80 */ err |= __put_user(0xb858, (short *)(frame->retcode+0)); err |= __put_user(__NR_sigreturn, (int *)(frame->retcode+2)); err |= __put_user(0x80cd, (short *)(frame->retcode+6)); +#endif } if (err) @@ -496,11 +500,15 @@ if (ka->sa.sa_flags & SA_RESTORER) { err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); } else { +#ifdef CONFIG_HARDEN_STACK + err |= __put_user(MAGIC_RT_SIGRETURN, &frame->pretcode); +#else err |= __put_user(frame->retcode, &frame->pretcode); /* This is movl $,%eax ; int $0x80 */ err |= __put_user(0xb8, (char *)(frame->retcode+0)); err |= __put_user(__NR_rt_sigreturn, (int *)(frame->retcode+1)); err |= __put_user(0x80cd, (short *)(frame->retcode+5)); +#endif } if (err) diff -urPX nopatch linux-2.4.21/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c --- linux-2.4.21/arch/i386/kernel/traps.c Thu Nov 28 23:53:09 2002 +++ linux/arch/i386/kernel/traps.c Sun Jun 15 16:29:52 2003 @@ -397,13 +397,202 @@ DO_ERROR(12, SIGBUS, "stack segment", stack_segment) DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, get_cr2()) +#if defined(CONFIG_HARDEN_STACK) && defined(CONFIG_HARDEN_STACK_SMART) +/* + * These two functions aren't performance critical (trampolines are + * extremely rare and slow even without emulation). + */ +static unsigned long *get_reg(struct pt_regs *regs, unsigned char regnum) +{ + switch (regnum) { + case 0: return ®s->eax; + case 1: return ®s->ecx; + case 2: return ®s->edx; + case 3: return ®s->ebx; + case 4: return ®s->esp; + case 5: return ®s->ebp; + case 6: return ®s->esi; + case 7: return ®s->edi; + } + + return NULL; +} + +static unsigned long get_modrm(struct pt_regs *regs, int *err) +{ + unsigned char modrm, sib; + signed char rel8; + unsigned long rel32; + int size, regnum, scale; + unsigned long index, base, addr, value; + + *err |= __get_user(modrm, (unsigned char *)(regs->eip + 1)); + size = 2; + regnum = modrm & 7; + addr = *get_reg(regs, regnum); + if (regnum == 4 && (modrm & 0xC0) != 0xC0) { + *err |= __get_user(sib, (unsigned char *)(regs->eip + 2)); + size = 3; + scale = sib >> 6; + index = *get_reg(regs, (sib >> 3) & 7); + base = *get_reg(regs, sib & 7); + addr = base + (index << scale); + } + + switch (modrm & 0xC0) { + case 0x00: + if (regnum == 5) { + *err |= __get_user(addr, + (unsigned long *)(regs->eip + 2)); + size = 6; + } + *err |= get_user(value, (unsigned long *)addr); + break; + + case 0x40: + *err |= __get_user(rel8, (signed char *)(regs->eip + size)); + size++; + addr += rel8; + *err |= get_user(value, (unsigned long *)addr); + break; + + case 0x80: + *err |= __get_user(rel32, (unsigned long *)(regs->eip + size)); + size += 4; + addr += rel32; + *err |= get_user(value, (unsigned long *)addr); + break; + + case 0xC0: + default: + value = addr; + } + + if (*err) return 0; + regs->eip += size; + return value; +} +#endif + asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) { +#ifdef CONFIG_HARDEN_STACK + unsigned long addr; + unsigned char insn; +#ifdef CONFIG_HARDEN_STACK_SMART + int err, count; +#endif +#endif + if (regs->eflags & VM_MASK) goto gp_in_vm86; if (!(regs->xcs & 3)) goto gp_in_kernel; + +#ifdef CONFIG_HARDEN_STACK + if ((regs->xcs & 0xFFFF) != __USER_CS || + __get_user(insn, (unsigned char *)regs->eip)) + goto gp_in_user; + +/* Check if it was a return instruction */ + if (insn == 0xC3) { + if (get_user(addr, (unsigned long *)regs->esp)) + goto gp_in_user; + +/* Check if it was return from a signal handler */ + if ((addr & 0xFFFFFFFE) == MAGIC_SIGRETURN) { +/* Call sys_sigreturn() or sys_rt_sigreturn() to restore the context */ + regs->esp += 8; + __asm__("movl %3,%%esi\n\t" + "subl %1,%%esp\n\t" + "movl %2,%%ecx\n\t" + "movl %%esp,%%edi\n\t" + "rep; movsl\n\t" + "testl $1,%4\n\t" + "jnz 1f\n\t" + "call sys_sigreturn\n\t" + "leal %3,%%edi\n\t" + "jmp 2f\n\t" + "1:\n\t" + "call sys_rt_sigreturn\n\t" + "leal %3,%%edi\n\t" + "2:\n\t" + "addl %1,%%edi\n\t" + "movl %%esp,%%esi\n\t" + "movl %2,%%ecx\n\t" + "movl (%%edi),%%edi\n\t" + "rep; movsl\n\t" + "movl %%esi,%%esp" + : +/* %eax is returned separately */ + "=a" (regs->eax) + : + "i" (sizeof(*regs)), + "i" (sizeof(*regs) >> 2), + "m" (regs), + "r" (addr) + : + "cx", "dx", "si", "di", "cc", "memory"); + return; + } + +/* + * Check if we're returning to the stack area, which is only likely to happen + * when attempting to exploit a buffer overflow. + */ + if (addr >= PAGE_OFFSET - _STK_LIM && addr < PAGE_OFFSET) + security_alert("return onto stack running as " + "UID %d, EUID %d, process %s:%d", + "returns onto stack", + current->uid, current->euid, + current->comm, current->pid); + } + +#ifdef CONFIG_HARDEN_STACK_SMART +/* Check if it could have been a trampoline call */ + else + if (insn == 0xFF && + !__get_user(insn, (unsigned char *)(regs->eip + 1)) && + (insn & 0x38) == 0x10 && insn != 0xD4) { /* call mod r/m */ +/* First, emulate the call */ + err = 0; + addr = get_modrm(regs, &err); + if (!err) { + regs->esp -= 4; + err = put_user(regs->eip, (unsigned long *)regs->esp); + regs->eip = addr; + } +/* Then, start emulating the trampoline itself */ + count = 0; + while (!err && !__get_user(insn, (unsigned char *)regs->eip++)) + if ((insn & 0xF8) == 0xB8) { /* movl imm32,%reg */ +/* We only have 8 GP registers, no reason to initialize one twice */ + if (count++ >= 8) break; + err |= __get_user(addr, (unsigned long *)regs->eip); + regs->eip += 4; + *get_reg(regs, insn & 7) = addr; + } else + if (insn == 0xFF) { + err |= __get_user(insn, (unsigned char *)regs->eip); + if ((insn & 0xF8) == 0xE0) { /* jmp *%reg */ + regs->eip = *get_reg(regs, insn & 7); + if (err) break; else return; + } + break; + } else + if (insn == 0xE9) { /* jmp rel32 */ + err |= __get_user(addr, (unsigned long *)regs->eip); + if (err) break; + regs->eip += 4 + addr; + return; + } else + break; + } +#endif + +gp_in_user: +#endif current->thread.error_code = error_code; current->thread.trap_no = 13; diff -urPX nopatch linux-2.4.21/arch/ia64/ia32/sys_ia32.c linux/arch/ia64/ia32/sys_ia32.c --- linux-2.4.21/arch/ia64/ia32/sys_ia32.c Fri Jun 13 14:51:29 2003 +++ linux/arch/ia64/ia32/sys_ia32.c Sun Jun 15 17:21:08 2003 @@ -109,6 +109,8 @@ *ap++ = (char *) A(addr); arg += sizeof(unsigned int); n++; + if (n >= (MAX_ARG_PAGES * PAGE_SIZE) / sizeof(char *)) + return -E2BIG; } while (addr); return n - 1; } diff -urPX nopatch linux-2.4.21/arch/mips64/kernel/linux32.c linux/arch/mips64/kernel/linux32.c --- linux-2.4.21/arch/mips64/kernel/linux32.c Thu Nov 28 23:53:10 2002 +++ linux/arch/mips64/kernel/linux32.c Sun Jun 15 17:23:00 2003 @@ -434,6 +450,8 @@ return ret; arg += sizeof(unsigned int); n++; + if (n >= (MAX_ARG_PAGES * PAGE_SIZE) / sizeof(char *)) + return -E2BIG; } while (ptr); return n - 1; diff -urPX nopatch linux-2.4.21/arch/x86_64/ia32/sys_ia32.c linux/arch/x86_64/ia32/sys_ia32.c --- linux-2.4.21/arch/x86_64/ia32/sys_ia32.c Fri Jun 13 14:51:32 2003 +++ linux/arch/x86_64/ia32/sys_ia32.c Sun Jun 15 17:23:47 2003 @@ -2120,7 +2120,7 @@ dst[cnt] = (char *)(u64)val; cnt++; src += 4; - if (cnt >= (MAX_ARG_PAGES*PAGE_SIZE)/sizeof(void*)) + if (cnt >= (MAX_ARG_PAGES * PAGE_SIZE) / sizeof(char *)) return -E2BIG; } while(val); if (dst) diff -urPX nopatch linux-2.4.21/drivers/char/agp/agpgart_be.c linux/drivers/char/agp/agpgart_be.c --- linux-2.4.21/drivers/char/agp/agpgart_be.c Fri Jun 13 14:51:32 2003 +++ linux/drivers/char/agp/agpgart_be.c Sun Jun 15 15:51:12 2003 @@ -577,7 +577,7 @@ for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) SetPageReserved(page); - agp_bridge.gatt_table_real = (unsigned long *) table; + agp_bridge.gatt_table_real = (u32 *) table; agp_gatt_table = (void *)table; #ifdef CONFIG_X86 err = change_page_attr(virt_to_page(table), 1<drv_block >= 0) STps->drv_block += 1; - return (-ENOMEM); + return (-EIO); } (STp->buffer)->buffer_bytes = bytes - transfer; } else { diff -urPX nopatch linux-2.4.21/fs/binfmt_aout.c linux/fs/binfmt_aout.c --- linux-2.4.21/fs/binfmt_aout.c Sat Nov 3 01:39:20 2001 +++ linux/fs/binfmt_aout.c Sun Jun 15 15:51:12 2003 @@ -4,6 +4,7 @@ * Copyright (C) 1991, 1992, 1996 Linus Torvalds */ +#include #include #include @@ -307,6 +308,9 @@ current->mm->mmap = NULL; compute_creds(bprm); current->flags &= ~PF_FORKNOEXEC; +#ifdef CONFIG_HARDEN_STACK + if (N_FLAGS(ex) & F_STACKEXEC) current->flags |= PF_STACKEXEC; +#endif #ifdef __sparc__ if (N_MAGIC(ex) == NMAGIC) { loff_t pos = fd_offset; diff -urPX nopatch linux-2.4.21/fs/binfmt_elf.c linux/fs/binfmt_elf.c --- linux-2.4.21/fs/binfmt_elf.c Sat Aug 3 00:39:45 2002 +++ linux/fs/binfmt_elf.c Sun Jun 15 15:51:12 2003 @@ -9,6 +9,7 @@ * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com). */ +#include #include #include @@ -73,7 +76,10 @@ #define ELF_PAGEOFFSET(_v) ((_v) & (ELF_MIN_ALIGN-1)) #define ELF_PAGEALIGN(_v) (((_v) + ELF_MIN_ALIGN - 1) & ~(ELF_MIN_ALIGN - 1)) +#ifndef CONFIG_HARDEN_STACK +static +#endif -static struct linux_binfmt elf_format = { +struct linux_binfmt elf_format = { NULL, THIS_MODULE, load_elf_binary, load_elf_library, elf_core_dump, ELF_EXEC_PAGESIZE }; @@ -599,6 +625,9 @@ current->mm->end_code = 0; current->mm->mmap = NULL; current->flags &= ~PF_FORKNOEXEC; +#ifdef CONFIG_HARDEN_STACK + if (elf_ex.e_flags & EF_STACKEXEC) current->flags |= PF_STACKEXEC; +#endif elf_entry = (unsigned long) elf_ex.e_entry; /* Do this so that we can load the interpreter, if need be. We will diff -urPX nopatch linux-2.4.21/fs/exec.c linux/fs/exec.c --- linux-2.4.21/fs/exec.c Fri Jun 13 14:51:37 2003 +++ linux/fs/exec.c Sun Jun 15 16:48:25 2003 @@ -590,6 +594,10 @@ } current->comm[i] = '\0'; +#ifdef CONFIG_HARDEN_STACK + current->flags &= ~PF_STACKEXEC; +#endif + flush_thread(); de_thread(current); @@ -725,6 +733,8 @@ || atomic_read(¤t->fs->count) > 1 || atomic_read(¤t->files->count) > 1 || atomic_read(¤t->sig->count) > 1) { + /* XXX: should fail rather than execute with no raised + * effective privileges */ if(!capable(CAP_SETUID)) { bprm->e_uid = current->uid; bprm->e_gid = current->gid; diff -urPX nopatch linux-2.4.21/include/asm-i386/a.out.h linux/include/asm-i386/a.out.h --- linux-2.4.21/include/asm-i386/a.out.h Fri Jun 16 18:33:06 1995 +++ linux/include/asm-i386/a.out.h Sun Jun 15 15:51:12 2003 @@ -19,7 +19,16 @@ #ifdef __KERNEL__ +#include + +#ifdef CONFIG_HARDEN_STACK +#define STACK_TOP ( \ + (current->flags & PF_STACKEXEC) \ + ? TASK_SIZE - _STK_LIM \ + : TASK_SIZE ) +#else #define STACK_TOP TASK_SIZE +#endif #endif diff -urPX nopatch linux-2.4.21/include/asm-i386/processor.h linux/include/asm-i386/processor.h --- linux-2.4.21/include/asm-i386/processor.h Fri Jun 13 14:51:38 2003 +++ linux/include/asm-i386/processor.h Sun Jun 15 15:51:12 2003 @@ -272,10 +272,28 @@ */ #define TASK_SIZE (PAGE_OFFSET) +/* + * Magic addresses to return to the kernel from signal handlers. These two + * should be beyond user code segment limit, adjacent, and MAGIC_SIGRETURN + * should be even. + */ +#define MAGIC_SIGRETURN (PAGE_OFFSET + 0xDE0000) +#define MAGIC_RT_SIGRETURN (PAGE_OFFSET + 0xDE0001) + /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ +#if defined(CONFIG_HARDEN_STACK) && defined(CONFIG_BINFMT_ELF) +extern struct linux_binfmt elf_format; +#define TASK_UNMAPPED_BASE(size) ( \ + current->binfmt == &elf_format && \ + !(current->flags & PF_STACKEXEC) && \ + (size) < 0x00ef0000UL \ + ? 0x00110000UL \ + : TASK_SIZE / 3 ) +#else #define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#endif /* * Size of io_bitmap in longwords: 32 is ports 0-0x3ff. diff -urPX nopatch linux-2.4.21/include/linux/a.out.h linux/include/linux/a.out.h --- linux-2.4.21/include/linux/a.out.h Thu Nov 22 19:46:18 2001 +++ linux/include/linux/a.out.h Sun Jun 15 15:51:12 2003 @@ -37,6 +37,9 @@ M_MIPS2 = 152 /* MIPS R6000/R4000 binary */ }; +/* Constants for the N_FLAGS field */ +#define F_STACKEXEC 1 /* Executable stack area forced */ + #if !defined (N_MAGIC) #define N_MAGIC(exec) ((exec).a_info & 0xffff) #endif diff -urPX nopatch linux-2.4.21/include/linux/binfmts.h linux/include/linux/binfmts.h --- linux-2.4.21/include/linux/binfmts.h Thu Nov 22 19:46:19 2001 +++ linux/include/linux/binfmts.h Sun Jun 15 15:51:12 2003 @@ -1,6 +1,7 @@ #ifndef _LINUX_BINFMTS_H #define _LINUX_BINFMTS_H +#include #include #include diff -urPX nopatch linux-2.4.21/include/linux/elf.h linux/include/linux/elf.h --- linux-2.4.21/include/linux/elf.h Thu Nov 28 23:53:15 2002 +++ linux/include/linux/elf.h Sun Jun 15 15:51:12 2003 @@ -255,6 +255,8 @@ #define R_MIPS_LOVENDOR 100 #define R_MIPS_HIVENDOR 127 +/* Constants for the e_flags field */ +#define EF_STACKEXEC 1 /* Executable stack area forced */ /* * Sparc ELF relocation types diff -urPX nopatch linux-2.4.21/include/linux/kernel.h linux/include/linux/kernel.h --- linux-2.4.21/include/linux/kernel.h Thu Nov 28 23:53:15 2002 +++ linux/include/linux/kernel.h Sun Jun 15 15:51:12 2003 @@ -71,14 +71,17 @@ extern long long simple_strtoll(const char *,char **,unsigned int); extern int sprintf(char * buf, const char * fmt, ...) __attribute__ ((format (printf, 2, 3))); -extern int vsprintf(char *buf, const char *, va_list); +extern int vsprintf(char *buf, const char *, va_list) + __attribute__ ((format (printf, 2, 0))); extern int snprintf(char * buf, size_t size, const char * fmt, ...) __attribute__ ((format (printf, 3, 4))); -extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args); +extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) + __attribute__ ((format (printf, 3, 0))); extern int sscanf(const char *, const char *, ...) - __attribute__ ((format (scanf,2,3))); -extern int vsscanf(const char *, const char *, va_list); + __attribute__ ((format (scanf, 2, 3))); +extern int vsscanf(const char *, const char *, va_list) + __attribute__ ((format (scanf, 2, 0))); extern int get_option(char **str, int *pint); extern char *get_options(char *str, int nints, int *ints); @@ -170,6 +173,26 @@ ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) #define max_t(type,x,y) \ ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; }) + +#define security_alert(normal_msg, flood_msg, args...) \ +({ \ + static unsigned long warning_time = 0, no_flood_yet = 0; \ + static spinlock_t security_alert_lock = SPIN_LOCK_UNLOCKED; \ +\ + spin_lock(&security_alert_lock); \ +\ +/* Make sure at least one minute passed since the last warning logged */ \ + if (!warning_time || jiffies - warning_time > 60 * HZ) { \ + warning_time = jiffies; no_flood_yet = 1; \ + printk(KERN_ALERT "Security: " normal_msg "\n", ## args); \ + } else if (no_flood_yet) { \ + warning_time = jiffies; no_flood_yet = 0; \ + printk(KERN_ALERT "Security: more " flood_msg \ + ", logging disabled for a minute\n"); \ + } \ +\ + spin_unlock(&security_alert_lock); \ +}) extern void __out_of_line_bug(int line) ATTRIB_NORET; #define out_of_line_bug() __out_of_line_bug(__LINE__) diff -urPX nopatch linux-2.4.21/include/linux/sched.h linux/include/linux/sched.h --- linux-2.4.21/include/linux/sched.h Fri Jun 13 14:51:39 2003 +++ linux/include/linux/sched.h Sun Jun 15 15:51:12 2003 @@ -435,6 +435,8 @@ #define PF_USEDFPU 0x00100000 /* task used FPU this quantum (SMP) */ +#define PF_STACKEXEC 0x01000000 /* Executable stack area forced */ + /* * Ptrace flags */ diff -urPX nopatch linux-2.4.21/kernel/sysctl.c linux/kernel/sysctl.c --- linux-2.4.21/kernel/sysctl.c Fri Jun 13 14:51:39 2003 +++ linux/kernel/sysctl.c Sun Jun 15 15:51:12 2003 @@ -344,6 +344,9 @@ int old_len; if (!oldlenp || get_user(old_len, oldlenp)) return -EFAULT; + /* XXX: insufficient for SMP, but should be redundant anyway */ + if ((ssize_t)old_len < 0) + return -EINVAL; } tmp = &root_table_header.ctl_entry; do { @@ -466,7 +469,8 @@ * zero, proceed with automatic r/w */ if (table->data && table->maxlen) { if (oldval && oldlenp) { - get_user(len, oldlenp); + if (get_user(len, oldlenp)) + return -EFAULT; if (len) { if (len > table->maxlen) len = table->maxlen; @@ -1368,7 +1372,8 @@ for (i = 0; i < length; i++) { int value; - get_user(value, vec + i); + if (get_user(value, vec + i)) + return -EFAULT; if (min && value < min[i]) return -EINVAL; if (max && value > max[i]) diff -urPX nopatch linux-2.4.21/mm/mmap.c linux/mm/mmap.c --- linux-2.4.21/mm/mmap.c Fri Jun 13 14:51:39 2003 +++ linux/mm/mmap.c Sun Jun 15 15:51:12 2003 @@ -3,6 +3,7 @@ * * Written by obz. */ +#include #include #include #include @@ -626,7 +627,11 @@ (!vma || addr + len <= vma->vm_start)) return addr; } +#if defined(CONFIG_HARDEN_STACK) && defined(CONFIG_BINFMT_ELF) + addr = PAGE_ALIGN(TASK_UNMAPPED_BASE(len)); +#else addr = PAGE_ALIGN(TASK_UNMAPPED_BASE); +#endif for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { /* At this point: (!vma || addr < vma->vm_end). */ diff -urPX nopatch linux-2.4.21/mm/swapfile.c linux/mm/swapfile.c --- linux-2.4.21/mm/swapfile.c Fri Jun 13 14:51:39 2003 +++ linux/mm/swapfile.c Sun Jun 15 15:51:12 2003 @@ -725,8 +725,10 @@ for (type = swap_list.head; type >= 0; type = swap_info[type].next) { p = swap_info + type; if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) { - if (p->swap_file == nd.dentry) - break; + if (p->swap_file == nd.dentry || + (S_ISBLK(nd.dentry->d_inode->i_mode) && + p->swap_device == nd.dentry->d_inode->i_rdev)) + break; } prev = type; } diff -urPX nopatch linux-2.4.21/net/socket.c linux/net/socket.c --- linux-2.4.21/net/socket.c Fri Jun 13 14:51:39 2003 +++ linux/net/socket.c Sun Jun 15 15:51:12 2003 @@ -1305,10 +1305,18 @@ asmlinkage long sys_getsockopt(int fd, int level, int optname, char *optval, int *optlen) { int err; + int len; struct socket *sock; if ((sock = sockfd_lookup(fd, &err))!=NULL) { + /* XXX: insufficient for SMP, but should be redundant anyway */ + if (get_user(len, optlen)) + err = -EFAULT; + else + if (len < 0) + err = -EINVAL; + else if (level == SOL_SOCKET) err=sock_getsockopt(sock,level,optname,optval,optlen); else