Repository navigation
Potential improvements to use of /dev/random on Linux/Android #451
Description
Activity
- 3. PR Linux/Android: Read a byte from
/dev/randominstead of polling it. #449 and PR Linux/Android: Improve sandbox compatibility when checking/dev/random. #450 both attempt to preventgetrandomfrom failing in the case where a sandbox blockspoll().pollreturnsENOSYSunikraft/lib-musl#58 describes such a case. Interestingly, they note thatlibstdinternally usespollin some situations. The libstd code is especially interesting because it bails out to a fallback path onEINVAL,EAGAIN, orENOMEMinstead of retrying. https://github.com/rust-lang/rust/blob/master/library/std/src/sys/pal/unix/mod.rs#L101-L113 shows this, updated to address theUnikraftissue.
- 3. PR Linux/Android: Read a byte from
- 4. The above PRs mention a few syscalls that
poll()may be mapped to.ppoll_time64is available from Linux 5.1+. Thus, people may need to update their seccomp filters to work on Linux 5.1. In any case, if we're going to document seccomp compatibliity anywhere then we should mention this in that documentation. [Edit: Addressed in PR Linux/Android: Document /dev/random polling considerations. #452].
- 4. The above PRs mention a few syscalls that
- 5. https://doc.libsodium.org/usage#sodium_init-stalling-on-linux notes that even on pretty new Linux kernels, in certain environments that seems actually increasingly important, blocking on
/dev/randombecoming readable will stall an application. We might want to provide similar guidance.
- 5. https://doc.libsodium.org/usage#sodium_init-stalling-on-linux notes that even on pretty new Linux kernels, in certain environments that seems actually increasingly important, blocking on
- 6. See https://github.com/llvm/llvm-project/blob/3b2df5b6ee81cf2685c95728ff1baf795051c926/compiler-rt/include/sanitizer/linux_syscall_hooks.h#L1182-L1185. When sanitizers are enabled, it seems like we should be calling
__sanitizer_syscall_pre_impl_polland__sanitizer_syscall_post_impl_poll?
- 6. See https://github.com/llvm/llvm-project/blob/3b2df5b6ee81cf2685c95728ff1baf795051c926/compiler-rt/include/sanitizer/linux_syscall_hooks.h#L1182-L1185. When sanitizers are enabled, it seems like we should be calling
- See https://github.com/llvm/llvm-project/blob/3b2df5b6ee81cf2685c95728ff1baf795051c926/compiler-rt/include/sanitizer/linux_syscall_hooks.h#L1182-L1185. When sanitizers are enabled, it seems like we should be calling
__sanitizer_syscall_pre_impl_polland__sanitizer_syscall_post_impl_poll?
It seems like they also have methods in there for
read,open, andclose. I'm wondering if sanitizers being enabled just requires using alibcthat has been modified to make those particular calls- See https://github.com/llvm/llvm-project/blob/3b2df5b6ee81cf2685c95728ff1baf795051c926/compiler-rt/include/sanitizer/linux_syscall_hooks.h#L1182-L1185. When sanitizers are enabled, it seems like we should be calling
I don't think we should spend too much effort on the fallback path trying to handle every possible edge case. This path is quite rare in practice and becomes even rarer with every passing day. The current code works fine and we do not have any complains from users.
- The man page says that Linux returns ENOMEM and never EAGAIN. Since this code is Linux-specific, should we remove the EAGAIN case in the poll loop? Should we replace it with an ENOMEM case?
Removal of the EAGAIN check sounds reasonable. I am not sure we can reasonably handle ENOMEM, so we probably should just return it.
- The man page directs the user to note that poll may return "spurious readiness notifications" where poll indicates the file is readable when it actually isn't.
IIUC it mostly happens with network devices. The
select(2)man page (to whichpolldocs refer) states the following:This could for example happen when data has arrived but upon examination has the wrong checksum and is discarded.
There is also a caveat about "other circumstances", but I couldn't find anything that applies to "virtual" files like
/dev/random. We could replace the polling code with one byte read, but I think we can just ignore "spurious readiness" in our case. Especially considering that other libraries apparently do the same.- https://doc.libsodium.org/usage#sodium_init-stalling-on-linux notes that even on pretty new Linux kernels, in certain environments that seems actually increasingly important, blocking on /dev/random becoming readable will stall an application. We might want to provide similar guidance.
I think this is already sufficiently addressed in the "early boot" section.
- When sanitizers are enabled, it seems like we should be calling __sanitizer_syscall_pre_impl_poll and __sanitizer_syscall_post_impl_poll?
I think we should just move responsibility for this to
libc.
ENOMEMand neverEAGAIN. Since this code is Linux-specific, should we remove theEAGAINcase in the poll loop? Should we replace it with anENOMEMcase?getrandom-syscall-capable Linux versions, are such spurious readiness notifications possible? If so, this would be counter to the goal of polling but not reading/dev/random.