[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1437036437-25408-5-git-send-email-bhe@redhat.com>
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