bb_sanitize_stdio_maybe_daemonize faulty logic...
David Daney
ddaney at avtrex.com
Tue Feb 13 10:28:13 PST 2007
Consider this program:
---------------------------------------
#include <stdio.h>
#include <sys/socket.h>
static int open_a_socket()
{
int s = socket(PF_INET, SOCK_DGRAM, 0);
printf("Opened on fd %d\n", s);
return s;
}
int
main(int argc, char *argv[])
{
int c;
open_a_socket();
open_a_socket();
open_a_socket();
open_a_socket();
open_a_socket();
open_a_socket();
c = open_a_socket();
open_a_socket();
open_a_socket();
open_a_socket();
open_a_socket();
close(c);
open_a_socket();
return 0;
}
-----------------------------------
Note that the last open reuses the fd of the closed socket, but there
are a lot of open sockets with fd values greater than the last socket
opened.
Now look at bb_sanitize_stdio_maybe_daemonize:
-----------------------------------------
void bb_sanitize_stdio_maybe_daemonize(int daemonize)
{
int fd;
/* Mega-paranoid */
fd = xopen(bb_dev_null, O_RDWR);
while ((unsigned)fd < 2)
fd = dup(fd); /* have 0,1,2 open at least to /dev/null */
if (daemonize) {
pid_t pid = fork();
if (pid < 0) /* wtf? */
bb_perror_msg_and_die("fork");
if (pid) /* parent */
exit(0);
/* child */
/* if daemonizing, make sure we detach from stdio */
setsid();
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
}
while (fd > 2)
close(fd--); /* close everything after fd#2 */
}
-----------------------------------------
The result of the first xopen is used as a marker to try to find the
highest active descriptor. Then all descriptors greater than 2 and less
than the marker are closed.
The problem is that the marker could fall in a hole in the middle of the
range of open descriptors (as in the top example), in which case
bb_sanitize_stdio_maybe_daemonize could leave some descriptors open that
should have been closed.
David Daney
More information about the busybox
mailing list