4 ms·
Reducing the time a secret lingers in memory is at best a mitigation. Linux has MADV_DONTDUMP for the madvise system call to exclude certain pages from core dum
by planede 3y ago
Reducing the time a secret lingers in memory is at best a mitigation. Linux has MADV_DONTDUMP for the madvise system call to exclude certain pages from core dumps. I'm not sure if something like this could be available in golang, preferably wrapped in some platform-agnostic way.
- djbusby 3y agoOh yea. They moved on from Go and are now fiddling w/Rust. Kinda laughed at me when I said: just use C.
- marcosdumay 3y agoC has one of the worst interfaces available for that kind of thing. Not only it follows the C's "you just have to remember it every time" convention, but you also have to remember to check if your compiler isn't optimizing the settings away.
- weinzierl 3y agoAlso mlock to prevent the memory page being written to disk and make sure to properly overwrite the secret data once you no longer need it. Make sure this doesn't get optimized away. libsodium has functions for all of that. Rust has the "secrets" crate that is a wrapper around these. I don't know much Go, but a quick search looks like it has libraries that take care of these things as well - unsurprisingly.
- jerf 3y agoYou could bash together system calls to get some memory allocated that way that you could access, but any language that makes values some combination of easy to copy and not having first-class access to the memory layout is going to be a constant uphill battle to keep the secrets where they "belong". And almost everything nowadays has easy-copy values, because almost everything copies all function parameters. It will be difficult, twitchy, and subject to whatever local compiler/interpreter optimizations as to whether or not any sort of code does or does not safely keep all values only in the "correct" space. I wouldn't trust Go qua Go to keep my secrets only where I "put" them, and I wouldn't trust hardly any other modern language either. They're all based on copying arguments around. Rust is closest and I'm not sure I'd trust even that without a lot of checking, because while the language layer may have best-of-class controls over sharing, that's not to say the optimizer won't create copies of things under the hood. Those sharing controls are not, as I understand it, hardware-level promises as to how memory will be treated, just language-level promises. You almost have to reduce to a minimal kernel and program it in assembler, if you want to be sure the secrets can't flow, and that may be easier said than done depending on how complicated that kernel is. (e.g., simply reading something from a file and keeping it confined is easy, but if I have to do crypto with a secret that's a very large chunk of code to worry about.) It isn't even just the software, even the hardware stack is just not designed for the CPU to not make copies. The hardware is designed to present an isolated view of the world to the software it is running on but it has numerous and large abstractions between the view of the world the software running normally sees and the actual state of the hardware. What you will see when those abstractions are penetrated (e.g., a straight-up RAM dump or disk dump) can be difficult to predict. A RAM page swapped to an SSD can physically reside on that SSD indefinitely because the SSD is remapping sectors continuously, you could get unlucky and that's the last thing ever written to that physical bit of the disk if the controller marks it bad. And that's just an example, not the complete list; I wouldn't count on madvise to protect me from all copies without a lot more research. Everything from the highest software layer to the lowest hardware layer is fighting you if you try to exercise this much control over where your data goes.