bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS) does not close extra fds

Denys Vlasenko vda.linux at googlemail.com
Fri Mar 15 09:30:20 UTC 2019


On Thu, Mar 14, 2019 at 4:35 PM Arnout Vandecappelle <arnout at mind.be> wrote:
>  I've noticed that bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS +
> DAEMON_DEVNULL_STDIO) does not actually close all fds. This is what gets called
> by start-stop-daemon -b, so it means that start-stop-daemon will propagate all
> non-CLOEXEC fds from the parent.
>
>  To test:
>
> sh -c 'exec 3>&1; busybox start-stop-daemon -S -b -x /bin/sleep -- 10000'
> ls -l /proc/$(pidof sleep)/fd

Does debian ssd close fd#3 in this case?

>  This happens because we do:
>
>         if (flags & DAEMON_DEVNULL_STDIO) {
>                 close(0);
>                 close(1);
>                 close(2);
>         }
>
>         fd = open(bb_dev_null, O_RDWR);
> ...
>         while (fd > 2) {
>                 close(fd--);
>         }
>
>  Since we just did close(0), fd will be 0.

You skipped this part:

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

fd will be >= 2, not 0.

>  The problem is that the assumption that open() returns an fd that is larger
> than all existing fds is simply wrong.
>
>  I think that there is no other way to close all open fds than to iterate over
> /proc/self/fd. But that is of course not very portable.

Yes, there is no easy way to close all fds. Usually people go with
something like

fd = 1024;
while (fd) close(fd--);


More information about the busybox mailing list