kernel-hardening.lists.openwall.com archive mirror
 help / color / mirror / Atom feed
* [kernel-hardening] [PATCH 0/2] LKDTM test updates
@ 2016-02-23  1:27 Laura Abbott
  2016-02-23  1:27 ` [kernel-hardening] [PATCHv3 1/2] lkdtm: Add READ_AFTER_FREE test Laura Abbott
  2016-02-23  1:27 ` [kernel-hardening] [PATCH 2/2] lkdtm: Add read/write after free tests for buddy memory Laura Abbott
  0 siblings, 2 replies; 4+ messages in thread
From: Laura Abbott @ 2016-02-23  1:27 UTC (permalink / raw)
  To: Arnd Bergmann, Greg Kroah-Hartman, Kees Cook
  Cc: Laura Abbott, linux-kernel, kernel-hardening

Hi,

Per the suggestion of Kees, I added tests for read/write after free on
buddy memory as well as slab memory. I combined the two into one
series for ease of dependencies and review.

Laura Abbott (2):
  lkdtm: Add READ_AFTER_FREE test
  lkdtm: Add read/write after free tests for buddy memory

 drivers/misc/lkdtm.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 74 insertions(+)

-- 
2.5.0

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [kernel-hardening] [PATCHv3 1/2] lkdtm: Add READ_AFTER_FREE test
  2016-02-23  1:27 [kernel-hardening] [PATCH 0/2] LKDTM test updates Laura Abbott
@ 2016-02-23  1:27 ` Laura Abbott
  2016-02-23  1:27 ` [kernel-hardening] [PATCH 2/2] lkdtm: Add read/write after free tests for buddy memory Laura Abbott
  1 sibling, 0 replies; 4+ messages in thread
From: Laura Abbott @ 2016-02-23  1:27 UTC (permalink / raw)
  To: Arnd Bergmann, Greg Kroah-Hartman, Kees Cook
  Cc: Laura Abbott, linux-kernel, kernel-hardening


In a similar manner to WRITE_AFTER_FREE, add a READ_AFTER_FREE
test to test free poisoning features. Sample output when
no sanitization is present:

[   22.414170] lkdtm: Performing direct entry READ_AFTER_FREE
[   22.415124] lkdtm: Value in memory before free: 12345678
[   22.415900] lkdtm: Attempting to read from freed memory
[   22.416394] lkdtm: Successfully read value: 12345678

with slub_debug=P:

[   25.874585] lkdtm: Performing direct entry READ_AFTER_FREE
[   25.875527] lkdtm: Value in memory before free: 12345678
[   25.876382] lkdtm: Attempting to read from freed memory
[   25.876900] general protection fault: 0000 [#1] SMP

Signed-off-by: Laura Abbott <labbott@fedoraproject.org>
---
v3: Add mention of slub debug option to give example crash.
Change 'return' to 'break' to better match with the other
functions.
---
 drivers/misc/lkdtm.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index 11fdadc..f95a582 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -92,6 +92,7 @@ enum ctype {
 	CT_UNALIGNED_LOAD_STORE_WRITE,
 	CT_OVERWRITE_ALLOCATION,
 	CT_WRITE_AFTER_FREE,
+	CT_READ_AFTER_FREE,
 	CT_SOFTLOCKUP,
 	CT_HARDLOCKUP,
 	CT_SPINLOCKUP,
@@ -129,6 +130,7 @@ static char* cp_type[] = {
 	"UNALIGNED_LOAD_STORE_WRITE",
 	"OVERWRITE_ALLOCATION",
 	"WRITE_AFTER_FREE",
+	"READ_AFTER_FREE",
 	"SOFTLOCKUP",
 	"HARDLOCKUP",
 	"SPINLOCKUP",
@@ -417,6 +419,38 @@ static void lkdtm_do_action(enum ctype which)
 		memset(data, 0x78, len);
 		break;
 	}
+	case CT_READ_AFTER_FREE: {
+		int **base;
+		int *val, *tmp;
+		size_t len = 1024;
+		/*
+		 * The slub allocator uses the first word to store the free
+		 * pointer in some configurations. Use the middle of the
+		 * allocation to avoid running into the freelist
+		 */
+		size_t offset = (len/sizeof(int *))/2;
+
+		base = kmalloc(len, GFP_KERNEL);
+		if (!base)
+			break;
+
+		val = kmalloc(len, GFP_KERNEL);
+		if (!val)
+			break;
+
+		*val = 0x12345678;
+		pr_info("Value in memory before free: %x\n", *val);
+
+		base[offset] = val;
+		kfree(base);
+
+		tmp = base[offset];
+		pr_info("Attempting to read from freed memory\n");
+		pr_info("Successfully read value: %x\n", *tmp);
+
+		kfree(val);
+		break;
+	}
 	case CT_SOFTLOCKUP:
 		preempt_disable();
 		for (;;)
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [kernel-hardening] [PATCH 2/2] lkdtm: Add read/write after free tests for buddy memory
  2016-02-23  1:27 [kernel-hardening] [PATCH 0/2] LKDTM test updates Laura Abbott
  2016-02-23  1:27 ` [kernel-hardening] [PATCHv3 1/2] lkdtm: Add READ_AFTER_FREE test Laura Abbott
@ 2016-02-23  1:27 ` Laura Abbott
  2016-02-23 22:13   ` [kernel-hardening] " Kees Cook
  1 sibling, 1 reply; 4+ messages in thread
From: Laura Abbott @ 2016-02-23  1:27 UTC (permalink / raw)
  To: Arnd Bergmann, Greg Kroah-Hartman, Kees Cook
  Cc: Laura Abbott, linux-kernel, kernel-hardening


The current tests for read/write after free work on slab
allocated memory. Memory straight from the buddy allocator
may behave slightly differently and have a different set
of parameters to test. Add tests for those cases as well.

On a basic x86 boot:

 # echo WRITE_BUDDY_AFTER_FREE > /sys/kernel/debug/provoke-crash/DIRECT
[   20.358964] lkdtm: Performing direct entry WRITE_BUDDY_AFTER_FREE
[   20.359979] lkdtm: Writing to the buddy page before free
[   20.360943] lkdtm: Writing to the buddy page after free
[   20.361838] lkdtm: Wrote to free page successfully

 # echo READ_BUDDY_AFTER_FREE > /sys/kernel/debug/provoke-crash/DIRECT
[   32.590826] lkdtm: Performing direct entry READ_BUDDY_AFTER_FREE
[   32.591692] lkdtm: Value in memory before free: 12345678
[   32.592459] lkdtm: Attempting to read from freed memory
[   32.593213] lkdtm: Successfully read value: 12345678

On x86 with CONFIG_DEBUG_PAGEALLOC and debug_pagealloc=on:

 # echo WRITE_BUDDY_AFTER_FREE > /sys/kernel/debug/provoke-crash/DIRECT
[   49.761358] lkdtm: Performing direct entry WRITE_BUDDY_AFTER_FREE
[   49.762177] lkdtm: Writing to the buddy page before free
[   49.762890] lkdtm: Writing to the buddy page after free
[   49.763606] BUG: unable to handle kernel paging request at
ffff880000034000

 # echo READ_BUDDY_AFTER_FREE > /sys/kernel/debug/provoke-crash/DIRECT
[   20.454176] lkdtm: Performing direct entry READ_BUDDY_AFTER_FREE
[   20.455198] lkdtm: Value in memory before free: 12345678
[   20.456107] BUG: unable to handle kernel paging request at
ffff880000039000

Note that arches without ARCH_SUPPORTS_DEBUG_PAGEALLOC may not
produce the same crash.

Signed-off-by: Laura Abbott <labbott@fedoraproject.org>
---
The examples I gave were for ARCH_SUPPORTS_DEBUG_PAGEALLOC because
that's going to look different that the slab allocators. With
page poisoning, the behavior is going to look similar to the slab
allocators (write will succeed quietly, read should abort).
---
 drivers/misc/lkdtm.c | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index f95a582..2ef99e9 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -93,6 +93,8 @@ enum ctype {
 	CT_OVERWRITE_ALLOCATION,
 	CT_WRITE_AFTER_FREE,
 	CT_READ_AFTER_FREE,
+	CT_WRITE_BUDDY_AFTER_FREE,
+	CT_READ_BUDDY_AFTER_FREE,
 	CT_SOFTLOCKUP,
 	CT_HARDLOCKUP,
 	CT_SPINLOCKUP,
@@ -131,6 +133,8 @@ static char* cp_type[] = {
 	"OVERWRITE_ALLOCATION",
 	"WRITE_AFTER_FREE",
 	"READ_AFTER_FREE",
+	"WRITE_BUDDY_AFTER_FREE",
+	"READ_BUDDY_AFTER_FREE",
 	"SOFTLOCKUP",
 	"HARDLOCKUP",
 	"SPINLOCKUP",
@@ -451,6 +455,42 @@ static void lkdtm_do_action(enum ctype which)
 		kfree(val);
 		break;
 	}
+	case CT_WRITE_BUDDY_AFTER_FREE: {
+		unsigned long p = __get_free_page(GFP_KERNEL);
+		if (!p)
+			break;
+		pr_info("Writing to the buddy page before free\n");
+		memset((void *)p, 0x3, PAGE_SIZE);
+		free_page(p);
+		schedule();
+		pr_info("Writing to the buddy page after free\n");
+		memset((void *)p, 0x78, PAGE_SIZE);
+		pr_info("Wrote to free page successfully\n");
+		break;
+	}
+	case CT_READ_BUDDY_AFTER_FREE: {
+		unsigned long p = __get_free_page(GFP_KERNEL);
+		int *tmp, *val = kmalloc(1024, GFP_KERNEL);
+		int **base;
+
+		if (!p)
+			break;
+
+		if (!val)
+			break;
+
+		base = (int **)p;
+
+		*val = 0x12345678;
+		pr_info("Value in memory before free: %x\n", *val);
+		base[0] = val;
+		free_page(p);
+		tmp = base[0];
+		pr_info("Attempting to read from freed memory\n");
+		pr_info("Successfully read value: %x\n", *tmp);
+		kfree(val);
+		break;
+	}
 	case CT_SOFTLOCKUP:
 		preempt_disable();
 		for (;;)
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [kernel-hardening] Re: [PATCH 2/2] lkdtm: Add read/write after free tests for buddy memory
  2016-02-23  1:27 ` [kernel-hardening] [PATCH 2/2] lkdtm: Add read/write after free tests for buddy memory Laura Abbott
@ 2016-02-23 22:13   ` Kees Cook
  0 siblings, 0 replies; 4+ messages in thread
From: Kees Cook @ 2016-02-23 22:13 UTC (permalink / raw)
  To: Laura Abbott; +Cc: Arnd Bergmann, Greg Kroah-Hartman, LKML, kernel-hardening

On Mon, Feb 22, 2016 at 5:27 PM, Laura Abbott <labbott@fedoraproject.org> wrote:
>
> The current tests for read/write after free work on slab
> allocated memory. Memory straight from the buddy allocator
> may behave slightly differently and have a different set
> of parameters to test. Add tests for those cases as well.
>
> On a basic x86 boot:
>
>  # echo WRITE_BUDDY_AFTER_FREE > /sys/kernel/debug/provoke-crash/DIRECT
> [   20.358964] lkdtm: Performing direct entry WRITE_BUDDY_AFTER_FREE
> [   20.359979] lkdtm: Writing to the buddy page before free
> [   20.360943] lkdtm: Writing to the buddy page after free
> [   20.361838] lkdtm: Wrote to free page successfully
>
>  # echo READ_BUDDY_AFTER_FREE > /sys/kernel/debug/provoke-crash/DIRECT
> [   32.590826] lkdtm: Performing direct entry READ_BUDDY_AFTER_FREE
> [   32.591692] lkdtm: Value in memory before free: 12345678
> [   32.592459] lkdtm: Attempting to read from freed memory
> [   32.593213] lkdtm: Successfully read value: 12345678
>
> On x86 with CONFIG_DEBUG_PAGEALLOC and debug_pagealloc=on:
>
>  # echo WRITE_BUDDY_AFTER_FREE > /sys/kernel/debug/provoke-crash/DIRECT
> [   49.761358] lkdtm: Performing direct entry WRITE_BUDDY_AFTER_FREE
> [   49.762177] lkdtm: Writing to the buddy page before free
> [   49.762890] lkdtm: Writing to the buddy page after free
> [   49.763606] BUG: unable to handle kernel paging request at
> ffff880000034000
>
>  # echo READ_BUDDY_AFTER_FREE > /sys/kernel/debug/provoke-crash/DIRECT
> [   20.454176] lkdtm: Performing direct entry READ_BUDDY_AFTER_FREE
> [   20.455198] lkdtm: Value in memory before free: 12345678
> [   20.456107] BUG: unable to handle kernel paging request at
> ffff880000039000
>
> Note that arches without ARCH_SUPPORTS_DEBUG_PAGEALLOC may not
> produce the same crash.

As part of my benchmarking of all these changes, I'm going to end up
with matrix of what results can be expected under various states.

>
> Signed-off-by: Laura Abbott <labbott@fedoraproject.org>
> ---
> The examples I gave were for ARCH_SUPPORTS_DEBUG_PAGEALLOC because
> that's going to look different that the slab allocators. With
> page poisoning, the behavior is going to look similar to the slab
> allocators (write will succeed quietly, read should abort).
> ---
>  drivers/misc/lkdtm.c | 40 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 40 insertions(+)
>
> diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
> index f95a582..2ef99e9 100644
> --- a/drivers/misc/lkdtm.c
> +++ b/drivers/misc/lkdtm.c
> @@ -93,6 +93,8 @@ enum ctype {
>         CT_OVERWRITE_ALLOCATION,
>         CT_WRITE_AFTER_FREE,
>         CT_READ_AFTER_FREE,
> +       CT_WRITE_BUDDY_AFTER_FREE,
> +       CT_READ_BUDDY_AFTER_FREE,
>         CT_SOFTLOCKUP,
>         CT_HARDLOCKUP,
>         CT_SPINLOCKUP,
> @@ -131,6 +133,8 @@ static char* cp_type[] = {
>         "OVERWRITE_ALLOCATION",
>         "WRITE_AFTER_FREE",
>         "READ_AFTER_FREE",
> +       "WRITE_BUDDY_AFTER_FREE",
> +       "READ_BUDDY_AFTER_FREE",
>         "SOFTLOCKUP",
>         "HARDLOCKUP",
>         "SPINLOCKUP",
> @@ -451,6 +455,42 @@ static void lkdtm_do_action(enum ctype which)
>                 kfree(val);
>                 break;
>         }
> +       case CT_WRITE_BUDDY_AFTER_FREE: {
> +               unsigned long p = __get_free_page(GFP_KERNEL);
> +               if (!p)
> +                       break;
> +               pr_info("Writing to the buddy page before free\n");
> +               memset((void *)p, 0x3, PAGE_SIZE);
> +               free_page(p);
> +               schedule();
> +               pr_info("Writing to the buddy page after free\n");

I think it might be clearer to have these read like this:

Attempting good write to buddy page before free
Attempting bad write to buddy page after free
Unexpectedly wrote to free page!

> +               memset((void *)p, 0x78, PAGE_SIZE);
> +               pr_info("Wrote to free page successfully\n");
> +               break;
> +       }
> +       case CT_READ_BUDDY_AFTER_FREE: {
> +               unsigned long p = __get_free_page(GFP_KERNEL);
> +               int *tmp, *val = kmalloc(1024, GFP_KERNEL);
> +               int **base;
> +
> +               if (!p)
> +                       break;
> +
> +               if (!val)
> +                       break;
> +
> +               base = (int **)p;
> +
> +               *val = 0x12345678;
> +               pr_info("Value in memory before free: %x\n", *val);
> +               base[0] = val;
> +               free_page(p);
> +               tmp = base[0];
> +               pr_info("Attempting to read from freed memory\n");
> +               pr_info("Successfully read value: %x\n", *tmp);

Attempting bad read from freed memory
Unexpectedly read value: %x

> +               kfree(val);
> +               break;
> +       }
>         case CT_SOFTLOCKUP:
>                 preempt_disable();
>                 for (;;)
> --
> 2.5.0
>

But I think these changes could be done later -- best to try to make
all the test reports say similar things. (e.g. right now the EXEC_*
cases don't say "Oh no, I failed" if they failed to Oops.)

-Kees

-- 
Kees Cook
Chrome OS & Brillo Security

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2016-02-23 22:13 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-23  1:27 [kernel-hardening] [PATCH 0/2] LKDTM test updates Laura Abbott
2016-02-23  1:27 ` [kernel-hardening] [PATCHv3 1/2] lkdtm: Add READ_AFTER_FREE test Laura Abbott
2016-02-23  1:27 ` [kernel-hardening] [PATCH 2/2] lkdtm: Add read/write after free tests for buddy memory Laura Abbott
2016-02-23 22:13   ` [kernel-hardening] " Kees Cook

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).