Skip to content
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

BSD mountinfo implementation is unsound #51

Open
cyphar opened this issue Oct 21, 2020 · 6 comments
Open

BSD mountinfo implementation is unsound #51

cyphar opened this issue Oct 21, 2020 · 6 comments
Labels
help wanted Extra attention is needed

Comments

@cyphar
Copy link
Contributor

cyphar commented Oct 21, 2020

There are two problems:

  • According to the documentation of reflect.SliceHeader it's never safe to modify or otherwise make use of the contents of SliceHeader:

    SliceHeader is the runtime representation of a slice. It cannot be used safely or portably and its representation may change in a later release. Moreover, the Data field is not sufficient to guarantee the data it references will not be garbage collected, so programs must keep a separate, correctly typed pointer to the underlying data.

    I'm sure that this is more of a CYA statement than anything else, but it does mean that technically our usage of this is unsound -- and ultimately the fix is just to switch to a C-style loop over the pointers.

  • getmntinfo modifies a global variable, which means that if multiple goroutines try to get mountinfo at the same time we will end up potentially modifying the global structure during iteration. We could work around this by mutexing it or something, but a simpler solution would be to just use getfsstat(2) which allows us to pass our own allocated array.

@kolyshkin
Copy link
Collaborator

Related: #24 (one other issue is freebsd implementation requires cgo)

We need someone who works with FreeBSD to fix this, and we need some CI to test it on.

@kolyshkin
Copy link
Collaborator

Related to using reflect.SliceHeader: moby/moby#41626

@kolyshkin kolyshkin added the help wanted Extra attention is needed label Nov 6, 2020
@cuonglm
Copy link

cuonglm commented Nov 6, 2020

@cyphar Would you elaborating more? I don't see problem with current usage of reflect.SliceHeader in

header := (*reflect.SliceHeader)(unsafe.Pointer(&entries))

@cyphar
Copy link
Contributor Author

cyphar commented Nov 7, 2020

I'm not saying it doesn't work, the issue is that reflect.SliceHeader is explicitly described in the documentation as being fundamentally unsound to use. There are other issues with it (namely the GC doesn't know how to track the pointer and there are cases where you could get use-after-frees) but because getmntinfo returns a static pointer in memory, this isn't as much of a concern (though I do wonder if there are cases where Go would decide to try to GC the head of a SliceHeader...).

@cuonglm
Copy link

cuonglm commented Nov 7, 2020

I'm not saying it doesn't work, the issue is that reflect.SliceHeader is explicitly described in the documentation as being fundamentally unsound to use. There are other issues with it (namely the GC doesn't know how to track the pointer and there are cases where you could get use-after-frees) but because getmntinfo returns a static pointer in memory, this isn't as much of a concern (though I do wonder if there are cases where Go would decide to try to GC the head of a SliceHeader...).

I dont think it can be the issue if you did use reflect.SliceHeader correctly. I invite you to read golang/go#41705 (comment)

@cyphar
Copy link
Contributor Author

cyphar commented Jan 18, 2021

Fair enough, I was going by the literal reading of the documentation (and I've been bitten by Go's runtime far too many times to be optimistic that its behaviour will be nice). But if the Go authors say the example is valid then there's only one correctness issue in the BSD implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

3 participants