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
x/net/unix: support credentials on unix sockets #1101
Comments
The best interface I could come up with is: func (c *UnixConn) SendRights(fds []os.File) os.Error func (c *UnixConn) SendCredentials(cred Ucred) os.Error func (c *UnixConn) ReceiveAncillary() (fds []os.File, cred []Ucred, err os.Error) As far as I understand the documentation, recvmsg can receive a mixed bag of cmsgs, so there's no way of separating them beforehand. Comments? |
rather than sending/receiving os.File, which is: type File struct { fd int name string dirinfo *dirInfo // nil unless directory being read nepipe int // number of consecutive EPIPE in Write } ... why not just send the fd int? We wouldn't have a name, dirinfo, or nepipe, anyway? If they want an os.File they can make one with os.Newle(fd int, name string) *os.File |
As discussed here: http://groups.google.com/group/golang-nuts/browse_thread/thread/73a5186029a8d670 it seems most of sockets, pipes, etc. will be getting a Fd() that returns *os.File, so based on that I reasoned that defining the API in terms of os.File made more sense. As you pointed out, ReceiveAncillary will have to use os.NewFile then... |
More discussion: http://groups.google.com/group/golang-dev/t/464c20c2e8363a92 Having a ReceiveAncillary on its own isn't going to work. |
Something to look out for: The kernel doesn't translate PIDs in SCM_CREDENTIALS across PID namespaces (bug in 2.6.30). Google Breakpad has some code related to this: http://google-breakpad.googlecode.com/svn-history/r515/trunk/src/client/linux/crash_generation/crash_generation_server.cc |
Work in progress is here: http://golang.org/cl/2331044/ Hopefully this will get merged soon, after which we can tackle the high-level API. |
We have the functionality to send and receive bytes using sendmsg/recvmsg, but we need to create some functions to go from the specific ancillary messages to []byte and back. For SCM_CREDENTIALS, we need to convert syscall.Ucred to bytes. We also need an API to enable SO_PASSCRED on the socket. SCM_RIGHTS is more tricky. In C there's a bunch of CMSG_* macros for packing in the file descriptors you want to send. See man 3 cmsg. Up until now I've just wrapped these macros with cgo, but that's probably not ideal. I've written some test code to this stuff. I'll upload it on Monday. |
Here's some test code I used at one point: http://codereview.appspot.com/download/issue2331044_53001_54003.diff Also, there was another CL to fix Recvmsg: http://golang.org/cl/3766042 I've also attached some code for dealing with cmsg. But we probably want to do something that doesn't depend on cgo. Attachments:
|
http://www.normalesup.org/~george/comp/libancillary/ might provide some inspiration. |
It seems like this all works. Here's a new test for passing fds: http://golang.org/cl/5849057/ Should we close this? Is anything missing from this bug? |
I wrote a SO_PASSCRED test, but it digs around in sysfd because of the lack of an API for doing that. Might still be worth it to add it: http://codereview.appspot.com/download/issue2331044_53001_54003.diff I've also attached a test I have in our local tree for testing the basic stuff in syscall. I think I wrote it before it was easy to test stuff in the syscall package. It might be worth it to include these. Attachments:
|
I've submitted my test for SCM_CREDENTIALS and SO_PASSCRED on Linux: http://golang.org/cl/5846059 What's missing to completely close out this case: Support for parsing SCM_CREDS messages in syscall for the BSDs and Darwin. A way to enable SO_PASSCRED or the Darwin/BSD equivalent on a UnixConn with setsockopt without breaking timeouts. This is related to issue #2458 in that you can't just call File() on the socket to get its descriptor to pass to syscall.SetsockoptInt or whatever. |
What's also potentially missing is some plan for SO_PEERCRED. SO_PASSCRED allows credentials to be sent, and root can send anything. SO_PEERCRED allows a local credentials query of the remote end by the local end. http://welz.org.za/notes/on-peer-cred.html |
func (c *UnixConn) PeerCred (pid, uid, gid int, err os.Error) is probably easy to add after Go 1. It's just a getsockopt call. We could also add func (c *UnixConn) SetPassCred(enabled bool) error after Go 1. Just a setsockopt. All that's missing then is SCM_CREDS for Darwin/BSDs in syscall. Thoughts? |
Tests were removed until after Go 1. http://code.google.com/p/go/source/detail?r=3ac08431bcc9c71b48d59356a19f1164aa4cec07 http://code.google.com/p/go/source/detail?r=087c6e15702e2c28e570325b8c962e430d7bdfe6 Linux's Recvmsg definitely needs these tests, wherever they end up: http://code.google.com/p/go/source/browse/src/pkg/syscall/syscall_linux.go#527 |
For run around SO_PASSCRED to think about: Autobind Feature If a bind(2) call specifies addrlen as sizeof(sa_family_t), or the SO_PASSCRED socket option was specified for a socket that was not explicitly bound to an address, then the socket is autobound to an abstract address. The address consists of a null byte followed by 5 bytes in the character set [0-9a-f]. (Thus, there is a limit of 2^20 autobind addresses.) |
For fun around SO_PASSCRED to think about: Autobind Feature If a bind(2) call specifies addrlen as sizeof(sa_family_t), or the SO_PASSCRED socket option was specified for a socket that was not explicitly bound to an address, then the socket is autobound to an abstract address. The address consists of a null byte followed by 5 bytes in the character set [0-9a-f]. (Thus, there is a limit of 2^20 autobind addresses.) |
Passing fd's using SCM_RIGHTS is already supported: https://golang.org/src/syscall/syscall_unix_test.go?h=TestUnixRightsRoundtrip#L260 Passing credentials is already supported: https://golang.org/src/syscall/creds_test.go?h=TestSCMCredentials#L21 The autobind stuff is not supported but if someone needs it, they can implement it themselves with the pieces that already exist in the stdlib. Please close this issue. |
@jeffallen Thanks. Closing. |
The text was updated successfully, but these errors were encountered: