GnuTLS leaks file descriptors in child processes
Description of problem:
A program using GnuTLS might (outside GnuTLS) spawn a child process. With POSIX systems, a multithread application can do this either via fork()
then an exec*()
family function, or via a posix_spawn*()
family function. First (at fork time), the child process is created and inherits all the file descriptors of the parent. Then (at exec time), the file descriptors marked with the close-on-exec flag are closed; others are left open in the new executed program.
To avoid leaks, all file descriptors should be marked close-on-exec (unless explicitly intended to be inherited). The program cannot know what file descriptors GnuTLS has opened, so GnuTLS has to set the flag. Furthermore because the application might have one thread using GnuTLS while another is forking, the flag must be set "atomically" while file descriptor is being allocated.
Consequences of not closing the file descriptors vary with the type. For regular files, this can prevent un-mounting a file system. In the worst case, it might lead to privilege escalation if the child process has different privileges than the parent.
POSIX.next specifies the "e" open flag for the fopen()
, for instance fopen(file, "re")
. Likewise the SOCK_CLOEXEC
socket type mask for socket()
, for instance socket(AF_INET6, SOCK_STREAM | SOCK_CLOEXEC, 0)
. POSIX.2008 already specifies O_CLOEXEC
for the open()
call.
This is not a problem for the tests and sample programs in GnuTLS, but it is a problem for the few fopen()
calls within the library itself.
Version of gnutls used:
3.6.13-49-gd5139927
Distributor of gnutls (e.g., Ubuntu, Fedora, RHEL)
upstream