Subject: kern/10698: accept returns garbage w/evanescent connects to unix domain sockets
To: None <gnats-bugs@gnats.netbsd.org>
From: Castor Fu <castor@geocast.com>
List: netbsd-bugs
Date: 07/27/2000 17:07:16
>Number: 10698
>Category: kern
>Synopsis: accept returns garbage w/evanescent connects to unix domain sockets
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Thu Jul 27 17:08:00 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator: Castor Fu
>Release: NetBSD-1.4
>Organization:
Geocast Network Systems
>Environment:
Seen on NetBSD/i386 and Geocast's internal mips based platform.
Also seen with NetBSD-1.5 branch as of a few days ago on i386.
System: NetBSD swamp.sfo.geocast.net 1.4P NetBSD 1.4P (GEO_STANDARD) #171: Thu Jun 29 15:56:03 PDT 2000 castor@swamp.sfo.geocast.net:/usr/export/home/castor/nb/usr/src/sys/arch/i386/compile/GEO_STANDARD i386
>Description:
accept(2) on a unix domain socket returns an invalid value
for the address family in a sockaddr when connector closes
before the accept is executed.
>How-To-Repeat:
The following two programs and the script can be used to exercise
this bug.
#!/bin/sh
set -x
./nps &
spid=$!
sleep 1
./xclient &
sleep 1
c1pid=$!
./xclient&
c2pid=$!
sleep 1
kill $c2pid
sleep 1
kill $c1pid
sleep 1
kill -0 $spid
/* nps.c, no NSPR */
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include <stdio.h>
#define SOCKET_NAME "/ftsoNSPR"
int main(int argc, char *argv[])
{
struct sockaddr_un addr;
int rv;
int conn = -1;
struct sockaddr_un serverAddr;
int listenSocket;
char buf[256];
int size;
int i;
int addr_len;
unlink("ftsoNSPR");
memset(&serverAddr, 0, sizeof(serverAddr)); /* set up address structure */
serverAddr.sun_len = sizeof(serverAddr);
serverAddr.sun_family = AF_UNIX;
if (getcwd(serverAddr.sun_path, sizeof(serverAddr.sun_path)) == NULL) {
fprintf(stderr, "Can't get current directory.\n");
return -1;
}
size = strlen(serverAddr.sun_path);
strncat(serverAddr.sun_path, SOCKET_NAME,
sizeof(serverAddr.sun_path) - size);
/* create the socket */
listenSocket = socket(AF_UNIX, SOCK_STREAM, 0);
if (listenSocket == -1) {
fprintf(stderr, "Error returned from PR_Socket: %d", errno);
return -1;
}
fprintf(stderr, "path is %s\n", serverAddr.sun_path);
/* bind the socket */
if (bind(listenSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) == -1) {
fprintf(stderr, "Server error binding to server address: OS error
%d\n",
errno);
return -1;
}
/* set the socket up to receive inbound connections */
if ( listen(listenSocket, 10) == -1) {
fprintf(stderr, "Server error listening to server socket\n");
return -1;
}
while(1) {
if (conn == -1) {
addr_len = sizeof(addr);
printf("calling accept\n");
conn = accept(listenSocket, (struct sockaddr *)&addr, &addr_len);
printf("returns %d\n", conn);
if (addr.sun_family != AF_UNIX) {
fprintf(stderr, "address family is %d\n", addr.sun_family);
abort();
}
continue;
}
if(read(conn, buf, 10) > 0) {
fprintf(stderr, "read this: ");
for(i = 0; i < 10; i++)
fprintf(stderr, "%c", buf[i]);
} else {
close(conn);
conn = -1;
}
}
return 0;
}
/* xclient.c */
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#define SOCKET_NAME "/ftsoNSPR"
int main(int argc, char *argv[])
{
struct sockaddr_un serverAddr;
int l;
int scriptSock;
/* set up address structure */
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sun_len = sizeof(serverAddr);
serverAddr.sun_family = AF_LOCAL;
if (getcwd(serverAddr.sun_path, sizeof(serverAddr.sun_path)) == NULL) {
fprintf(stderr, "Can't get current directory.\n");
exit(1);
}
l = strlen(serverAddr.sun_path);
strncat(serverAddr.sun_path, SOCKET_NAME,
sizeof(serverAddr.sun_path) - l);
/* create the socket */
scriptSock = socket(AF_LOCAL, SOCK_STREAM, 0);
if ( scriptSock < 0 ) {
fprintf(stderr,
"initScriptSocket: Error returned from socket: %s %s\n",
strerror(errno), serverAddr.sun_path);
exit(1);
}
/* connect */
if ( connect(scriptSock, (struct sockaddr *) &serverAddr,
sizeof(serverAddr)) != 0) {
fprintf(stderr,
"initScriptSocket: Error returned from connect: %s\n",
strerror(errno));
exit(1);
}
write(scriptSock, "hi there.\n", 10);
while(1) {
sleep(1000);
}
}
>Fix:
none yet.
>Release-Note:
>Audit-Trail:
>Unformatted: