-
Notifications
You must be signed in to change notification settings - Fork 18k
syscall: wrong addrlen passed to bind()/connect()/sendto() for SockaddrUnix #15381
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
Can you show us a program that fails? |
Sure, here it is. Thank you. Client code: package main
import "net"
func main() {
_, err := net.Dial("unix", "@/Foo/bar1234")
if err != nil {
panic(err)
}
} Failing server code: #include <fcntl.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
int main() {
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
fcntl(fd, F_SETFD, FD_CLOEXEC);
struct sockaddr_un sun;
memset(&sun, 0, sizeof(sun));
sun.sun_family = AF_UNIX;
strncpy(sun.sun_path, "@/Foo/bar1234", sizeof(sun.sun_path));
sun.sun_path[0] = '\0';
bind(fd, (sockaddr *) &sun, sizeof(sun));
listen(fd, 255);
while (true) {}
} Working server code: #include <fcntl.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
int main() {
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
fcntl(fd, F_SETFD, FD_CLOEXEC);
struct sockaddr_un sun;
memset(&sun, 0, sizeof(sun));
sun.sun_family = AF_UNIX;
strncpy(sun.sun_path, "@/Foo/bar1234", sizeof(sun.sun_path));
int sun_len = strlen(sun.sun_path);
sun.sun_path[0] = '\0';
bind(fd, (sockaddr *) &sun, sun_len + sizeof(sun.sun_family));
listen(fd, 255);
while (true) {}
} The server was compiled with Output:
|
From bind(2) manual:
From unix(7) about AF_UNIX family sockets:
From sys/un.h # define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
+ strlen ((ptr)->sun_path)) IMHO: The patched C++ code ( |
FWIW the if (bind(sfd, (struct sockaddr *) &my_addr,
sizeof(struct sockaddr_un)) == -1)
handle_error("bind"); |
The example in the bind(2) man page is not for an abstract socket address. I don't know that we should consider it as more relevant than the unix(7) man page. For an abstract socket address the unix(7) man page says that addrlen describes the socket address. Evidently the client and server must agree on the how the length is set, but it's not clear that the Go approach is incorrect, given that it seems to match what the unix(7) man page says. |
That's right, kind of confusing but I guess Go is doing the right thing. Thank you for looking into this. |
go version
)?go version go1.6 darwin/amd64
go env
)?Compiled on
darwin/amd64
forlinux/386
, where it's running.Tried to connect a Go client to a C++ server using a UNIX domain socket
The client connecting successfully
dial unix @/Foo/bar1234: connection refused
The C++ server looks like this:
while the Go client simply does:
If I apply the following diff to the C++ code, it works:
According to bind(2):
So it appears that the C++ code is correct without the change. On the Go side, I see a comment in the
sockaddr()
implementation forSockaddrUnix
dating back to 602a446:// length is family (uint16), name, NUL.
but that's about all the context I could find. Shouldn't
sockaddr()
return something like this instead?The text was updated successfully, but these errors were encountered: