[PATCH] sanitize when kernel starts init without any fd opened

Denis Vlasenko vda.linux at googlemail.com
Tue Jun 12 22:42:41 UTC 2007


On Monday 11 June 2007 19:40, Maxime Bizon wrote:
> 
> Since [17937], the "controlling tty hack" code has been removed from
> init.c.
> 
> It added an (I think) unwanted side effect.
> 
> The kernel may be unable to open a console, and then starts init without
> any fd opened. The previous code would end up opening /dev/null and set
> std(in|out|err) to it for any inittab line with "terminal" field empty,
> but the new code doesn't, and it took me some time to understand why
> some daemons were not working.

Which daemons are not working?

I would like to have all busybox applets work right even if they
happen to be started with some of fd 0,1,2 closed.

How to fix it in daemons and init. Example from login.c

        /* Mandatory paranoia for suid applet:
         * ensure that fd# 0,1,2 are opened (at least to /dev/null)
         * and any extra open fd's are closed.
         * (The name of the function is misleading. Not daemonizing here.) */
        bb_daemonize_or_rexec(DAEMON_ONLY_SANITIZE | DAEMON_CLOSE_EXTRA_FDS, NULL);

DAEMON_ONLY_SANITIZE disables daemonization code in bb_daemonize_or_rexec
(and makes function name sound wrong), leaving only code
which open("/dev/null")+dup2() as needed to make sure fd 0,1,2 are open.

Use DAEMON_CLOSE_EXTRA_FDS if you want to additionally close stray fds > 2.

The code itself is below sig for your easy reference.
--
vda


void bb_daemonize_or_rexec(int flags, char **argv)
{
        int fd;

        fd = xopen(bb_dev_null, O_RDWR);

        if (flags & DAEMON_CHDIR_ROOT)
                xchdir("/");

        if (flags & DAEMON_DEVNULL_STDIO) {
                close(0);
                close(1);
                close(2);
        }

        while ((unsigned)fd < 2)
                fd = dup(fd); /* have 0,1,2 open at least to /dev/null */

        if (!(flags & DAEMON_ONLY_SANITIZE)) {
                forkexit_or_rexec(argv);
                /* if daemonizing, make sure we detach from stdio */
                setsid();
                dup2(fd, 0);
                dup2(fd, 1);
                dup2(fd, 2);
        }
        if (fd > 2)
                close(fd--);
        if (flags & DAEMON_CLOSE_EXTRA_FDS)
                while (fd > 2)
                        close(fd--); /* close everything after fd#2 */
}



More information about the busybox mailing list