Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1167635 > unrolled thread

[PATCH v6 1/1] x86_64: fix KASan shadow region page tables

Started byAlexander Popov <alpopov@ptsecurity.com>
First post2015-06-18 09:40 +0200
Last post2015-06-19 16:20 +0200
Articles 5 — 4 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH v6 1/1] x86_64: fix KASan shadow region page tables Alexander Popov <alpopov@ptsecurity.com> - 2015-06-18 09:40 +0200
    Re: [PATCH v6 1/1] x86_64: fix KASan shadow region page tables Andrey Ryabinin <a.ryabinin@samsung.com> - 2015-06-19 15:40 +0200
      Re: [PATCH v6 1/1] x86_64: fix KASan shadow region page tables Borislav Petkov <bp@alien8.de> - 2015-06-19 16:10 +0200
      Re: [PATCH v6 1/1] x86_64: fix KASan shadow region page tables Ingo Molnar <mingo@kernel.org> - 2015-06-19 16:10 +0200
        Re: [PATCH v6 1/1] x86_64: fix KASan shadow region page tables Andrey Ryabinin <a.ryabinin@samsung.com> - 2015-06-19 16:20 +0200

#1167635 — [PATCH v6 1/1] x86_64: fix KASan shadow region page tables

FromAlexander Popov <alpopov@ptsecurity.com>
Date2015-06-18 09:40 +0200
Subject[PATCH v6 1/1] x86_64: fix KASan shadow region page tables
Message-ID<pCCAz-1Mb-29@gated-at.bofh.it>
Physical addresses in KASan shadow region page tables need fixup similarly
to the other page tables. Current code doesn't do it which causes
kernel halt if phys_base is not zero.
So let's initialize KASan shadow region page tables in kasan_early_init()
using __pa_nodebug() which considers phys_base.

Signed-off-by: Alexander Popov <alpopov@ptsecurity.com>
---

Notes:
    Changes from v2:
    - move KASan shadow region page tables to BSS;
    - use __PAGE_KERNEL flags for describing kasan_zero_page in kasan_zero_pte.
    
    Changes from v3:
    - improve commit message.
    
    Changes from v4:
    - add Andrey's patch which removes faulty clear_page(init_level4_pgt);
    - call kasan_map_early_shadow() for early_level4_pgt and init_level4_pgt
        in kasan_early_init().
    
    Changes from v5:
    - restore clear_page(init_level4_pgt), but put it just after clear_bss()
        to consolidate early KASan initialization;
    - remove the comment which stopped bringing much profit to the code
        readability. Otherwise describing all the new order dependences
        would be too verbose.

 arch/x86/include/asm/kasan.h |  8 ++------
 arch/x86/kernel/head64.c     | 10 ++++------
 arch/x86/kernel/head_64.S    | 29 -----------------------------
 arch/x86/mm/kasan_init_64.c  | 36 ++++++++++++++++++++++++++++++++++--
 4 files changed, 40 insertions(+), 43 deletions(-)

diff --git a/arch/x86/include/asm/kasan.h b/arch/x86/include/asm/kasan.h
index 8b22422..74a2a8d 100644
--- a/arch/x86/include/asm/kasan.h
+++ b/arch/x86/include/asm/kasan.h
@@ -14,15 +14,11 @@
 
 #ifndef __ASSEMBLY__
 
-extern pte_t kasan_zero_pte[];
-extern pte_t kasan_zero_pmd[];
-extern pte_t kasan_zero_pud[];
-
 #ifdef CONFIG_KASAN
-void __init kasan_map_early_shadow(pgd_t *pgd);
+void __init kasan_early_init(void);
 void __init kasan_init(void);
 #else
-static inline void kasan_map_early_shadow(pgd_t *pgd) { }
+static inline void kasan_early_init(void) { }
 static inline void kasan_init(void) { }
 #endif
 
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 5a46681..f129a9a 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -161,11 +161,12 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
 	/* Kill off the identity-map trampoline */
 	reset_early_page_tables();
 
-	kasan_map_early_shadow(early_level4_pgt);
-
-	/* clear bss before set_intr_gate with early_idt_handler */
 	clear_bss();
 
+	clear_page(init_level4_pgt);
+
+	kasan_early_init();
+
 	for (i = 0; i < NUM_EXCEPTION_VECTORS; i++)
 		set_intr_gate(i, early_idt_handler_array[i]);
 	load_idt((const struct desc_ptr *)&idt_descr);
@@ -177,12 +178,9 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
 	 */
 	load_ucode_bsp();
 
-	clear_page(init_level4_pgt);
 	/* set init_level4_pgt kernel high mapping*/
 	init_level4_pgt[511] = early_level4_pgt[511];
 
-	kasan_map_early_shadow(init_level4_pgt);
-
 	x86_64_start_reservations(real_mode_data);
 }
 
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index df7e780..7e5da2c 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -516,38 +516,9 @@ ENTRY(phys_base)
 	/* This must match the first entry in level2_kernel_pgt */
 	.quad   0x0000000000000000
 
-#ifdef CONFIG_KASAN
-#define FILL(VAL, COUNT)				\
-	.rept (COUNT) ;					\
-	.quad	(VAL) ;					\
-	.endr
-
-NEXT_PAGE(kasan_zero_pte)
-	FILL(kasan_zero_page - __START_KERNEL_map + _KERNPG_TABLE, 512)
-NEXT_PAGE(kasan_zero_pmd)
-	FILL(kasan_zero_pte - __START_KERNEL_map + _KERNPG_TABLE, 512)
-NEXT_PAGE(kasan_zero_pud)
-	FILL(kasan_zero_pmd - __START_KERNEL_map + _KERNPG_TABLE, 512)
-
-#undef FILL
-#endif
-
-
 #include "../../x86/xen/xen-head.S"
 	
 	__PAGE_ALIGNED_BSS
 NEXT_PAGE(empty_zero_page)
 	.skip PAGE_SIZE
 
-#ifdef CONFIG_KASAN
-/*
- * This page used as early shadow. We don't use empty_zero_page
- * at early stages, stack instrumentation could write some garbage
- * to this page.
- * Latter we reuse it as zero shadow for large ranges of memory
- * that allowed to access, but not instrumented by kasan
- * (vmalloc/vmemmap ...).
- */
-NEXT_PAGE(kasan_zero_page)
-	.skip PAGE_SIZE
-#endif
diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c
index 4860906..0e4a05f 100644
--- a/arch/x86/mm/kasan_init_64.c
+++ b/arch/x86/mm/kasan_init_64.c
@@ -11,7 +11,19 @@
 extern pgd_t early_level4_pgt[PTRS_PER_PGD];
 extern struct range pfn_mapped[E820_X_MAX];
 
