[67300de] | 1 | Submitted By: Ken Moffat <ken at linuxfromscratch dot org>
|
---|
| 2 | Date: 2008-06-17
|
---|
| 3 | Initial Package Version: 2.6.24.7
|
---|
| 4 | Upstream Status: Merged
|
---|
| 5 | Origin: Debian
|
---|
| 6 | Description: 2.6.24 is no longer maintained by -stable. These patches from
|
---|
| 7 | debian (some are straight git pulls from upstream, others are backports)
|
---|
| 8 | fix 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 |
|
---|
| 34 | diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
|
---|
| 35 | index 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;
|
---|
| 73 | diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c
|
---|
| 74 | index 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
|
---|
| 116 | diff -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 |
|
---|
| 142 | diff -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 |
|
---|
| 174 | diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c
|
---|
| 175 | index 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(¤t->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(¤t->mm->mmap_sem);
|
---|
| 242 | out:
|
---|
| 243 | return ret;
|
---|
| 244 | diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
|
---|
| 245 | index 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(¤t->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(¤t->mm->mmap_sem);
|
---|
| 306 | out:
|
---|
| 307 | return ret;
|
---|
| 308 | diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
|
---|
| 309 | index 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(¤t->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(¤t->mm->mmap_sem);
|
---|
| 357 | out:
|
---|
| 358 | return ret;
|
---|
| 359 | diff --git a/include/asm-sparc/mman.h b/include/asm-sparc/mman.h
|
---|
| 360 | index 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 |
|
---|
| 375 | diff --git a/include/asm-sparc64/mman.h b/include/asm-sparc64/mman.h
|
---|
| 376 | index 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 |
|
---|
| 403 | diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c
|
---|
| 404 | index 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 */
|
---|
| 417 | diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
|
---|
| 418 | index 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 |
|
---|
| 469 | diff --git a/fs/utimes.c b/fs/utimes.c
|
---|
| 470 | index 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;
|
---|