9 ms·
Linux RNG RFC Patch: implement getrandom() in vDSO
- mustache_kimono 4y agoNowhere near an expert, but this seems like a bad idea?
- zx2c4 4y agoIt's kind of wild, yea. I'd rather not do it. But if it's between unsafe userspace implementations and this thing, this thing is better. Maybe people will decide they don't care about hyperspeed card shuffling or whatever else. But if they do, this is an attempt to provide it safely.
- nneonneo 4y agoI guess my biggest concern here is the notion that vDSO is going to manage the state in user space, if I understand correctly. That seems like a big footgun. If I call the getrandom system call, and it succeeds, I am (pretty much) guaranteed that the results are properly random no matter what state my userspace program might be in. With vDSO, it seems we lose this critical guarantee. If a memory corruption occurs, or my process’s memory contents can be disclosed somehow (easier to do against a userspace process than against the kernel!), I don’t have truly random numbers anymore. Using a superficially similar API to the system call for this seems like a really bad idea.
- saagarjha 4y agoIf you have memory corruption in your process, what makes you confident your program state will let you do something useful with the randomness you get back from getrandom()?
- nneonneo 4y agoI guess my concern is with “silent” memory corruption, e.g. someone putting in a “bzero(state, …)” by accident and winding up with deterministic randomness. Sure, they could also just as well do a “bzero(randombuf, …)” before using it but that’s much easier to detect (and in my head, somewhat harder to do by accident). Silly mistakes like the Debian randomness bug come to mind - a program can be totally well-behaved even in the face of a glaring entropy failure, in a way that’s hard for developers to detect.
- saagarjha 4y agoI guess? I mean, I see "something overflowed on the stack and into my randomness buffer" as being similarly common and about as undetectable. That's not to say we shouldn't invest in making APIs that are harder to misuse even if you hold them incorrectly, but I'm not sure the benefits are very compelling here.
- zx2c4 4y ago> If a memory corruption occurs, or my process’s memory contents can be disclosed somehow (easier to do against a userspace process than against the kernel!), I don’t have truly random numbers anymore. Yea, that's definitely a downside of sorts. Jeffrey Walton mentioned that in the glibc discussion a few days ago: https://lore.kernel.org/linux-crypto/CAH8yC8n2FM9uXimT71Ej0mUw8TsDR-2RRQaN_DJ2g=UG_TBKWA@mail.gmail.com/ https://lore.kernel.org/linux-crypto/CAH8yC8n2FM9uXimT71Ej0m... A mitigating factor might be that if your process memory leaks, then the secrets generated leak anyway, no matter what generated them, so maybe not as large of a difference. But of course a generator leaking means future secrets potentially leak too. I suppose frequent reseeds could mitigate this, just as they do for potential leaks in the kernel. But anyway, I agree that compromising application memory is somewhat more possible than compromising kernel memory, though both obviously happen.
- sophacles 4y agoThe vDSO page is mapped without write though, just r and x.
- deathanatos 4y ago> hyperspeed card shuffling The article mentions this case too. getrandom() on my system seems to return the required amount of random bits to perform a shuffle of a deck in less time than my clock seems to have precision for; … that's … too slow?
- AlotOfReading 4y agoThere are cases where you want tons of random numbers (e.g. monte carlo) and the line between "good enough" and "disastrously bad" is often unclear. Providing cryptographic random numbers is the only possible API that's both safe and generic. As the post says, it's worth entertaining the idea of having the kernel provide a blessed way for userspace to do that, though I admit I've never personally seen a scenario where RNG was truly the bottleneck. But it'd still be nice to kill all the custom RNGs out there.
- kzrdude 4y agoDon't you always want a reproducible random sequence for such simulations? I.e you use getrandom for the initial seed only, record it, and do the rest of your RNG state in userspace code?
- AlotOfReading 4y agoIt's a nice property, but a lot of people skip it because of the tradeoffs. I'm also sure there are lots of use cases I'm not aware of where you don't want reproducibility.
- deleted 4y ago[deleted]
- mjb 4y agoMaking providing high-quality randomness without compromises a first-class OS feature seems like a great idea. Especially because it reduces the chances of using a bad/incorrectly seeded/inadequately seeded/cloned from snapshot userspace cryptographic PRNG, and of using a non-cryptographic PRNG for cryptographic stuff. I'm a kernel expert, so I don't know if VDSO is the right implementation, but the idea seems sound. Make it harder for people to make mistakes that break security!
- mjb 4y agoTo clarify, I am not a kernel expert.
- rogers18445 4y agoThere is always the option to reseed userspace PRNG with with getrandom() regularly. This makes userspace PRNG safe and more versatile than getrandom().
- LukeShu 4y agoThe article specifically addresses why this is a bad idea.
- rogers18445 4y agoAnd it's wrong. If you initialize your own PRNG properly with multiple reseeds you saturate the entropy pool of your PRNG and subsequent reseeds are only relevant for ratcheting and state compromise proofing. This assumes you aren't starved for entropy on initialization. If you are, it would imply a constrained environment and you are better off using getrandom() then.
- tptacek 4y agoThere is no such thing as being "starved for entropy", once you've hit whatever threshold you require for considering your RNG to be seeded in the first place.
- rogers18445 4y agoIf your PRNG state is is x bits, if you initialize it with less than x bits of entropy you are starved. Since you cannot know how many bits of entropy getrandom() would give you and when it itself is reseeded with fresh entropy, you usually have your userspace PRNG sample getrandom() for some amount of time, after which it is considered initialized.
- amluto 4y ago> you usually have your userspace PRNG sample getrandom() for some amount of time, after which it is considered initialized. Who is “you”? Calling getrandom() extra times to get extra bits on the hope that the result is magically better is entirely useless.
- 10000truths 4y agoWhy not just have the kernel map a page containing random bytes, that it rewrites with newly seeded random bytes when needed? Then userspace CSPRNGs could use that as a basis for their own reseeding.
- quesomaster9000 4y agoHow often do you reseed? How frequently does the kernel populate these pages with new entropy (for every process, pre-emptively?) Does this avoid pagefaults or other process interrupts? Don't want process interrupting every time it accesses the 'magic page of random'. Surely these are all pain points that Intel's `RDRAND` is supposed to alleviate.
- fefe23 4y agoThis looks like an excellent idea. I will implement support for it in my libc immediately when it's available in a release kernel. Currently userspace has incentive to roll their own RNG stuff. This removes that, which is good for everyone. The less incentive you give people to write code that has already been written by other, more experienced people, the better. I would go even further and export the kernel ciphers via vDSO. Then user space could rely on those ciphers being optimized for the host CPU and side channel free instead of everybody bringing their own crypto primitives. I don't think there is a good reason why gnupg and openssl would bring different crypto primitives.
- thadt 4y agoIsn't there already userspace access to the kernel's crypto machinery? https://www.kernel.org/doc/html/latest/crypto/userspace-if.html https://www.kernel.org/doc/html/latest/crypto/userspace-if.h...
- simcop2387 4y agoDoing it through vdso has performance advantages because it elides a lot of the syscall overhead. This works make the crypto stack be more advantageous they it was previously
- fefe23 4y agoYou are right, I was not aware of that! This way may actually have advantages over vDSO. Maybe you can set up IV and key with the kernel and then let the kernel do the crypto without having to have them in user space memory anymore. That would be a way to reduce risk in crypto applications, as long as you can prevent an attacker who has taken over the crypto app to retrieve the keys from the kernel. Maybe seccomp can help here. Very exciting!
- _8j50 4y agoWhat is your libc?
- mschuster91 4y ago
- colmmacc 4y agoThis change makes me sad, not because it isn't brilliant work - it is - but because this kind of brilliant work is unlikely to move the needle in the real-world. I can't use this RNG because it isn't FIPS validated. I can't sponsor getting it FIPS validated because the cryptography it uses isn't even FIPS compatible. It wouldn't make it past the cursory skim of a reviewer. That says more about FIPS than it does this work, but it still means that it's a non-starter for many libraries and applications that end up having US Federal Government users ... which is to say that basically everything important gets pushed away from benefiting from work like this. Seperately, I'm also a little sad that there are no distinct RNGs for secret and non-secret output. It is an indispensable layer of defense to have separately seeded RNGs for these use-cases. That way if there is an implementation flaw or bug in the RNG that leads to re-use or predictability, it is vastly harder for that flaw to be abused. s2n, BouncyCastle, OpenSSL, and more user-space libraries use separately seeded RNGs for this reason and I don't think I could justify removing that protection.
- tptacek 4y agoOn the other hand, there's the FIPS-accelerationist perspective, which suggests that as more and more modern cryptography is mainstreamed irrespective of FIPS silly requirements, FIPS will itself gradually become untenable, leaving us all better off.
- oittaa 4y agoI'm not a cryptographer so disregard my opinions as you please, but I really like OpenSSH's approach. They just implement whatever the cryptographer community thinks is the best approach at the moment and disregard NIST and other authorities. For example they already have a post quantum key exchange as one of the default algorithms.
- matheusmoreira 4y agoI'm not a cryptographer either and I certainly trust OpenSSH developers and actual cryptographers a lot mote than outdated government standards. As far as I'm concerned, what these people say is the standard and they're the people I look for when I want to learn something about cryptography from websites, LWN articles, mailing list discussions and other such sources. I've learned a lot reading about getrandom on LWN, plenty of knowledgeable people involved in that work.
- a-dub 4y ago> hyperspeed card shuffling i think that's mostly scientific computing where you want the ability to control the RNG and even intentionally use deterministic seeds for reproducibility. i think if the kernel is going to provide secure random numbers (which seems like a good idea), it should be through a (new) specific system call that fails unless a hardware entropy facility is available. performance seems like a secondary goal, where the primary is ensuring that people are using the right thing to generate keys and such.
- secondcoming 4y agoI think you need reproducible RNGs for financial modelling audits.
- marcodiego 4y agoFor those who need it: vDSO is almost a hack that allows implementation of syscalls without context switch.
- onmobile2022 4y agoSlightly more verbose: it is an ELF library that is mapped into every process containing kernel code that runs (due to app calls) in userspace. Most often it works (like in the case of gettimeofday) by reading values from another shared memory segment mapped between the kernel and user space. Getting time just involves carefully ordered reading from that shared mem
- matheusmoreira 4y agoEven more details: The vDSO is part of the Linux kernel binary interface and considered stable. There's documentation for it on the kernel tree: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/ABI/stable/vdso https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/lin... The vDSO functions are called using the C compiler's ABI for the platform. It's completely optional infrastructure that offers higher performance, normal system calls can still be used. The address of the vDSO shared object is passed by the kernel to the program through the auxiliary vector, a list of key-value pairs. It's located on the stack right after the environment vector. The key for the address of the vDSO is AT_SYSINFO_EHDR. There's more useful data in there too: system page size, CPU capabilities, loaded program's own ELF header and entry point locations and even its file name, user and group IDs, some bytes of random data. In most cases glibc will be the consumer of this data but it's perfectly possible to use of it ourselves. More about the auxiliary vector: https://lwn.net/Articles/519085/ https://lwn.net/Articles/519085/ https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/auxvec.h https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/lin... https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/include/uapi/asm/auxvec.h https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/lin...
- comex 4y agoOn many operating systems, including macOS and Windows, the only ABI-stable interface is a userland-to-userland interface. Application code loads a shared library vended by the system and calls functions from that library like open() or CreateFileW(), in userland. These functions are in turn are usually thin wrappers around system calls with equivalent argument lists – but not always, and even when they are, it's only an implementation detail. Trying to call system calls directly without going through the wrappers risks incompatibility with future OS versions, e.g. [1]. On Linux, traditionally, the userland-kernel interface itself is ABI-stable. The userland code can be fully custom and doesn't even need to support dynamic linking. Syscall numbers and arguments are fixed, and application code can perform its own syscall instructions. You can then layer something like glibc on top of that, which provides its own syscall wrapper functions with a corresponding stable (userland-to-userland) ABI, but that's separate. The vDSO has always been a step away from that. It's userland code, automatically mapped by the kernel, that provides its own system call wrappers. Applications are still allowed to make system calls manually, but they're encouraged to use the vDSO instead. Its original purpose was to allow certain functions such as gettimeofday() to be completed in userland rather than actually performing a syscall [2], but it's been used for a few other things. It's worked pretty well, but it does have the drawback that statically linked binaries no longer control all of the code in their address space. This, for instance, caused a problem with the Go runtime [3], which expected userland code to follow a certain stack discipline. Anyway, this patch seems to me like a significant further step. Not just putting an RNG into the vDSO, which is more complicated than anything the vDSO currently does, but also essentially saying that you must use the vDSO's RNG to be secure (to quote the RFC, "userspace rolling its own RNG from a getrandom() seed is fraught"), and explicitly choosing not to provide stable APIs for custom userland RNGs to access the same entropy information. I don't think that's necessarily a bad thing. It's not that complicated, and to me, macOS' and Windows' approach always seemed more sensible in the first place. But it's a step worth noting. [1] https://github.com/jart/cosmopolitan/issues/426 https://github.com/jart/cosmopolitan/issues/426 [2] https://man7.org/linux/man-pages/man7/vdso.7.html https://man7.org/linux/man-pages/man7/vdso.7.html [3] https://marcan.st/2017/12/debugging-an-evil-go-runtime-bug/ https://marcan.st/2017/12/debugging-an-evil-go-runtime-bug/
- tptacek 4y ago