[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

connect() access bytes after socket address

From: Tanaka Akira
Subject: connect() access bytes after socket address
Date: Wed, 27 Feb 2013 11:50:34 +0900


I found that connect() access bytes after socket address.

The test program below specifies a same struct sockaddr_un for
bind() and connect().

I expect connect() success but
"connect: No such file or directory" error occured.

rpctrace shows that bind() binds a socket as the socket file "AB" and
connect() try to connect for the socket file "ABCD".

This is caused by the socket address and its length.
The socket address is AF_UNIX and sun_path field is "AB"
The socket length is offsetof(struct sockaddr_un, sun_path) + 2.
However sun_path field has garbage "CD\0" just after "AB".
It seems that bind() properly uses the socket length and
connect() doesn't use that.

The problem is the socket address is not NUL terminated.
Strictly speaking, this is not POSIX confoming because
POSIX defines sun_path is pathname and pathname is terminated by NUL.

However I think this behavior is a bug of connect() because
1.  bind() and connect() consistency and
2.  accessing undefined bytes is a really bad idea.

  % uname -srvm
  GNU 0.3 GNU-Mach 1.3.99-486/Hurd-0.3 i686-AT386
  % cat tst.c
  #include <stddef.h>
  #include <stdlib.h>
  #include <stdio.h>
  #include <sys/socket.h>
  #include <sys/un.h>

  int main(int argc, char *argv[])
    int s, c, ret;
    struct sockaddr_un addr;
    socklen_t addrlen;

    s = socket(AF_UNIX, SOCK_STREAM, 0);
    if (s == -1) { perror("socket"); exit(EXIT_FAILURE); }

    addrlen = offsetof(struct sockaddr_un, sun_path) + 2;
    addr.sun_family = AF_UNIX;
    addr.sun_path[0] = 'A';
    addr.sun_path[1] = 'B';
    addr.sun_path[2] = 'C';
    addr.sun_path[3] = 'D';
    addr.sun_path[4] = '\0';

    ret = bind(s, (struct sockaddr *)&addr, addrlen);
    if (s == -1) { perror("bind"); exit(EXIT_FAILURE); }

    ret = listen(s, SOMAXCONN);
    if (ret == -1) { perror("listen"); exit(EXIT_FAILURE); }

    c = socket(AF_UNIX, SOCK_STREAM, 0);
    if (c == -1) { perror("socket"); exit(EXIT_FAILURE); }

    ret = connect(c, (struct sockaddr *)&addr, addrlen);
    if (ret == -1) { perror("connect"); exit(EXIT_FAILURE); }

    return EXIT_SUCCESS;
  % gcc -Wall tst.c
  % ls
  a.out  tst.c
  % ./a.out
  connect: No such file or directory
  % ls
  AB  a.out  tst.c
  % rm AB
  % rpctrace ./a.out |& grep AB
    92<--119(pid565)->dir_link (   136<--135(pid565) "AB" 1) = 0
    92<--119(pid565)->dir_lookup ("AB" 0 0) = 0 1 ""    136<--137(pid565)
    92<--119(pid565)->dir_lookup ("ABCD" 0 0) = 0x40000002 (No such
file or directory)
Tanaka Akira

reply via email to

[Prev in Thread] Current Thread [Next in Thread]