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: Lay down the foundations #725

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
Draft

ASLR: Lay down the foundations #725

wants to merge 12 commits into from

Conversation

n0toose
Copy link
Member

@n0toose n0toose commented Jul 6, 2024

  • Move x86_64-related paging code to src/arch/x86_64/paging
  • Tests: x86_64-related paging tests should use a guest_address that is
    not 0
  • Tests: Move them in separate files, use appropriate 'use' directives
  • Tests: Use init_guest_mem wrapper in test_virt_to_phys
  • Fix kernel memory loading
  • Add guest_address getter in UhyveVm
  • Change names of constants to clarify their purpose
  • Remove pagetable_l0 from virt_to_phys function
  • Various cargo fmt-related changes
  • aarch64: Blindly replace constant names and similar RAM_START change

We currently rely on guest_address in MmapMemory to calculate the
offsets during the initialization of the VM and when converting
virtual addresses to physical addresses. The latter case is intended
to be temporary - we should read the value from the CR3 register at
a later point.

Although this current revision does work with relocatable binaries, it
is not making use of this functionality just yet.

Fixes #719.
Fixes #713.

@n0toose
Copy link
Member Author

n0toose commented Jul 6, 2024

This change was not tested on macOS (x86_64, aarch64) because of a lack of hardware, and, in the case of macOS (x86_64), there's no CI - I may have to bring up a VM for this, but it will take at least an hour to prepare it. This involved some guess work in both aarch64 and x86_64 - because of this, I will explicitly disable the upcoming ASLR feature in both of these cases.

The change looks artificially bigger than it is because of the x86_64 paging code being moved to a separate file. This is easy for me to undo.

  • This is a rebased and somewhat "cleaned up" version of https://github.com/n0toose/uhyve/tree/make-it-boot (might help with the review), plus lots of tiny changes:
    • I had to fix lots of things in aarch64 (very often, formatting mistakes caught by cargo fmt).
    • Everything aarch64 and macOS-related is not part of the tree
  • Despite the refactoring, the guest_address should always be zero for the time being. The work to change this was done here: ASLR: PoC for generating random address before Uhyve launches #711
  • These two changes were kept separate because of the very big scope of this change - and because some further thought has to be poured into the case of the hello_c case.

Copy link
Member Author

@n0toose n0toose left a comment

Choose a reason for hiding this comment

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

There has been a regression (commit currently unknown) that makes hello_c not run.

EDIT:

Copy link
Member Author

@n0toose n0toose left a comment

Choose a reason for hiding this comment

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

cargo test new_file_test (test kernel is written in Rust, should therefore be relocatable) fails:

EDIT: Unrelated to this change, also happens on main. See #726 (with log).

Copy link

codecov bot commented Jul 6, 2024

Codecov Report

Attention: Patch coverage is 96.98492% with 6 lines in your changes missing coverage. Please review.

Project coverage is 68.86%. Comparing base (e6ffffa) to head (08bfcfd).
Report is 10 commits behind head on main.

Files Patch % Lines
src/hypercall.rs 42.85% 4 Missing ⚠️
src/arch/x86_64/paging/mod.rs 99.15% 1 Missing ⚠️
src/vm.rs 95.65% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #725      +/-   ##
==========================================
+ Coverage   68.17%   68.86%   +0.68%     
==========================================
  Files          20       21       +1     
  Lines        2319     2370      +51     
==========================================
+ Hits         1581     1632      +51     
  Misses        738      738              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Member Author

@n0toose n0toose left a comment

Choose a reason for hiding this comment

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

I spent 15 minutes trying to give more context behind the macOS changes on x86_64 and aarch64 to help the review process - where I tried to change the least amount of things possible until the compiler stopped being mad at me (and as a way of double-checking the changes).

The goal is to have this changed merged directly into main or in a feature branch, so that I can continue working on top of these foundations. Hope this helps.

(EDIT: I marked all of these comments as "resolved" to keep the PR log cleaner.)

src/arch/aarch64/mod.rs Outdated Show resolved Hide resolved
src/arch/aarch64/mod.rs Show resolved Hide resolved
src/arch/x86_64/mod.rs Outdated Show resolved Hide resolved
src/arch/aarch64/mod.rs Show resolved Hide resolved
src/macos/aarch64/vcpu.rs Show resolved Hide resolved
src/macos/x86_64/vcpu.rs Show resolved Hide resolved
src/macos/x86_64/vcpu.rs Show resolved Hide resolved
src/vm.rs Outdated Show resolved Hide resolved
src/vm.rs Outdated Show resolved Hide resolved
@n0toose n0toose force-pushed the aslr branch 2 times, most recently from 3589fe8 to 08bfcfd Compare July 8, 2024 12:47
src/arch/x86_64/mod.rs Outdated Show resolved Hide resolved
// TODO: guest_address is only taken into account on Linux platforms.
// TODO: Before changing this, fix init_guest_mem in `src/arch/aarch64/mod.rs`
#[cfg(target_os = "linux")]
#[cfg(not(target_arch = "x86_64"))]
Copy link
Member Author

