On Mon, 17 Jun 2024 09:07:29 +0200
Alexander Graf<graf@xxxxxxxxxx> wrote:
Hey Steve,Note, it's not random. It picks from the top of available memory every
I believe we're talking about 2 different things :). Let me rephrase a
bit and make a concrete example.
Imagine you have passed the "reserve_mem=12M:4096:trace" kernel command
line option. The kernel now comes up and allocates a random chunk of
memory that - by (admittedly good) chance - may be at the same physical
location as before. Let's assume it deemed 0x1000000 as a good offset.
time. But things can mess with it (see below).
Let's now assume you're running on a UEFI system. There, you always haveThis could be an added feature, but it is very architecture specific,
non-volatile storage available to you even in the pre-boot phase. That
means the kernel could create a UEFI variable that says "12M:4096:trace
-> 0x1000000". The pre-boot phase takes all these UEFI variables and
marks them as reserved. When you finally reach your command line parsing
logic for reserve_mem=, you can flip all reservations that were not on
the command line back to normal memory.
That way you have pretty much guaranteed persistent memory regions, even
with KASLR changing your memory layout across boots.
The nice thing is that the above is an extension of what you've already
built: Systems with UEFI simply get better guarantees that their regions
persist.
and would likely need architecture specific updates.
So I just ran it a hundred times in a loop. I added a patch to printOnce is pretty good. Do you know why? Also once out of how many runs? IsI think I was hit by it once in all my testing. For our use case, theRequirement:With KASLR is enabled, doesn't this approach break too often to be
Need a way to reserve memory that will be at a consistent location for
every boot, if the kernel and system are the same. Does not need to work
if rebooting to a different kernel, or if the system can change the
memory layout between boots.
The reserved memory can not be an hard coded address, as the same kernel /
command line needs to run on several different machines. The picked memory
reservation just needs to be the same for a given machine, but may be
reliable enough for the data you want to extract?
Picking up the idea above, with a persistent variable we could even make
KASLR avoid that reserved pstore region in its search for a viable KASLR
offset.
few times it fails to map is not going to affect what we need this for
at all.
the randomness source not as random as it should be or are the number of
bits for KASLR maybe so few on your target architecture that the odds of
hitting anything become low? Do these same constraints hold true outside
of your testing environment?
the location of "_text". The loop was this:
for i in `seq 100`; do
ssh root@debiantesting-x86-64 "dmesg | grep -e 'text starts' -e 'mapped boot' >> text; grub-reboot '1>0'; sleep 0.5; reboot"
sleep 25
done
It searches dmesg for my added printk as well as the print of were the
ring buffer was loaded in physical memory.
It takes about 15 seconds to reboot, so I waited 25. The results are
attached. I found that it was consistent 76 times, which means 1 out of
4 it's not. Funny enough, it broke whenever it loaded the kernel below
0x100000000. And then it would be off by a little.
It was consistently at:
0x27d000000
And when it failed, it was at 0x27ce00000.
Note, when I used the e820 tables to do this, I never saw a failure. My
assumption is that when it is below 0x100000000, something else gets
allocated causing this to get pushed down.
As this code relies on memblock_phys_alloc() being consistent, if
something gets allocated before it differently depending on where the
kernel is, it can also move the location. A plugin to UEFI would mean
that it would need to reserve the memory, and the code here will need
to know where it is. We could always make the function reserve_mem()
global and weak so that architectures can override it.