-
Notifications
You must be signed in to change notification settings - Fork 124
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
Memguard must manage memory allocation to work #3
Comments
I've been reading all of the comments, and I do realise that there's a lot of things that I've missed. Luckily this is version v0.1.0 and I plan to have all of these issues fixed soon. |
Might be prudent to post a warning in the README so nobody ends up using this for truly sensitive data. |
To be clear: it's not that this isn't ready for use in production. It's that this doesn't work. That's a bigger concern here. |
So I've had to deal with a problem very similar to this (for encryption keys in Go). The other commenters are correct, you need to allocate and release the memory yourself. I took the approach of using a call to prot := unix.PROT_READ | unix.PROT_WRITE
flags := unix.MAP_PRIVATE | unix.MAP_ANONYMOUS | unix.MAP_LOCKED
buffer, err := unix.Mmap(-1, 0, length, prot, flags) According to the I only did this for Linux, but NetBSD has Windows is sort of weird there is |
@josephlr Yep, on Unix there's also Mprotect which is available on all the kernels since it seems to be available in the sys package. And on Windows there's VirtualProtect too, in addition to VirtualLock. However, VirtualProtect isn't available in sys/windows either, so we'll see how that's going to be handled. |
Looking more into it, |
@libeclipse To spell this out more clearly, none of those calls matter. The issue is you can't use any of them with memory allocated by the Go runtime because it owns those buffers and can move them at will without telling you. For this to work you need to fundamentally rework the API such that "protected" data lives in memory allocated some other way, probably directly by libc's malloc. This is further complicated by the fact that you can't ever return data from a safe buffer to an unsafe one or you lose the game. So every API that consumes a locked buffer will have to understand whatever custom data structure you come up with. This feels like a losing proposition to me but if you want to go for it, then 👍. |
@libeclipse It doesn't seem like buffer, err := unix.Mmap(-1, 0, 10, unix.PROT_NONE, unix.MAP_PRIVATE|unix.MAP_ANONYMOUS)
if err != nil {
panic(err)
}
// This will SEGSEGV
buffer[0] = 1 As for using @coderanger It would probably be easier to just use It seems like if you simplified the API to just have two functions: func Make(length int) (data []byte, err error) {}
func Destroy(data []byte) (err error) {} or perhaps using a containing struct to make it harder to mess up: type LockedBuffer struct {
Buffer []byte
}
func Make(length int) (*LockedBuffer, error) {}
func (b *LockedBuffer) Destory() (error) {} you could get something working. |
@josephlr Having something throw a And good point about For Windows, there is this library by one of the Golang developers that implements |
See HN article for more detail. TL;DR, golang does not specify any particular semantics about memory addresses. Calling
mlock
on a go-managed memory address provide little to nothing in the way of guarantees, because that memory will be copied and moved around as the runtime sees fit.This is pretty much unavoidable. The address you call
mlock
on isn't even guaranteed to be the address passed in viamemlock.Lock(b)
.The text was updated successfully, but these errors were encountered: