diff options
author | Paul Gortmaker <paul.gortmaker@windriver.com> | 2012-11-11 20:46:20 -0500 |
---|---|---|
committer | Paul Gortmaker <paul.gortmaker@windriver.com> | 2012-11-11 20:46:20 -0500 |
commit | de8314e6bce3a00cba4b524d9ee71d526fada7a1 (patch) | |
tree | 91336acb311ccaadab7b1c111840806b30f0a2b0 | |
parent | 501871719a80080804d8d635c8d1efc469b4c282 (diff) | |
download | longterm-queue-2.6.34-de8314e6bce3a00cba4b524d9ee71d526fada7a1.tar.gz |
add a couple CVE like fixes
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
-rw-r--r-- | queue/genalloc-stop-crashing-the-system-when-destroying-a-.patch | 132 | ||||
-rw-r--r-- | queue/inotify-stop-kernel-memory-leak-on-file-creation-fai.patch | 33 | ||||
-rw-r--r-- | queue/series | 2 |
3 files changed, 167 insertions, 0 deletions
diff --git a/queue/genalloc-stop-crashing-the-system-when-destroying-a-.patch b/queue/genalloc-stop-crashing-the-system-when-destroying-a-.patch new file mode 100644 index 0000000..a9f9d6c --- /dev/null +++ b/queue/genalloc-stop-crashing-the-system-when-destroying-a-.patch @@ -0,0 +1,132 @@ +From 1509309d1a9fde19371131b7131966626ff84d7c Mon Sep 17 00:00:00 2001 +From: Thadeu Lima de Souza Cascardo <cascardo@linux.vnet.ibm.com> +Date: Thu, 25 Oct 2012 13:37:51 -0700 +Subject: [PATCH] genalloc: stop crashing the system when destroying a pool + +commit eedce141cd2dad8d0cefc5468ef41898949a7031 upstream. + +The genalloc code uses the bitmap API from include/linux/bitmap.h and +lib/bitmap.c, which is based on long values. Both bitmap_set from +lib/bitmap.c and bitmap_set_ll, which is the lockless version from +genalloc.c, use BITMAP_LAST_WORD_MASK to set the first bits in a long in +the bitmap. + +That one uses (1 << bits) - 1, 0b111, if you are setting the first three +bits. This means that the API counts from the least significant bits +(LSB from now on) to the MSB. The LSB in the first long is bit 0, then. +The same works for the lookup functions. + +The genalloc code uses longs for the bitmap, as it should. In +include/linux/genalloc.h, struct gen_pool_chunk has unsigned long +bits[0] as its last member. When allocating the struct, genalloc should +reserve enough space for the bitmap. This should be a proper number of +longs that can fit the amount of bits in the bitmap. + +However, genalloc allocates an integer number of bytes that fit the +amount of bits, but may not be an integer amount of longs. 9 bytes, for +example, could be allocated for 70 bits. + +This is a problem in itself if the Least Significat Bit in a long is in +the byte with the largest address, which happens in Big Endian machines. +This means genalloc is not allocating the byte in which it will try to +set or check for a bit. + +This may end up in memory corruption, where genalloc will try to set the +bits it has not allocated. In fact, genalloc may not set these bits +because it may find them already set, because they were not zeroed since +they were not allocated. And that's what causes a BUG when +gen_pool_destroy is called and check for any set bits. + +What really happens is that genalloc uses kmalloc_node with __GFP_ZERO +on gen_pool_add_virt. With SLAB and SLUB, this means the whole slab +will be cleared, not only the requested bytes. Since struct +gen_pool_chunk has a size that is a multiple of 8, and slab sizes are +multiples of 8, we get lucky and allocate and clear the right amount of +bytes. + +Hower, this is not the case with SLOB or with older code that did memset +after allocating instead of using __GFP_ZERO. + +So, a simple module as this (running 3.6.0), will cause a crash when +rmmod'ed. + + [root@phantom-lp2 foo]# cat foo.c + #include <linux/kernel.h> + #include <linux/module.h> + #include <linux/init.h> + #include <linux/genalloc.h> + + MODULE_LICENSE("GPL"); + MODULE_VERSION("0.1"); + + static struct gen_pool *foo_pool; + + static __init int foo_init(void) + { + int ret; + foo_pool = gen_pool_create(10, -1); + if (!foo_pool) + return -ENOMEM; + ret = gen_pool_add(foo_pool, 0xa0000000, 32 << 10, -1); + if (ret) { + gen_pool_destroy(foo_pool); + return ret; + } + return 0; + } + + static __exit void foo_exit(void) + { + gen_pool_destroy(foo_pool); + } + + module_init(foo_init); + module_exit(foo_exit); + [root@phantom-lp2 foo]# zcat /proc/config.gz | grep SLOB + CONFIG_SLOB=y + [root@phantom-lp2 foo]# insmod ./foo.ko + [root@phantom-lp2 foo]# rmmod foo + ------------[ cut here ]------------ + kernel BUG at lib/genalloc.c:243! + cpu 0x4: Vector: 700 (Program Check) at [c0000000bb0e7960] + pc: c0000000003cb50c: .gen_pool_destroy+0xac/0x110 + lr: c0000000003cb4fc: .gen_pool_destroy+0x9c/0x110 + sp: c0000000bb0e7be0 + msr: 8000000000029032 + current = 0xc0000000bb0e0000 + paca = 0xc000000006d30e00 softe: 0 irq_happened: 0x01 + pid = 13044, comm = rmmod + kernel BUG at lib/genalloc.c:243! + [c0000000bb0e7ca0] d000000004b00020 .foo_exit+0x20/0x38 [foo] + [c0000000bb0e7d20] c0000000000dff98 .SyS_delete_module+0x1a8/0x290 + [c0000000bb0e7e30] c0000000000097d4 syscall_exit+0x0/0x94 + --- Exception: c00 (System Call) at 000000800753d1a0 + SP (fffd0b0e640) is in userspace + +Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@linux.vnet.ibm.com> +Cc: Paul Gortmaker <paul.gortmaker@windriver.com> +Cc: Benjamin Gaignard <benjamin.gaignard@stericsson.com> +Cc: <stable@vger.kernel.org> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + lib/genalloc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/genalloc.c b/lib/genalloc.c +index 736c3b0..3c76249 100644 +--- a/lib/genalloc.c ++++ b/lib/genalloc.c +@@ -54,7 +54,7 @@ int gen_pool_add(struct gen_pool *pool, unsigned long addr, size_t size, + struct gen_pool_chunk *chunk; + int nbits = size >> pool->min_alloc_order; + int nbytes = sizeof(struct gen_pool_chunk) + +- (nbits + BITS_PER_BYTE - 1) / BITS_PER_BYTE; ++ BITS_TO_LONGS(nbits) * sizeof(long); + + chunk = kmalloc_node(nbytes, GFP_KERNEL | __GFP_ZERO, nid); + if (unlikely(chunk == NULL)) +-- +1.7.12.1 + diff --git a/queue/inotify-stop-kernel-memory-leak-on-file-creation-fai.patch b/queue/inotify-stop-kernel-memory-leak-on-file-creation-fai.patch new file mode 100644 index 0000000..4dcda06 --- /dev/null +++ b/queue/inotify-stop-kernel-memory-leak-on-file-creation-fai.patch @@ -0,0 +1,33 @@ +From aa0923d85d7a9cc59fd4e5ea8555e045d8dacaa7 Mon Sep 17 00:00:00 2001 +From: Eric Paris <eparis@redhat.com> +Date: Tue, 23 Nov 2010 18:18:37 -0500 +Subject: [PATCH] inotify: stop kernel memory leak on file creation failure + +commit a2ae4cc9a16e211c8a128ba10d22a85431f093ab upstream. + +If inotify_init is unable to allocate a new file for the new inotify +group we leak the new group. This patch drops the reference on the +group on file allocation failure. + +Reported-by: Vegard Nossum <vegard.nossum@gmail.com> +Signed-off-by: Eric Paris <eparis@redhat.com> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + fs/notify/inotify/inotify_user.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c +index 0c6bbc0..72f8825 100644 +--- a/fs/notify/inotify/inotify_user.c ++++ b/fs/notify/inotify/inotify_user.c +@@ -674,6 +674,7 @@ SYSCALL_DEFINE1(inotify_init1, int, flags) + if (ret >= 0) + return ret; + ++ fsnotify_put_group(group); + atomic_dec(&user->inotify_devs); + out_free_uid: + free_uid(user); +-- +1.7.12.1 + diff --git a/queue/series b/queue/series index 587c099..b5d97d9 100644 --- a/queue/series +++ b/queue/series @@ -12,6 +12,8 @@ cifs-fix-cifs-stable-patch-cifs-fix-oplock-break-han.patch gro-reset-vlan_tci-on-reuse.patch md-Fix-handling-for-devices-from-2TB-to-4TB-in-0.90-.patch md-Don-t-truncate-size-at-4TB-for-RAID0-and-Linear.patch +genalloc-stop-crashing-the-system-when-destroying-a-.patch +inotify-stop-kernel-memory-leak-on-file-creation-fai.patch # from .50 i2c-algo-bit-Generate-correct-i2c-address-sequence-f.patch |