POSIX specifies EACCES as a "may fail" condition for connect() on an AF_UNIX
socket; it is a "shall fail" condition for open().  I take this to mean that a
conforming connect() implementation could ignore directory search permissions
and/or the socket's own file mode.  Indeed, a couple of decades ago, some
systems did ignore the socket's own file mode:

http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-1999-1402

Do any porting targets of contemporary relevance still behave this way?  If
so, which OS versions are known affected?  I have attached a test program that
illustrates the exact behavior in question, which you can use to test your own
system if curious.

The most gnulib could do is to document this portability hazard, since nothing
outside the kernel could effectively eliminate it.  I ask here since the
gnulib documentation is one of my go-to sources for portability information.

Thanks,
nm
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <unistd.h>

const char sockpath[] = "/tmp/sockperm_test";

int
main(int argc, char **argv)
{
    int server_fd, client_fd;
    struct sockaddr_un addr;

    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    strcpy(addr.sun_path, sockpath);

    server_fd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (server_fd < 0)
    {
        perror("socket");
        return 1;
    }
    if (bind(server_fd, (struct sockaddr *) &addr, sizeof(addr)) != 0)
    {
        perror("bind");
        return 1;
    }
    if (chmod(sockpath, 0) != 0)
    {
        perror("chmod");
        return 1;
    }
    if (listen(server_fd, 0) != 0)
    {
        perror("listen");
        return 1;
    }

    client_fd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (client_fd < 0)
    {
        perror("socket");
        return 1;
    }
    if (connect(client_fd, (struct sockaddr *) &addr, sizeof(addr)) == 0)
        puts("connect: unexpected non-failure");
    else if (errno == EACCES)
        puts("connect: normal behavior (EACCES)");
    else
        perror("connect: unexpected failure");

    if (unlink(sockpath) != 0)
    {
        perror("unlink");
        return 1;
    }

    return 0;
}

Reply via email to