[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 |
Hi.
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
- connect() access bytes after socket address,
Tanaka Akira <=