Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

uefi: alloc_pages() and alloc_pool() now return NonNull<[u8]>#1606

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Closed
phip1611 wants to merge2 commits intomainfromuefi-alloc

Conversation

phip1611
Copy link
Member

uefi: alloc_pages() and alloc_pool() now returnNonNull<[u8]>. This aligns the signature with the Rust allocator API and also makes more sense.

Checklist

  • Sensible git history (for example, squash "typo" or "fix" commits). See theRewriting History guide for help.
  • Update the changelog (if necessary)

@phip1611phip1611 mentioned this pull requestApr 6, 2025
15 tasks
@phip1611phip1611 self-assigned thisApr 7, 2025

Ok(NonNull::new(ptr).expect("allocate_pool must not return a null pointer if successful"))
if let Some(ptr) = NonNull::new(ptr) {
Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Suggested change
ifletSome(ptr) =NonNull::new(ptr){
NonNull::new(ptr).map(|ptr|NonNull::slice_from_raw_parts(ptr, size)).ok_or(Status::OUT_OF_RESOURCES.into())

@@ -281,7 +281,7 @@ impl MemoryMapBackingMemory {
pub(crate) fn new(memory_type: MemoryType) -> crate::Result<Self> {
let memory_map_meta = boot::memory_map_size();
let len = Self::safe_allocation_size_hint(memory_map_meta);
let ptr = boot::allocate_pool(memory_type, len)?.as_ptr();
let ptr = boot::allocate_pool(memory_type, len)?.cast::<u8>().as_ptr();
Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Just making the new API compatible with existing code; shortcut

@@ -100,7 +102,8 @@ unsafe impl GlobalAlloc for Allocator {
// `allocate_pool` always provides eight-byte alignment, so we can
// use `allocate_pool` directly.
boot::allocate_pool(memory_type, size)
.map(|ptr| ptr.as_ptr())
.map(|mut ptr: NonNull<[u8]>| unsafe { ptr.as_mut() })

Choose a reason for hiding this comment

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

I think this is unsound:as_mut creates a reference, but that's not valid because the allocated memory is uninitialized. I think instead this can be:

            boot::allocate_pool(memory_type, size).map(|ptr:NonNull<[u8]>| ptr.as_ptr().cast::<u8>()).unwrap_or(ptr::null_mut())

(Potentially in the future it could be further simplified toptr.as_mut_ptr(), butit's not yet stable.)

Copy link
MemberAuthor

@phip1611phip1611Apr 15, 2025
edited
Loading

Choose a reason for hiding this comment

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

I think this is unsound: as_mut creates a reference, but that's not valid because the allocated memory is uninitialized.

Discussion continues here:#1606 (comment)

let addr = ptr.as_ptr() as usize;
assert_eq!(addr % 4096, 0, "Page pointer is not page-aligned");

let buffer = unsafe { ptr.as_mut() };

Choose a reason for hiding this comment

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

Same issue here, this is unsound with uninitialized memory. I don't think we have to usewrite_volatile like the code here did originally, but we do need to use some pointer function likeptr::write orptr::write_bytes.

Since so many of theNonNull<[T]>/*mut [T] functions are unstable, I think it's most convenient to cast it back to*mut u8. Then you can dounsafe { ptr.write_bytes(...) }.

Ditto for the docstring examples onboot::allocate_pages/boot::allocate_pool.

Copy link
MemberAuthor

@phip1611phip1611Apr 15, 2025
edited
Loading

Choose a reason for hiding this comment

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

I think the concern you raised is not correct:#1606 (comment)

This aligns the signature with the Rust allocator API.
This aligns the signature with the Rust allocator API.
@phip1611
Copy link
MemberAuthor

phip1611 commentedApr 15, 2025
edited
Loading

I think we are safe if we write the following into the documentation of each function:

image

I think this is valid as Miri verifies my assumptions in this code:

#![feature(allocator_api)]use std::alloc::{Allocator,GlobalAlloc,Layout,System};fnmain(){let layout =Layout::from_size_align(4096,4096).unwrap();letmut buffer_ptr =System.allocate(layout).unwrap();let buffer =unsafe{ buffer_ptr.as_mut()};    buffer[1] =42;let _x = buffer[1];let _y = buffer[2];unsafe{System.dealloc(buffer_ptr.as_ptr().cast(), layout);}}

What do you think, are we on the same page?

@nicholasbishop
Copy link
Member

Miri is a runtime checker, so it can't fully detect all cases of UB. I'm pretty confident that creating a reference to uninitialized memory is always UB, regardless of whether the reference is read from, unless you useMaybeUninit or a similar construct. TheMaybeUninit doc has some examples of instant-UB that don't require a read.

So there's no documentation-level exemption we can give ourselves -- the allocation must be initialized via the pointer API (or&[MaybeUninit<u8>]).

@phip1611phip1611 mentioned this pull requestMay 5, 2025
10 tasks
@phip1611
Copy link
MemberAuthor

phip1611 commentedMay 6, 2025
edited
Loading

  • It seems as the allocator API was created long before the discussions aboutMaybeUninit came up. Afterasking the community, Matthieu M.pointed out to me that the allocator API wasn't as thoroughly designed as I expected. Also, the progress on that feature is currently dead.

  • The discussion above was whether creating a reference to uninitalized memory creates undefined behavior. This is not yet decided in theRust reference. It might be okay, it might be not.

    Note that the last point (about pointing to a valid value) remains a subject of some
    debate.

This leaves us (and the community) in an unfortunate situation. Wonderful!

My suggestion:

What do you think?@nicholasbishop

@nicholasbishop
Copy link
Member

Yes, I'm fine with closing. I think we can leave the existingNonNull<u8> though, rather than switching to*mut u8. There isn't a big difference, right? So might as well avoid API churn.

@phip1611
Copy link
MemberAuthor

Leftovers have been moved to#1665

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@nicholasbishopnicholasbishopnicholasbishop left review comments

Assignees

@phip1611phip1611

Labels
None yet
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

2 participants
@phip1611@nicholasbishop

[8]ページ先頭

©2009-2025 Movatter.jp