]>
Commit | Line | Data |
---|---|---|
a10bcd7f JR |
1 | diff -urPX nopatch linux-2.4.22/Documentation/Configure.help linux-2.4.22-ow1/Documentation/Configure.help |
2 | --- linux-2.4.22/Documentation/Configure.help Mon Aug 25 15:44:39 2003 | |
3 | +++ linux-2.4.22-ow1/Documentation/Configure.help Thu Aug 28 06:23:03 2003 | |
4 | @@ -27486,6 +27490,31 @@ | |
5 | ||
6 | CONFIG_CRYPTO_TEST | |
7 | Quick & dirty crypto test module. | |
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.22/arch/i386/config.in linux-2.4.22-ow1/arch/i386/config.in | |
37 | --- linux-2.4.22/arch/i386/config.in Mon Aug 25 15:44:39 2003 | |
38 | +++ linux-2.4.22-ow1/arch/i386/config.in Thu Aug 28 06:20:31 2003 | |
39 | @@ -461,6 +464,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.22/arch/i386/kernel/head.S linux-2.4.22-ow1/arch/i386/kernel/head.S | |
57 | --- linux-2.4.22/arch/i386/kernel/head.S Fri Jun 13 18:51:29 2003 | |
58 | +++ linux-2.4.22-ow1/arch/i386/kernel/head.S Thu Aug 28 06:20:31 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.22/arch/i386/kernel/signal.c linux-2.4.22-ow1/arch/i386/kernel/signal.c | |
72 | --- linux-2.4.22/arch/i386/kernel/signal.c Sat Aug 3 04:39:42 2002 | |
73 | +++ linux-2.4.22-ow1/arch/i386/kernel/signal.c Thu Aug 28 06:20:31 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.22/arch/i386/kernel/traps.c linux-2.4.22-ow1/arch/i386/kernel/traps.c | |
107 | --- linux-2.4.22/arch/i386/kernel/traps.c Fri Nov 29 02:53:09 2002 | |
108 | +++ linux-2.4.22-ow1/arch/i386/kernel/traps.c Thu Aug 28 06:20:31 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.22/arch/ia64/ia32/sys_ia32.c linux-2.4.22-ow1/arch/ia64/ia32/sys_ia32.c | |
313 | --- linux-2.4.22/arch/ia64/ia32/sys_ia32.c Mon Aug 25 15:44:39 2003 | |
314 | +++ linux-2.4.22-ow1/arch/ia64/ia32/sys_ia32.c Thu Aug 28 06:20:31 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.22/arch/mips64/kernel/linux32.c linux-2.4.22-ow1/arch/mips64/kernel/linux32.c | |
325 | --- linux-2.4.22/arch/mips64/kernel/linux32.c Mon Aug 25 15:44:40 2003 | |
326 | +++ linux-2.4.22-ow1/arch/mips64/kernel/linux32.c Thu Aug 28 06:32:24 2003 | |
327 | @@ -455,6 +471,8 @@ | |
328 | *ap++ = (char *) A(addr); | |
329 | arg += sizeof(unsigned int); | |
330 | n++; | |
331 | + if (n >= (MAX_ARG_PAGES * PAGE_SIZE) / sizeof(char *)) | |
332 | + return -E2BIG; | |
333 | } while (addr); | |
334 | return n - 1; | |
335 | } | |
336 | diff -urPX nopatch linux-2.4.22/arch/x86_64/ia32/sys_ia32.c linux-2.4.22-ow1/arch/x86_64/ia32/sys_ia32.c | |
337 | --- linux-2.4.22/arch/x86_64/ia32/sys_ia32.c Mon Aug 25 15:44:40 2003 | |
338 | +++ linux-2.4.22-ow1/arch/x86_64/ia32/sys_ia32.c Thu Aug 28 06:20:31 2003 | |
339 | @@ -2135,7 +2135,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.22/drivers/scsi/st.c linux-2.4.22-ow1/drivers/scsi/st.c | |
349 | --- linux-2.4.22/drivers/scsi/st.c Mon Aug 25 15:44:42 2003 | |
350 | +++ linux-2.4.22-ow1/drivers/scsi/st.c Thu Aug 28 06:44:05 2003 | |
351 | @@ -1639,7 +1639,7 @@ | |
352 | if (STps->drv_block >= 0) | |
353 | STps->drv_block += 1; | |
354 | (STp->buffer)->buffer_bytes = 0; | |
355 | - return (-ENOMEM); | |
356 | + return (-EIO); | |
357 | } | |
358 | (STp->buffer)->buffer_bytes = bytes - transfer; | |
359 | } else { | |
360 | diff -urPX nopatch linux-2.4.22/fs/binfmt_aout.c linux-2.4.22-ow1/fs/binfmt_aout.c | |
361 | --- linux-2.4.22/fs/binfmt_aout.c Sat Nov 3 04:39:20 2001 | |
362 | +++ linux-2.4.22-ow1/fs/binfmt_aout.c Thu Aug 28 06:20:52 2003 | |
363 | @@ -4,6 +4,7 @@ | |
364 | * Copyright (C) 1991, 1992, 1996 Linus Torvalds | |
365 | */ | |
366 | ||
367 | +#include <linux/config.h> | |
368 | #include <linux/module.h> | |
369 | ||
370 | #include <linux/sched.h> | |
371 | @@ -307,6 +308,9 @@ | |
372 | current->mm->mmap = NULL; | |
373 | compute_creds(bprm); | |
374 | current->flags &= ~PF_FORKNOEXEC; | |
375 | +#ifdef CONFIG_HARDEN_STACK | |
376 | + if (N_FLAGS(ex) & F_STACKEXEC) current->flags |= PF_STACKEXEC; | |
377 | +#endif | |
378 | #ifdef __sparc__ | |
379 | if (N_MAGIC(ex) == NMAGIC) { | |
380 | loff_t pos = fd_offset; | |
381 | diff -urPX nopatch linux-2.4.22/fs/binfmt_elf.c linux-2.4.22-ow1/fs/binfmt_elf.c | |
382 | --- linux-2.4.22/fs/binfmt_elf.c Mon Aug 25 15:44:43 2003 | |
383 | +++ linux-2.4.22-ow1/fs/binfmt_elf.c Thu Aug 28 06:46:34 2003 | |
384 | @@ -9,6 +9,7 @@ | |
385 | * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com). | |
386 | */ | |
387 | ||
388 | +#include <linux/config.h> | |
389 | #include <linux/module.h> | |
390 | ||
391 | #include <linux/fs.h> | |
392 | @@ -73,8 +76,17 @@ | |
393 | #define ELF_PAGEOFFSET(_v) ((_v) & (ELF_MIN_ALIGN-1)) | |
394 | #define ELF_PAGEALIGN(_v) (((_v) + ELF_MIN_ALIGN - 1) & ~(ELF_MIN_ALIGN - 1)) | |
395 | ||
396 | -static struct linux_binfmt elf_format = { | |
397 | - NULL, THIS_MODULE, load_elf_binary, load_elf_library, elf_core_dump, ELF_EXEC_PAGESIZE | |
398 | +#ifndef CONFIG_HARDEN_STACK | |
399 | +static | |
400 | +#endif | |
401 | +struct linux_binfmt elf_format = { | |
402 | + NULL, THIS_MODULE, load_elf_binary, | |
403 | +#ifdef CONFIG_BINFMT_ELF_AOUT | |
404 | + load_elf_library, | |
405 | +#else | |
406 | + NULL, | |
407 | +#endif | |
408 | + elf_core_dump, ELF_EXEC_PAGESIZE | |
409 | }; | |
410 | ||
411 | #define BAD_ADDR(x) ((unsigned long)(x) > TASK_SIZE) | |
412 | @@ -618,6 +644,9 @@ | |
413 | current->mm->end_code = 0; | |
414 | current->mm->mmap = NULL; | |
415 | current->flags &= ~PF_FORKNOEXEC; | |
416 | +#ifdef CONFIG_HARDEN_STACK | |
417 | + if (elf_ex.e_flags & EF_STACKEXEC) current->flags |= PF_STACKEXEC; | |
418 | +#endif | |
419 | elf_entry = (unsigned long) elf_ex.e_entry; | |
420 | ||
421 | /* Do this so that we can load the interpreter, if need be. We will | |
422 | diff -urPX nopatch linux-2.4.22/fs/exec.c linux-2.4.22-ow1/fs/exec.c | |
423 | --- linux-2.4.22/fs/exec.c Mon Aug 25 15:44:43 2003 | |
424 | +++ linux-2.4.22-ow1/fs/exec.c Thu Aug 28 06:20:52 2003 | |
425 | @@ -610,6 +614,10 @@ | |
426 | } | |
427 | current->comm[i] = '\0'; | |
428 | ||
429 | +#ifdef CONFIG_HARDEN_STACK | |
430 | + current->flags &= ~PF_STACKEXEC; | |
431 | +#endif | |
432 | + | |
433 | flush_thread(); | |
434 | ||
435 | de_thread(current); | |
436 | @@ -747,6 +755,8 @@ | |
437 | || atomic_read(¤t->fs->count) > 1 | |
438 | || atomic_read(¤t->files->count) > 1 | |
439 | || atomic_read(¤t->sig->count) > 1) { | |
440 | + /* XXX: should fail rather than execute with no raised | |
441 | + * effective privileges */ | |
442 | if(!capable(CAP_SETUID)) { | |
443 | bprm->e_uid = current->uid; | |
444 | bprm->e_gid = current->gid; | |
445 | diff -urPX nopatch linux-2.4.22/include/asm-i386/a.out.h linux-2.4.22-ow1/include/asm-i386/a.out.h | |
446 | --- linux-2.4.22/include/asm-i386/a.out.h Fri Jun 16 22:33:06 1995 | |
447 | +++ linux-2.4.22-ow1/include/asm-i386/a.out.h Thu Aug 28 06:20:52 2003 | |
448 | @@ -19,7 +19,16 @@ | |
449 | ||
450 | #ifdef __KERNEL__ | |
451 | ||
452 | +#include <linux/config.h> | |
453 | + | |
454 | +#ifdef CONFIG_HARDEN_STACK | |
455 | +#define STACK_TOP ( \ | |
456 | + (current->flags & PF_STACKEXEC) \ | |
457 | + ? TASK_SIZE - _STK_LIM \ | |
458 | + : TASK_SIZE ) | |
459 | +#else | |
460 | #define STACK_TOP TASK_SIZE | |
461 | +#endif | |
462 | ||
463 | #endif | |
464 | ||
465 | diff -urPX nopatch linux-2.4.22/include/asm-i386/processor.h linux-2.4.22-ow1/include/asm-i386/processor.h | |
466 | --- linux-2.4.22/include/asm-i386/processor.h Mon Aug 25 15:44:43 2003 | |
467 | +++ linux-2.4.22-ow1/include/asm-i386/processor.h Thu Aug 28 06:20:52 2003 | |
468 | @@ -261,10 +261,28 @@ | |
469 | */ | |
470 | #define TASK_SIZE (PAGE_OFFSET) | |
471 | ||
472 | +/* | |
473 | + * Magic addresses to return to the kernel from signal handlers. These two | |
474 | + * should be beyond user code segment limit, adjacent, and MAGIC_SIGRETURN | |
475 | + * should be even. | |
476 | + */ | |
477 | +#define MAGIC_SIGRETURN (PAGE_OFFSET + 0xDE0000) | |
478 | +#define MAGIC_RT_SIGRETURN (PAGE_OFFSET + 0xDE0001) | |
479 | + | |
480 | /* This decides where the kernel will search for a free chunk of vm | |
481 | * space during mmap's. | |
482 | */ | |
483 | +#if defined(CONFIG_HARDEN_STACK) && defined(CONFIG_BINFMT_ELF) | |
484 | +extern struct linux_binfmt elf_format; | |
485 | +#define TASK_UNMAPPED_BASE(size) ( \ | |
486 | + current->binfmt == &elf_format && \ | |
487 | + !(current->flags & PF_STACKEXEC) && \ | |
488 | + (size) < 0x00ef0000UL \ | |
489 | + ? 0x00110000UL \ | |
490 | + : TASK_SIZE / 3 ) | |
491 | +#else | |
492 | #define TASK_UNMAPPED_BASE (TASK_SIZE / 3) | |
493 | +#endif | |
494 | ||
495 | /* | |
496 | * Size of io_bitmap in longwords: 32 is ports 0-0x3ff. | |
497 | diff -urPX nopatch linux-2.4.22/include/linux/a.out.h linux-2.4.22-ow1/include/linux/a.out.h | |
498 | --- linux-2.4.22/include/linux/a.out.h Thu Nov 22 22:46:18 2001 | |
499 | +++ linux-2.4.22-ow1/include/linux/a.out.h Thu Aug 28 06:20:52 2003 | |
500 | @@ -37,6 +37,9 @@ | |
501 | M_MIPS2 = 152 /* MIPS R6000/R4000 binary */ | |
502 | }; | |
503 | ||
504 | +/* Constants for the N_FLAGS field */ | |
505 | +#define F_STACKEXEC 1 /* Executable stack area forced */ | |
506 | + | |
507 | #if !defined (N_MAGIC) | |
508 | #define N_MAGIC(exec) ((exec).a_info & 0xffff) | |
509 | #endif | |
510 | diff -urPX nopatch linux-2.4.22/include/linux/binfmts.h linux-2.4.22-ow1/include/linux/binfmts.h | |
511 | --- linux-2.4.22/include/linux/binfmts.h Thu Nov 22 22:46:19 2001 | |
512 | +++ linux-2.4.22-ow1/include/linux/binfmts.h Thu Aug 28 06:20:52 2003 | |
513 | @@ -1,6 +1,7 @@ | |
514 | #ifndef _LINUX_BINFMTS_H | |
515 | #define _LINUX_BINFMTS_H | |
516 | ||
517 | +#include <linux/config.h> | |
518 | #include <linux/ptrace.h> | |
519 | #include <linux/capability.h> | |
520 | ||
521 | diff -urPX nopatch linux-2.4.22/include/linux/elf.h linux-2.4.22-ow1/include/linux/elf.h | |
522 | --- linux-2.4.22/include/linux/elf.h Fri Nov 29 02:53:15 2002 | |
523 | +++ linux-2.4.22-ow1/include/linux/elf.h Thu Aug 28 06:20:52 2003 | |
524 | @@ -255,6 +255,8 @@ | |
525 | #define R_MIPS_LOVENDOR 100 | |
526 | #define R_MIPS_HIVENDOR 127 | |
527 | ||
528 | +/* Constants for the e_flags field */ | |
529 | +#define EF_STACKEXEC 1 /* Executable stack area forced */ | |
530 | ||
531 | /* | |
532 | * Sparc ELF relocation types | |
533 | diff -urPX nopatch linux-2.4.22/include/linux/kernel.h linux-2.4.22-ow1/include/linux/kernel.h | |
534 | --- linux-2.4.22/include/linux/kernel.h Fri Nov 29 02:53:15 2002 | |
535 | +++ linux-2.4.22-ow1/include/linux/kernel.h Thu Aug 28 06:20:52 2003 | |
536 | @@ -71,14 +71,17 @@ | |
537 | extern long long simple_strtoll(const char *,char **,unsigned int); | |
538 | extern int sprintf(char * buf, const char * fmt, ...) | |
539 | __attribute__ ((format (printf, 2, 3))); | |
540 | -extern int vsprintf(char *buf, const char *, va_list); | |
541 | +extern int vsprintf(char *buf, const char *, va_list) | |
542 | + __attribute__ ((format (printf, 2, 0))); | |
543 | extern int snprintf(char * buf, size_t size, const char * fmt, ...) | |
544 | __attribute__ ((format (printf, 3, 4))); | |
545 | -extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args); | |
546 | +extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) | |
547 | + __attribute__ ((format (printf, 3, 0))); | |
548 | ||
549 | extern int sscanf(const char *, const char *, ...) | |
550 | - __attribute__ ((format (scanf,2,3))); | |
551 | -extern int vsscanf(const char *, const char *, va_list); | |
552 | + __attribute__ ((format (scanf, 2, 3))); | |
553 | +extern int vsscanf(const char *, const char *, va_list) | |
554 | + __attribute__ ((format (scanf, 2, 0))); | |
555 | ||
556 | extern int get_option(char **str, int *pint); | |
557 | extern char *get_options(char *str, int nints, int *ints); | |
558 | @@ -170,6 +173,26 @@ | |
559 | ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) | |
560 | #define max_t(type,x,y) \ | |
561 | ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; }) | |
562 | + | |
563 | +#define security_alert(normal_msg, flood_msg, args...) \ | |
564 | +({ \ | |
565 | + static unsigned long warning_time = 0, no_flood_yet = 0; \ | |
566 | + static spinlock_t security_alert_lock = SPIN_LOCK_UNLOCKED; \ | |
567 | +\ | |
568 | + spin_lock(&security_alert_lock); \ | |
569 | +\ | |
570 | +/* Make sure at least one minute passed since the last warning logged */ \ | |
571 | + if (!warning_time || jiffies - warning_time > 60 * HZ) { \ | |
572 | + warning_time = jiffies; no_flood_yet = 1; \ | |
573 | + printk(KERN_ALERT "Security: " normal_msg "\n", ## args); \ | |
574 | + } else if (no_flood_yet) { \ | |
575 | + warning_time = jiffies; no_flood_yet = 0; \ | |
576 | + printk(KERN_ALERT "Security: more " flood_msg \ | |
577 | + ", logging disabled for a minute\n"); \ | |
578 | + } \ | |
579 | +\ | |
580 | + spin_unlock(&security_alert_lock); \ | |
581 | +}) | |
582 | ||
583 | extern void __out_of_line_bug(int line) ATTRIB_NORET; | |
584 | #define out_of_line_bug() __out_of_line_bug(__LINE__) | |
585 | diff -urPX nopatch linux-2.4.22/include/linux/sched.h linux-2.4.22-ow1/include/linux/sched.h | |
586 | --- linux-2.4.22/include/linux/sched.h Fri Jun 13 18:51:39 2003 | |
587 | +++ linux-2.4.22-ow1/include/linux/sched.h Thu Aug 28 06:20:52 2003 | |
588 | @@ -435,6 +435,8 @@ | |
589 | ||
590 | #define PF_USEDFPU 0x00100000 /* task used FPU this quantum (SMP) */ | |
591 | ||
592 | +#define PF_STACKEXEC 0x01000000 /* Executable stack area forced */ | |
593 | + | |
594 | /* | |
595 | * Ptrace flags | |
596 | */ | |
597 | diff -urPX nopatch linux-2.4.22/kernel/sysctl.c linux-2.4.22-ow1/kernel/sysctl.c | |
598 | --- linux-2.4.22/kernel/sysctl.c Mon Aug 25 15:44:44 2003 | |
599 | +++ linux-2.4.22-ow1/kernel/sysctl.c Thu Aug 28 06:20:52 2003 | |
600 | @@ -352,6 +352,9 @@ | |
601 | int old_len; | |
602 | if (!oldlenp || get_user(old_len, oldlenp)) | |
603 | return -EFAULT; | |
604 | + /* XXX: insufficient for SMP, but should be redundant anyway */ | |
605 | + if ((ssize_t)old_len < 0) | |
606 | + return -EINVAL; | |
607 | } | |
608 | tmp = &root_table_header.ctl_entry; | |
609 | do { | |
610 | diff -urPX nopatch linux-2.4.22/mm/mmap.c linux-2.4.22-ow1/mm/mmap.c | |
611 | --- linux-2.4.22/mm/mmap.c Fri Jun 13 18:51:39 2003 | |
612 | +++ linux-2.4.22-ow1/mm/mmap.c Thu Aug 28 06:20:52 2003 | |
613 | @@ -3,6 +3,7 @@ | |
614 | * | |
615 | * Written by obz. | |
616 | */ | |
617 | +#include <linux/config.h> | |
618 | #include <linux/slab.h> | |
619 | #include <linux/shm.h> | |
620 | #include <linux/mman.h> | |
621 | @@ -626,7 +627,11 @@ | |
622 | (!vma || addr + len <= vma->vm_start)) | |
623 | return addr; | |
624 | } | |
625 | +#if defined(CONFIG_HARDEN_STACK) && defined(CONFIG_BINFMT_ELF) | |
626 | + addr = PAGE_ALIGN(TASK_UNMAPPED_BASE(len)); | |
627 | +#else | |
628 | addr = PAGE_ALIGN(TASK_UNMAPPED_BASE); | |
629 | +#endif | |
630 | ||
631 | for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { | |
632 | /* At this point: (!vma || addr < vma->vm_end). */ | |
633 | diff -urPX nopatch linux-2.4.22/mm/swapfile.c linux-2.4.22-ow1/mm/swapfile.c | |
634 | --- linux-2.4.22/mm/swapfile.c Mon Aug 25 15:44:44 2003 | |
635 | +++ linux-2.4.22-ow1/mm/swapfile.c Thu Aug 28 06:20:52 2003 | |
636 | @@ -738,8 +738,10 @@ | |
637 | for (type = swap_list.head; type >= 0; type = swap_info[type].next) { | |
638 | p = swap_info + type; | |
639 | if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) { | |
640 | - if (p->swap_file == nd.dentry) | |
641 | - break; | |
642 | + if (p->swap_file == nd.dentry || | |
643 | + (S_ISBLK(nd.dentry->d_inode->i_mode) && | |
644 | + p->swap_device == nd.dentry->d_inode->i_rdev)) | |
645 | + break; | |
646 | } | |
647 | prev = type; | |
648 | } | |
649 | diff -urPX nopatch linux-2.4.22/net/socket.c linux-2.4.22-ow1/net/socket.c | |
650 | --- linux-2.4.22/net/socket.c Mon Aug 25 15:44:44 2003 | |
651 | +++ linux-2.4.22-ow1/net/socket.c Thu Aug 28 06:20:52 2003 | |
652 | @@ -1305,10 +1305,18 @@ | |
653 | asmlinkage long sys_getsockopt(int fd, int level, int optname, char *optval, int *optlen) | |
654 | { | |
655 | int err; | |
656 | + int len; | |
657 | struct socket *sock; | |
658 | ||
659 | if ((sock = sockfd_lookup(fd, &err))!=NULL) | |
660 | { | |
661 | + /* XXX: insufficient for SMP, but should be redundant anyway */ | |
662 | + if (get_user(len, optlen)) | |
663 | + err = -EFAULT; | |
664 | + else | |
665 | + if (len < 0) | |
666 | + err = -EINVAL; | |
667 | + else | |
668 | if (level == SOL_SOCKET) | |
669 | err=sock_getsockopt(sock,level,optname,optval,optlen); | |
670 | else |