bug#61095: possible misuse of posix_spawn API on non-linux OSes

Josselin Poiret via "Bug reports for GUILE, GNU's Ubiquitous Extension Language" <[email protected]>
Newsgroups gmane.lisp.guile.bugs
Message-ID <[email protected]>
Hi Ludo,

Ludovic Courtès <[email protected]> writes:

> -      posix_spawn_file_actions_addclose (actions, fd);
> +      /* Adding invalid file descriptors to an 'addclose' action leads
> +         to 'posix_spawn' failures on some operating systems:
> +         <https://bugs.gnu.org/61095>.  Hence the extra check.  */
> +      int flags = fcntl (max_fd, F_GETFD, NULL);
> +      if ((flags >= 0) && ((flags & FD_CLOEXEC) == 0))
> +        posix_spawn_file_actions_addclose (actions, max_fd);
>      }

I'm worried about TOCTOU in multi-threaded contexts here, which is why I
opted for the heavy handed-approach here.  In general I don't think we
can know in advance which fdes to close :/ It's a shame that the
posix_spawn actions fails on other kernels, since I don't really see a
way to mitigate this problem (apart from the new
posix_spawn_file_actions_addclosefrom_np as you mentioned).  I don't
know what we could do here.  Maybe not provide spawn?  Or provide it in
spite of the broken fd closing?

> -
> -  closedir (dirp);
>  }
>  
>  static pid_t
> @@ -1366,6 +1345,26 @@ do_spawn (char *exec_file, char **exec_argv, char **exec_env,
>    posix_spawn_file_actions_t actions;
>    posix_spawnattr_t *attrp = NULL;
>  
> +  posix_spawn_file_actions_init (&actions);
> +
> +  /* Duplicate IN, OUT, and ERR unconditionally to clear their
> +     FD_CLOEXEC flag, if any.  */
> +  posix_spawn_file_actions_adddup2 (&actions, in, STDIN_FILENO);
> +  posix_spawn_file_actions_adddup2 (&actions, out, STDOUT_FILENO);
> +  posix_spawn_file_actions_adddup2 (&actions, err, STDERR_FILENO);

This won't work, and actually this was one of the original logic bugs I
was trying to fix.  If err is equal to, let's say, STDIN_FILENO, then
the first call will overwrite the initial file descriptor at
STDIN_FILENO, and the second call won't do what the caller intended.
This is why I was moving them out of the way first, so that they would
not overwrite each other.

> +  /* TODO: Use 'closefrom' where available.  */
> +#if 0
> +  /* Version 2.34 of the GNU libc provides this function.  */
> +  posix_spawn_file_actions_addclosefrom_np (&actions, 3);
> +#else
> +  if (in > 2)
> +    posix_spawn_file_actions_addclose (&actions, in);
> +  if (out > 2 && out != in)
> +    posix_spawn_file_actions_addclose (&actions, out);
> +  if (err > 2 && err != out && err != in)
> +    posix_spawn_file_actions_addclose (&actions, err);

Isn't this unneeded given we call close_inherited_fds below?

> [...]
>
> Josselin: I simplified the ‘dup2’ logic somewhat.

See my comments above.

> Guile does that for file descriptors it opens internally, but
> applications using ‘open-file’ without the recently-added “e” flag, or
> ‘socket’ without ‘SOCK_CLOEXEC’, etc., end up with more file descriptors
> that need to be taken care of.
>
> I wish the default were close-on-exec, but we’re not there yet.

+1

Best,
-- 
Josselin Poiret
signature.asc (application/pgp-signature, 682 B)
-----BEGIN PGP SIGNATURE-----

iQHEBAEBCAAuFiEEOSSM2EHGPMM23K8vUF5AuRYXGooFAmQjEXMQHGRldkBqcG9p
cmV0Lnh5egAKCRBQXkC5Fhcail3ZC/4q3n0W2AOoRdNaXOzROGyxrfTd7dz3Ehx/
xEko14Ury/kPiV+x8MxIQXZ2Vo9m8LXTbuhhiLzeRNwS+fBwwnZQbEDDE4GvDkLd
Vwh6IRmxKk3A5PxVqaX3EJypcwCABxMHzj1et3I/393na3UbPB/nVJaLAs27L/al
XrFwd6k1aUGCPNYMPOVkulJXx6NNrOVcV1fSm23VlwpQzeeRUqVQBWWLPWi7MJ4n
lnH+iwbLOAPIgywltXrCkf4rsook8KEBGWvQXSCgAqlCycdNIiBid7bTNaoitbeW
HX5LP314uiMjSktOVVQrK+Q1+PhLJXUSGPxXRrxDTZf6/fXYAF4OrR343KjwxHJQ
KWwC2yCENFkyHlh3RKkXkfmH41ezkaHQu2o64uD/1QcpFyv7Vx5Rde41pTPSEd8M
3umstB4vWNb2bzuBczeNXaoTFpAGKZHwXkGjfCWCZVEmyGBnbRm16VWxyPHtlvAp
WizmvpOzWpM63lTajCdzwlPnckxPlfM=
=pbCP
-----END PGP SIGNATURE-----
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.