Skip to content

Conversation

@vapier
Copy link

@vapier vapier commented Jan 20, 2026

If the C library supports these random functions, use them directly instead of reading the /dev/urandom file. This makes life easier on platforms that don't have /dev/urandom (like WASM).

@achernya
Copy link
Collaborator

What platforms have arc4random but not getrandom? I'd rather not add support for arc4 which has known weaknesses

@vapier
Copy link
Author

vapier commented Jan 20, 2026

WASI (standardized WASM interface) doesn't have getrandom() unfortunately. it has getentropy().

i can swap the define preference so getrandom() comes first.

@achernya
Copy link
Collaborator

Preferring getrandom over arc4random sounds like a good move -- how does that help with getentropy, though?

@vapier
Copy link
Author

vapier commented Jan 20, 2026

Preferring getrandom over arc4random sounds like a good move

done

how does that help with getentropy, though?

it's orthogonal of course. I was just noting that WASI supports arc4random & getentropy, but not getrandom. I can drop arc4random & add getentropy if you want as it still makes things work for me (just tested).

@achernya
Copy link
Collaborator

If that works, that sounds preferable. getrandom and getentropy are both reasonable modern APIs.

Copy link

@Lillecarl Lillecarl left a comment

Choose a reason for hiding this comment

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

Works on my machine

@vapier
Copy link
Author

vapier commented Jan 20, 2026

ok, it'll take me a little bit to adjust to getentropy in the general case. the documented API says it operates on max size of 256, and while all the calls in mosh production code are well below that, src/tests/encrypt-decrypt.cc grabs a couple KB :).

@vapier
Copy link
Author

vapier commented Jan 20, 2026

okidoki, this version supports getrandom first, then getentropy, then /dev/urandom. while the getentropy code is annoying due to the loop, a spot check on x86_64 shows it's only a few bytes larger than getrandom when compiled with -O2.

}

#if defined(HAVE_GETRANDOM)
if ( getrandom( dest, size, 0 ) != static_cast<ssize_t>( size ) ) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Reading https://manpages.debian.org/trixie/manpages-dev/getrandom.2.en.html#Interruption_by_a_signal_handler I think we should use the same loop for getrandom as we do for getentropy. It looks like otherwise we might get EINTR, which I believe would have been handled for /dev/urandom and getentropy otherwise.

Copy link
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 std::basic_istream read() handles signals for you either tbh

not that this is an argument against being defensive against EINTR

Copy link
Collaborator

Choose a reason for hiding this comment

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

Fair point, but given you already wrote the code, may as well reuse it?

Copy link
Author

Choose a reason for hiding this comment

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

hmm, if we want to be defensive against EINTR, should we do it comprehensively ? from a quick scan of the codebase, i think the only time we register signal handlers is in the select wrapper. so if we leverage SA_RESTART, then the kernel should take care of this transparently for us normally.

--- a/src/util/select.h
+++ b/src/util/select.h
@@ -108,7 +108,7 @@ public:
     /* Register a handler, which will only be called when pselect()
        is interrupted by a (possibly queued) signal. */
     struct sigaction sa;
-    sa.sa_flags = 0;
+    sa.sa_flags = SA_RESTART;
     sa.sa_handler = &handle_signal;
     fatal_assert( 0 == sigfillset( &sa.sa_mask ) );
     fatal_assert( 0 == sigaction( signum, &sa, NULL ) );

Copy link
Collaborator

Choose a reason for hiding this comment

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

SA_RESTART is probably worthwhile. I will note that https://man7.org/linux/man-pages/man7/signal.7.html says it's only "some" syscalls, but getrandom and most file IO are on there. But on the BSD side, FreeBSD https://man.freebsd.org/cgi/man.cgi?query=signal at leaste claims that getentropy is not on the list. But it also doesn't seem to list EINTR as a valid return, so maybe that's fine?

@vapier vapier changed the title prng: support getrandom & arc4random_buf prng: support getrandom & getentropy Jan 20, 2026
}

#if defined(HAVE_GETRANDOM)
if ( getrandom( dest, size, 0 ) != static_cast<ssize_t>( size ) ) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Fair point, but given you already wrote the code, may as well reuse it?

If the C library supports these random functions, use them directly
instead of reading the /dev/urandom file.  This makes life easier on
platforms that don't have /dev/urandom (like WASM).
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