Re: [RFC][PATCH] Randomize kernel base address on boot

Ingo Molnar
2011-05-25T14:29:49Z

* Dan Rosenberg <drosenberg@vsecurity.com> wrote:

> On Wed, 2011-05-25 at 13:23 +0200, Ingo Molnar wrote:
> > * Dan Rosenberg <drosenberg@vsecurity.com> wrote:
> >
> > > > No, the right solution is what i suggested a few mails ago:
> > > > /proc/kallsyms (and other RIP printing places) should report the
> > > > non-randomized RIP.
> > > >
> > > > That way we do not have to change the kptr_restrict default and
> > > > tools will continue to work ...
> > >
> > > Ok, I'll do it this way, and leave the kptr_restrict default to 0.
> > > But I still think having the dmesg_restrict default depend on
> > > randomization makes sense, since kernel .text is explicitly
> > > revealed in the syslog.
> >
> > Hm, where is it revealed beyond intcall addresses, which ought to be
> > handled if they are printed via %pK?
> >
> > All such information leaks need to be fixed. (This will be the
> > slowest part of the process i suspect - there's many channels.)
> >
> > in the syslog we obviously want any RIPs converted to the canonical
> > 'unrandomized' address, so that it can be matched against
> > /proc/kallsyms, etc. Their randomized value isnt very useful. That
> > will also protect the randomization secret as a side effect.
> >
>
> %pK doesn't seem like the right thing to do in many cases, since
> the capability check doesn't have proper meaning if the caller
> isn't in process context. [...]

Oh, ok, i see what you mean.

I was not thinking of %pK as a way to restrict access really. I am
thinking of it as a nicely central way to create constant RIPs out of
random RIPs.

In that sense if %pK cannot be called everywhere please introduce a
%pk variant that just prints a raw kernel address value and does no
access check, just the unrandomization.

> [...] If I'm understanding you right (correct if I'm wrong),
> you're looking for kptr_restrict to be completely separate from
> this randomization, and when randomization is enabled, all pointers
> are unconditionally de-randomized. It seems like the right way to
> do this is to include code in vsprintf.c for all %p-type specifiers
> that would normally print the actual pointer (as opposed to some of
> the specialized cases that print other data) that does something
> like this:
>
> if((unsigned long)ptr >= (unsigned long)_stext &&
> (unsigned long)ptr <= (unsigned long)_end)
> ptr -= (_text - (CONFIG_PHYSICAL_START + PAGE_OFFSET));
>
> This way, we don't have to go tracking down every printk caller and
> convert them to %pK, which isn't usable anyway in some cases.

Yeah, but please also provide %pk to not have to hunt down every
single place that might print a kernel address via a "%016Lx" or "%p"
and thus leaks the randomization secret.

That way you can convert *every* known kernel-address-printing format
string to one of the %p variants and thus have the above
unrandomization step done automatically.

Perhaps as a debugging help also try to flag %p printouts that are
suspiciously within kernel image boundaries. (Note: you dont want to
printk from that place though, as you could already be executing
within printk.) Maybe even %x/%X printouts that are in that range. As
a debugging help, there could easily be false positives.

> I'm tempted to just say "leave OOPS alone", and if you want to preserve
> secrecy past an OOPS, you should be disabling dmesg access anyway. But
> I'll think more about this.

It's definitely a good first-approximation answer. We only do perfect
kernels anyway, so they wont oops.

Please convert RIPs in oops decoding nevertheless, so that it can be
correlated with the symbol table...

Thanks,

Ingo