@n0toose n0toose Jul 10, 2024

Choose a reason for hiding this comment

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

TODO: Remove this #[cfg... mess and replace it with a feature as soon as

https://github.com/hermit-os/uhyve/pull/725/files#r1672908739 is answered.

&mut self,
entry_point: u64,
stack_address: u64,
guest_address: u64,
Copy link
Member

Choose a reason for hiding this comment

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

What is guest_address? I think we need some documentation here.

Copy link
Member Author

Choose a reason for hiding this comment

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

I could not clarify this in time, but guest_address is necessary for setting the registers to their correct values.

This was not done for every architecture and operating system - it was only done on x86_64 Linux and, using guesswork, on x86_64 macOS - however, I had to put it in there everywhere nevertheless, even if it has no effect on some architectures.

Comment on lines 311 to 313
entry_point: u64,
stack_address: u64,
guest_address: u64,
Copy link
Member

Choose a reason for hiding this comment

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

This could be GuestPhysicalAddresses, whilst we are on it, right?

Copy link
Member Author

Choose a reason for hiding this comment

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

Partially resolved, stack_address and entry_point possibly unnecessary?

@@ -233,7 +233,7 @@ impl XhyveCpu {
Ok(())
}

fn setup_system_64bit(&mut self) -> Result<(), xhypervisor::Error> {
fn setup_system_64bit(&mut self, guest_address: u64) -> Result<(), xhypervisor::Error> {
Copy link
Member

Choose a reason for hiding this comment

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

Please add a doc comment on what guest_address is

@@ -219,7 +263,7 @@ impl<VCpuType: VirtualCPU> UhyveVm<VCpuType> {
};
unsafe {
let raw_boot_info_ptr =
self.mem.host_address.add(BOOT_INFO_ADDR.as_u64() as usize) as *mut RawBootInfo;
self.mem.host_address.add(BOOT_INFO_ADDR_OFFSET as usize) as *mut RawBootInfo;
*raw_boot_info_ptr = RawBootInfo::from(boot_info);
self.boot_info = raw_boot_info_ptr;
}
Copy link
Member Author

@n0toose n0toose Jul 22, 2024

Choose a reason for hiding this comment

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

In the following line (270-271, GitHub won't let me comment) the self.stack_address = ... check is possibly unsound?

Copy link
Member Author

@n0toose n0toose left a comment

Choose a reason for hiding this comment

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

Some notes on the latest revision which does not fully work...

src/vm.rs Outdated Show resolved Hide resolved
src/vm.rs Outdated
@@ -152,6 +231,10 @@ impl<VCpuType: VirtualCPU> UhyveVm<VCpuType> {
self.stack_address
}

pub fn guest_address(&self) -> u64 {
self.guest_address.as_u64()
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 should be fixed, and start_address should be appended.

src/vm.rs Outdated Show resolved Hide resolved
src/vm.rs Show resolved Hide resolved
src/vm.rs Outdated
let kernel_end_address = kernel_start_address + object.mem_size();
self.offset = kernel_start_address as u64;
let kernel_end_address = self.start_address.as_u64() as usize + object.mem_size();
self.offset = self.start_address.as_u64();
Copy link
Member Author

Choose a reason for hiding this comment

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

Currently, UhyveVm has two entries: self.offset, self.start_address, which effectively do the same thing. One of them should be removed, probably.

n0toose and others added 3 commits September 18, 2024 19:01
- Move x86_64-related paging code to src/arch/x86_64/paging
- Tests: x86_64-related paging tests should use a guest_address that is
  not 0
- Tests: Move them in separate files, use appropriate 'use' directives
- Tests: Use init_guest_mem wrapper in test_virt_to_phys
- Fix kernel memory loading
- Add guest_address getter in UhyveVm
- Change names of constants to clarify their purpose
- Use u64 for arch::RAM_START instead of GuestVirtAddr
- Remove pagetable_l0 from virt_to_phys function
- Various `cargo fmt`-related changes
- aarch64: Blindly replace constant names and similar RAM_START change

We currently rely on guest_address in MmapMemory to calculate the
offsets during the initialization of the VM and when converting
virtual addresses to physical addresses. The latter case is intended
to be temporary - we should read the value from the CR3 register at
a later point, but this is too complex for the time being because of
the different architectures.

Although this current revision does work with relocatable binaries, it
is not making use of this functionality _just_ yet.

Fixes hermit-os#719.

Co-authored-by: Jonathan <[email protected]>
This will be used by other functions for now, instead of
relying on mem.guest_address.

guest_address should only be a GuestPhysAddr internally for now,
as other functions in places like src/linux/x86_64/kvm_cpu.rs
use it.
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.

Remove pagetable_l0 parameter in virt_to_phys. virt_to_phys: breaks if guest_address is not equal to 0
2 participants