Hi, while debugging, I apparently stumbled upon a bug of getsockname() for a bound unix socket, as also the attached test program shows: sun_path is left unfilled, as also the comment of S_socket_whatis_address() in hurd/pflocal/pf.c would suggest.
There's also another possibly weird behaviour in that: S_socket_whatis_address() sets its sockaddr_len parameter in what seems also what Linux does, ie offsetof(struct sockaddr, sa_data) + strlen(sun_path) + 1 instead of sizeof(struct sockaddr_un), like apparently most of other OSes do[1]; of course, given that sun_path is never filled (as said above), the returned sockaddr_len is always 3. [1] in perl's code, I've seen this snippet: unpack_sockaddr_un(sun_sv) [...] # ifndef __linux__ /* On Linux sockaddrlen on sockets returned by accept, recvfrom, getpeername and getsockname is not equal to sizeof(addr). */ if (sockaddrlen != sizeof(addr)) { croak("Bad arg length for %s, length is %d, should be %d", "Socket::unpack_sockaddr_un", sockaddrlen, sizeof(addr)); } # endif -- Pino Toscano
#include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <stddef.h> static const char s_socketpath[] = "/tmp/test.sn.sock"; void die(int x, const char *s) { perror(s); unlink(s_socketpath); exit(x); } int main() { int ret; int s; struct sockaddr_un sock; char namebuf[256]; socklen_t bufsize = sizeof(namebuf); namebuf[0] = 'a'; namebuf[1] = 0; memset(&sock, 0, sizeof(sock)); sock.sun_family = AF_UNIX; strcpy(sock.sun_path, s_socketpath); s = socket(AF_UNIX, SOCK_STREAM, PF_UNSPEC); if (s < 0) die(1, "socket"); ret = bind(s, (struct sockaddr *)&sock, sizeof(sock)); if (ret < 0) die(2, "bind"); ret = getsockname(s, (struct sockaddr *)namebuf, &bufsize); { struct sockaddr_un *ss = (struct sockaddr_un *)namebuf; printf("> getsockname: %d, %d ('%s') vs %u/%u\n", ret, bufsize, namebuf, offsetof(struct sockaddr, sa_data) + strlen(ss->sun_path) + 1,sizeof(sock)); printf("> ... %d vs %d, %s (%u)\n", ss->sun_family, AF_UNIX, ss->sun_path, strlen(ss->sun_path)); } if (ret < 0) die(3, "getsockname"); shutdown(s, SHUT_RDWR); close(s); unlink(s_socketpath); return 0; }
signature.asc
Description: This is a digitally signed message part.