kernel BUG at include/linux/mm.h:LINE!

64 views
Skip to first unread message

syzbot

unread,
May 1, 2018, 4:31:02 AM5/1/18
to ak...@linux-foundation.org, b...@redhat.com, dyo...@redhat.com, h...@zytor.com, kirill....@linux.intel.com, linux-...@vger.kernel.org, mi...@redhat.com, pr...@linux.vnet.ibm.com, syzkall...@googlegroups.com, takahir...@linaro.org, tg...@linutronix.de, thomas....@amd.com, x...@kernel.org, xlp...@redhat.com
Hello,

syzbot found the following crash on:

HEAD commit: 6da6c0db5316 Linux v4.17-rc3
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?id=5229040734568448
kernel config:
https://syzkaller.appspot.com/x/.config?id=6493557782959164711
dashboard link: https://syzkaller.appspot.com/bug?extid=d96f60296ef613fe1d69
compiler: gcc (GCC) 8.0.1 20180413 (experimental)

Unfortunately, I don't have any reproducer for this crash yet.

IMPORTANT: if you fix the bug, please add the following tag to the commit:
Reported-by: syzbot+d96f60...@syzkaller.appspotmail.com

flags: 0x2fffc0000000000()
raw: 02fffc0000000000 0000000000000000 0000000000000000 00000000ffffffff
raw: ffffea00071786e0 ffff8801daf2fdd8 0000000000000000 0000000000000000
page dumped because: VM_BUG_ON_PAGE(page_ref_count(page) == 0)
------------[ cut here ]------------
kernel BUG at include/linux/mm.h:492!
invalid opcode: 0000 [#1] SMP KASAN
Dumping ftrace buffer:
(ftrace buffer empty)
Modules linked in:
CPU: 1 PID: 10012 Comm: syz-executor1 Not tainted 4.17.0-rc3+ #25
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
RIP: 0010:put_page_testzero include/linux/mm.h:492 [inline]
RIP: 0010:__free_pages+0x14f/0x180 mm/page_alloc.c:4427
RSP: 0018:ffff8801b881fc08 EFLAGS: 00010203
RAX: 0000000000000000 RBX: 1ffff10037103f82 RCX: 0000000000000000
RDX: 0000000000040000 RSI: ffffffff81a5b455 RDI: ffffed0037103f70
RBP: ffff8801b881fc98 R08: ffff8801b0c9a080 R09: 0000000000000006
R10: ffff8801b0c9a080 R11: 0000000000000000 R12: ffffea00072e24c0
R13: 1ffff10037103f86 R14: ffff8801b881fc70 R15: ffffea00072e24dc
FS: 00007f2e2794c700(0000) GS:ffff8801daf00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000020000000 CR3: 00000001ae61b000 CR4: 00000000001406e0
DR0: 0000000020000000 DR1: 0000000020000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000600
Call Trace:
free_pages+0x50/0x90 mm/page_alloc.c:4441
free_transition_pgtable+0x68/0xf0 arch/x86/kernel/machine_kexec_64.c:42
machine_kexec_cleanup+0x9/0x10 arch/x86/kernel/machine_kexec_64.c:268
kimage_free+0x1f2/0x270 kernel/kexec_core.c:639
do_kexec_load+0x53a/0x790 kernel/kexec.c:170
__do_sys_kexec_load kernel/kexec.c:243 [inline]
__se_sys_kexec_load kernel/kexec.c:218 [inline]
__x64_sys_kexec_load+0x1bf/0x230 kernel/kexec.c:218
do_syscall_64+0x1b1/0x800 arch/x86/entry/common.c:287
entry_SYSCALL_64_after_hwframe+0x49/0xbe
RIP: 0033:0x455979
RSP: 002b:00007f2e2794bc68 EFLAGS: 00000246 ORIG_RAX: 00000000000000f6
RAX: ffffffffffffffda RBX: 00007f2e2794c6d4 RCX: 0000000000455979
RDX: 0000000020000000 RSI: 0000000000000001 RDI: 0000000000000000
RBP: 000000000072bea0 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000013
R13: 0000000000000403 R14: 00000000006fa0e8 R15: 000000000000000a
Code: 68 5b 41 5c 41 5d 41 5e 41 5f 5d c3 8b b5 74 ff ff ff 4c 89 e7 e8 02
87 ff ff eb c6 48 c7 c6 00 66 d0 87 4c 89 e7 e8 81 7a 0d 00 <0f> 0b 4c 89
ef 89 85 70 ff ff ff e8 51 7b 1d 00 8b 85 70 ff ff
RIP: put_page_testzero include/linux/mm.h:492 [inline] RSP: ffff8801b881fc08
RIP: __free_pages+0x14f/0x180 mm/page_alloc.c:4427 RSP: ffff8801b881fc08
---[ end trace f3320966708ec92c ]---


---
This bug is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzk...@googlegroups.com.

syzbot will keep track of this bug report.
If you forgot to add the Reported-by tag, once the fix for this bug is
merged
into any tree, please reply to this email with:
#syz fix: exact-commit-title
To mark this as a duplicate of another syzbot report, please reply with:
#syz dup: exact-subject-of-another-report
If it's a one-off invalid bug report, please reply with:
#syz invalid
Note: if the crash happens again, it will cause creation of a new bug
report.
Note: all commands must start from beginning of the line in the email body.

Tetsuo Handa

unread,
May 1, 2018, 6:10:45 AM5/1/18
to syzbot, kirill....@linux.intel.com, linux-...@vger.kernel.org, syzkall...@googlegroups.com, Huang Ying, H. Peter Anvin, Ingo Molnar, ak...@linux-foundation.org, b...@redhat.com, dyo...@redhat.com, mi...@redhat.com, pr...@linux.vnet.ibm.com, takahir...@linaro.org, tg...@linutronix.de, thomas....@amd.com, x...@kernel.org, xlp...@redhat.com
From d54b2acf63191eba3d5052bf34fe6d26e3580ac2 Mon Sep 17 00:00:00 2001
From: Tetsuo Handa <penguin...@I-love.SAKURA.ne.jp>
Date: Tue, 1 May 2018 15:36:52 +0900
Subject: [PATCH] x86/kexec: avoid double free_page() upon do_kexec_load()
failure.

syzbot is reporting crashes after memory allocation failure inside
do_kexec_load() [1]. This is because free_transition_pgtable() is called
by both init_transition_pgtable() and machine_kexec_cleanup() when memory
allocation failed inside init_transition_pgtable().

Regarding 32bit code, machine_kexec_free_page_tables() is called by both
machine_kexec_alloc_page_tables() and machine_kexec_cleanup() when memory
allocation failed inside machine_kexec_alloc_page_tables().

Fix this by explicitly setting NULL after free_page().

[1] https://syzkaller.appspot.com/bug?id=91e52396168cf2bdd572fe1e1bc0bc645c1c6b40

Signed-off-by: Tetsuo Handa <penguin...@I-love.SAKURA.ne.jp>
Reported-by: syzbot <syzbot+d96f60...@syzkaller.appspotmail.com>
Fixes: f5deb79679af6eb4 ("x86: kexec: Use one page table in x86_64 machine_kexec")
Fixes: 92be3d6bdf2cb349 ("kexec/i386: allocate page table pages dynamically")
Cc: Huang Ying <ying....@intel.com>
Cc: H. Peter Anvin <h...@zytor.com>
Cc: Ingo Molnar <mi...@elte.hu>
---
arch/x86/kernel/machine_kexec_32.c | 5 +++++
arch/x86/kernel/machine_kexec_64.c | 4 ++++
2 files changed, 9 insertions(+)

diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c
index 60cdec6..ceccfe4 100644
--- a/arch/x86/kernel/machine_kexec_32.c
+++ b/arch/x86/kernel/machine_kexec_32.c
@@ -57,12 +57,17 @@ static void load_segments(void)
static void machine_kexec_free_page_tables(struct kimage *image)
{
free_page((unsigned long)image->arch.pgd);
+ image->arch.pgd = NULL;
#ifdef CONFIG_X86_PAE
free_page((unsigned long)image->arch.pmd0);
+ image->arch.pmd0 = NULL;
free_page((unsigned long)image->arch.pmd1);
+ image->arch.pmd1 = NULL;
#endif
free_page((unsigned long)image->arch.pte0);
+ image->arch.pte0 = NULL;
free_page((unsigned long)image->arch.pte1);
+ image->arch.pte1 = NULL;
}

static int machine_kexec_alloc_page_tables(struct kimage *image)
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index a5e55d8..76aaee9 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -39,9 +39,13 @@
static void free_transition_pgtable(struct kimage *image)
{
free_page((unsigned long)image->arch.p4d);
+ image->arch.p4d = NULL;
free_page((unsigned long)image->arch.pud);
+ image->arch.pud = NULL;
free_page((unsigned long)image->arch.pmd);
+ image->arch.pmd = NULL;
free_page((unsigned long)image->arch.pte);
+ image->arch.pte = NULL;
}

static int init_transition_pgtable(struct kimage *image, pgd_t *pgd)
--
1.8.3.1

syzbot

unread,
May 3, 2018, 5:04:02 PM5/3/18
to ak...@linux-foundation.org, b...@redhat.com, dyo...@redhat.com, h...@zytor.com, kirill....@linux.intel.com, linux-...@vger.kernel.org, mi...@elte.hu, mi...@redhat.com, penguin...@i-love.sakura.ne.jp, pr...@linux.vnet.ibm.com, syzkall...@googlegroups.com, takahir...@linaro.org, tg...@linutronix.de, thomas....@amd.com, x...@kernel.org, xlp...@redhat.com, ying....@intel.com
syzbot has found a reproducer for the following crash on:

HEAD commit: c15f6d8d4715 Merge tag 'dma-mapping-4.17-4' of git://git.i..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=165343c7800000
kernel config: https://syzkaller.appspot.com/x/.config?x=5a1dc06635c10d27
dashboard link: https://syzkaller.appspot.com/bug?extid=d96f60296ef613fe1d69
compiler: gcc (GCC) 8.0.1 20180413 (experimental)
syzkaller repro:https://syzkaller.appspot.com/x/repro.syz?x=105a4437800000

IMPORTANT: if you fix the bug, please add the following tag to the commit:
Reported-by: syzbot+d96f60...@syzkaller.appspotmail.com

flags: 0x2fffc0000000000()
raw: 02fffc0000000000 0000000000000000 0000000000000000 00000000ffffffff
raw: ffffea0006b60aa0 ffff8801dae2fdd8 0000000000000000 0000000000000000
page dumped because: VM_BUG_ON_PAGE(page_ref_count(page) == 0)
------------[ cut here ]------------
kernel BUG at include/linux/mm.h:492!
invalid opcode: 0000 [#1] SMP KASAN
Dumping ftrace buffer:
(ftrace buffer empty)
Modules linked in:
CPU: 0 PID: 4524 Comm: syz-executor0 Not tainted 4.17.0-rc3+ #31
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
RIP: 0010:put_page_testzero include/linux/mm.h:492 [inline]
RIP: 0010:__free_pages+0x14f/0x180 mm/page_alloc.c:4427
RSP: 0018:ffff8801ad01fc08 EFLAGS: 00010203
RAX: 0000000000000000 RBX: 1ffff10035a03f82 RCX: 0000000000000000
RDX: 0000000000000000 RSI: ffffffff81a5b2e5 RDI: ffffed0035a03f70
RBP: ffff8801ad01fc98 R08: ffff8801ad09e740 R09: ffffed003b5c4fb0
R10: ffffed003b5c4fb0 R11: ffff8801dae27d87 R12: ffffea0006b6e740
R13: 1ffff10035a03f86 R14: ffff8801ad01fc70 R15: ffffea0006b6e75c
FS: 0000000002891940(0000) GS:ffff8801dae00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00000000004d9fc4 CR3: 00000001ad7ed000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
free_pages+0x50/0x90 mm/page_alloc.c:4441
free_transition_pgtable+0x68/0xf0 arch/x86/kernel/machine_kexec_64.c:42
machine_kexec_cleanup+0x9/0x10 arch/x86/kernel/machine_kexec_64.c:268
kimage_free+0x1f2/0x270 kernel/kexec_core.c:639
do_kexec_load+0x53a/0x790 kernel/kexec.c:170
__do_sys_kexec_load kernel/kexec.c:243 [inline]
__se_sys_kexec_load kernel/kexec.c:218 [inline]
__x64_sys_kexec_load+0x1bf/0x230 kernel/kexec.c:218
do_syscall_64+0x1b1/0x800 arch/x86/entry/common.c:287
entry_SYSCALL_64_after_hwframe+0x49/0xbe
RIP: 0033:0x455979
RSP: 002b:00007ffdca50c2b8 EFLAGS: 00000246 ORIG_RAX: 00000000000000f6
RAX: ffffffffffffffda RBX: 0000000002891914 RCX: 0000000000455979
RDX: 00000000200001c0 RSI: 0000000000000001 RDI: 0000000000000000
RBP: 000000000072bea0 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000004
R13: 0000000000000403 R14: 00000000006fa0e8 R15: 0000000000000005
Code: 68 5b 41 5c 41 5d 41 5e 41 5f 5d c3 8b b5 74 ff ff ff 4c 89 e7 e8 02
87 ff ff eb c6 48 c7 c6 00 66 d0 87 4c 89 e7 e8 81 7a 0d 00 <0f> 0b 4c 89
ef 89 85 70 ff ff ff e8 51 7b 1d 00 8b 85 70 ff ff
RIP: put_page_testzero include/linux/mm.h:492 [inline] RSP: ffff8801ad01fc08
RIP: __free_pages+0x14f/0x180 mm/page_alloc.c:4427 RSP: ffff8801ad01fc08
---[ end trace dbb114ab9bd59585 ]---

Tetsuo Handa

unread,
May 3, 2018, 7:38:38 PM5/3/18
to ying....@intel.com, h...@zytor.com, mi...@elte.hu, mi...@redhat.com, syzbot+d96f60...@syzkaller.appspotmail.com, kirill....@linux.intel.com, ak...@linux-foundation.org, b...@redhat.com, dyo...@redhat.com, linux-...@vger.kernel.org, pr...@linux.vnet.ibm.com, syzkall...@googlegroups.com, takahir...@linaro.org, tg...@linutronix.de, thomas....@amd.com, x...@kernel.org, xlp...@redhat.com
>From 91a78abed036e1662b11cb54ae6300864e17b709 Mon Sep 17 00:00:00 2001
From: Tetsuo Handa <penguin...@I-love.SAKURA.ne.jp>
Date: Fri, 4 May 2018 08:26:41 +0900
Subject: [PATCH v2] x86/kexec: avoid double free_page() upon do_kexec_load() failure.

syzbot is reporting crashes after memory allocation failure inside
do_kexec_load() [1]. This is because free_transition_pgtable() is called
by both init_transition_pgtable() and machine_kexec_cleanup() when memory
allocation failed inside init_transition_pgtable().

Regarding 32bit code, machine_kexec_free_page_tables() is called by both
machine_kexec_alloc_page_tables() and machine_kexec_cleanup() when memory
allocation failed inside machine_kexec_alloc_page_tables().

Fix this by leaving the error handling to machine_kexec_cleanup().

[1] https://syzkaller.appspot.com/bug?id=91e52396168cf2bdd572fe1e1bc0bc645c1c6b40

Signed-off-by: Tetsuo Handa <penguin...@I-love.SAKURA.ne.jp>
Reported-by: syzbot <syzbot+d96f60...@syzkaller.appspotmail.com>
Fixes: f5deb79679af6eb4 ("x86: kexec: Use one page table in x86_64 machine_kexec")
Fixes: 92be3d6bdf2cb349 ("kexec/i386: allocate page table pages dynamically")
Cc: Huang Ying <ying....@intel.com>
Cc: H. Peter Anvin <h...@zytor.com>
Cc: Ingo Molnar <mi...@elte.hu>
---
arch/x86/kernel/machine_kexec_32.c | 1 -
arch/x86/kernel/machine_kexec_64.c | 1 -
2 files changed, 2 deletions(-)

diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c
index 60cdec6..170fbf8 100644
--- a/arch/x86/kernel/machine_kexec_32.c
+++ b/arch/x86/kernel/machine_kexec_32.c
@@ -79,7 +79,6 @@ static int machine_kexec_alloc_page_tables(struct kimage *image)
!image->arch.pmd0 || !image->arch.pmd1 ||
#endif
!image->arch.pte0 || !image->arch.pte1) {
- machine_kexec_free_page_tables(image);
return -ENOMEM;
}
return 0;
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index a5e55d8..ffe0174 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -91,7 +91,6 @@ static int init_transition_pgtable(struct kimage *image, pgd_t *pgd)
set_pte(pte, pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL_EXEC_NOENC));
return 0;
err:
- free_transition_pgtable(image);
return result;
}

