Add security fixes and CVE references for 2.6.39.2

partitions/efi: Fix crash (oops) caused by corrupted GUID partition table (CVE-2011-1577)
ksm: fix NULL pointer dereference in scan_get_next_rmap_item() (CVE-2011-2183)
inet_diag: Fix infinite loop in inet_diag_bc_audit() (CVE-2011-2213)
taskstats: don't allow duplicate entries in listener mode (CVE-2011-2484)
bluetooth: Prevent buffer overflow in l2cap config request (CVE-2011-2497)

2.6.39.2:
- nl80211: fix check for valid SSID size in scan operations (CVE-2011-2517)
- TOMOYO: Fix oops in tomoyo_mount_acl() (CVE-2011-2518)

svn path=/dists/sid/linux-2.6/; revision=17795
This commit is contained in:
Ben Hutchings 2011-07-04 05:49:30 +00:00
parent 7ee1a2fe77
commit b71b1068dc
7 changed files with 348 additions and 0 deletions

10
debian/changelog vendored
View File

@ -12,11 +12,20 @@ linux-2.6 (2.6.39-3) UNRELEASED; urgency=low
* Update debconf template translations:
- Danish (Joe Dalton) (Closes: #632551)
- Slovak (Slavko) (Closes: #608684)
* partitions/efi: Fix crash (oops) caused by corrupted GUID partition
table (CVE-2011-1577)
* ksm: fix NULL pointer dereference in scan_get_next_rmap_item()
(CVE-2011-2183)
* inet_diag: Fix infinite loop in inet_diag_bc_audit() (CVE-2011-2213)
* taskstats: don't allow duplicate entries in listener mode (CVE-2011-2484)
* bluetooth: Prevent buffer overflow in l2cap config request
(CVE-2011-2497)
[ maximilian attems ]
* Add stable 2.6.39.2, including:
- block: Fix crash (oops) in blkdev_get() on failed exclusive open
(Closes: #631574)
- nl80211: fix check for valid SSID size in scan operations (CVE-2011-2517)
- drm/radeon/kms: viewport height has to be even
- drm/radeon/kms: fix for radeon on systems >4GB without hardware iommu
- fat: Fix corrupt inode flags when remove ATTR_SYS flag
@ -24,6 +33,7 @@ linux-2.6 (2.6.39-3) UNRELEASED; urgency=low
- cifs: don't allow cifs_reconnect to exit with NULL socket pointer
- drm/radeon/kms: do bounds checking for 3D_LOAD_VBPNTR and bump array
limit
- TOMOYO: Fix oops in tomoyo_mount_acl() (CVE-2011-2518)
For the complete list of changes, see:
http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.39.2

View File

@ -0,0 +1,30 @@
Subject: [PATCH] Bluetooth: Prevent buffer overflow in l2cap config request
From: Dan Rosenberg <drosenberg@vsecurity.com>
Date: 2011-06-24 12:38:05
A remote user can provide a small value for the command size field in
the command header of an l2cap configuration request, resulting in an
integer underflow when subtracting the size of the configuration request
header. This results in copying a very large amount of data via
memcpy() and destroying the kernel heap. Check for underflow.
Signed-off-by: Dan Rosenberg <drosenberg@vsecurity.com>
Cc: stable <stable@kernel.org>
[bwh: Adjust for 2.6.39: replace chan with l2cap_pi(sk) or sk as appropriate]
---
net/bluetooth/l2cap_core.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index e64a1c2..06ea272 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -2334,7 +2334,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
/* Reject if config buffer is too small. */
len = cmd_len - sizeof(*req);
- if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
+ if (len < 0 || l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
l2cap_build_conf_rsp(sk, rsp,
L2CAP_CONF_REJECT, flags), rsp);

View File

@ -0,0 +1,61 @@
From: Timo Warns <Warns@pre-sense.de>
Date: Thu, 26 May 2011 16:25:57 -0700
Subject: [PATCH] fs/partitions/efi.c: corrupted GUID partition tables can
cause kernel oops
commit 3eb8e74ec72736b9b9d728bad30484ec89c91dde upstream.
The kernel automatically evaluates partition tables of storage devices.
The code for evaluating GUID partitions (in fs/partitions/efi.c) contains
a bug that causes a kernel oops on certain corrupted GUID partition
tables.
This bug has security impacts, because it allows, for example, to
prepare a storage device that crashes a kernel subsystem upon connecting
the device (e.g., a "USB Stick of (Partial) Death").
crc = efi_crc32((const unsigned char *) (*gpt), le32_to_cpu((*gpt)->header_size));
computes a CRC32 checksum over gpt covering (*gpt)->header_size bytes.
There is no validation of (*gpt)->header_size before the efi_crc32 call.
A corrupted partition table may have large values for (*gpt)->header_size.
In this case, the CRC32 computation access memory beyond the memory
allocated for gpt, which may cause a kernel heap overflow.
Validate value of GUID partition table header size.
[akpm@linux-foundation.org: fix layout and indenting]
Signed-off-by: Timo Warns <warns@pre-sense.de>
Cc: Matt Domsch <Matt_Domsch@dell.com>
Cc: Eugene Teo <eugeneteo@kernel.sg>
Cc: Dave Jones <davej@codemonkey.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
fs/partitions/efi.c | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/fs/partitions/efi.c b/fs/partitions/efi.c
index 19d6750..6296b40 100644
--- a/fs/partitions/efi.c
+++ b/fs/partitions/efi.c
@@ -310,6 +310,15 @@ static int is_gpt_valid(struct parsed_partitions *state, u64 lba,
goto fail;
}
+ /* Check the GUID Partition Table header size */
+ if (le32_to_cpu((*gpt)->header_size) >
+ bdev_logical_block_size(state->bdev)) {
+ pr_debug("GUID Partition Table Header size is wrong: %u > %u\n",
+ le32_to_cpu((*gpt)->header_size),
+ bdev_logical_block_size(state->bdev));
+ goto fail;
+ }
+
/* Check the GUID Partition Table CRC */
origcrc = le32_to_cpu((*gpt)->header_crc32);
(*gpt)->header_crc32 = 0;
--
1.7.5.4

View File

@ -0,0 +1,75 @@
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Fri, 17 Jun 2011 16:25:39 -0400
Subject: [PATCH] inet_diag: fix inet_diag_bc_audit()
commit eeb1497277d6b1a0a34ed36b97e18f2bd7d6de0d upstream.
A malicious user or buggy application can inject code and trigger an
infinite loop in inet_diag_bc_audit()
Also make sure each instruction is aligned on 4 bytes boundary, to avoid
unaligned accesses.
Reported-by: Dan Rosenberg <drosenberg@vsecurity.com>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
net/ipv4/inet_diag.c | 14 ++++++--------
1 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 6ffe94c..3267d38 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -437,7 +437,7 @@ static int valid_cc(const void *bc, int len, int cc)
return 0;
if (cc == len)
return 1;
- if (op->yes < 4)
+ if (op->yes < 4 || op->yes & 3)
return 0;
len -= op->yes;
bc += op->yes;
@@ -447,11 +447,11 @@ static int valid_cc(const void *bc, int len, int cc)
static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
{
- const unsigned char *bc = bytecode;
+ const void *bc = bytecode;
int len = bytecode_len;
while (len > 0) {
- struct inet_diag_bc_op *op = (struct inet_diag_bc_op *)bc;
+ const struct inet_diag_bc_op *op = bc;
//printk("BC: %d %d %d {%d} / %d\n", op->code, op->yes, op->no, op[1].no, len);
switch (op->code) {
@@ -462,22 +462,20 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
case INET_DIAG_BC_S_LE:
case INET_DIAG_BC_D_GE:
case INET_DIAG_BC_D_LE:
- if (op->yes < 4 || op->yes > len + 4)
- return -EINVAL;
case INET_DIAG_BC_JMP:
- if (op->no < 4 || op->no > len + 4)
+ if (op->no < 4 || op->no > len + 4 || op->no & 3)
return -EINVAL;
if (op->no < len &&
!valid_cc(bytecode, bytecode_len, len - op->no))
return -EINVAL;
break;
case INET_DIAG_BC_NOP:
- if (op->yes < 4 || op->yes > len + 4)
- return -EINVAL;
break;
default:
return -EINVAL;
}
+ if (op->yes < 4 || op->yes > len + 4 || op->yes & 3)
+ return -EINVAL;
bc += op->yes;
len -= op->yes;
}
--
1.7.5.4

View File

@ -0,0 +1,86 @@
From: Hugh Dickins <hughd@google.com>
Date: Wed, 15 Jun 2011 15:08:58 -0700
Subject: [PATCH] ksm: fix NULL pointer dereference in
scan_get_next_rmap_item()
commit 2b472611a32a72f4a118c069c2d62a1a3f087afd upstream.
Andrea Righi reported a case where an exiting task can race against
ksmd::scan_get_next_rmap_item (http://lkml.org/lkml/2011/6/1/742) easily
triggering a NULL pointer dereference in ksmd.
ksm_scan.mm_slot == &ksm_mm_head with only one registered mm
CPU 1 (__ksm_exit) CPU 2 (scan_get_next_rmap_item)
list_empty() is false
lock slot == &ksm_mm_head
list_del(slot->mm_list)
(list now empty)
unlock
lock
slot = list_entry(slot->mm_list.next)
(list is empty, so slot is still ksm_mm_head)
unlock
slot->mm == NULL ... Oops
Close this race by revalidating that the new slot is not simply the list
head again.
Andrea's test case:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#define BUFSIZE getpagesize()
int main(int argc, char **argv)
{
void *ptr;
if (posix_memalign(&ptr, getpagesize(), BUFSIZE) < 0) {
perror("posix_memalign");
exit(1);
}
if (madvise(ptr, BUFSIZE, MADV_MERGEABLE) < 0) {
perror("madvise");
exit(1);
}
*(char *)NULL = 0;
return 0;
}
Reported-by: Andrea Righi <andrea@betterlinux.com>
Tested-by: Andrea Righi <andrea@betterlinux.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Signed-off-by: Hugh Dickins <hughd@google.com>
Signed-off-by: Chris Wright <chrisw@sous-sol.org>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
mm/ksm.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/mm/ksm.c b/mm/ksm.c
index d708b3e..9a68b0c 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -1302,6 +1302,12 @@ static struct rmap_item *scan_get_next_rmap_item(struct page **page)
slot = list_entry(slot->mm_list.next, struct mm_slot, mm_list);
ksm_scan.mm_slot = slot;
spin_unlock(&ksm_mmlist_lock);
+ /*
+ * Although we tested list_empty() above, a racing __ksm_exit
+ * of the last mm on the list may have removed it since then.
+ */
+ if (slot == &ksm_mm_head)
+ return NULL;
next_mm:
ksm_scan.address = 0;
ksm_scan.rmap_list = &slot->rmap_list;
--
1.7.5.4

View File

@ -0,0 +1,81 @@
From: Vasiliy Kulikov <segoon@openwall.com>
Date: Mon, 27 Jun 2011 16:18:11 -0700
Subject: [PATCH] taskstats: don't allow duplicate entries in listener mode
commit 26c4caea9d697043cc5a458b96411b86d7f6babd upstream.
Currently a single process may register exit handlers unlimited times.
It may lead to a bloated listeners chain and very slow process
terminations.
Eg after 10KK sent TASKSTATS_CMD_ATTR_REGISTER_CPUMASKs ~300 Mb of
kernel memory is stolen for the handlers chain and "time id" shows 2-7
seconds instead of normal 0.003. It makes it possible to exhaust all
kernel memory and to eat much of CPU time by triggerring numerous exits
on a single CPU.
The patch limits the number of times a single process may register
itself on a single CPU to one.
One little issue is kept unfixed - as taskstats_exit() is called before
exit_files() in do_exit(), the orphaned listener entry (if it was not
explicitly deregistered) is kept until the next someone's exit() and
implicit deregistration in send_cpu_listeners(). So, if a process
registered itself as a listener exits and the next spawned process gets
the same pid, it would inherit taskstats attributes.
Signed-off-by: Vasiliy Kulikov <segooon@gmail.com>
Cc: Balbir Singh <bsingharora@gmail.com>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
kernel/taskstats.c | 15 ++++++++++++---
1 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/kernel/taskstats.c b/kernel/taskstats.c
index 9ffea36..fc0f220 100644
--- a/kernel/taskstats.c
+++ b/kernel/taskstats.c
@@ -285,16 +285,18 @@ ret:
static int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd)
{
struct listener_list *listeners;
- struct listener *s, *tmp;
+ struct listener *s, *tmp, *s2;
unsigned int cpu;
if (!cpumask_subset(mask, cpu_possible_mask))
return -EINVAL;
+ s = NULL;
if (isadd == REGISTER) {
for_each_cpu(cpu, mask) {
- s = kmalloc_node(sizeof(struct listener), GFP_KERNEL,
- cpu_to_node(cpu));
+ if (!s)
+ s = kmalloc_node(sizeof(struct listener),
+ GFP_KERNEL, cpu_to_node(cpu));
if (!s)
goto cleanup;
s->pid = pid;
@@ -303,9 +305,16 @@ static int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd)
listeners = &per_cpu(listener_array, cpu);
down_write(&listeners->sem);
+ list_for_each_entry_safe(s2, tmp, &listeners->list, list) {
+ if (s2->pid == pid)
+ goto next_cpu;
+ }
list_add(&s->list, &listeners->list);
+ s = NULL;
+next_cpu:
up_write(&listeners->sem);
}
+ kfree(s);
return 0;
}
--
1.7.5.4

View File

@ -2,3 +2,8 @@
+ bugfix/all/stable/2.6.39.2
+ bugfix/arm/rtc-twl-Switch-to-using-threaded_irq.patch
+ bugfix/all/bridge-provide-a-cow_metrics-method-for-fake_ops.patch
+ bugfix/all/fs-partitions-efi.c-corrupted-GUID-partition-tables-.patch
+ bugfix/all/ksm-fix-NULL-pointer-dereference-in-scan_get_next_rm.patch
+ bugfix/all/inet_diag-fix-inet_diag_bc_audit.patch
+ bugfix/all/taskstats-don-t-allow-duplicate-entries-in-listener-.patch
+ bugfix/all/bluetooth-prevent-buffer-overflow-in-l2cap-config-req.patch