-extern unsigned char kasan_zero_page[PAGE_SIZE];
+static pud_t kasan_zero_pud[PTRS_PER_PUD] __page_aligned_bss;
+static pmd_t kasan_zero_pmd[PTRS_PER_PMD] __page_aligned_bss;
+static pte_t kasan_zero_pte[PTRS_PER_PTE] __page_aligned_bss;
+
+/*
+ * This page used as early shadow. We don't use empty_zero_page
+ * at early stages, stack instrumentation could write some garbage
+ * to this page.
+ * Latter we reuse it as zero shadow for large ranges of memory
+ * that allowed to access, but not instrumented by kasan
+ * (vmalloc/vmemmap ...).
+ */
+static unsigned char kasan_zero_page[PAGE_SIZE] __page_aligned_bss;
 
 static int __init map_range(struct range *range)
 {
@@ -36,7 +48,7 @@ static void __init clear_pgds(unsigned long start,
 		pgd_clear(pgd_offset_k(start));
 }
 
-void __init kasan_map_early_shadow(pgd_t *pgd)
+static void __init kasan_map_early_shadow(pgd_t *pgd)
 {
 	int i;
 	unsigned long start = KASAN_SHADOW_START;
@@ -166,6 +178,26 @@ static struct notifier_block kasan_die_notifier = {
 };
 #endif
 
+void __init kasan_early_init(void)
+{
+	int i;
+	pteval_t pte_val = __pa_nodebug(kasan_zero_page) | __PAGE_KERNEL;
+	pmdval_t pmd_val = __pa_nodebug(kasan_zero_pte) | _KERNPG_TABLE;
+	pudval_t pud_val = __pa_nodebug(kasan_zero_pmd) | _KERNPG_TABLE;
+
+	for (i = 0; i < PTRS_PER_PTE; i++)
+		kasan_zero_pte[i] = __pte(pte_val);
+
+	for (i = 0; i < PTRS_PER_PMD; i++)
+		kasan_zero_pmd[i] = __pmd(pmd_val);
+
+	for (i = 0; i < PTRS_PER_PUD; i++)
+		kasan_zero_pud[i] = __pud(pud_val);
+
+	kasan_map_early_shadow(early_level4_pgt);
+	kasan_map_early_shadow(init_level4_pgt);
+}
+
 void __init kasan_init(void)
 {
 	int i;
-- 
1.9.1

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

[toc] | [next] | [standalone]


#1168783

FromAndrey Ryabinin <a.ryabinin@samsung.com>
Date2015-06-19 15:40 +0200
Message-ID<pD4Gu-n9-15@gated-at.bofh.it>
In reply to#1167635
On 06/19/2015 03:06 PM, Borislav Petkov wrote:
> On Fri, Jun 19, 2015 at 02:49:19PM +0300, Andrey Ryabinin wrote:
>> I guess that AMD cpus is more strict (unlike Intel) about violation
>> of reserved/unused bits in page table entries. Please, try with this
>> patch.
> 
> With that the guest boots.
> 

Great! Thanks.

> How do I check whether KASan actually works? I don't see any note in
> dmesg or some file named "*kasan*" in sysfs...
> 

kasan will print report in dmesg whant it will find anything.

To make sure that it works you could try to load testing module (CONFIG_TEST_KASAN).
This module has bugs that kasan should catch.
Also 'slub_debug=U' in bootcmdline will improve reports and out-of-bounds accesses detection.

> Thanks.
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1168796

FromBorislav Petkov <bp@alien8.de>
Date2015-06-19 16:10 +0200
Message-ID<pD59w-1ao-3@gated-at.bofh.it>
In reply to#1168783
On Fri, Jun 19, 2015 at 04:00:51PM +0200, Ingo Molnar wrote:
> It should also printk a one line message at bootup, so that people can
> be sure they are running a KASan-enabled kernel.

Yeah, especially if it slows down teh kernel by orders of magnitude.

In any case, here's what it says in the guest:

[  117.061393] kasan test: kmalloc_oob_right out-of-bounds to right
[  117.067973] ==================================================================
[  117.071656] BUG: KASan: out of bounds access in kmalloc_oob_right+0x65/0x75 [test_kasan] at addr ffff88006816915b
[  117.071656] Write of size 1 by task insmod/3942
[  117.071656] =============================================================================
[  117.071656] BUG kmalloc-128 (Not tainted): kasan: bad access detected
[  117.071656] -----------------------------------------------------------------------------
[  117.071656] 
[  117.071656] Disabling lock debugging due to kernel taint
[  117.071656] INFO: Allocated in kmalloc_oob_right+0x3d/0x75 [test_kasan] age=5 cpu=1 pid=3942
[  117.071656] 	__slab_alloc.isra.60.constprop.62+0x4c4/0x5e0
[  117.071656] 	kmem_cache_alloc_trace+0x167/0x330
[  117.071656] 	kmalloc_oob_right+0x3d/0x75 [test_kasan]
[  117.071656] 	kmalloc_tests_init+0x9/0x51 [test_kasan]
[  117.071656] 	do_one_initcall+0xb1/0x220
[  117.071656] 	do_init_module+0xf7/0x2f8
[  117.071656] 	load_module+0x2fe7/0x3e00
[  117.071656] 	SyS_init_module+0x10d/0x120
[  117.071656] 	system_call_fastpath+0x16/0x73
[  117.071656] INFO: Freed in rcu_process_callbacks+0x3d3/0xd90 age=1511 cpu=6 pid=0
[  117.071656] 	__slab_free+0x433/0x610
[  117.071656] 	kfree+0x279/0x380
[  117.071656] 	rcu_process_callbacks+0x3d3/0xd90
[  117.071656] 	__do_softirq+0x154/0x7b0
[  117.071656] 	irq_exit+0xba/0xe0
[  117.071656] 	smp_apic_timer_interrupt+0x6a/0x80
[  117.071656] 	apic_timer_interrupt+0x6d/0x80
[  117.071656] 	arch_cpu_idle+0xf/0x20
[  117.071656] 	cpu_startup_entry+0x5f1/0x7a0
[  117.071656] 	start_secondary+0x21d/0x230
[  117.071656] INFO: Slab 0xffffea0001a05a00 objects=37 used=31 fp=0xffff880068169290 flags=0x4000000000004080
[  117.071656] INFO: Object 0xffff8800681690e0 @offset=4320 fp=0xffff88006816a880
[  117.071656] 
[  117.071656] Bytes b4 ffff8800681690d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
[  117.071656] Object ffff8800681690e0: 80 a8 16 68 00 88 ff ff ff ff ff ff 00 00 00 00  ...h............
[  117.071656] Object ffff8800681690f0: ff ff ff ff ff ff ff ff c0 f2 01 83 ff ff ff ff  ................
[  117.071656] Object ffff880068169100: 60 91 87 82 ff ff ff ff 00 00 00 00 00 00 00 00  `...............
[  117.071656] Object ffff880068169110: 05 0a c4 81 ff ff ff ff 06 00 00 00 1c 00 1b 00  ................
[  117.071656] Object ffff880068169120: 74 d6 0d 81 ff ff ff ff 28 91 16 68 00 88 ff ff  t.......(..h....
[  117.071656] Object ffff880068169130: 28 91 16 68 00 88 ff ff 00 00 00 00 00 00 00 00  (..h............
[  117.071656] Object ffff880068169140: 00 00 00 00 00 00 00 00 60 00 00 00 00 00 00 00  ........`.......
[  117.071656] Object ffff880068169150: 00 00 00 00 40 00 38 00 07 00 40 00 18 00 17 00  ....@.8...@.....
[  117.071656] CPU: 1 PID: 3942 Comm: insmod Tainted: G    B           4.1.0-rc8+ #3
[  117.071656] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.7.5-20140531_083030-gandalf 04/01/2014
[  117.071656]  0000000000000001 ffff880061c77a28 ffffffff819af359 00000000000001b0
[  117.071656]  ffff88006ac07800 ffff880061c77a58 ffffffff8121280d ffff88006ac07800
[  117.071656]  ffffea0001a05a00 ffff8800681690e0 ffffffffa0008765 ffff880061c77a88
[  117.071656] Call Trace:
[  117.071656]  [<ffffffff819af359>] dump_stack+0x4f/0x7b
[  117.071656]  [<ffffffff8121280d>] print_trailer+0xfd/0x160
[  117.071656]  [<ffffffffa0008765>] ? kmem_cache_oob+0xbc/0xbc [test_kasan]
[  117.071656]  [<ffffffff81218501>] object_err+0x41/0x50
[  117.071656]  [<ffffffff8121a4b8>] kasan_report_error+0x1e8/0x410
[  117.071656]  [<ffffffffa0008765>] ? kmem_cache_oob+0xbc/0xbc [test_kasan]
[  117.071656]  [<ffffffff8121ab90>] kasan_report+0x40/0x50
[  117.071656]  [<ffffffffa0008111>] ? kmalloc_oob_right+0x65/0x75 [test_kasan]
[  117.071656]  [<ffffffff81219c54>] __asan_store1+0x54/0x80
[  117.071656]  [<ffffffffa0008765>] ? kmem_cache_oob+0xbc/0xbc [test_kasan]
[  117.071656]  [<ffffffffa0008111>] kmalloc_oob_right+0x65/0x75 [test_kasan]
[  117.071656]  [<ffffffffa000876e>] kmalloc_tests_init+0x9/0x51 [test_kasan]
[  117.071656]  [<ffffffff81000301>] do_one_initcall+0xb1/0x220
[  117.071656]  [<ffffffff81219d19>] ? kasan_kmalloc+0x49/0x50
[  117.071656]  [<ffffffff812170f6>] ? kmem_cache_alloc_trace+0x106/0x330
[  117.071656]  [<ffffffff819ae865>] ? do_init_module+0x3b/0x2f8
[  117.071656]  [<ffffffff819ae921>] do_init_module+0xf7/0x2f8
[  117.071656]  [<ffffffff8114aa37>] load_module+0x2fe7/0x3e00
[  117.071656]  [<ffffffff811454d0>] ? store_uevent+0x50/0x50
[  117.071656]  [<ffffffff8114b95d>] SyS_init_module+0x10d/0x120
[  117.071656]  [<ffffffff819ba31b>] system_call_fastpath+0x16/0x73
[  117.071656] Memory state around the buggy address:
[  117.071656]  ffff880068169000: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  117.071656]  ffff880068169080: fc fc fc fc fc fc fc fc fc fc fc fc 00 00 00 00
[  117.071656] >ffff880068169100: 00 00 00 00 00 00 00 00 00 00 00 03 fc fc fc fc
[  117.071656]                                                     ^
[  117.071656]  ffff880068169180: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  117.071656]  ffff880068169200: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  117.071656] ==================================================================
...

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1168799

