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


Groups > linux.kernel > #1312429 > unrolled thread

[PATCH v4 0/8] introduce post-init read-only memory

Started byKees Cook <keescook@chromium.org>
First post2016-01-19 19:20 +0100
Last post2016-01-23 10:50 +0100
Articles 6 — 4 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH v4 0/8] introduce post-init read-only memory Kees Cook <keescook@chromium.org> - 2016-01-19 19:20 +0100
    [PATCH v4 7/8] lkdtm: verify that __ro_after_init works correctly Kees Cook <keescook@chromium.org> - 2016-01-19 19:20 +0100
    Re: [kernel-hardening] [PATCH v4 0/8] introduce post-init read-only  memory David Brown <david.brown@linaro.org> - 2016-01-22 18:30 +0100
      Re: [kernel-hardening] [PATCH v4 0/8] introduce post-init read-only  memory Laura Abbott <laura@labbott.name> - 2016-01-22 20:20 +0100
        Re: [kernel-hardening] [PATCH v4 0/8] introduce post-init read-only memory Kees Cook <keescook@chromium.org> - 2016-01-22 21:00 +0100
          Re: [kernel-hardening] [PATCH v4 0/8] introduce post-init read-only memory Geert Uytterhoeven <geert@linux-m68k.org> - 2016-01-23 10:50 +0100

#1312429 — [PATCH v4 0/8] introduce post-init read-only memory

FromKees Cook <keescook@chromium.org>
Date2016-01-19 19:20 +0100
Subject[PATCH v4 0/8] introduce post-init read-only memory
Message-ID<qSIT8-33H-5@gated-at.bofh.it>
One of the easiest ways to protect the kernel from attack is to reduce
the internal attack surface exposed when a "write" flaw is available. By
making as much of the kernel read-only as possible, we reduce the
attack surface.

Many things are written to only during __init, and never changed
again. These cannot be made "const" since the compiler will do the wrong
thing (we do actually need to write to them). Instead, move these items
into a memory region that will be made read-only during mark_rodata_ro()
which happens after all kernel __init code has finished.

This introduces __ro_after_init as a way to mark such memory, and uses
it on the x86 vDSO to kill an extant kernel exploitation method. Also
adds a new kernel parameter to help debug future use and adds an lkdtm
test to check the results.

-Kees

v4:
- rebased
v3:
- conslidated mark_rodata_ro()
- make CONFIG_DEBUG_RODATA always enabled on x86, mingo
- enhanced strtobool and potential callers to use "on"/"off"
- use strtobool for rodata= param, gregkh
v2:
- renamed __read_only to __ro_after_init

[toc] | [next] | [standalone]


#1312431 — [PATCH v4 7/8] lkdtm: verify that __ro_after_init works correctly

FromKees Cook <keescook@chromium.org>
Date2016-01-19 19:20 +0100
Subject[PATCH v4 7/8] lkdtm: verify that __ro_after_init works correctly
Message-ID<qSJ2O-36W-25@gated-at.bofh.it>
In reply to#1312429
The new __ro_after_init section should be writable before init, but
not after. Validate that it gets updated at init and can't be written
to afterwards.

Signed-off-by: Kees Cook <keescook@chromium.org>
---
 drivers/misc/lkdtm.c | 29 ++++++++++++++++++++++++++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index 11fdadc68e53..2a6eaf1122b4 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -103,6 +103,7 @@ enum ctype {
 	CT_EXEC_USERSPACE,
 	CT_ACCESS_USERSPACE,
 	CT_WRITE_RO,
+	CT_WRITE_RO_AFTER_INIT,
 	CT_WRITE_KERN,
 };
 
@@ -140,6 +141,7 @@ static char* cp_type[] = {
 	"EXEC_USERSPACE",
 	"ACCESS_USERSPACE",
 	"WRITE_RO",
+	"WRITE_RO_AFTER_INIT",
 	"WRITE_KERN",
 };
 
@@ -162,6 +164,7 @@ static DEFINE_SPINLOCK(lock_me_up);
 static u8 data_area[EXEC_SIZE];
 
 static const unsigned long rodata = 0xAA55AA55;
+static unsigned long ro_after_init __ro_after_init = 0x55AA5500;
 
 module_param(recur_count, int, 0644);
 MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test");
@@ -503,11 +506,28 @@ static void lkdtm_do_action(enum ctype which)
 		break;
 	}
 	case CT_WRITE_RO: {
-		unsigned long *ptr;
+		/* Explicitly cast away "const" for the test. */
+		unsigned long *ptr = (unsigned long *)&rodata;
 
-		ptr = (unsigned long *)&rodata;
+		pr_info("attempting bad rodata write at %p\n", ptr);
+		*ptr ^= 0xabcd1234;
 
-		pr_info("attempting bad write at %p\n", ptr);
+		break;
+	}
+	case CT_WRITE_RO_AFTER_INIT: {
+		unsigned long *ptr = &ro_after_init;
+
+		/*
+		 * Verify we were written to during init. Since an Oops
+		 * is considered a "success", a failure is to just skip the
+		 * real test.
+		 */
+		if ((*ptr & 0xAA) != 0xAA) {
+			pr_info("%p was NOT written during init!?\n", ptr);
+			break;
+		}
+
+		pr_info("attempting bad ro_after_init write at %p\n", ptr);
 		*ptr ^= 0xabcd1234;
 
 		break;
@@ -817,6 +837,9 @@ static int __init lkdtm_module_init(void)
 	int n_debugfs_entries = 1; /* Assume only the direct entry */
 	int i;
 
+	/* Make sure we can write to __ro_after_init values during __init */
+	ro_after_init |= 0xAA;
+
 	/* Register debugfs interface */
 	lkdtm_debugfs_root = debugfs_create_dir("provoke-crash", NULL);
 	if (!lkdtm_debugfs_root) {
-- 
2.6.3

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


#1315153 — Re: [kernel-hardening] [PATCH v4 0/8] introduce post-init read-only memory

FromDavid Brown <david.brown@linaro.org>
Date2016-01-22 18:30 +0100
SubjectRe: [kernel-hardening] [PATCH v4 0/8] introduce post-init read-only memory
Message-ID<qTNH3-7bM-3@gated-at.bofh.it>
In reply to#1312429
On Tue, Jan 19, 2016 at 10:08:34AM -0800, Kees Cook wrote:

>This introduces __ro_after_init as a way to mark such memory, and uses
>it on the x86 vDSO to kill an extant kernel exploitation method. Also
>adds a new kernel parameter to help debug future use and adds an lkdtm
>test to check the results.

I've tested these patches on 32-bit ARM using the provoke-crashes
test.  However, they do require CONFIG_ARM_KERNMEM_PERMS to be enabled
as well, which does incur additional memory usage.

Do we want to consider making CONFIG_ARM_KERNMEM_PERMS default y for
security reasons, and just document that memory-constrained systems
may want to turn it off?

I'll test the arm64 next.

David

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


#1315234 — Re: [kernel-hardening] [PATCH v4 0/8] introduce post-init read-only memory

FromLaura Abbott <laura@labbott.name>
Date2016-01-22 20:20 +0100
SubjectRe: [kernel-hardening] [PATCH v4 0/8] introduce post-init read-only memory
Message-ID<qTPpw-8pj-19@gated-at.bofh.it>
In reply to#1315153
On 1/22/16 9:19 AM, David Brown wrote:
> On Tue, Jan 19, 2016 at 10:08:34AM -0800, Kees Cook wrote:
>
>> This introduces __ro_after_init as a way to mark such memory, and uses
>> it on the x86 vDSO to kill an extant kernel exploitation method. Also
>> adds a new kernel parameter to help debug future use and adds an lkdtm
>> test to check the results.
>
> I've tested these patches on 32-bit ARM using the provoke-crashes
> test.  However, they do require CONFIG_ARM_KERNMEM_PERMS to be enabled
> as well, which does incur additional memory usage.
>
> Do we want to consider making CONFIG_ARM_KERNMEM_PERMS default y for
> security reasons, and just document that memory-constrained systems
> may want to turn it off?
>
> I'll test the arm64 next.
>
> David

Kees had previously pushed a patch to do so but it exposed a couple of
underlying issues, mostly with low power paths
(c.f. http://article.gmane.org/gmane.linux.ports.arm.kernel/471199,
http://article.gmane.org/gmane.linux.kernel.mm/143489)
Those will need to be all fixed up before this could be made default.

Thanks,
Laura

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


#1315242 — Re: [kernel-hardening] [PATCH v4 0/8] introduce post-init read-only memory

FromKees Cook <keescook@chromium.org>
Date2016-01-22 21:00 +0100
SubjectRe: [kernel-hardening] [PATCH v4 0/8] introduce post-init read-only memory
Message-ID<qTQ2d-cO-1@gated-at.bofh.it>
In reply to#1315234
On Fri, Jan 22, 2016 at 11:16 AM, Laura Abbott <laura@labbott.name> wrote:
> On 1/22/16 9:19 AM, David Brown wrote:
>>
>> On Tue, Jan 19, 2016 at 10:08:34AM -0800, Kees Cook wrote:
>>
>>> This introduces __ro_after_init as a way to mark such memory, and uses
>>> it on the x86 vDSO to kill an extant kernel exploitation method. Also
>>> adds a new kernel parameter to help debug future use and adds an lkdtm
>>> test to check the results.
>>
>>
>> I've tested these patches on 32-bit ARM using the provoke-crashes
>> test.  However, they do require CONFIG_ARM_KERNMEM_PERMS to be enabled
>> as well, which does incur additional memory usage.

Thanks for testing!

>> Do we want to consider making CONFIG_ARM_KERNMEM_PERMS default y for
>> security reasons, and just document that memory-constrained systems
>> may want to turn it off?
>>
>> I'll test the arm64 next.
>>
>> David
>
>
> Kees had previously pushed a patch to do so but it exposed a couple of
> underlying issues, mostly with low power paths
> (c.f. http://article.gmane.org/gmane.linux.ports.arm.kernel/471199,
> http://article.gmane.org/gmane.linux.kernel.mm/143489)
> Those will need to be all fixed up before this could be made default.

Yeah, I've got a patch waiting to reorganize CONFIG_ARM_KERNMEM_PERMS
to look more like arm64 (and x86) and get the feature correctly under
CONFIG_DEBUG_RODATA. I made it default=y on v7+. rmk asked me to wait
until -rc1 before resubmitting it.

http://git.kernel.org/cgit/linux/kernel/git/kees/linux.git/commit/?h=kspp/arm-rodata&id=08bebfd2e7fb8a9f364ced74c356642d64e1f43e

and a small improvement too:

http://git.kernel.org/cgit/linux/kernel/git/kees/linux.git/commit/?h=kspp/arm-rodata&id=8e16f005ce0d4069aee5502379cff845b4c6f950

-Kees

-- 
Kees Cook
Chrome OS & Brillo Security

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


#1315551 — Re: [kernel-hardening] [PATCH v4 0/8] introduce post-init read-only memory

FromGeert Uytterhoeven <geert@linux-m68k.org>
Date2016-01-23 10:50 +0100
SubjectRe: [kernel-hardening] [PATCH v4 0/8] introduce post-init read-only memory
Message-ID<qU2Zr-K2-7@gated-at.bofh.it>
In reply to#1315242
Hi Kees,

On Fri, Jan 22, 2016 at 8:57 PM, Kees Cook <keescook@chromium.org> wrote:
> On Fri, Jan 22, 2016 at 11:16 AM, Laura Abbott <laura@labbott.name> wrote:
>> Kees had previously pushed a patch to do so but it exposed a couple of
>> underlying issues, mostly with low power paths
>> (c.f. http://article.gmane.org/gmane.linux.ports.arm.kernel/471199,
>> http://article.gmane.org/gmane.linux.kernel.mm/143489)
>> Those will need to be all fixed up before this could be made default.

I'm working on fixing that...

BTW, making the sections read-only is done quite late in the kernel startup
process, which means it doesn't trigger for the writes to the text segment in
secondary CPU bringup, but only for suspend/resume.

> Yeah, I've got a patch waiting to reorganize CONFIG_ARM_KERNMEM_PERMS
> to look more like arm64 (and x86) and get the feature correctly under
> CONFIG_DEBUG_RODATA. I made it default=y on v7+. rmk asked me to wait
> until -rc1 before resubmitting it.
>
> http://git.kernel.org/cgit/linux/kernel/git/kees/linux.git/commit/?h=kspp/arm-rodata&id=08bebfd2e7fb8a9f364ced74c356642d64e1f43e

One other concern is indeed memory usage ("ALIGN(1<<SECTION_SHIFT)"?).
Enabling CONFIG_ARM_KERNMEM_PERMS and CONFIG_DEBUG_RODATA in my test kernel
configs make the kernel too big to boot (overwritten DTB?) for 3 out of 4 arm
shmobile targets...

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web