--
1.8.3.1

Baoquan He

unread,
May 3, 2018, 8:32:16 PM5/3/18
to Tetsuo Handa, syzbot, kirill....@linux.intel.com, linux-...@vger.kernel.org, syzkall...@googlegroups.com, Huang Ying, H. Peter Anvin, Ingo Molnar, ak...@linux-foundation.org, dyo...@redhat.com, mi...@redhat.com, pr...@linux.vnet.ibm.com, takahir...@linaro.org, tg...@linutronix.de, thomas....@amd.com, x...@kernel.org
On 05/01/18 at 07:10pm, Tetsuo Handa wrote:
> From d54b2acf63191eba3d5052bf34fe6d26e3580ac2 Mon Sep 17 00:00:00 2001
> From: Tetsuo Handa <penguin...@I-love.SAKURA.ne.jp>
> Date: Tue, 1 May 2018 15:36:52 +0900
> Subject: [PATCH] x86/kexec: avoid double free_page() upon do_kexec_load()
> failure.
>
> syzbot is reporting crashes after memory allocation failure inside
> do_kexec_load() [1]. This is because free_transition_pgtable() is called
> by both init_transition_pgtable() and machine_kexec_cleanup() when memory
> allocation failed inside init_transition_pgtable().
>
> Regarding 32bit code, machine_kexec_free_page_tables() is called by both
> machine_kexec_alloc_page_tables() and machine_kexec_cleanup() when memory
> allocation failed inside machine_kexec_alloc_page_tables().
>
> Fix this by explicitly setting NULL after free_page().

Setting them NULL after free_page() is a good idea. Maybe can remove the
double calling of free_transition_pgtable() too in init_transition_pgtable()
because the returned value will trigger the later calling.

Tetsuo Handa

unread,
May 8, 2018, 7:26:52 AM5/8/18
to b...@redhat.com, ying....@intel.com, h...@zytor.com, mi...@elte.hu, syzbot+d96f60...@syzkaller.appspotmail.com, kirill....@linux.intel.com, linux-...@vger.kernel.org, syzkall...@googlegroups.com, ak...@linux-foundation.org, dyo...@redhat.com, mi...@redhat.com, pr...@linux.vnet.ibm.com, takahir...@linaro.org, tg...@linutronix.de, thomas....@amd.com, x...@kernel.org
Baoquan He wrote:
> On 05/01/18 at 07:10pm, Tetsuo Handa wrote:
> > From d54b2acf63191eba3d5052bf34fe6d26e3580ac2 Mon Sep 17 00:00:00 2001
> > From: Tetsuo Handa <penguin...@I-love.SAKURA.ne.jp>
> > Date: Tue, 1 May 2018 15:36:52 +0900
> > Subject: [PATCH] x86/kexec: avoid double free_page() upon do_kexec_load()
> > failure.
> >
> > syzbot is reporting crashes after memory allocation failure inside
> > do_kexec_load() [1]. This is because free_transition_pgtable() is called
> > by both init_transition_pgtable() and machine_kexec_cleanup() when memory
> > allocation failed inside init_transition_pgtable().
> >
> > Regarding 32bit code, machine_kexec_free_page_tables() is called by both
> > machine_kexec_alloc_page_tables() and machine_kexec_cleanup() when memory
> > allocation failed inside machine_kexec_alloc_page_tables().
> >
> > Fix this by explicitly setting NULL after free_page().
>
> Setting them NULL after free_page() is a good idea.

