Skip to content

getpeername() does not store the peer address for connected AF_UNIX sockets #1672

Description

@lukkrusz

Description

For a connected AF_UNIX SOCK_STREAM socket whose peer is bound to a filesystem path, getpeername() returns 0 but
does not store the peer address in the supplied sockaddr structure and does not update the address_len value-result
argument. The sun_family field is left as 0 and sun_path is left empty.

AF_INET sockets are not affected and return the peer address correctly.

Expected behavior

getpeername() shall store the peer address in the sockaddr structure pointed to by the address argument and store the
length of this address in the object pointed to by the address_len argument.

Actual behavior

getpeername() returns 0 but leaves the address structure unpopulated (sun_family = 0, sun_path empty) and does not
update address_len.

Observed output:

getpeername(client): ret=0 family=0 path='' len=110

POSIX requirement (if applicable)

POSIX.1-2017 (IEEE Std 1003.1-2017), getpeername(3p), section DESCRIPTION:

"The getpeername() function shall retrieve the peer address of the specified socket, store this address in the sockaddr
structure pointed to by the address argument, and store the length of this address in the object pointed to by the
address_len argument."

Minimal reproduction code

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/un.h>

int main(void)
{
    int lfd, cfd, afd, ret;
    struct sockaddr_un srv, peer;
    socklen_t len;
    int flags;

    unlink("/tmp/gp_srv");
    lfd = socket(AF_UNIX, SOCK_STREAM, 0);
    memset(&srv, 0, sizeof(srv));
    srv.sun_family = AF_UNIX;
    strcpy(srv.sun_path, "/tmp/gp_srv");
    bind(lfd, (struct sockaddr *)&srv, sizeof(srv));
    listen(lfd, 5);

    cfd = socket(AF_UNIX, SOCK_STREAM, 0);
    flags = fcntl(cfd, F_GETFL, 0);
    fcntl(cfd, F_SETFL, flags | O_NONBLOCK);
    connect(cfd, (struct sockaddr *)&srv, sizeof(srv));
    afd = accept(lfd, NULL, NULL);

    memset(&peer, 0, sizeof(peer));
    len = sizeof(peer);
    ret = getpeername(cfd, (struct sockaddr *)&peer, &len);
    peer.sun_path[sizeof(peer.sun_path) - 1] = '\0';
    printf("getpeername(client): ret=%d family=%u path='%s' len=%u\n",
        ret, (unsigned)peer.sun_family, peer.sun_path, (unsigned)len);

    close(afd);
    close(cfd);
    close(lfd);
    unlink("/tmp/gp_srv");
    return 0;
}

Host behavior

getpeername(client): ret=0 family=1 path='/tmp/gp_srv' len=14

Revision

Discovered on 62b46f9

Target

Reproduced on ia32-generic-qemu, not tested on other targets yet.

Related tests

  • phoenix-rtos-tests/libc/socket/getpeername.c

These tests are currently skipped on the affected target. After applying a fix, re-enable them and re-run the suite to
verify the fix.

Metadata

Metadata

Assignees

No one assigned

    Labels

    POSIXmissing featurebugSomething isn't workinglibphoenix

    Type

    Fields

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions