Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Wed, 2 Oct 2013 07:25:32 +0200
From: Ingo Molnar <mingo@...nel.org>
To: "H. Peter Anvin" <hpa@...or.com>
Cc: Kees Cook <keescook@...omium.org>, linux-kernel@...r.kernel.org,
	x86@...nel.org, kernel-hardening@...ts.openwall.com,
	adurbin@...gle.com, Eric Northup <digitaleric@...gle.com>,
	jln@...gle.com, wad@...gle.com,
	Mathias Krause <minipli@...glemail.com>,
	Zhang Yanfei <zhangyanfei@...fujitsu.com>,
	Linus Torvalds <torvalds@...ux-foundation.org>,
	Andrew Morton <akpm@...ux-foundation.org>,
	Arnaldo Carvalho de Melo <acme@...radead.org>,
	Peter Zijlstra <a.p.zijlstra@...llo.nl>,
	Thomas Gleixner <tglx@...utronix.de>
Subject: Re: [PATCH v6 0/7] Kernel base address randomization


* H. Peter Anvin <hpa@...or.com> wrote:

> I think that the randomization offset would be necessary in order to 
> identify pointers.

I mean, for example in an oops message we print data in words: the RIP, 
other registers and stack contents. If any of these values lies within the 
randomization range then we could de-randomize it.

So instead of exposing randomized values, we could expose de-randomized 
values.

( This isn't fool-proof: if some data value happens to lie within the 
  random range spuriously then we'll incorrectly transform it. In the 
  context of oops messages this should not be a big practical problem 
  though. )

For example, assume that the following oops is from a distro kernel and 
contains raw randomized addresses:

[    0.000000] ------------[ cut here ]------------
[    0.000000] WARNING: CPU: 0 PID: 0 at init/main.c:544 start_kernel+0x1fa/0x3e8()
[    0.000000] PANIC: double fault, error_code: 0xffffffff810e74ed
[    0.000000] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 3.12.0-rc1-01728-gd787a30-dirty #54
[    0.000000] Hardware name: Supermicro X8DTN/X8DTN, BIOS 4.6.3 09/04/2008
[    0.000000] task: ffffffff81e104a0 ti: ffffffff81e00000 task.ti: ffffffff81e00000
[    0.000000] RIP: 0246:[<0000000000000010>]  [<0000000000000010>] 0xf
[    0.000000] RSP: 0000:0000000000000000  EFLAGS: ffffffff81e01de8
[    0.000000] RAX: 0000000005330533 RBX: 0000000000000001 RCX: 000000000000023f
[    0.000000] RDX: 0000000000000533 RSI: 0000000000000046 RDI: ffffffff82099944
[    0.000000] RBP: ffffffff81e01e68 R08: 000000004e524157 R09: 00000000000000ca
[    0.000000] R10: 3a4449502030203a R11: 555043203a474e49 R12: 00000000ffffffff
[    0.000000] R13: 0000000000000000 R14: 0000000000000044 R15: 0000000000000006
[    0.000000] FS:  0000000000000000(0000) GS:ffff8801b9c00000(0000) knlGS:0000000000000000
[    0.000000] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
[    0.000000] CR2: ffff88033ffff000 CR3: 0000000001e0b000 CR4: 00000000000006b0
[    0.000000] 
[    0.000000] Kernel panic - not syncing: Machine halted.
[    0.000000] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 3.12.0-rc1-01728-gd787a30-dirty #54
[    0.000000] Hardware name: Supermicro X8DTN/X8DTN, BIOS 4.6.3 09/04/2008
[    0.000000]  ffff8801b9c06f60 ffff8801b9c06e80 ffffffff81822bd3 0000000000000586
[    0.000000]  ffffffff81c8e10b ffff8801b9c06f00 ffffffff8181efdb ffffffff81e00000
[    0.000000]  0000000000000008 ffff8801b9c06f10 ffff8801b9c06eb0 6230653130303030
[    0.000000] Call Trace:
[    0.000000]  <#DF>  [<ffffffff81822bd3>] dump_stack+0x46/0x58
[    0.000000]  [<ffffffff8181efdb>] panic+0xb6/0x1bf
[    0.000000]  [<ffffffff81078980>] df_debug+0x30/0x30
[    0.000000]  [<ffffffff810e74ed>] ? vprintk_emit+0x1ed/0x4e0
[    0.000000]  [<ffffffff810e74ed>] ? vprintk_emit+0x1ed/0x4e0
[    0.000000]  [<ffffffff81046471>] do_double_fault+0x61/0x90
[    0.000000]  [<ffffffff818324d2>] double_fault+0x22/0x30
[    0.000000]  <<EOE>>  [<ffffffff813ba281>] ? vsnprintf+0x471/0x650
[    0.000000]  [<ffffffff81f28c9f>] ? start_kernel+0x1fa/0x3e8
[    0.000000]  [<ffffffff8181f505>] printk+0x5c/0x5e
[    0.000000]  [<ffffffff81f28c9f>] ? start_kernel+0x1fa/0x3e8
[    0.000000]  [<ffffffff810962ec>] warn_slowpath_common+0x6c/0xb0
[    0.000000]  [<ffffffff810963d1>] warn_slowpath_fmt+0x41/0x50
[    0.000000]  [<ffffffff81f28c9f>] start_kernel+0x1fa/0x3e8
[    0.000000]  [<ffffffff81f288a4>] ? repair_env_string+0x5e/0x5e
[    0.000000]  [<ffffffff81f285a5>] x86_64_start_reservations+0x2a/0x2c
[    0.000000]  [<ffffffff81f286a4>] x86_64_start_kernel+0xfd/0x101

Anyone who reads this oops can recover the random offset by knowing the 
non-randomized value:

   $ grep -w printk /boot/System.map-3.9.10-100.fc17.x86_64
   ffffffff81651a64 T printk

and substracting that from the value seen in the oops:

[    0.000000]  [<ffffffff8181f505>] printk+0x5c/0x5e

So my suggestion would be to check each printed out value in an oops 
message and de-randomize it if it's within the randomized range. So the 
above entry would be printed as the 'static' address:

[    0.000000]  [<ffffffff81651a64>] printk+0x5c/0x5e

Note how this entry does not expose the random offset anymore. It's also 
easy to stick the raw value into 'gdb vmlinux' and use it for debugging.

Something similar can be done for profiling streams where we _know_ that 
it's a kernel text address (the perf profiling trace entries for example), 
and the same could be done for /proc/kallsyms.

The random range is a fairly narrow region of 64-bit address space so 
spurious hits should be relatively rare.

Now, a 'raw' address might still lie in places like mixed up in registers 
or lying non-word-aligned on the kernel stack - but at least the 'typical' 
oops would be fairly safe to post and there would be no 'obvious' places 
to recover the secret from, even if you happen to have access to some logs 
and some profiling.

At least that's the argument that can be made. I'm not entirely sure it's 
valid and I'm leaning towards the simplicity of only outputting raw oops 
values.

Thanks,

	Ingo

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.