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

Switch to using the arandom sysctl on NetBSD (same as FreeBSD). #115

Merged
merged 6 commits into from
Oct 23, 2019

Conversation

alarixnia
Copy link
Contributor

Rename it from freebsd.rs to sysctl_arandom.rs.

NetBSD has been patching rustc for some time to use the FreeBSD implementation because every single invocation of the compiler may drain from the entropy pool and cause the next to block.

This can massively inflate build times for rust software, or cause it to fail entirely, especially in VMs (for example, our Xen package building cluster).

Rename it from freebsd.rs to sysctl_arandom.rs.

NetBSD has been patching rustc for some time to use the FreeBSD
implementation because every single invocation of the compiler
may drain from the entropy pool and cause the next to block.

This can massively inflate build times for rust software, or cause
it to fail entirely, especially in VMs (for example, our Xen package
building cluster).
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.

Is this syscall documented anywhere for NetBSD

I couldn't find it in:

src/lib.rs Outdated Show resolved Hide resolved
src/sysctl_arandom.rs Outdated Show resolved Hide resolved
@josephlr
Copy link
Member

@Niacat thanks for the contribution. I hope this works, so that we can have the weird /dev/random polling code only on LInux.

We would ideally like to test this. It's not a hard requirement (as we weren't testing FreeBSD before), but it would be nice. Right now, I wouldn't know how to go about making sure this change functions on a FreeBSD system.

Do you have a setup for testing FreeBSD Rust stuff in CI?

@alarixnia
Copy link
Contributor Author

alarixnia commented Oct 22, 2019

Is this syscall documented anywhere for NetBSD

in sysctl(7):

     kern.arandom
             This variable picks a random number each time it is queried.  The
             used random number generator (RNG) is based on arc4random(3).

(this actually means it uses chacha20, as arc4random does on NetBSD).

the arguments are documented in sys/sysctl.h:

#define KERN_ARND               81      /* void *buf, size_t siz random */

on the limits of the function: it can return up to 256 bytes in a single system call, for reasons that are unclear to me. anything larger fails. (possibly historical reasons, to avoid trivial DoS attacks). however, it can be called repeatedly without blocking.

I hope this works, so that we can have the weird /dev/random polling code only on LInux.

The documentation has probably confused people here. /dev/random isn't supposed to be polled except at boot, presumably by init, and not by application software or libraries.

Do you have a setup for testing FreeBSD Rust stuff in CI?

personally no. I'm not a rust programmer or FreeBSD user, just a NetBSD developer.

@josephlr
Copy link
Member

Is this syscall documented anywhere for NetBSD

in sysctl(7):

Perfect, thanks for the link. It looks like kern.arandom was introduced in NetBSD 6.0 (Released 2011), so it probably fine to just use it without any (other) fallback, just like with FreeBSD.

I hope this works, so that we can have the weird /dev/random polling code only on LInux.

The documentation has probably confused people here. /dev/random isn't supposed to be polled except at boot, presumably by init, and not by application software or libraries.

You're correct here, I wrote that code with Linux specifically in mind, and then just had NetBSD code use it without much additional thought. That was clearly wrong.

Do you have a setup for testing FreeBSD Rust stuff in CI?

personally no. I'm not a rust programmer or FreeBSD user, just a NetBSD developer.

facepalm the above should all say NetBSD, rather than FreeBSD.

@josephlr
Copy link
Member

As for testing, it looks like none of the major CI services have NetBSD, Cirrus CI has FreeBSD.

Both FreeBSD and NetBSD are Tier 2 Targets, so we probobly should have some testing for them. However, that shouldn't block this PR.

@josephlr
Copy link
Member

One last thing, this current implementation will check for getrandom via dlopen before falling back to kern.arandom. This was added in #57 to support FreeBSD's getrandom(2) syscall.

Despite NetBSD not having getrandom, I think it's fine to keep the implementations unified. The dlopen call is only done once, and will always fail on NetBSD,

@newpavlov
Copy link
Member

Hm, I think it may be use cfgs here to gate out unnecessary code, something like this:

#[cfg(target_os = "freebsd")]
type GetRandomFn = ...;

fn kern_arnd(buf: &mut [u8]) -> libc::ssize_t { .. }

#[cfg(target_os = "freebsd")]
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { .. }

#[cfg(target_os = "netbsd")]
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { .. }

It's not so much code and we will not do useless stuff on NetBSD.

@newpavlov
Copy link
Member

on the limits of the function: it can return up to 256 bytes in a single system call, for reasons that are unclear to me. anything larger fails.

Wait, by fails you mean it returns an error for buffers larger than 256 bytes? Right now we assume that for large buffers it will return how many bytes have been written.

@josephlr
Copy link
Member

on the limits of the function: it can return up to 256 bytes in a single system call, for reasons that are unclear to me. anything larger fails.

Wait, by fails you mean it returns an error for buffers larger than 256 bytes? Right now we assume that for large buffers it will return how many bytes have been written.

I think it just does a short read for long buffers, instead of failing. I think this is the right part of the kernel source.

It also looks like the NetBSD OpenSSL implementation assumes that keyctl will just do short (<= 256 byte) reads when given long buffers.

@josephlr
Copy link
Member

Hm, I think it may be use cfgs here to gate out unnecessary code, something like this:

Added, I just moved all of the FreeBSD specific code/declarations to a #[cfg(target_os = "freebsd")] block inside of getrandom_inner. @newpavlov if it looks good to you, feel free to merge this.

@newpavlov newpavlov merged commit 2fa1bba into rust-random:master Oct 23, 2019
alarixnia added a commit to alarixnia/rust that referenced this pull request Nov 4, 2019
This system call is present on all supported NetBSD versions and
provides an endless stream of non-blocking random data from the
kernel's ChaCha20-based CSPRNG. It doesn't require a file descriptor
to be opened.

The system call is documented here (under kern.arandom):
https://netbsd.gw.com/cgi-bin/man-cgi?sysctl+7+NetBSD-7.0

And defined here:
https://nxr.netbsd.org/xref/src/sys/sys/sysctl.h#273

The semantics are the same as FreeBSD so reading 256 bytes per call
is fine.

Similar change for getrandom crate: rust-random/getrandom#115
Centril added a commit to Centril/rust that referenced this pull request Nov 6, 2019
Use KERN_ARND syscall for random numbers on NetBSD, same as FreeBSD.

This system call is present on all supported NetBSD versions and provides an endless stream of non-blocking random data from the kernel's ChaCha20-based CSPRNG. It doesn't require a file like `/dev/urandom` to be opened.

The system call is documented here (under kern.arandom):
https://netbsd.gw.com/cgi-bin/man-cgi?sysctl+7+NetBSD-7.0

And defined here:
https://nxr.netbsd.org/xref/src/sys/sys/sysctl.h#273

The semantics are the same as FreeBSD so reading 256 bytes per call is fine.

Similar change for getrandom crate: rust-random/getrandom#115
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