lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Thu, 16 Jul 2015 16:46:59 +0800
From:	Baoquan He <bhe@...hat.com>
To:	linux-kernel@...r.kernel.org, ncroxon@...hat.com,
	dyoung@...hat.com, mhuang@...hat.com
Cc:	Baoquan He <bhe@...hat.com>
Subject: [RHEL6.8 Patch 2/3] vmcore: prevent PT_NOTE p_memsz overflow during header update

Resolves: bz1236437
https://bugzilla.redhat.com/show_bug.cgi?id=1236437

Brew build:
https://brewweb.devel.redhat.com/taskinfo?taskID=9499237

This is back ported from upstream. Conflicts existed since there's no
update_note_header_size_elf64 yet in rhel6.

In commit 087350c9dcf1b38c597b31d7761f7366e2866e6b the notes size adding
in "for loop" is changed to "while loop". In this patch only this code
snippet is back ported since it can make later back port easier.

commit 38dfac843cb6d7be1874888839817404a15a6b3c
Author: Greg Pearson <greg.pearson@...com>
Date:   Mon Feb 10 14:25:36 2014 -0800

    vmcore: prevent PT_NOTE p_memsz overflow during header update

    Currently, update_note_header_size_elf64() and
    update_note_header_size_elf32() will add the size of a PT_NOTE entry to
    real_sz even if that causes real_sz to exceeds max_sz.  This patch
    corrects the while loop logic in those routines to ensure that does not
    happen and prints a warning if a PT_NOTE entry is dropped.  If zero
    PT_NOTE entries are found or this condition is encountered because the
    only entry was dropped, a warning is printed and an error is returned.

    One possible negative side effect of exceeding the max_sz limit is an
    allocation failure in merge_note_headers_elf64() or
    merge_note_headers_elf32() which would produce console output such as
    the following while booting the crash kernel.

      vmalloc: allocation failure: 14076997632 bytes
      swapper/0: page allocation failure: order:0, mode:0x80d2
      CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.10.0-gbp1 #7
      Call Trace:
        dump_stack+0x19/0x1b
        warn_alloc_failed+0xf0/0x160
        __vmalloc_node_range+0x19e/0x250
        vmalloc_user+0x4c/0x70
        merge_note_headers_elf64.constprop.9+0x116/0x24a
        vmcore_init+0x2d4/0x76c
        do_one_initcall+0xe2/0x190
        kernel_init_freeable+0x17c/0x207
        kernel_init+0xe/0x180
        ret_from_fork+0x7c/0xb0

      Kdump: vmcore not initialized

      kdump: dump target is /dev/sda4
      kdump: saving to /sysroot//var/crash/127.0.0.1-2014.01.28-13:58:52/
      kdump: saving vmcore-dmesg.txt
      Cannot open /proc/vmcore: No such file or directory
      kdump: saving vmcore-dmesg.txt failed
      kdump: saving vmcore
      kdump: saving vmcore failed

    This type of failure has been seen on a four socket prototype system
    with certain memory configurations.  Most PT_NOTE sections have a single
    entry similar to:

      n_namesz = 0x5
      n_descsz = 0x150
      n_type   = 0x1

    Occasionally, a second entry is encountered with very large n_namesz and
    n_descsz sizes:

      n_namesz = 0x80000008
      n_descsz = 0x510ae163
      n_type   = 0x80000008

    Not yet sure of the source of these extra entries, they seem bogus, but
    they shouldn't cause crash dump to fail.

    Signed-off-by: Greg Pearson <greg.pearson@...com>
    Acked-by: Vivek Goyal <vgoyal@...hat.com>
    Cc: HATAYAMA Daisuke <d.hatayama@...fujitsu.com>
    Cc: Michael Holzheu <holzheu@...ux.vnet.ibm.com>
    Cc: "Eric W. Biederman" <ebiederm@...ssion.com>
    Signed-off-by: Andrew Morton <akpm@...ux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds@...ux-foundation.org>

Signed-off-by: Baoquan He <bhe@...hat.com>
---
 fs/proc/vmcore.c | 29 +++++++++++++++++++++--------
 1 file changed, 21 insertions(+), 8 deletions(-)

diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
index b53862a..97c950b 100644
--- a/fs/proc/vmcore.c
+++ b/fs/proc/vmcore.c
@@ -217,7 +217,6 @@ static int __init merge_note_headers_elf64(char *elfptr, size_t *elfsz,
 	ehdr_ptr = (Elf64_Ehdr *)elfptr;
 	phdr_ptr = (Elf64_Phdr*)(elfptr + sizeof(Elf64_Ehdr));
 	for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
-		int j;
 		void *notes_section;
 		struct vmcore *new;
 		u64 offset, max_sz, sz, real_sz = 0;
@@ -235,12 +234,15 @@ static int __init merge_note_headers_elf64(char *elfptr, size_t *elfsz,
 			return rc;
 		}
 		nhdr_ptr = notes_section;
-		for (j = 0; j < max_sz; j += sz) {
-			if (nhdr_ptr->n_namesz == 0)
-				break;
+		while (nhdr_ptr->n_namesz != 0) {
 			sz = sizeof(Elf64_Nhdr) +
 				((nhdr_ptr->n_namesz + 3) & ~3) +
 				((nhdr_ptr->n_descsz + 3) & ~3);
+			if ((real_sz + sz) > max_sz) {
+				pr_warn("Warning: Exceeded p_memsz, dropping PT_NOTE entry n_namesz=0x%x, n_descsz=0x%x\n",
+					nhdr_ptr->n_namesz, nhdr_ptr->n_descsz);
+				break;
+			}
 			real_sz += sz;
 			nhdr_ptr = (Elf64_Nhdr*)((char*)nhdr_ptr + sz);
 		}
@@ -256,6 +258,10 @@ static int __init merge_note_headers_elf64(char *elfptr, size_t *elfsz,
 		list_add_tail(&new->list, vc_list);
 		phdr_sz += real_sz;
 		kfree(notes_section);
+		if (real_sz == 0) {
+			pr_warn("Warning: Zero PT_NOTE entries found\n");
+			return -EINVAL;
+		}
 	}
 
 	/* Prepare merged PT_NOTE program header. */
@@ -298,7 +304,6 @@ static int __init merge_note_headers_elf32(char *elfptr, size_t *elfsz,
 	ehdr_ptr = (Elf32_Ehdr *)elfptr;
 	phdr_ptr = (Elf32_Phdr*)(elfptr + sizeof(Elf32_Ehdr));
 	for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
-		int j;
 		void *notes_section;
 		struct vmcore *new;
 		u64 offset, max_sz, sz, real_sz = 0;
@@ -316,12 +321,15 @@ static int __init merge_note_headers_elf32(char *elfptr, size_t *elfsz,
 			return rc;
 		}
 		nhdr_ptr = notes_section;
-		for (j = 0; j < max_sz; j += sz) {
-			if (nhdr_ptr->n_namesz == 0)
-				break;
+		while (nhdr_ptr->n_namesz != 0) {
 			sz = sizeof(Elf32_Nhdr) +
 				((nhdr_ptr->n_namesz + 3) & ~3) +
 				((nhdr_ptr->n_descsz + 3) & ~3);
+			if ((real_sz + sz) > max_sz) {
+				pr_warn("Warning: Exceeded p_memsz, dropping PT_NOTE entry n_namesz=0x%x, n_descsz=0x%x\n",
+					nhdr_ptr->n_namesz, nhdr_ptr->n_descsz);
+				break;
+			}
 			real_sz += sz;
 			nhdr_ptr = (Elf32_Nhdr*)((char*)nhdr_ptr + sz);
 		}
@@ -337,6 +345,11 @@ static int __init merge_note_headers_elf32(char *elfptr, size_t *elfsz,
 		list_add_tail(&new->list, vc_list);
 		phdr_sz += real_sz;
 		kfree(notes_section);
+		if (real_sz == 0) {
+			pr_warn("Warning: Zero PT_NOTE entries found\n");
+			return -EINVAL;
+		}
+
 	}
 
 	/* Prepare merged PT_NOTE program header. */
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