That's what the V1 patch did.

> Maybe can remove the
> double calling of free_transition_pgtable() too in init_transition_pgtable()
> because the returned value will trigger the later calling.

That's what the V2 patch did. You can apply V1 or V2 or V1 + V2.

>From 91a78abed036e1662b11cb54ae6300864e17b709 Mon Sep 17 00:00:00 2001
From: Tetsuo Handa <penguin...@I-love.SAKURA.ne.jp>
Date: Fri, 4 May 2018 08:26:41 +0900
Subject: [PATCH v2] x86/kexec: avoid double free_page() upon do_kexec_load() failure.

syzbot is reporting crashes after memory allocation failure inside
do_kexec_load() [1]. This is because free_transition_pgtable() is called
by both init_transition_pgtable() and machine_kexec_cleanup() when memory
allocation failed inside init_transition_pgtable().

Regarding 32bit code, machine_kexec_free_page_tables() is called by both
machine_kexec_alloc_page_tables() and machine_kexec_cleanup() when memory
allocation failed inside machine_kexec_alloc_page_tables().

Fix this by leaving the error handling to machine_kexec_cleanup().

[1] https://syzkaller.appspot.com/bug?id=91e52396168cf2bdd572fe1e1bc0bc645c1c6b40

Signed-off-by: Tetsuo Handa <penguin...@I-love.SAKURA.ne.jp>
Reported-by: syzbot <syzbot+d96f60...@syzkaller.appspotmail.com>
Fixes: f5deb79679af6eb4 ("x86: kexec: Use one page table in x86_64 machine_kexec")
Fixes: 92be3d6bdf2cb349 ("kexec/i386: allocate page table pages dynamically")
Cc: Huang Ying <ying....@intel.com>
Cc: H. Peter Anvin <h...@zytor.com>
Cc: Ingo Molnar <mi...@elte.hu>
---
arch/x86/kernel/machine_kexec_32.c | 1 -
arch/x86/kernel/machine_kexec_64.c | 1 -
2 files changed, 2 deletions(-)

diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c
index 60cdec6..170fbf8 100644
--- a/arch/x86/kernel/machine_kexec_32.c
+++ b/arch/x86/kernel/machine_kexec_32.c
@@ -79,7 +79,6 @@ static int machine_kexec_alloc_page_tables(struct kimage *image)
!image->arch.pmd0 || !image->arch.pmd1 ||
#endif
!image->arch.pte0 || !image->arch.pte1) {
- machine_kexec_free_page_tables(image);
return -ENOMEM;
}
return 0;
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index a5e55d8..ffe0174 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c

Tetsuo Handa

unread,
May 9, 2018, 6:42:48 AM5/9/18
to b...@redhat.com, ying....@intel.com, h...@zytor.com, mi...@elte.hu, syzbot+d96f60...@syzkaller.appspotmail.com, kirill....@linux.intel.com, linux-...@vger.kernel.org, syzkall...@googlegroups.com, ak...@linux-foundation.org, dyo...@redhat.com, mi...@redhat.com, pr...@linux.vnet.ibm.com, takahir...@linaro.org, tg...@linutronix.de, thomas....@amd.com, x...@kernel.org
>From ff82bedd3e12f0d3353282054ae48c3bd8c72012 Mon Sep 17 00:00:00 2001
From: Tetsuo Handa <penguin...@I-love.SAKURA.ne.jp>
Date: Wed, 9 May 2018 12:12:39 +0900
Subject: [PATCH v3] x86/kexec: avoid double free_page() upon do_kexec_load() failure.

syzbot is reporting crashes after memory allocation failure inside
do_kexec_load() [1]. This is because free_transition_pgtable() is called
by both init_transition_pgtable() and machine_kexec_cleanup() when memory
allocation failed inside init_transition_pgtable().

Regarding 32bit code, machine_kexec_free_page_tables() is called by both
machine_kexec_alloc_page_tables() and machine_kexec_cleanup() when memory
allocation failed inside machine_kexec_alloc_page_tables().

Fix this by leaving the error handling to machine_kexec_cleanup()
(and optionally setting NULL after free_page()).

[1] https://syzkaller.appspot.com/bug?id=91e52396168cf2bdd572fe1e1bc0bc645c1c6b40

Signed-off-by: Tetsuo Handa <penguin...@I-love.SAKURA.ne.jp>
Reported-by: syzbot <syzbot+d96f60...@syzkaller.appspotmail.com>
Fixes: f5deb79679af6eb4 ("x86: kexec: Use one page table in x86_64 machine_kexec")
Fixes: 92be3d6bdf2cb349 ("kexec/i386: allocate page table pages dynamically")
Cc: Huang Ying <ying....@intel.com>
Cc: H. Peter Anvin <h...@zytor.com>
Cc: Ingo Molnar <mi...@elte.hu>
---
arch/x86/kernel/machine_kexec_32.c | 6 +++++-
arch/x86/kernel/machine_kexec_64.c | 5 ++++-
2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c
index 60cdec6..d1ab07e 100644
--- a/arch/x86/kernel/machine_kexec_32.c
+++ b/arch/x86/kernel/machine_kexec_32.c
@@ -57,12 +57,17 @@ static void load_segments(void)
static void machine_kexec_free_page_tables(struct kimage *image)
{
free_page((unsigned long)image->arch.pgd);
+ image->arch.pgd = NULL;
#ifdef CONFIG_X86_PAE
free_page((unsigned long)image->arch.pmd0);
+ image->arch.pmd0 = NULL;
free_page((unsigned long)image->arch.pmd1);
+ image->arch.pmd1 = NULL;
#endif
free_page((unsigned long)image->arch.pte0);
+ image->arch.pte0 = NULL;
free_page((unsigned long)image->arch.pte1);
+ image->arch.pte1 = NULL;
}

