source: patches/linux-2.6.24.7-security_fixes-1.patch@ d51db58

Last change on this file since d51db58 was 67300de, checked in by Joe Ciccone <jciccone@…>, 16 years ago

Create a clfs-1.1 branch in preperation for a RC.

  • Property mode set to 100644
File size: 15.5 KB
RevLine 
[67300de]1Submitted By: Ken Moffat <ken at linuxfromscratch dot org>
2Date: 2008-06-17
3Initial Package Version: 2.6.24.7
4Upstream Status: Merged
5Origin: Debian
6Description: 2.6.24 is no longer maintained by -stable. These patches from
7debian (some are straight git pulls from upstream, others are backports)
8fix the following: CVE-2008-{1615,1673,2136,2137,2148}.
9
10 fixes CVE-2008-1673
11 Subject: asn1: additional sanity checking during BER decoding
12 X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=ddb2c43594f22843e9f3153da151deaba1a834c5
13
14 asn1: additional sanity checking during BER decoding
15
16 - Don't trust a length which is greater than the working buffer.
17 An invalid length could cause overflow when calculating buffer size
18 for decoding oid.
19
20 - An oid length of zero is invalid and allows for an off-by-one error when
21 decoding oid because the first subid actually encodes first 2 subids.
22
23 - A primitive encoding may not have an indefinite length.
24
25 Thanks to Wei Wang from McAfee for report.
26
27 Cc: Steven French <sfrench@us.ibm.com>
28 Cc: stable@kernel.org
29 Acked-by: Patrick McHardy <kaber@trash.net>
30 Signed-off-by: Chris Wright <chrisw@sous-sol.org>
31 Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
32 ---
33
34diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
35index cb52cbb..f58e41d 100644
36--- a/fs/cifs/asn1.c
37+++ b/fs/cifs/asn1.c
38@@ -186,6 +186,11 @@ asn1_length_decode(struct asn1_ctx *ctx, unsigned int *def, unsigned int *len)
39 }
40 }
41 }
42+
43+ /* don't trust len bigger than ctx buffer */
44+ if (*len > ctx->end - ctx->pointer)
45+ return 0;
46+
47 return 1;
48 }
49
50@@ -203,6 +208,10 @@ asn1_header_decode(struct asn1_ctx *ctx,
51 if (!asn1_length_decode(ctx, &def, &len))
52 return 0;
53
54+ /* primitive shall be definite, indefinite shall be constructed */
55+ if (*con == ASN1_PRI && !def)
56+ return 0;
57+
58 if (def)
59 *eoc = ctx->pointer + len;
60 else
61@@ -389,6 +398,11 @@ asn1_oid_decode(struct asn1_ctx *ctx,
62 unsigned long *optr;
63
64 size = eoc - ctx->pointer + 1;
65+
66+ /* first subid actually encodes first two subids */
67+ if (size < 2 || size > ULONG_MAX/sizeof(unsigned long))
68+ return 0;
69+
70 *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
71 if (*oid == NULL)
72 return 0;
73diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c
74index 5daefad..7750c97 100644
75--- a/net/ipv4/netfilter/nf_nat_snmp_basic.c
76+++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c
77@@ -232,6 +232,11 @@ static unsigned char asn1_length_decode(struct asn1_ctx *ctx,
78 }
79 }
80 }
81+
82+ /* don't trust len bigger than ctx buffer */
83+ if (*len > ctx->end - ctx->pointer)
84+ return 0;
85+
86 return 1;
87 }
88
89@@ -250,6 +255,10 @@ static unsigned char asn1_header_decode(struct asn1_ctx *ctx,
90 if (!asn1_length_decode(ctx, &def, &len))
91 return 0;
92
93+ /* primitive shall be definite, indefinite shall be constructed */
94+ if (*con == ASN1_PRI && !def)
95+ return 0;
96+
97 if (def)
98 *eoc = ctx->pointer + len;
99 else
100@@ -434,6 +443,11 @@ static unsigned char asn1_oid_decode(struct asn1_ctx *ctx,
101 unsigned long *optr;
102
103 size = eoc - ctx->pointer + 1;
104+
105+ /* first subid actually encodes first two subids */
106+ if (size < 2 || size > ULONG_MAX/sizeof(unsigned long))
107+ return 0;
108+
109 *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
110 if (*oid == NULL) {
111 if (net_ratelimit())
112
113
114 fixes local ptrace dos on x86_64, CVE-2008-1615
115 from debian's 2.6.24, backported by dann frazier
116diff -urpN linux-source-2.6.24.orig/arch/x86/kernel/entry_64.S linux-source-2.6.24/arch/x86/kernel/entry_64.S
117--- linux-source-2.6.24.orig/arch/x86/kernel/entry_64.S 2008-01-24 15:58:37.000000000 -0700
118+++ linux-source-2.6.24/arch/x86/kernel/entry_64.S 2008-06-03 01:26:47.000000000 -0600
119@@ -779,7 +779,7 @@ paranoid_swapgs\trace:
120 swapgs
121 paranoid_restore\trace:
122 RESTORE_ALL 8
123- iretq
124+ jmp iret_label
125 paranoid_userspace\trace:
126 GET_THREAD_INFO(%rcx)
127 movl threadinfo_flags(%rcx),%ebx
128
129 fix ipv6 over ipv4 remotely triggerable memory leak, CVE-2008-2136
130 commit 36ca34cc3b8335eb1fe8bd9a1d0a2592980c3f02
131 Author: David S. Miller <davem@davemloft.net>
132 Date: Thu May 8 23:40:26 2008 -0700
133
134 sit: Add missing kfree_skb() on pskb_may_pull() failure.
135
136 Noticed by Paul Marks <paul@pmarks.net>.
137
138 Signed-off-by: David S. Miller <davem@davemloft.net>
139
140 Adjusted to apply to Debian's 2.6.24 by dann frazier <dannf@debian.org>
141
142diff -urpN linux-source-2.6.24.orig/net/ipv6/sit.c linux-source-2.6.24/net/ipv6/sit.c
143--- linux-source-2.6.24.orig/net/ipv6/sit.c 2008-01-24 15:58:37.000000000 -0700
144+++ linux-source-2.6.24/net/ipv6/sit.c 2008-05-21 00:00:08.000000000 -0600
145@@ -395,9 +395,9 @@ static int ipip6_rcv(struct sk_buff *skb
146 }
147
148 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
149- kfree_skb(skb);
150 read_unlock(&ipip6_lock);
151 out:
152+ kfree_skb(skb);
153 return 0;
154 }
155
156
157 * [sparc] Validate address ranges regardless of MAP_FIXED (CVE-2008-2137)
158 commit 94d149c34cda933ff5096aca94bb23bf68602f4e
159 Author: David S. Miller <davem@davemloft.net>
160 Date: Mon May 12 16:33:33 2008 -0700
161
162 sparc: Fix mremap address range validation.
163
164 Just like mmap, we need to validate address ranges regardless
165 of MAP_FIXED.
166
167 sparc{,64}_mmap_check()'s flag argument is unused, remove.
168
169 Based upon a report and preliminary patch by
170 Jan Lieskovsky <jlieskov@redhat.com>
171
172 Signed-off-by: David S. Miller <davem@davemloft.net>
173
174diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c
175index e995491..3c6b49a 100644
176--- a/arch/sparc/kernel/sys_sparc.c
177+++ b/arch/sparc/kernel/sys_sparc.c
178@@ -219,7 +219,7 @@ out:
179 return err;
180 }
181
182-int sparc_mmap_check(unsigned long addr, unsigned long len, unsigned long flags)
183+int sparc_mmap_check(unsigned long addr, unsigned long len)
184 {
185 if (ARCH_SUN4C_SUN4 &&
186 (len > 0x20000000 ||
187@@ -295,52 +295,14 @@ asmlinkage unsigned long sparc_mremap(unsigned long addr,
188 unsigned long old_len, unsigned long new_len,
189 unsigned long flags, unsigned long new_addr)
190 {
191- struct vm_area_struct *vma;
192 unsigned long ret = -EINVAL;
193- if (ARCH_SUN4C_SUN4) {
194- if (old_len > 0x20000000 || new_len > 0x20000000)
195- goto out;
196- if (addr < 0xe0000000 && addr + old_len > 0x20000000)
197- goto out;
198- }
199- if (old_len > TASK_SIZE - PAGE_SIZE ||
200- new_len > TASK_SIZE - PAGE_SIZE)
201+
202+ if (unlikely(sparc_mmap_check(addr, old_len)))
203+ goto out;
204+ if (unlikely(sparc_mmap_check(new_addr, new_len)))
205 goto out;
206 down_write(&current->mm->mmap_sem);
207- if (flags & MREMAP_FIXED) {
208- if (ARCH_SUN4C_SUN4 &&
209- new_addr < 0xe0000000 &&
210- new_addr + new_len > 0x20000000)
211- goto out_sem;
212- if (new_addr + new_len > TASK_SIZE - PAGE_SIZE)
213- goto out_sem;
214- } else if ((ARCH_SUN4C_SUN4 && addr < 0xe0000000 &&
215- addr + new_len > 0x20000000) ||
216- addr + new_len > TASK_SIZE - PAGE_SIZE) {
217- unsigned long map_flags = 0;
218- struct file *file = NULL;
219-
220- ret = -ENOMEM;
221- if (!(flags & MREMAP_MAYMOVE))
222- goto out_sem;
223-
224- vma = find_vma(current->mm, addr);
225- if (vma) {
226- if (vma->vm_flags & VM_SHARED)
227- map_flags |= MAP_SHARED;
228- file = vma->vm_file;
229- }
230-
231- new_addr = get_unmapped_area(file, addr, new_len,
232- vma ? vma->vm_pgoff : 0,
233- map_flags);
234- ret = new_addr;
235- if (new_addr & ~PAGE_MASK)
236- goto out_sem;
237- flags |= MREMAP_FIXED;
238- }
239 ret = do_mremap(addr, old_len, new_len, flags, new_addr);
240-out_sem:
241 up_write(&current->mm->mmap_sem);
242 out:
243 return ret;
244diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
245index 0dbc941..ac1bff5 100644
246--- a/arch/sparc64/kernel/sys_sparc.c
247+++ b/arch/sparc64/kernel/sys_sparc.c
248@@ -542,8 +542,7 @@ asmlinkage long sparc64_personality(unsigned long personality)
249 return ret;
250 }
251
252-int sparc64_mmap_check(unsigned long addr, unsigned long len,
253- unsigned long flags)
254+int sparc64_mmap_check(unsigned long addr, unsigned long len)
255 {
256 if (test_thread_flag(TIF_32BIT)) {
257 if (len >= STACK_TOP32)
258@@ -609,46 +608,19 @@ asmlinkage unsigned long sys64_mremap(unsigned long addr,
259 unsigned long old_len, unsigned long new_len,
260 unsigned long flags, unsigned long new_addr)
261 {
262- struct vm_area_struct *vma;
263 unsigned long ret = -EINVAL;
264
265 if (test_thread_flag(TIF_32BIT))
266 goto out;
267 if (unlikely(new_len >= VA_EXCLUDE_START))
268 goto out;
269- if (unlikely(invalid_64bit_range(addr, old_len)))
270+ if (unlikely(sparc64_mmap_check(addr, old_len)))
271+ goto out;
272+ if (unlikely(sparc64_mmap_check(new_addr, new_len)))
273 goto out;
274
275 down_write(&current->mm->mmap_sem);
276- if (flags & MREMAP_FIXED) {
277- if (invalid_64bit_range(new_addr, new_len))
278- goto out_sem;
279- } else if (invalid_64bit_range(addr, new_len)) {
280- unsigned long map_flags = 0;
281- struct file *file = NULL;
282-
283- ret = -ENOMEM;
284- if (!(flags & MREMAP_MAYMOVE))
285- goto out_sem;
286-
287- vma = find_vma(current->mm, addr);
288- if (vma) {
289- if (vma->vm_flags & VM_SHARED)
290- map_flags |= MAP_SHARED;
291- file = vma->vm_file;
292- }
293-
294- /* MREMAP_FIXED checked above. */
295- new_addr = get_unmapped_area(file, addr, new_len,
296- vma ? vma->vm_pgoff : 0,
297- map_flags);
298- ret = new_addr;
299- if (new_addr & ~PAGE_MASK)
300- goto out_sem;
301- flags |= MREMAP_FIXED;
302- }
303 ret = do_mremap(addr, old_len, new_len, flags, new_addr);
304-out_sem:
305 up_write(&current->mm->mmap_sem);
306 out:
307 return ret;
308diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
309index 1aa4288..ba5bd62 100644
310--- a/arch/sparc64/kernel/sys_sparc32.c
311+++ b/arch/sparc64/kernel/sys_sparc32.c
312@@ -867,44 +867,15 @@ asmlinkage unsigned long sys32_mremap(unsigned long addr,
313 unsigned long old_len, unsigned long new_len,
314 unsigned long flags, u32 __new_addr)
315 {
316- struct vm_area_struct *vma;
317 unsigned long ret = -EINVAL;
318 unsigned long new_addr = __new_addr;
319
320- if (old_len > STACK_TOP32 || new_len > STACK_TOP32)
321+ if (unlikely(sparc64_mmap_check(addr, old_len)))
322 goto out;
323- if (addr > STACK_TOP32 - old_len)
324+ if (unlikely(sparc64_mmap_check(new_addr, new_len)))
325 goto out;
326 down_write(&current->mm->mmap_sem);
327- if (flags & MREMAP_FIXED) {
328- if (new_addr > STACK_TOP32 - new_len)
329- goto out_sem;
330- } else if (addr > STACK_TOP32 - new_len) {
331- unsigned long map_flags = 0;
332- struct file *file = NULL;
333-
334- ret = -ENOMEM;
335- if (!(flags & MREMAP_MAYMOVE))
336- goto out_sem;
337-
338- vma = find_vma(current->mm, addr);
339- if (vma) {
340- if (vma->vm_flags & VM_SHARED)
341- map_flags |= MAP_SHARED;
342- file = vma->vm_file;
343- }
344-
345- /* MREMAP_FIXED checked above. */
346- new_addr = get_unmapped_area(file, addr, new_len,
347- vma ? vma->vm_pgoff : 0,
348- map_flags);
349- ret = new_addr;
350- if (new_addr & ~PAGE_MASK)
351- goto out_sem;
352- flags |= MREMAP_FIXED;
353- }
354 ret = do_mremap(addr, old_len, new_len, flags, new_addr);
355-out_sem:
356 up_write(&current->mm->mmap_sem);
357 out:
358 return ret;
359diff --git a/include/asm-sparc/mman.h b/include/asm-sparc/mman.h
360index e18be98..3d16b40 100644
361--- a/include/asm-sparc/mman.h
362+++ b/include/asm-sparc/mman.h
363@@ -24,9 +24,8 @@
364
365 #ifdef __KERNEL__
366 #ifndef __ASSEMBLY__
367-#define arch_mmap_check sparc_mmap_check
368-int sparc_mmap_check(unsigned long addr, unsigned long len,
369- unsigned long flags);
370+#define arch_mmap_check(addr,len,flags) sparc_mmap_check(addr,len)
371+int sparc_mmap_check(unsigned long addr, unsigned long len);
372 #endif
373 #endif
374
375diff --git a/include/asm-sparc64/mman.h b/include/asm-sparc64/mman.h
376index e584563..625be4d 100644
377--- a/include/asm-sparc64/mman.h
378+++ b/include/asm-sparc64/mman.h
379@@ -24,9 +24,8 @@
380
381 #ifdef __KERNEL__
382 #ifndef __ASSEMBLY__
383-#define arch_mmap_check sparc64_mmap_check
384-int sparc64_mmap_check(unsigned long addr, unsigned long len,
385- unsigned long flags);
386+#define arch_mmap_check(addr,len,flags) sparc64_mmap_check(addr,len)
387+int sparc64_mmap_check(unsigned long addr, unsigned long len);
388 #endif
389 #endif
390
391
392 a second part for this
393 commit 5816339310b2d9623cf413d33e538b45e815da5d
394 Author: David S. Miller <davem@davemloft.net>
395 Date: Wed May 7 02:24:28 2008 -0700
396
397 sparc: Fix mmap VA span checking.
398
399 We should not conditionalize VA range checks on MAP_FIXED.
400
401 Signed-off-by: David S. Miller <davem@davemloft.net>
402
403diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c
404index f188b5d..e995491 100644
405--- a/arch/sparc/kernel/sys_sparc.c
406+++ b/arch/sparc/kernel/sys_sparc.c
407@@ -223,8 +223,7 @@ int sparc_mmap_check(unsigned long addr, unsigned long len, unsigned long flags)
408 {
409 if (ARCH_SUN4C_SUN4 &&
410 (len > 0x20000000 ||
411- ((flags & MAP_FIXED) &&
412- addr < 0xe0000000 && addr + len > 0x20000000)))
413+ (addr < 0xe0000000 && addr + len > 0x20000000)))
414 return -EINVAL;
415
416 /* See asm-sparc/uaccess.h */
417diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
418index 8d4761f..0dbc941 100644
419--- a/arch/sparc64/kernel/sys_sparc.c
420+++ b/arch/sparc64/kernel/sys_sparc.c
421@@ -549,13 +549,13 @@ int sparc64_mmap_check(unsigned long addr, unsigned long len,
422 if (len >= STACK_TOP32)
423 return -EINVAL;
424
425- if ((flags & MAP_FIXED) && addr > STACK_TOP32 - len)
426+ if (addr > STACK_TOP32 - len)
427 return -EINVAL;
428 } else {
429 if (len >= VA_EXCLUDE_START)
430 return -EINVAL;
431
432- if ((flags & MAP_FIXED) && invalid_64bit_range(addr, len))
433+ if (invalid_64bit_range(addr, len))
434 return -EINVAL;
435 }
436
437
438 fix CVE-2008-2148 (prevent local users modifying file times without permission)
439 commit 02c6be615f1fcd37ac5ed93a3ad6692ad8991cd9
440 Author: Miklos Szeredi <mszeredi@suse.cz>
441 Date: Thu May 1 04:34:45 2008 -0700
442
443 vfs: fix permission checking in sys_utimensat
444
445 If utimensat() is called with both times set to UTIME_NOW or one of them to
446 UTIME_NOW and the other to UTIME_OMIT, then it will update the file time
447 without any permission checking.
448
449 I don't think this can be used for anything other than a local DoS, but could
450 be quite bewildering at that (e.g. "Why was that large source tree rebuilt
451 when I didn't modify anything???")
452
453 This affects all kernels from 2.6.22, when the utimensat() syscall was
454 introduced.
455
456 Fix by doing the same permission checking as for the "times == NULL" case.
457
458 Thanks to Michael Kerrisk, whose utimensat-non-conformances-and-fixes.patch in
459 -mm also fixes this (and breaks other stuff), only he didn't realize the
460 security implications of this bug.
461
462 Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
463 Cc: Ulrich Drepper <drepper@redhat.com>
464 Cc: Michael Kerrisk <mtk-manpages@gmx.net>
465 Cc: <stable@kernel.org>
466 Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
467 Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
468
469diff --git a/fs/utimes.c b/fs/utimes.c
470index a2bef77..af059d5 100644
471--- a/fs/utimes.c
472+++ b/fs/utimes.c
473@@ -40,9 +40,14 @@ asmlinkage long sys_utime(char __user *filename, struct utimbuf __user *times)
474
475 #endif
476
477+static bool nsec_special(long nsec)
478+{
479+ return nsec == UTIME_OMIT || nsec == UTIME_NOW;
480+}
481+
482 static bool nsec_valid(long nsec)
483 {
484- if (nsec == UTIME_OMIT || nsec == UTIME_NOW)
485+ if (nsec_special(nsec))
486 return true;
487
488 return nsec >= 0 && nsec <= 999999999;
489@@ -119,7 +124,15 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
490 newattrs.ia_mtime.tv_nsec = times[1].tv_nsec;
491 newattrs.ia_valid |= ATTR_MTIME_SET;
492 }
493- } else {
494+ }
495+
496+ /*
497+ * If times is NULL or both times are either UTIME_OMIT or
498+ * UTIME_NOW, then need to check permissions, because
499+ * inode_change_ok() won't do it.
500+ */
501+ if (!times || (nsec_special(times[0].tv_nsec) &&
502+ nsec_special(times[1].tv_nsec))) {
503 error = -EACCES;
504 if (IS_IMMUTABLE(inode))
505 goto mnt_drop_write_and_out;
Note: See TracBrowser for help on using the repository browser.