FromIngo Molnar <mingo@kernel.org>
Date2015-06-19 16:10 +0200
Message-ID<pD59w-1ao-5@gated-at.bofh.it>
In reply to#1168783
* Andrey Ryabinin <a.ryabinin@samsung.com> wrote:

> On 06/19/2015 03:06 PM, Borislav Petkov wrote:
> > On Fri, Jun 19, 2015 at 02:49:19PM +0300, Andrey Ryabinin wrote:
> >> I guess that AMD cpus is more strict (unlike Intel) about violation
> >> of reserved/unused bits in page table entries. Please, try with this
> >> patch.
> > 
> > With that the guest boots.
> > 
> 
> Great! Thanks.
> 
> > How do I check whether KASan actually works? I don't see any note in
> > dmesg or some file named "*kasan*" in sysfs...
> > 
> 
> kasan will print report in dmesg whant it will find anything.

It should also printk a one line message at bootup, so that people can be sure 
they are running a KASan-enabled kernel.

> To make sure that it works you could try to load testing module (CONFIG_TEST_KASAN).
> This module has bugs that kasan should catch.

That's a way too obscure mechanism just to determine whether the right kernel 
config was booted. Please add a printk(), ok?

Thanks,

	Ingo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1168812

FromAndrey Ryabinin <a.ryabinin@samsung.com>
Date2015-06-19 16:20 +0200
Message-ID<pD5jd-1lD-17@gated-at.bofh.it>
In reply to#1168799
On 06/19/2015 05:00 PM, Ingo Molnar wrote:
> 
> That's a way too obscure mechanism just to determine whether the right kernel 
> config was booted. Please add a printk(), ok?
> 

Sure, will do.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web