Subject: Re: bug#33965: handling of closed file descriptors

From: Bruno Haible <[email-masked]>
Date: Sat, 05 Jan 2019 10:44:17 +0100

[CCing bug-gnulib. This is a followup to
 https://debbugs.gnu.org/cgi/bugreport.cgi?bug=33965 ]

Hi Paul,

> The feature is not portable to POSIX 
> platforms. Besides, I doubt whether anybody is using the feature anyway. 

OK, if you question the "feature" as a whole, then I'd say:

* Users don't *need* the "feature", in the sense that:
  - The normal way of invoking a program is by providing arguments
    and standard input/output streams. Users who want to invoke a program
    are not actively looking for this contorted way to invoke a program.
  - For most programs, equivalent functionality to the "feature" is available
    by passing an empty string, a reference to an empty file, or /dev/null
    as argument. If a program exists for which the equivalent functionality
    is not available through the normal way of invocation, the developers
    should better add it.

* But it's a security risk that a program can be invoked in ways in which it
  was surely never tested. Anything can happen then - from overwriting precious
  files of the user to endless loops.

* Therefore if you want to take out the "feature", you still have to think
  about how to mitigate the security risks.

  > Although the HP-UX solution to this problem may not be best, it's better 
  > than the traditional behavior as it is a simple change to the kernel 
  > that fixes the issue for all applications, as opposed to the 
  > more-complicated dances we do in openat-safer and friends.

  Given
    - the prevalent "worse is better" attitude,
    - the "never break userland behaviour that programs may rely upon"
      principle of the Linux kernel community,
    - the fact that the glibc people looked at the problem and used the
      HP-UX solution only for setuid programs,
  I predict that this "simple change to the kernel" will not make it into
  the majority of the operating systems in the next 10 years. (But you
  could start lobbying for it among the OpenBSD people. They would be the
  most likely to adopt it, I guess.)

  In the mean time, the remaining options I can see are:

    (a) Keep using the *-safer Gnulib modules.

    (b) Introduce a sanity_check_file_descriptors() function that all programs
        can invoke right at the beginning of main(), and that exits with an
        exit code if it detects a closed fd.

        void
        sanity_check_file_descriptors (void)
        {
          int fd;
          for (fd = 0; fd <= 2; fd++)
            if (fcntl (fd, F_GETFD, NULL) < 0 && errno == EBADF)
              exit (125);
        }

        On platforms like HP-UX, this code would not cause an exit, but
        the exec() call has already provided substitutes for the closed fds;
        this mitigates the security risks.
        I would propose exit code 125, since 127 and 126 are already taken [1].

  (b) surely is simpler than (a).

Bruno

[1] http://tldp.org/LDP/abs/html/exitcodes.html