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

netbsd: Simplify weak lookup. #484

Merged
merged 2 commits into from
Jun 19, 2024
Merged

Conversation

briansmith
Copy link
Contributor

Remove LazyPtr. Avoid constructing an invalid pointer as a sentinel to indicate that the pointer is uninitialized. Now, a null pointer means it is uninitialized, and a non-null pointer means it is initialized. This is less questionable from a safety perspective, and should also be more efficient.

Reduce duplication between the "getrandom is available" and the fallback case.

@briansmith briansmith force-pushed the b/netbsd-weak branch 6 times, most recently from c008fee to 1a0a475 Compare June 18, 2024 20:48
@newpavlov
Copy link
Member

newpavlov commented Jun 18, 2024

What about the following comment about KERN_ARND?

NetBSD will only return up to 256 bytes at a time, and older NetBSD kernels will fail on longer buffers.

Is it no longer relevant? To be safe it may be worth to use let buflen = min(buflen, 256) in the polyfill function.

@briansmith briansmith force-pushed the b/netbsd-weak branch 2 times, most recently from e8095c6 to 5d152be Compare June 18, 2024 21:02
src/netbsd.rs Outdated Show resolved Hide resolved
@briansmith briansmith force-pushed the b/netbsd-weak branch 5 times, most recently from 40669fd to ea3436e Compare June 18, 2024 21:41
@briansmith briansmith marked this pull request as ready for review June 18, 2024 22:25
@briansmith
Copy link
Contributor Author

What about the following comment about KERN_ARND?

NetBSD will only return up to 256 bytes at a time, and older NetBSD kernels will fail on longer buffers.

Is it no longer relevant? To be safe it may be worth to use let buflen = min(buflen, 256) in the polyfill function.

Thanks. As I mentioned in the other comment, I did make this change.

Copy link
Member

@newpavlov newpavlov left a comment

Choose a reason for hiding this comment

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

Outside of several minor nits, LGTM.

src/netbsd.rs Outdated Show resolved Hide resolved
src/netbsd.rs Show resolved Hide resolved
src/netbsd.rs Outdated
let ptr = match unsafe { libc::dlsym(libc::RTLD_DEFAULT, name_ptr) } {
ptr if !ptr.is_null() => ptr,
_ => polyfill_using_kern_arand as *mut libc::c_void,
};
Copy link
Member

Choose a reason for hiding this comment

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

I think the following code will be a bit easier to read:

let mut ptr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, name_ptr) };
// If getrandom(2) is not availalbe, use KERN_ARAND polyfill
if ptr.is_null() {
    ptr = polyfill_using_kern_arand as *mut libc::c_void;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In other PRs, @josephlr asked me to write things the way I wrote it here, and to not write it the let mut ... way.

Copy link
Contributor Author

@briansmith briansmith Jun 18, 2024

Choose a reason for hiding this comment

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

BTW, the other reason I use a match is because it helps with code coverage measurement. Though we don't have that yet, I hope we do soon.

Copy link
Member

@newpavlov newpavlov Jun 18, 2024

Choose a reason for hiding this comment

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

Ok. :) I don't have a strong preference here, so I will wait for him to confirm that he prefers this way.

it helps with code coverage measurement

I think the if branch should be handled by code coverage tools without issues.

Copy link
Member

Choose a reason for hiding this comment

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

In other PRs, @josephlr asked me to write things the way I wrote it here, and to not write it the let mut ... way.

Looking at this, I think that was a bad call on my part (sorry). I agree w/ @newpavlov that the if is more readable here. @briansmith's point is a good one about code coverage, but we would ideally handle that via branch coverage (see #288 (comment))

src/netbsd.rs Show resolved Hide resolved
Copy link
Member

@josephlr josephlr left a comment

Choose a reason for hiding this comment

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

Looks nice! Thanks for simplifying this.

src/netbsd.rs Outdated
let ptr = match unsafe { libc::dlsym(libc::RTLD_DEFAULT, name_ptr) } {
ptr if !ptr.is_null() => ptr,
_ => polyfill_using_kern_arand as *mut libc::c_void,
};
Copy link
Member

Choose a reason for hiding this comment

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

In other PRs, @josephlr asked me to write things the way I wrote it here, and to not write it the let mut ... way.

Looking at this, I think that was a bad call on my part (sorry). I agree w/ @newpavlov that the if is more readable here. @briansmith's point is a good one about code coverage, but we would ideally handle that via branch coverage (see #288 (comment))

src/netbsd.rs Outdated
@@ -24,28 +44,33 @@ fn kern_arnd(buf: &mut [MaybeUninit<u8>]) -> libc::ssize_t {

type GetRandomFn = unsafe extern "C" fn(*mut u8, libc::size_t, libc::c_uint) -> libc::ssize_t;
Copy link
Member

Choose a reason for hiding this comment

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

Should the first argument be *mut c_void here? That's what the man pages has: https://man.freebsd.org/cgi/man.cgi?query=getrandom&sektion=2

I'm not sure if it particularly matters

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure if it particularly matters

In theory it could matter depending on the CFI rules. I changed it.

src/netbsd.rs Show resolved Hide resolved
Match the type signature that the NetBSD man page gives for
getrandom.
Remove LazyPtr. Avoid constructing an invalid pointer as a sentinel to
indicate that the pointer is uninitialized. Now, a null pointer means
it is uninitialized, and a non-null pointer means it is initialized.
This is less questionable from a safety perspective, and should also be
more efficient.

Reduce duplication between the "getrandom is available" and the
fallback case.
if ptr.is_null() {
// Verify `polyfill_using_kern_arand` has the right signature.
const POLYFILL: GetRandomFn = polyfill_using_kern_arand;
ptr = POLYFILL as *mut c_void;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tweaked this by splitting the conversion into two clearly-correct parts because polyfill_using_kern_arand as *mut c_void is quite a dangerous cast.

@@ -22,30 +42,37 @@ fn kern_arnd(buf: &mut [MaybeUninit<u8>]) -> libc::ssize_t {
}
}

type GetRandomFn = unsafe extern "C" fn(*mut u8, libc::size_t, libc::c_uint) -> libc::ssize_t;
type GetRandomFn = unsafe extern "C" fn(*mut c_void, libc::size_t, libc::c_uint) -> libc::ssize_t;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I changed this signature as @josephlr suggested.

// the one in libstd, meaning that the use of non-Relaxed operations is
// probably unnecessary.
let mut fptr = GETRANDOM.load(Ordering::Acquire);
if fptr.is_null() {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed this from the match style that people didn't like.

static NAME: &[u8] = b"getrandom\0";
let name_ptr = NAME.as_ptr().cast::<libc::c_char>();
unsafe { libc::dlsym(libc::RTLD_DEFAULT, name_ptr) }
let mut ptr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, name_ptr) };
if ptr.is_null() {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed this from the match style that people didn't like.

@josephlr josephlr merged commit 267639e into rust-random:master Jun 19, 2024
54 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.

3 participants