]>
Commit | Line | Data |
---|---|---|
02b47204 JR |
1 | diff -urPX nopatch linux-2.4.21/Documentation/Configure.help linux/Documentation/Configure.help |
2 | --- linux-2.4.21/Documentation/Configure.help Fri Jun 13 14:51:29 2003 | |
3 | +++ linux/Documentation/Configure.help Sun Jun 15 15:56:24 2003 | |
4 | @@ -26648,6 +26652,31 @@ | |
5 | IPMI Watchdog Timer | |
6 | CONFIG_IPMI_WATCHDOG | |
7 | This enables the IPMI watchdog timer. | |
8 | + | |
9 | +Non-executable user stack area | |
10 | +CONFIG_HARDEN_STACK | |
11 | + Most buffer overflow exploits are based on overwriting a function's | |
12 | + return address on the stack to point to some arbitrary code, which is | |
13 | + also put onto the stack. If the stack area is non-executable, buffer | |
14 | + overflow vulnerabilities become harder to exploit. However, a few | |
15 | + programs depend on the stack being executable, and might stop working | |
16 | + unless you also enable GCC trampolines autodetection and emulation | |
17 | + below, or enable the stack area execution permission for every such | |
18 | + program separately using chstk.c. If you don't know what all this is | |
19 | + about, or don't care about security that much, say N. | |
20 | + | |
21 | +Autodetect and emulate GCC trampolines | |
22 | +CONFIG_HARDEN_STACK_SMART | |
23 | + GCC generates trampolines on the stack to correctly pass control to | |
24 | + nested functions when calling from outside. Normally, this requires | |
25 | + the stack being executable. When this option is enabled, the kernel | |
26 | + will trap faults resulting from trampoline calls, and will emulate the | |
27 | + trampolines. However, in some cases this autodetection can be fooled | |
28 | + in a buffer overflow exploit, so, if you've got no programs that use | |
29 | + GCC trampolines, it is more secure to disable this option. If you're | |
30 | + too lazy to find that out, answer Y. Note: if you're using glibc 2.0 | |
31 | + (and not libc 5 or glibc 2.1+), you have to say Y here, or the system | |
32 | + won't even boot. | |
33 | ||
34 | # | |
35 | # A couple of things I keep forgetting: | |
36 | diff -urPX nopatch linux-2.4.21/arch/i386/config.in linux/arch/i386/config.in | |
37 | --- linux-2.4.21/arch/i386/config.in Fri Jun 13 14:51:29 2003 | |
38 | +++ linux/arch/i386/config.in Sun Jun 15 15:51:12 2003 | |
39 | @@ -467,6 +470,16 @@ | |
40 | source drivers/usb/Config.in | |
41 | ||
42 | source net/bluetooth/Config.in | |
43 | + | |
44 | +mainmenu_option next_comment | |
45 | +comment 'Security options' | |
46 | + | |
47 | +bool 'Non-executable user stack area' CONFIG_HARDEN_STACK | |
48 | +if [ "$CONFIG_HARDEN_STACK" = "y" ]; then | |
49 | + bool ' Autodetect and emulate GCC trampolines' CONFIG_HARDEN_STACK_SMART | |
50 | +fi | |
51 | + | |
52 | +endmenu | |
53 | ||
54 | mainmenu_option next_comment | |
55 | comment 'Kernel hacking' | |
56 | diff -urPX nopatch linux-2.4.21/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S | |
57 | --- linux-2.4.21/arch/i386/kernel/head.S Fri Jun 13 14:51:29 2003 | |
58 | +++ linux/arch/i386/kernel/head.S Sun Jun 15 15:51:12 2003 | |
59 | @@ -433,7 +433,11 @@ | |
60 | .quad 0x0000000000000000 /* not used */ | |
61 | .quad 0x00cf9a000000ffff /* 0x10 kernel 4GB code at 0x00000000 */ | |
62 | .quad 0x00cf92000000ffff /* 0x18 kernel 4GB data at 0x00000000 */ | |
63 | +#ifdef CONFIG_HARDEN_STACK | |
64 | + .quad 0x00cbfa000000f7ff /* 0x23 user 3GB-8MB code at 0 */ | |
65 | +#else | |
66 | .quad 0x00cffa000000ffff /* 0x23 user 4GB code at 0x00000000 */ | |
67 | +#endif | |
68 | .quad 0x00cff2000000ffff /* 0x2b user 4GB data at 0x00000000 */ | |
69 | .quad 0x0000000000000000 /* not used */ | |
70 | .quad 0x0000000000000000 /* not used */ | |
71 | diff -urPX nopatch linux-2.4.21/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c | |
72 | --- linux-2.4.21/arch/i386/kernel/signal.c Sat Aug 3 00:39:42 2002 | |
73 | +++ linux/arch/i386/kernel/signal.c Sun Jun 15 15:51:12 2003 | |
74 | @@ -421,11 +421,15 @@ | |
75 | if (ka->sa.sa_flags & SA_RESTORER) { | |
76 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); | |
77 | } else { | |
78 | +#ifdef CONFIG_HARDEN_STACK | |
79 | + err |= __put_user(MAGIC_SIGRETURN, &frame->pretcode); | |
80 | +#else | |
81 | err |= __put_user(frame->retcode, &frame->pretcode); | |
82 | /* This is popl %eax ; movl $,%eax ; int $0x80 */ | |
83 | err |= __put_user(0xb858, (short *)(frame->retcode+0)); | |
84 | err |= __put_user(__NR_sigreturn, (int *)(frame->retcode+2)); | |
85 | err |= __put_user(0x80cd, (short *)(frame->retcode+6)); | |
86 | +#endif | |
87 | } | |
88 | ||
89 | if (err) | |
90 | @@ -496,11 +500,15 @@ | |
91 | if (ka->sa.sa_flags & SA_RESTORER) { | |
92 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); | |
93 | } else { | |
94 | +#ifdef CONFIG_HARDEN_STACK | |
95 | + err |= __put_user(MAGIC_RT_SIGRETURN, &frame->pretcode); | |
96 | +#else | |
97 | err |= __put_user(frame->retcode, &frame->pretcode); | |
98 | /* This is movl $,%eax ; int $0x80 */ | |
99 | err |= __put_user(0xb8, (char *)(frame->retcode+0)); | |
100 | err |= __put_user(__NR_rt_sigreturn, (int *)(frame->retcode+1)); | |
101 | err |= __put_user(0x80cd, (short *)(frame->retcode+5)); | |
102 | +#endif | |
103 | } | |
104 | ||
105 | if (err) | |
106 | diff -urPX nopatch linux-2.4.21/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c | |
107 | --- linux-2.4.21/arch/i386/kernel/traps.c Thu Nov 28 23:53:09 2002 | |
108 | +++ linux/arch/i386/kernel/traps.c Sun Jun 15 16:29:52 2003 | |
109 | @@ -397,13 +397,202 @@ | |
110 | DO_ERROR(12, SIGBUS, "stack segment", stack_segment) | |
111 | DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, get_cr2()) | |
112 | ||
113 | +#if defined(CONFIG_HARDEN_STACK) && defined(CONFIG_HARDEN_STACK_SMART) | |
114 | +/* | |
115 | + * These two functions aren't performance critical (trampolines are | |
116 | + * extremely rare and slow even without emulation). | |
117 | + */ | |
118 | +static unsigned long *get_reg(struct pt_regs *regs, unsigned char regnum) | |
119 | +{ | |
120 | + switch (regnum) { | |
121 | + case 0: return ®s->eax; | |
122 | + case 1: return ®s->ecx; | |
123 | + case 2: return ®s->edx; | |
124 | + case 3: return ®s->ebx; | |
125 | + case 4: return ®s->esp; | |
126 | + case 5: return ®s->ebp; | |
127 | + case 6: return ®s->esi; | |
128 | + case 7: return ®s->edi; | |
129 | + } | |
130 | + | |
131 | + return NULL; | |
132 | +} | |
133 | + | |
134 | +static unsigned long get_modrm(struct pt_regs *regs, int *err) | |
135 | +{ | |
136 | + unsigned char modrm, sib; | |
137 | + signed char rel8; | |
138 | + unsigned long rel32; | |
139 | + int size, regnum, scale; | |
140 | + unsigned long index, base, addr, value; | |
141 | + | |
142 | + *err |= __get_user(modrm, (unsigned char *)(regs->eip + 1)); | |
143 | + size = 2; | |
144 | + regnum = modrm & 7; | |
145 | + addr = *get_reg(regs, regnum); | |
146 | + if (regnum == 4 && (modrm & 0xC0) != 0xC0) { | |
147 | + *err |= __get_user(sib, (unsigned char *)(regs->eip + 2)); | |
148 | + size = 3; | |
149 | + scale = sib >> 6; | |
150 | + index = *get_reg(regs, (sib >> 3) & 7); | |
151 | + base = *get_reg(regs, sib & 7); | |
152 | + addr = base + (index << scale); | |
153 | + } | |
154 | + | |
155 | + switch (modrm & 0xC0) { | |
156 | + case 0x00: | |
157 | + if (regnum == 5) { | |
158 | + *err |= __get_user(addr, | |
159 | + (unsigned long *)(regs->eip + 2)); | |
160 | + size = 6; | |
161 | + } | |
162 | + *err |= get_user(value, (unsigned long *)addr); | |
163 | + break; | |
164 | + | |
165 | + case 0x40: | |
166 | + *err |= __get_user(rel8, (signed char *)(regs->eip + size)); | |
167 | + size++; | |
168 | + addr += rel8; | |
169 | + *err |= get_user(value, (unsigned long *)addr); | |
170 | + break; | |
171 | + | |
172 | + case 0x80: | |
173 | + *err |= __get_user(rel32, (unsigned long *)(regs->eip + size)); | |
174 | + size += 4; | |
175 | + addr += rel32; | |
176 | + *err |= get_user(value, (unsigned long *)addr); | |
177 | + break; | |
178 | + | |
179 | + case 0xC0: | |
180 | + default: | |
181 | + value = addr; | |
182 | + } | |
183 | + | |
184 | + if (*err) return 0; | |
185 | + regs->eip += size; | |
186 | + return value; | |
187 | +} | |
188 | +#endif | |
189 | + | |
190 | asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) | |
191 | { | |
192 | +#ifdef CONFIG_HARDEN_STACK | |
193 | + unsigned long addr; | |
194 | + unsigned char insn; | |
195 | +#ifdef CONFIG_HARDEN_STACK_SMART | |
196 | + int err, count; | |
197 | +#endif | |
198 | +#endif | |
199 | + | |
200 | if (regs->eflags & VM_MASK) | |
201 | goto gp_in_vm86; | |
202 | ||
203 | if (!(regs->xcs & 3)) | |
204 | goto gp_in_kernel; | |
205 | + | |
206 | +#ifdef CONFIG_HARDEN_STACK | |
207 | + if ((regs->xcs & 0xFFFF) != __USER_CS || | |
208 | + __get_user(insn, (unsigned char *)regs->eip)) | |
209 | + goto gp_in_user; | |
210 | + | |
211 | +/* Check if it was a return instruction */ | |
212 | + if (insn == 0xC3) { | |
213 | + if (get_user(addr, (unsigned long *)regs->esp)) | |
214 | + goto gp_in_user; | |
215 | + | |
216 | +/* Check if it was return from a signal handler */ | |
217 | + if ((addr & 0xFFFFFFFE) == MAGIC_SIGRETURN) { | |
218 | +/* Call sys_sigreturn() or sys_rt_sigreturn() to restore the context */ | |
219 | + regs->esp += 8; | |
220 | + __asm__("movl %3,%%esi\n\t" | |
221 | + "subl %1,%%esp\n\t" | |
222 | + "movl %2,%%ecx\n\t" | |
223 | + "movl %%esp,%%edi\n\t" | |
224 | + "rep; movsl\n\t" | |
225 | + "testl $1,%4\n\t" | |
226 | + "jnz 1f\n\t" | |
227 | + "call sys_sigreturn\n\t" | |
228 | + "leal %3,%%edi\n\t" | |
229 | + "jmp 2f\n\t" | |
230 | + "1:\n\t" | |
231 | + "call sys_rt_sigreturn\n\t" | |
232 | + "leal %3,%%edi\n\t" | |
233 | + "2:\n\t" | |
234 | + "addl %1,%%edi\n\t" | |
235 | + "movl %%esp,%%esi\n\t" | |
236 | + "movl %2,%%ecx\n\t" | |
237 | + "movl (%%edi),%%edi\n\t" | |
238 | + "rep; movsl\n\t" | |
239 | + "movl %%esi,%%esp" | |
240 | + : | |
241 | +/* %eax is returned separately */ | |
242 | + "=a" (regs->eax) | |
243 | + : | |
244 | + "i" (sizeof(*regs)), | |
245 | + "i" (sizeof(*regs) >> 2), | |
246 | + "m" (regs), | |
247 | + "r" (addr) | |
248 | + : | |
249 | + "cx", "dx", "si", "di", "cc", "memory"); | |
250 | + return; | |
251 | + } | |
252 | + | |
253 | +/* | |
254 | + * Check if we're returning to the stack area, which is only likely to happen | |
255 | + * when attempting to exploit a buffer overflow. | |
256 | + */ | |
257 | + if (addr >= PAGE_OFFSET - _STK_LIM && addr < PAGE_OFFSET) | |
258 | + security_alert("return onto stack running as " | |
259 | + "UID %d, EUID %d, process %s:%d", | |
260 | + "returns onto stack", | |
261 | + current->uid, current->euid, | |
262 | + current->comm, current->pid); | |
263 | + } | |
264 | + | |
265 | +#ifdef CONFIG_HARDEN_STACK_SMART | |
266 | +/* Check if it could have been a trampoline call */ | |
267 | + else | |
268 | + if (insn == 0xFF && | |
269 | + !__get_user(insn, (unsigned char *)(regs->eip + 1)) && | |
270 | + (insn & 0x38) == 0x10 && insn != 0xD4) { /* call mod r/m */ | |
271 | +/* First, emulate the call */ | |
272 | + err = 0; | |
273 | + addr = get_modrm(regs, &err); | |
274 | + if (!err) { | |
275 | + regs->esp -= 4; | |
276 | + err = put_user(regs->eip, (unsigned long *)regs->esp); | |
277 | + regs->eip = addr; | |
278 | + } | |
279 | +/* Then, start emulating the trampoline itself */ | |
280 | + count = 0; | |
281 | + while (!err && !__get_user(insn, (unsigned char *)regs->eip++)) | |
282 | + if ((insn & 0xF8) == 0xB8) { /* movl imm32,%reg */ | |
283 | +/* We only have 8 GP registers, no reason to initialize one twice */ | |
284 | + if (count++ >= 8) break; | |
285 | + err |= __get_user(addr, (unsigned long *)regs->eip); | |
286 | + regs->eip += 4; | |
287 | + *get_reg(regs, insn & 7) = addr; | |
288 | + } else | |
289 | + if (insn == 0xFF) { | |
290 | + err |= __get_user(insn, (unsigned char *)regs->eip); | |
291 | + if ((insn & 0xF8) == 0xE0) { /* jmp *%reg */ | |
292 | + regs->eip = *get_reg(regs, insn & 7); | |
293 | + if (err) break; else return; | |
294 | + } | |
295 | + break; | |
296 | + } else | |
297 | + if (insn == 0xE9) { /* jmp rel32 */ | |
298 | + err |= __get_user(addr, (unsigned long *)regs->eip); | |
299 | + if (err) break; | |
300 | + regs->eip += 4 + addr; | |
301 | + return; | |
302 | + } else | |
303 | + break; | |
304 | + } | |
305 | +#endif | |
306 | + | |
307 | +gp_in_user: | |
308 | +#endif | |
309 | ||
310 | current->thread.error_code = error_code; | |
311 | current->thread.trap_no = 13; | |
312 | diff -urPX nopatch linux-2.4.21/arch/ia64/ia32/sys_ia32.c linux/arch/ia64/ia32/sys_ia32.c | |
313 | --- linux-2.4.21/arch/ia64/ia32/sys_ia32.c Fri Jun 13 14:51:29 2003 | |
314 | +++ linux/arch/ia64/ia32/sys_ia32.c Sun Jun 15 17:21:08 2003 | |
315 | @@ -109,6 +109,8 @@ | |
316 | *ap++ = (char *) A(addr); | |
317 | arg += sizeof(unsigned int); | |
318 | n++; | |
319 | + if (n >= (MAX_ARG_PAGES * PAGE_SIZE) / sizeof(char *)) | |
320 | + return -E2BIG; | |
321 | } while (addr); | |
322 | return n - 1; | |
323 | } | |
324 | diff -urPX nopatch linux-2.4.21/arch/mips64/kernel/linux32.c linux/arch/mips64/kernel/linux32.c | |
325 | --- linux-2.4.21/arch/mips64/kernel/linux32.c Thu Nov 28 23:53:10 2002 | |
326 | +++ linux/arch/mips64/kernel/linux32.c Sun Jun 15 17:23:00 2003 | |
327 | @@ -434,6 +450,8 @@ | |
328 | return ret; | |
329 | arg += sizeof(unsigned int); | |
330 | n++; | |
331 | + if (n >= (MAX_ARG_PAGES * PAGE_SIZE) / sizeof(char *)) | |
332 | + return -E2BIG; | |
333 | } while (ptr); | |
334 | ||
335 | return n - 1; | |
336 | diff -urPX nopatch linux-2.4.21/arch/x86_64/ia32/sys_ia32.c linux/arch/x86_64/ia32/sys_ia32.c | |
337 | --- linux-2.4.21/arch/x86_64/ia32/sys_ia32.c Fri Jun 13 14:51:32 2003 | |
338 | +++ linux/arch/x86_64/ia32/sys_ia32.c Sun Jun 15 17:23:47 2003 | |
339 | @@ -2120,7 +2120,7 @@ | |
340 | dst[cnt] = (char *)(u64)val; | |
341 | cnt++; | |
342 | src += 4; | |
343 | - if (cnt >= (MAX_ARG_PAGES*PAGE_SIZE)/sizeof(void*)) | |
344 | + if (cnt >= (MAX_ARG_PAGES * PAGE_SIZE) / sizeof(char *)) | |
345 | return -E2BIG; | |
346 | } while(val); | |
347 | if (dst) | |
348 | diff -urPX nopatch linux-2.4.21/drivers/char/agp/agpgart_be.c linux/drivers/char/agp/agpgart_be.c | |
349 | --- linux-2.4.21/drivers/char/agp/agpgart_be.c Fri Jun 13 14:51:32 2003 | |
350 | +++ linux/drivers/char/agp/agpgart_be.c Sun Jun 15 15:51:12 2003 | |
351 | @@ -577,7 +577,7 @@ | |
352 | for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) | |
353 | SetPageReserved(page); | |
354 | ||
355 | - agp_bridge.gatt_table_real = (unsigned long *) table; | |
356 | + agp_bridge.gatt_table_real = (u32 *) table; | |
357 | agp_gatt_table = (void *)table; | |
358 | #ifdef CONFIG_X86 | |
359 | err = change_page_attr(virt_to_page(table), 1<<page_order, PAGE_KERNEL_NOCACHE); | |
360 | diff -urPX nopatch linux-2.4.21/drivers/scsi/st.c linux/drivers/scsi/st.c | |
361 | --- linux-2.4.21/drivers/scsi/st.c Thu Nov 28 23:53:14 2002 | |
362 | +++ linux/drivers/scsi/st.c Sun Jun 15 15:51:12 2003 | |
363 | @@ -1628,7 +1628,7 @@ | |
364 | if (transfer < 0) { | |
365 | if (STps->drv_block >= 0) | |
366 | STps->drv_block += 1; | |
367 | - return (-ENOMEM); | |
368 | + return (-EIO); | |
369 | } | |
370 | (STp->buffer)->buffer_bytes = bytes - transfer; | |
371 | } else { | |
372 | diff -urPX nopatch linux-2.4.21/fs/binfmt_aout.c linux/fs/binfmt_aout.c | |
373 | --- linux-2.4.21/fs/binfmt_aout.c Sat Nov 3 01:39:20 2001 | |
374 | +++ linux/fs/binfmt_aout.c Sun Jun 15 15:51:12 2003 | |
375 | @@ -4,6 +4,7 @@ | |
376 | * Copyright (C) 1991, 1992, 1996 Linus Torvalds | |
377 | */ | |
378 | ||
379 | +#include <linux/config.h> | |
380 | #include <linux/module.h> | |
381 | ||
382 | #include <linux/sched.h> | |
383 | @@ -307,6 +308,9 @@ | |
384 | current->mm->mmap = NULL; | |
385 | compute_creds(bprm); | |
386 | current->flags &= ~PF_FORKNOEXEC; | |
387 | +#ifdef CONFIG_HARDEN_STACK | |
388 | + if (N_FLAGS(ex) & F_STACKEXEC) current->flags |= PF_STACKEXEC; | |
389 | +#endif | |
390 | #ifdef __sparc__ | |
391 | if (N_MAGIC(ex) == NMAGIC) { | |
392 | loff_t pos = fd_offset; | |
393 | diff -urPX nopatch linux-2.4.21/fs/binfmt_elf.c linux/fs/binfmt_elf.c | |
394 | --- linux-2.4.21/fs/binfmt_elf.c Sat Aug 3 00:39:45 2002 | |
395 | +++ linux/fs/binfmt_elf.c Sun Jun 15 15:51:12 2003 | |
396 | @@ -9,6 +9,7 @@ | |
397 | * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com). | |
398 | */ | |
399 | ||
400 | +#include <linux/config.h> | |
401 | #include <linux/module.h> | |
402 | ||
403 | #include <linux/fs.h> | |
404 | @@ -73,7 +76,10 @@ | |
405 | #define ELF_PAGEOFFSET(_v) ((_v) & (ELF_MIN_ALIGN-1)) | |
406 | #define ELF_PAGEALIGN(_v) (((_v) + ELF_MIN_ALIGN - 1) & ~(ELF_MIN_ALIGN - 1)) | |
407 | ||
408 | +#ifndef CONFIG_HARDEN_STACK | |
409 | +static | |
410 | +#endif | |
411 | -static struct linux_binfmt elf_format = { | |
412 | +struct linux_binfmt elf_format = { | |
413 | NULL, THIS_MODULE, load_elf_binary, load_elf_library, elf_core_dump, ELF_EXEC_PAGESIZE | |
414 | }; | |
415 | ||
416 | @@ -599,6 +625,9 @@ | |
417 | current->mm->end_code = 0; | |
418 | current->mm->mmap = NULL; | |
419 | current->flags &= ~PF_FORKNOEXEC; | |
420 | +#ifdef CONFIG_HARDEN_STACK | |
421 | + if (elf_ex.e_flags & EF_STACKEXEC) current->flags |= PF_STACKEXEC; | |
422 | +#endif | |
423 | elf_entry = (unsigned long) elf_ex.e_entry; | |
424 | ||
425 | /* Do this so that we can load the interpreter, if need be. We will | |
426 | diff -urPX nopatch linux-2.4.21/fs/exec.c linux/fs/exec.c | |
427 | --- linux-2.4.21/fs/exec.c Fri Jun 13 14:51:37 2003 | |
428 | +++ linux/fs/exec.c Sun Jun 15 16:48:25 2003 | |
429 | @@ -590,6 +594,10 @@ | |
430 | } | |
431 | current->comm[i] = '\0'; | |
432 | ||
433 | +#ifdef CONFIG_HARDEN_STACK | |
434 | + current->flags &= ~PF_STACKEXEC; | |
435 | +#endif | |
436 | + | |
437 | flush_thread(); | |
438 | ||
439 | de_thread(current); | |
440 | @@ -725,6 +733,8 @@ | |
441 | || atomic_read(¤t->fs->count) > 1 | |
442 | || atomic_read(¤t->files->count) > 1 | |
443 | || atomic_read(¤t->sig->count) > 1) { | |
444 | + /* XXX: should fail rather than execute with no raised | |
445 | + * effective privileges */ | |
446 | if(!capable(CAP_SETUID)) { | |
447 | bprm->e_uid = current->uid; | |
448 | bprm->e_gid = current->gid; | |
449 | diff -urPX nopatch linux-2.4.21/include/asm-i386/a.out.h linux/include/asm-i386/a.out.h | |
450 | --- linux-2.4.21/include/asm-i386/a.out.h Fri Jun 16 18:33:06 1995 | |
451 | +++ linux/include/asm-i386/a.out.h Sun Jun 15 15:51:12 2003 | |
452 | @@ -19,7 +19,16 @@ | |
453 | ||
454 | #ifdef __KERNEL__ | |
455 | ||
456 | +#include <linux/config.h> | |
457 | + | |
458 | +#ifdef CONFIG_HARDEN_STACK | |
459 | +#define STACK_TOP ( \ | |
460 | + (current->flags & PF_STACKEXEC) \ | |
461 | + ? TASK_SIZE - _STK_LIM \ | |
462 | + : TASK_SIZE ) | |
463 | +#else | |
464 | #define STACK_TOP TASK_SIZE | |
465 | +#endif | |
466 | ||
467 | #endif | |
468 | ||
469 | diff -urPX nopatch linux-2.4.21/include/asm-i386/processor.h linux/include/asm-i386/processor.h | |
470 | --- linux-2.4.21/include/asm-i386/processor.h Fri Jun 13 14:51:38 2003 | |
471 | +++ linux/include/asm-i386/processor.h Sun Jun 15 15:51:12 2003 | |
472 | @@ -272,10 +272,28 @@ | |
473 | */ | |
474 | #define TASK_SIZE (PAGE_OFFSET) | |
475 | ||
476 | +/* | |
477 | + * Magic addresses to return to the kernel from signal handlers. These two | |
478 | + * should be beyond user code segment limit, adjacent, and MAGIC_SIGRETURN | |
479 | + * should be even. | |
480 | + */ | |
481 | +#define MAGIC_SIGRETURN (PAGE_OFFSET + 0xDE0000) | |
482 | +#define MAGIC_RT_SIGRETURN (PAGE_OFFSET + 0xDE0001) | |
483 | + | |
484 | /* This decides where the kernel will search for a free chunk of vm | |
485 | * space during mmap's. | |
486 | */ | |
487 | +#if defined(CONFIG_HARDEN_STACK) && defined(CONFIG_BINFMT_ELF) | |
488 | +extern struct linux_binfmt elf_format; | |
489 | +#define TASK_UNMAPPED_BASE(size) ( \ | |
490 | + current->binfmt == &elf_format && \ | |
491 | + !(current->flags & PF_STACKEXEC) && \ | |
492 | + (size) < 0x00ef0000UL \ | |
493 | + ? 0x00110000UL \ | |
494 | + : TASK_SIZE / 3 ) | |
495 | +#else | |
496 | #define TASK_UNMAPPED_BASE (TASK_SIZE / 3) | |
497 | +#endif | |
498 | ||
499 | /* | |
500 | * Size of io_bitmap in longwords: 32 is ports 0-0x3ff. | |
501 | diff -urPX nopatch linux-2.4.21/include/linux/a.out.h linux/include/linux/a.out.h | |
502 | --- linux-2.4.21/include/linux/a.out.h Thu Nov 22 19:46:18 2001 | |
503 | +++ linux/include/linux/a.out.h Sun Jun 15 15:51:12 2003 | |
504 | @@ -37,6 +37,9 @@ | |
505 | M_MIPS2 = 152 /* MIPS R6000/R4000 binary */ | |
506 | }; | |
507 | ||
508 | +/* Constants for the N_FLAGS field */ | |
509 | +#define F_STACKEXEC 1 /* Executable stack area forced */ | |
510 | + | |
511 | #if !defined (N_MAGIC) | |
512 | #define N_MAGIC(exec) ((exec).a_info & 0xffff) | |
513 | #endif | |
514 | diff -urPX nopatch linux-2.4.21/include/linux/binfmts.h linux/include/linux/binfmts.h | |
515 | --- linux-2.4.21/include/linux/binfmts.h Thu Nov 22 19:46:19 2001 | |
516 | +++ linux/include/linux/binfmts.h Sun Jun 15 15:51:12 2003 | |
517 | @@ -1,6 +1,7 @@ | |
518 | #ifndef _LINUX_BINFMTS_H | |
519 | #define _LINUX_BINFMTS_H | |
520 | ||
521 | +#include <linux/config.h> | |
522 | #include <linux/ptrace.h> | |
523 | #include <linux/capability.h> | |
524 | ||
525 | diff -urPX nopatch linux-2.4.21/include/linux/elf.h linux/include/linux/elf.h | |
526 | --- linux-2.4.21/include/linux/elf.h Thu Nov 28 23:53:15 2002 | |
527 | +++ linux/include/linux/elf.h Sun Jun 15 15:51:12 2003 | |
528 | @@ -255,6 +255,8 @@ | |
529 | #define R_MIPS_LOVENDOR 100 | |
530 | #define R_MIPS_HIVENDOR 127 | |
531 | ||
532 | +/* Constants for the e_flags field */ | |
533 | +#define EF_STACKEXEC 1 /* Executable stack area forced */ | |
534 | ||
535 | /* | |
536 | * Sparc ELF relocation types | |
537 | diff -urPX nopatch linux-2.4.21/include/linux/kernel.h linux/include/linux/kernel.h | |
538 | --- linux-2.4.21/include/linux/kernel.h Thu Nov 28 23:53:15 2002 | |
539 | +++ linux/include/linux/kernel.h Sun Jun 15 15:51:12 2003 | |
540 | @@ -71,14 +71,17 @@ | |
541 | extern long long simple_strtoll(const char *,char **,unsigned int); | |
542 | extern int sprintf(char * buf, const char * fmt, ...) | |
543 | __attribute__ ((format (printf, 2, 3))); | |
544 | -extern int vsprintf(char *buf, const char *, va_list); | |
545 | +extern int vsprintf(char *buf, const char *, va_list) | |
546 | + __attribute__ ((format (printf, 2, 0))); | |
547 | extern int snprintf(char * buf, size_t size, const char * fmt, ...) | |
548 | __attribute__ ((format (printf, 3, 4))); | |
549 | -extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args); | |
550 | +extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) | |
551 | + __attribute__ ((format (printf, 3, 0))); | |
552 | ||
553 | extern int sscanf(const char *, const char *, ...) | |
554 | - __attribute__ ((format (scanf,2,3))); | |
555 | -extern int vsscanf(const char *, const char *, va_list); | |
556 | + __attribute__ ((format (scanf, 2, 3))); | |
557 | +extern int vsscanf(const char *, const char *, va_list) | |
558 | + __attribute__ ((format (scanf, 2, 0))); | |
559 | ||
560 | extern int get_option(char **str, int *pint); | |
561 | extern char *get_options(char *str, int nints, int *ints); | |
562 | @@ -170,6 +173,26 @@ | |
563 | ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) | |
564 | #define max_t(type,x,y) \ | |
565 | ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; }) | |
566 | + | |
567 | +#define security_alert(normal_msg, flood_msg, args...) \ | |
568 | +({ \ | |
569 | + static unsigned long warning_time = 0, no_flood_yet = 0; \ | |
570 | + static spinlock_t security_alert_lock = SPIN_LOCK_UNLOCKED; \ | |
571 | +\ | |
572 | + spin_lock(&security_alert_lock); \ | |
573 | +\ | |
574 | +/* Make sure at least one minute passed since the last warning logged */ \ | |
575 | + if (!warning_time || jiffies - warning_time > 60 * HZ) { \ | |
576 | + warning_time = jiffies; no_flood_yet = 1; \ | |
577 | + printk(KERN_ALERT "Security: " normal_msg "\n", ## args); \ | |
578 | + } else if (no_flood_yet) { \ | |
579 | + warning_time = jiffies; no_flood_yet = 0; \ | |
580 | + printk(KERN_ALERT "Security: more " flood_msg \ | |
581 | + ", logging disabled for a minute\n"); \ | |
582 | + } \ | |
583 | +\ | |
584 | + spin_unlock(&security_alert_lock); \ | |
585 | +}) | |
586 | ||
587 | extern void __out_of_line_bug(int line) ATTRIB_NORET; | |
588 | #define out_of_line_bug() __out_of_line_bug(__LINE__) | |
589 | diff -urPX nopatch linux-2.4.21/include/linux/sched.h linux/include/linux/sched.h | |
590 | --- linux-2.4.21/include/linux/sched.h Fri Jun 13 14:51:39 2003 | |
591 | +++ linux/include/linux/sched.h Sun Jun 15 15:51:12 2003 | |
592 | @@ -435,6 +435,8 @@ | |
593 | ||
594 | #define PF_USEDFPU 0x00100000 /* task used FPU this quantum (SMP) */ | |
595 | ||
596 | +#define PF_STACKEXEC 0x01000000 /* Executable stack area forced */ | |
597 | + | |
598 | /* | |
599 | * Ptrace flags | |
600 | */ | |
601 | diff -urPX nopatch linux-2.4.21/kernel/sysctl.c linux/kernel/sysctl.c | |
602 | --- linux-2.4.21/kernel/sysctl.c Fri Jun 13 14:51:39 2003 | |
603 | +++ linux/kernel/sysctl.c Sun Jun 15 15:51:12 2003 | |
604 | @@ -344,6 +344,9 @@ | |
605 | int old_len; | |
606 | if (!oldlenp || get_user(old_len, oldlenp)) | |
607 | return -EFAULT; | |
608 | + /* XXX: insufficient for SMP, but should be redundant anyway */ | |
609 | + if ((ssize_t)old_len < 0) | |
610 | + return -EINVAL; | |
611 | } | |
612 | tmp = &root_table_header.ctl_entry; | |
613 | do { | |
614 | @@ -466,7 +469,8 @@ | |
615 | * zero, proceed with automatic r/w */ | |
616 | if (table->data && table->maxlen) { | |
617 | if (oldval && oldlenp) { | |
618 | - get_user(len, oldlenp); | |
619 | + if (get_user(len, oldlenp)) | |
620 | + return -EFAULT; | |
621 | if (len) { | |
622 | if (len > table->maxlen) | |
623 | len = table->maxlen; | |
624 | @@ -1368,7 +1372,8 @@ | |
625 | ||
626 | for (i = 0; i < length; i++) { | |
627 | int value; | |
628 | - get_user(value, vec + i); | |
629 | + if (get_user(value, vec + i)) | |
630 | + return -EFAULT; | |
631 | if (min && value < min[i]) | |
632 | return -EINVAL; | |
633 | if (max && value > max[i]) | |
634 | diff -urPX nopatch linux-2.4.21/mm/mmap.c linux/mm/mmap.c | |
635 | --- linux-2.4.21/mm/mmap.c Fri Jun 13 14:51:39 2003 | |
636 | +++ linux/mm/mmap.c Sun Jun 15 15:51:12 2003 | |
637 | @@ -3,6 +3,7 @@ | |
638 | * | |
639 | * Written by obz. | |
640 | */ | |
641 | +#include <linux/config.h> | |
642 | #include <linux/slab.h> | |
643 | #include <linux/shm.h> | |
644 | #include <linux/mman.h> | |
645 | @@ -626,7 +627,11 @@ | |
646 | (!vma || addr + len <= vma->vm_start)) | |
647 | return addr; | |
648 | } | |
649 | +#if defined(CONFIG_HARDEN_STACK) && defined(CONFIG_BINFMT_ELF) | |
650 | + addr = PAGE_ALIGN(TASK_UNMAPPED_BASE(len)); | |
651 | +#else | |
652 | addr = PAGE_ALIGN(TASK_UNMAPPED_BASE); | |
653 | +#endif | |
654 | ||
655 | for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { | |
656 | /* At this point: (!vma || addr < vma->vm_end). */ | |
657 | diff -urPX nopatch linux-2.4.21/mm/swapfile.c linux/mm/swapfile.c | |
658 | --- linux-2.4.21/mm/swapfile.c Fri Jun 13 14:51:39 2003 | |
659 | +++ linux/mm/swapfile.c Sun Jun 15 15:51:12 2003 | |
660 | @@ -725,8 +725,10 @@ | |
661 | for (type = swap_list.head; type >= 0; type = swap_info[type].next) { | |
662 | p = swap_info + type; | |
663 | if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) { | |
664 | - if (p->swap_file == nd.dentry) | |
665 | - break; | |
666 | + if (p->swap_file == nd.dentry || | |
667 | + (S_ISBLK(nd.dentry->d_inode->i_mode) && | |
668 | + p->swap_device == nd.dentry->d_inode->i_rdev)) | |
669 | + break; | |
670 | } | |
671 | prev = type; | |
672 | } | |
673 | diff -urPX nopatch linux-2.4.21/net/socket.c linux/net/socket.c | |
674 | --- linux-2.4.21/net/socket.c Fri Jun 13 14:51:39 2003 | |
675 | +++ linux/net/socket.c Sun Jun 15 15:51:12 2003 | |
676 | @@ -1305,10 +1305,18 @@ | |
677 | asmlinkage long sys_getsockopt(int fd, int level, int optname, char *optval, int *optlen) | |
678 | { | |
679 | int err; | |
680 | + int len; | |
681 | struct socket *sock; | |
682 | ||
683 | if ((sock = sockfd_lookup(fd, &err))!=NULL) | |
684 | { | |
685 | + /* XXX: insufficient for SMP, but should be redundant anyway */ | |
686 | + if (get_user(len, optlen)) | |
687 | + err = -EFAULT; | |
688 | + else | |
689 | + if (len < 0) | |
690 | + err = -EINVAL; | |
691 | + else | |
692 | if (level == SOL_SOCKET) | |
693 | err=sock_getsockopt(sock,level,optname,optval,optlen); | |
694 | else |