From b71b1068dc3b86b04f8cbc447013924b89996735 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 4 Jul 2011 05:49:30 +0000 Subject: [PATCH] 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 --- debian/changelog | 10 +++ ...-buffer-overflow-in-l2cap-config-req.patch | 30 +++++++ ...i.c-corrupted-GUID-partition-tables-.patch | 61 +++++++++++++ .../inet_diag-fix-inet_diag_bc_audit.patch | 75 ++++++++++++++++ ...nter-dereference-in-scan_get_next_rm.patch | 86 +++++++++++++++++++ ...allow-duplicate-entries-in-listener-.patch | 81 +++++++++++++++++ debian/patches/series/3 | 5 ++ 7 files changed, 348 insertions(+) create mode 100644 debian/patches/bugfix/all/bluetooth-prevent-buffer-overflow-in-l2cap-config-req.patch create mode 100644 debian/patches/bugfix/all/fs-partitions-efi.c-corrupted-GUID-partition-tables-.patch create mode 100644 debian/patches/bugfix/all/inet_diag-fix-inet_diag_bc_audit.patch create mode 100644 debian/patches/bugfix/all/ksm-fix-NULL-pointer-dereference-in-scan_get_next_rm.patch create mode 100644 debian/patches/bugfix/all/taskstats-don-t-allow-duplicate-entries-in-listener-.patch diff --git a/debian/changelog b/debian/changelog index e186ddce4..be7ae57f8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -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 diff --git a/debian/patches/bugfix/all/bluetooth-prevent-buffer-overflow-in-l2cap-config-req.patch b/debian/patches/bugfix/all/bluetooth-prevent-buffer-overflow-in-l2cap-config-req.patch new file mode 100644 index 000000000..96101b6ee --- /dev/null +++ b/debian/patches/bugfix/all/bluetooth-prevent-buffer-overflow-in-l2cap-config-req.patch @@ -0,0 +1,30 @@ +Subject: [PATCH] Bluetooth: Prevent buffer overflow in l2cap config request +From: Dan Rosenberg +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 +Cc: stable +[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); diff --git a/debian/patches/bugfix/all/fs-partitions-efi.c-corrupted-GUID-partition-tables-.patch b/debian/patches/bugfix/all/fs-partitions-efi.c-corrupted-GUID-partition-tables-.patch new file mode 100644 index 000000000..2fbe02607 --- /dev/null +++ b/debian/patches/bugfix/all/fs-partitions-efi.c-corrupted-GUID-partition-tables-.patch @@ -0,0 +1,61 @@ +From: Timo Warns +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 +Cc: Matt Domsch +Cc: Eugene Teo +Cc: Dave Jones +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + 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 + diff --git a/debian/patches/bugfix/all/inet_diag-fix-inet_diag_bc_audit.patch b/debian/patches/bugfix/all/inet_diag-fix-inet_diag_bc_audit.patch new file mode 100644 index 000000000..6a277668c --- /dev/null +++ b/debian/patches/bugfix/all/inet_diag-fix-inet_diag_bc_audit.patch @@ -0,0 +1,75 @@ +From: Eric Dumazet +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 +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +--- + 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 + diff --git a/debian/patches/bugfix/all/ksm-fix-NULL-pointer-dereference-in-scan_get_next_rm.patch b/debian/patches/bugfix/all/ksm-fix-NULL-pointer-dereference-in-scan_get_next_rm.patch new file mode 100644 index 000000000..26cb19510 --- /dev/null +++ b/debian/patches/bugfix/all/ksm-fix-NULL-pointer-dereference-in-scan_get_next_rm.patch @@ -0,0 +1,86 @@ +From: Hugh Dickins +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 +#include +#include +#include + +#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 +Tested-by: Andrea Righi +Cc: Andrea Arcangeli +Signed-off-by: Hugh Dickins +Signed-off-by: Chris Wright +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + 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 + diff --git a/debian/patches/bugfix/all/taskstats-don-t-allow-duplicate-entries-in-listener-.patch b/debian/patches/bugfix/all/taskstats-don-t-allow-duplicate-entries-in-listener-.patch new file mode 100644 index 000000000..1e2ffaadf --- /dev/null +++ b/debian/patches/bugfix/all/taskstats-don-t-allow-duplicate-entries-in-listener-.patch @@ -0,0 +1,81 @@ +From: Vasiliy Kulikov +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 +Cc: Balbir Singh +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + 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 + diff --git a/debian/patches/series/3 b/debian/patches/series/3 index f7a6f9488..8006fce64 100644 --- a/debian/patches/series/3 +++ b/debian/patches/series/3 @@ -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