tnat64 icon indicating copy to clipboard operation
tnat64 copied to clipboard

getsockname fails for AF_NETLINK connections

Open Leseratte10 opened this issue 1 year ago • 0 comments

Sorry, yet another bug report :/

In your implementation of getsockname and getpeername there's the following code to abort if the sockaddr buffer is too small:

struct sockaddr_in * result;
if (*__len < sizeof(struct sockaddr_in))
{
    *__len = sizeof(struct sockaddr_in);
    errno = EINVAL;
    return -1;
}

Unfortunately, there's address families like AF_NETLINK where the corresponding sockaddr struct (sockaddr_nl) is shorter than sockaddr_in. sockaddr_in has 16 bytes on my machine, while sockaddr_nl only has 12.

So if there's an open socket of type AF_NETLINK and the program calls getsockname or getpeername on said socket, your library is always going to abort since it thinks there's not enough space.

Here's the log output:

socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT) = 24
12:09:47 libtnat64(449015): Got getsockname call for socket 24
getsockname(24, {sa_family=AF_NETLINK, nl_pid=-60857581, nl_groups=0x000002}, [12]) = 0
12:09:47 libtnat64(449015): too short: 12 16
libusb: error [linux_udev_start_event_monitor] failed to enable the udev monitor
libusb: error [op_init] error starting hotplug event monitor

First the socket is created with type AF_NETLINK. Then your lib receives the getsockname call with a len of 12 (which is the correct length for an AF_NETLINK socket), and since 12 is < 16 it sets errno = EINVAL and returns -1, and then the program using the library prints its error messages.

I'm going to see if I find a useful way to fix this issue. Maybe by only checking the length if sa_family is AF_INET6, and leave the length check and error handling to the original getsockname when it's not?

Leseratte10 avatar Dec 25 '22 11:12 Leseratte10