]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.4.133/x86-kexec-avoid-double-free_page-upon-do_kexec_load-failure.patch
Fixes for 5.10
[thirdparty/kernel/stable-queue.git] / releases / 4.4.133 / x86-kexec-avoid-double-free_page-upon-do_kexec_load-failure.patch
CommitLineData
10d555a3
GKH
1From a466ef76b815b86748d9870ef2a430af7b39c710 Mon Sep 17 00:00:00 2001
2From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
3Date: Wed, 9 May 2018 19:42:20 +0900
4Subject: x86/kexec: Avoid double free_page() upon do_kexec_load() failure
5
6From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
7
8commit a466ef76b815b86748d9870ef2a430af7b39c710 upstream.
9
10>From ff82bedd3e12f0d3353282054ae48c3bd8c72012 Mon Sep 17 00:00:00 2001
11From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
12Date: Wed, 9 May 2018 12:12:39 +0900
13Subject: x86/kexec: Avoid double free_page() upon do_kexec_load() failure
14
15syzbot is reporting crashes after memory allocation failure inside
16do_kexec_load() [1]. This is because free_transition_pgtable() is called
17by both init_transition_pgtable() and machine_kexec_cleanup() when memory
18allocation failed inside init_transition_pgtable().
19
20Regarding 32bit code, machine_kexec_free_page_tables() is called by both
21machine_kexec_alloc_page_tables() and machine_kexec_cleanup() when memory
22allocation failed inside machine_kexec_alloc_page_tables().
23
24Fix this by leaving the error handling to machine_kexec_cleanup()
25(and optionally setting NULL after free_page()).
26
27[1] https://syzkaller.appspot.com/bug?id=91e52396168cf2bdd572fe1e1bc0bc645c1c6b40
28
29Fixes: f5deb79679af6eb4 ("x86: kexec: Use one page table in x86_64 machine_kexec")
30Fixes: 92be3d6bdf2cb349 ("kexec/i386: allocate page table pages dynamically")
31Reported-by: syzbot <syzbot+d96f60296ef613fe1d69@syzkaller.appspotmail.com>
32Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
33Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
34Acked-by: Baoquan He <bhe@redhat.com>
35Cc: thomas.lendacky@amd.com
36Cc: prudo@linux.vnet.ibm.com
37Cc: Huang Ying <ying.huang@intel.com>
38Cc: syzkaller-bugs@googlegroups.com
39Cc: takahiro.akashi@linaro.org
40Cc: H. Peter Anvin <hpa@zytor.com>
41Cc: akpm@linux-foundation.org
42Cc: dyoung@redhat.com
43Cc: kirill.shutemov@linux.intel.com
44Link: https://lkml.kernel.org/r/201805091942.DGG12448.tMFVFSJFQOOLHO@I-love.SAKURA.ne.jp
45Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
46
47---
48 arch/x86/kernel/machine_kexec_32.c | 6 +++++-
49 arch/x86/kernel/machine_kexec_64.c | 4 +++-
50 2 files changed, 8 insertions(+), 2 deletions(-)
51
52--- a/arch/x86/kernel/machine_kexec_32.c
53+++ b/arch/x86/kernel/machine_kexec_32.c
54@@ -71,12 +71,17 @@ static void load_segments(void)
55 static void machine_kexec_free_page_tables(struct kimage *image)
56 {
57 free_page((unsigned long)image->arch.pgd);
58+ image->arch.pgd = NULL;
59 #ifdef CONFIG_X86_PAE
60 free_page((unsigned long)image->arch.pmd0);
61+ image->arch.pmd0 = NULL;
62 free_page((unsigned long)image->arch.pmd1);
63+ image->arch.pmd1 = NULL;
64 #endif
65 free_page((unsigned long)image->arch.pte0);
66+ image->arch.pte0 = NULL;
67 free_page((unsigned long)image->arch.pte1);
68+ image->arch.pte1 = NULL;
69 }
70
71 static int machine_kexec_alloc_page_tables(struct kimage *image)
72@@ -93,7 +98,6 @@ static int machine_kexec_alloc_page_tabl
73 !image->arch.pmd0 || !image->arch.pmd1 ||
74 #endif
75 !image->arch.pte0 || !image->arch.pte1) {
76- machine_kexec_free_page_tables(image);
77 return -ENOMEM;
78 }
79 return 0;
80--- a/arch/x86/kernel/machine_kexec_64.c
81+++ b/arch/x86/kernel/machine_kexec_64.c
82@@ -37,8 +37,11 @@ static struct kexec_file_ops *kexec_file
83 static void free_transition_pgtable(struct kimage *image)
84 {
85 free_page((unsigned long)image->arch.pud);
86+ image->arch.pud = NULL;
87 free_page((unsigned long)image->arch.pmd);
88+ image->arch.pmd = NULL;
89 free_page((unsigned long)image->arch.pte);
90+ image->arch.pte = NULL;
91 }
92
93 static int init_transition_pgtable(struct kimage *image, pgd_t *pgd)
94@@ -79,7 +82,6 @@ static int init_transition_pgtable(struc
95 set_pte(pte, pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL_EXEC));
96 return 0;
97 err:
98- free_transition_pgtable(image);
99 return result;
100 }
101