-
Notifications
You must be signed in to change notification settings - Fork 18k
syscall: Cmsghdr on GNU/Linux has unexpected size #17649
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
Comments
It's not clear to me what your test case shows except that the type But I also agree that the trailing The Go 1 guarantee does not cover the syscall package, but the Go 1 guarantee doc also says that the syscall package is frozen. The current code is problematic and error-prone but is not actually buggy in itself. It's not entirely clear to me whether the Go 1 guarantee permits us to remove it. |
I think UnixRights is fine. It sets a *Cmsghdr to point into a byte slice, but it only reads fields from the Cmsghdr; it does not read the entire struct, so it does not read the padding at the end. ParseSocketControlMessage is a bigger problem. The "Header: *h" in the middle of the loop does copy too many bytes out of the message, and if the message were right up against a page boundary or another piece of data, you'd get a seg fault or a race detector report. Two possible fixes:
I lean toward 2. |
/cc @bradfitz for opinion on 1 vs 2 |
I don't see any downside with 2. |
I'm fine with 2, but just for the record the downside is that this is a lurking trap for anyone else who uses an |
I searched around, and I couldn't find anyone using X__cmsg_data. It would surprise me if anyone was. Option 2 may not prevent any code that uses X__cmsg_data from compiling, but I believe that it will still break code that uses &h.X__cmsg_data as the address of the data start. Removing it is the more correct approach, so I would personally prefer that. I would personally much rather have a compile error than a runtime error. |
If we broke compatibility and deleted 0-length fields from the ends of structs, would we do them all? e.g.
|
We could, but frankly the one in |
CL https://golang.org/cl/32319 mentions this issue. |
On AMD64, the syscall.Cmsghdr struct is
Both
syscall.UnixRights()
andsyscall.ParseSocketControlMessage()
assume that the zero length array takes no space and that this struct is 16 bytes. This is not the case as since go1.5 trailing zero arrays take 1 byte thus making the struct 24 bytes. We can't change the size of socket control message headers and the X__cmsg_data field doesn't seem to serve any useful purpose, so I suggest we remove the X__cmsg_data field.Most of the time this isn't a problem and this code is probably correct and safe in practice. It does, however, trip the race detector.
Here is an example:
gorace.go
gorace_test.go
If one runs this with the race detector enabled, one gets something like this:
/cc @rsc
The text was updated successfully, but these errors were encountered: