Subject: kern/4280: sending fd's over AF_UNIX sockets causes kernel panic
To: None <gnats-bugs@gnats.netbsd.org>
From: Chris Jones <cjones@rupert.honors.montana.edu>
List: netbsd-bugs
Date: 10/16/1997 12:21:26
>Number: 4280
>Category: kern
>Synopsis: sending fd's over AF_UNIX sockets causes kernel panic
>Confidential: no
>Severity: serious
>Priority: low
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Thu Oct 16 11:35:02 1997
>Last-Modified:
>Originator: Chris Jones
>Organization:
-------------------------------------------------------------------------------
Chris Jones cjones@rupert.oscs.montana.edu
Mad scientist in training...
"Is this going to be a stand-up programming session, sir, or another bug hunt?"
>Release: Yesterday.
>Environment:
System: NetBSD rupert.honors.montana.edu 1.2G NetBSD 1.2G (RUPERT) #4: Thu Jul 24 13:05:55 MDT 1997 cjones@rupert.honors.montana.edu:/usr/src/sys/arch/mac68k/compile/RUPERT mac68k
>Description:
On two NetBSD-1.2G machines, one a mac68k and one i386, I can cause a
kernel panic by attempting to send multiple file descriptors in one
message. Even if the man page didn't say this was an acceptable thing
to do, it's a problem because a userland program shouldn't be able to
cause a kernel panic, IMHO. :)
>How-To-Repeat:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <sys/un.h>
#include <errno.h>
int
main(int argc,
char *argv[])
{
struct sockaddr_un sockname;
int i, sock;
char buf[1024];
struct msghdr msg;
struct cmsghdr cmsg;
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if(sock == -1) {
fprintf(stderr, "%s: socket: %s\n", argv[0], strerror(errno));
exit(1);
}
sockname.sun_family = AF_UNIX;
/* Use /var/run/printer, because it doesn't appear to matter what
process is on the other end of the socket, as long as it's
AF_UNIX and SOCK_STREAM. */
strcpy(sockname.sun_path, "/var/run/printer");
sockname.sun_len = sizeof(sockname) - sizeof(sockname.sun_path) +
strlen(sockname.sun_path);
if(connect(sock, (struct sockaddr *)&sockname, sockname.sun_len)
== -1) {
fprintf(stderr, "%s: connect: %s\n", argv[0], strerror(errno));
exit(1);
}
/* Send fd's 0, 1, and 2. */
cmsg.cmsg_len = sizeof(cmsg.cmsg_len) +
sizeof(cmsg.cmsg_level) + sizeof(cmsg.cmsg_type) +
sizeof(i) * 3;
cmsg.cmsg_level = SOL_SOCKET;
cmsg.cmsg_type = SCM_RIGHTS;
bcopy(&cmsg, buf, sizeof(cmsg));
for(i = 0; i < 3; i++)
bcopy(&i, buf + sizeof(cmsg) + sizeof(i) * i, sizeof(i));
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = NULL;
msg.msg_iovlen = 0;
msg.msg_control = buf;
msg.msg_controllen = cmsg.cmsg_len;
msg.msg_flags = 0;
if(sendmsg(sock, &msg, 0) == -1) {
fprintf(stderr, "%s: sendmsg: %s\n", argv[0],
strerror(errno));
exit(1);
}
printf("Wow; your machine didn't crash! You're lucky!\n");
exit(0);
}
>Fix:
The same program, if it's modified to send fd's one at a time, doesn't
crash anything.
>Audit-Trail:
>Unformatted: