Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ASLR: PoC for generating random address before Uhyve launches #711

Closed
wants to merge 14 commits into from

Conversation

n0toose
Copy link
Member

@n0toose n0toose commented Jun 17, 2024

The code itself is ready to be reviewed - I chose to open this PR with a full commit history (despite how it got very, very messy at times) to help make some (sometimes arbitrary) decisions more clear. All of it will be squashed later. The description will be edited later too.

This change was exclusively tested on Linux (x86_64).

Fixes: #707

n0toose added 13 commits June 15, 2024 15:04
The previous value, 0x8000, caused problems.

The minimum value required for relocatable images to load (starting from NULL)
is 0x13000. For additional buffer, the temporary hack here is to increase
that said value.
- Introduce end_address_upper_bound.
- Add mask.
  - Some additional investigation and testing is necessary.
  - Right now, it feels like the mask just works because of a magic
    spell called "Works on my machine.". I didn't get creative with
    the spell name (which does not exist), because I don't know how
    spells sound like. Sorrry.
- Some architecture-specific work may be needed.
- Some fine-tuning and debugging information for ASLR is necessary.
- 0xFFFFF0 cut off the upper 4 bits.
- Some sleep is required.
- Some bitwise arithmetic was avoided.
- Why over-engineer a literal mask value?
- I should take a break.
There is something wrong going on here in this current revision.
Not sure why.
- It's #[cfg(not(feature = aslr))], not #[not(cfg(feature = aslr))].
- Some additional typo-induced bug was fixed.

.-.
@n0toose
Copy link
Member Author

n0toose commented Jun 17, 2024

In the issue linked above, I made a massive TODO list that also documents some problems that I had: #707 (comment)

Many of the points I made (such as "comparing the generated address with the hardcoded address") were worked around. I tried to design this change with optimization in mind, e.g. not add any runtime delay in the event that ASLR is disabled.

Some points:

We should probably tell Uhyve that it is enabled once we are sure that nothing
has gone wrong. What we should do when something goes wrong (can anything go
wrong?) is an open question.
// TODO: Add test. (from start_address_upper_bound-0x000001 to start_address_upper_bound+0x000001)
//
// We use 0x100000 as the offset for the start address so as to not use the zero page.
rng.gen_range(0x100000..start_address_upper_bound) & 0xffff_ffff_ffff_fff0
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will not cut it for aarch64. I need to get Uhyve to run on aarch64 and adjust this or make this feature explicitly x86_64-only in the meantime.

@n0toose n0toose marked this pull request as draft June 18, 2024 10:54
@mkroening mkroening self-requested a review June 18, 2024 15:21
@mkroening mkroening self-assigned this Jun 18, 2024
@n0toose
Copy link
Member Author

n0toose commented Jun 19, 2024

As discussed with @jounathaen, the current approach is problematic because the kernel only uses the memory "ahead" of it, so loading the kernel at a random address results in a variable amount of available dynamic memory.

image

The last commit illustrating that problem is fe8cefacfb6dc759ba5c93a8bf0ac7ec4807e60b, which fails sometimes. Afterwards, the upper bound of 0x3000000 was introduced as a temporary hack.

The optimal approach would be to have a memory with a variable guest_address, but I could not get it to work with a correctly aligned address because the kernel would refuse to boot - spent a few hours using the debugger and it appears that the offset and entry_point is, unless if I missed something, always correct. Despite the code being future-proofed and nearly always considering self.mem.guest_memory, I assumed that this might not always be the case in Uhyve because of an exception that I sent a PR for: #712. @mkroening thinks this was a kernel issue.

If the cause is discovered and fixed, generate_random_address should be 90% good-to-go. I'll leave this on the back burner for now and focus on something else.

@n0toose
Copy link
Member Author

n0toose commented Jun 26, 2024

Once #713 and #719 are resolved, this PR should be overhauled a little.

Note to self: Use a better random number generator: https://media.ccc.de/v/gpn20-4-unikernel-security-analysis#t=933

@n0toose n0toose changed the title Initial ASLR implementation ASLR: PoC for generating random address before Uhyve launches Jul 6, 2024
@jounathaen
Copy link
Member

Superseeded by #725

@jounathaen jounathaen closed this Jul 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement ASLR
3 participants