static int machine_kexec_alloc_page_tables(struct kimage *image)
@@ -79,7 +84,6 @@ static int machine_kexec_alloc_page_tables(struct kimage *image)
!image->arch.pmd0 || !image->arch.pmd1 ||
#endif
!image->arch.pte0 || !image->arch.pte1) {
- machine_kexec_free_page_tables(image);
return -ENOMEM;
}
return 0;
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index a5e55d8..6010449 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -39,9 +39,13 @@
static void free_transition_pgtable(struct kimage *image)
{
free_page((unsigned long)image->arch.p4d);
+ image->arch.p4d = NULL;
free_page((unsigned long)image->arch.pud);
+ image->arch.pud = NULL;
free_page((unsigned long)image->arch.pmd);
+ image->arch.pmd = NULL;
free_page((unsigned long)image->arch.pte);
+ image->arch.pte = NULL;
}

static int init_transition_pgtable(struct kimage *image, pgd_t *pgd)
@@ -91,7 +95,6 @@ static int init_transition_pgtable(struct kimage *image, pgd_t *pgd)

Baoquan He

unread,
May 10, 2018, 2:39:32 AM5/10/18
to Tetsuo Handa, ying....@intel.com, h...@zytor.com, mi...@elte.hu, syzbot+d96f60...@syzkaller.appspotmail.com, kirill....@linux.intel.com, linux-...@vger.kernel.org, syzkall...@googlegroups.com, ak...@linux-foundation.org, dyo...@redhat.com, mi...@redhat.com, pr...@linux.vnet.ibm.com, takahir...@linaro.org, tg...@linutronix.de, thomas....@amd.com, x...@kernel.org
Looks good to me, thx!

Acked-by: Baoquan He <b...@redhat.com>

Thanks
Baoquan

Tetsuo Handa

unread,
May 19, 2018, 9:43:27 AM5/19/18
to syzbot+d96f60...@syzkaller.appspotmail.com, syzkall...@googlegroups.com
OK. Patch is in tip.git#x86/urgent as a466ef76b815b867.

#syz fix: x86/kexec: Avoid double free_page() upon do_kexec_load() failure
Reply all
Reply to author
Forward
0 new messages