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

mm: various improvements to PageRef #450

Merged
merged 5 commits into from
Sep 16, 2024
Merged

Conversation

Freax13
Copy link
Contributor

@Freax13 Freax13 commented Aug 29, 2024

This PR fixes some soundness issues around PageRef and adds save abstractions for reading, writing, and filling a PageRef.

@Freax13 Freax13 mentioned this pull request Aug 29, 2024
14 tasks
kernel/src/mm/alloc.rs Outdated Show resolved Hide resolved
@p4zuu
Copy link
Collaborator

p4zuu commented Aug 30, 2024

I think I don't fully understand why implementing PageRef::read()/write()/fill() in assembly fixes the soundness issue. It's just shortening the race window, right? Otherwise, looks good to me

@Freax13
Copy link
Contributor Author

Freax13 commented Aug 30, 2024

I think I don't fully understand why implementing PageRef::read()/write()/fill() in assembly fixes the soundness issue. It's just shortening the race window, right? Otherwise, looks good to me

Data races are only UB if they happen through normal reads or writes. If we implement the reads/writes in assembly, data races aren't UB.

Copy link
Member

@joergroedel joergroedel left a comment

Choose a reason for hiding this comment

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

In general this looks good to me, thanks for improving this. I just left two comments to improve future portability.

kernel/src/mm/alloc.rs Outdated Show resolved Hide resolved
kernel/src/mm/alloc.rs Outdated Show resolved Hide resolved
Previously PageRef::new was unsound because it allowed the caller to pass in
any virtual address and dereferene it through the returned PageRef.
allocate_file_page_ref is the only caller of PageRef::new, so moving the alloc
step into PageRef::new doesn't break anything.

Signed-off-by: Tom Dohrmann <[email protected]>
After the previous patch, this function did nothing but call another function,
so we might as well remove this function.

Signed-off-by: Tom Dohrmann <[email protected]>
These are safe methods to write to the pointed to memory that take care of any
bounds checks. Making these into methods also makes it easier to change to
their implementations to be more sound.

Signed-off-by: Tom Dohrmann <[email protected]>
Previously PageRef had AsMut<[u8; PAGE_SIZE]> and AsRef<[u8; PAGE_SIZE]>
implementations that provided access the the bytes in the page. Unfortunately,
this is not sound because PageRef doesn't have unique ownership over the page:
An aliasing page can be create by calling .clone() and the page is also aliased
when it's mapped into a page table. For these reasons, non-atomic accesses
could potentially cause a data race and those are UB. This leaves two
solutions for implementing the methods for PageRef:
1. Only use Relaxed atomic accesses. The codegen for this is generally quite
   bad because LLVM will access each byte individually.
2. Implement them in assembly. The upside of this is that if we control the
   assembly, so there's no compiler that will tell us what we can and can't do.
For this patch, I've opted for the second solution.

Signed-off-by: Tom Dohrmann <[email protected]>
drain is shorter and faster :)

Signed-off-by: Tom Dohrmann <[email protected]>
Copy link
Member

@joergroedel joergroedel left a comment

Choose a reason for hiding this comment

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

LGTM, including testing.

@joergroedel joergroedel merged commit f23151f into coconut-svsm:main Sep 16, 2024
3 checks passed
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.

4 participants