diff options
author | Philip Withnall <pwithnall@endlessos.org> | 2020-10-13 13:25:21 +0100 |
---|---|---|
committer | Philip Withnall <pwithnall@endlessos.org> | 2021-02-16 13:44:00 +0000 |
commit | f20f0d385ef0729653340477cd578ce721a486b2 (patch) | |
tree | b9a5038a68f5b93157e4f44d10c63c576c7cf1b2 | |
parent | 7be9767cc46366f0ea6601337d010226d283ed38 (diff) | |
download | glib-f20f0d385ef0729653340477cd578ce721a486b2.tar.gz |
gspawn: Avoid custom FDs conflicting with the child_err_report_fd
It was previously possible to specify the FD number which
`child_err_report_fd` was assigned, as a target FD in the FD mapping set
up using `g_subprocess_launcher_take_fd()`.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2097
-rw-r--r-- | glib/gspawn.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/glib/gspawn.c b/glib/gspawn.c index db4f5ad02..aae0be2e9 100644 --- a/glib/gspawn.c +++ b/glib/gspawn.c @@ -1410,6 +1410,20 @@ safe_closefrom (int lowfd) /* This function is called between fork() and exec() and hence must be * async-signal-safe (see signal-safety(7)). */ static gint +safe_dup (gint fd) +{ + gint ret; + + do + ret = dup (fd); + while (ret < 0 && (errno == EINTR || errno == EBUSY)); + + return ret; +} + +/* This function is called between fork() and exec() and hence must be + * async-signal-safe (see signal-safety(7)). */ +static gint safe_dup2 (gint fd1, gint fd2) { gint ret; @@ -1574,6 +1588,9 @@ do_exec (gint child_err_report_fd, * 5 -> 4, 4 -> 6 * * We do this by duping the source fds temporarily in a first pass. + * + * If any of the @target_fds conflict with @child_err_report_fd, dup the + * latter so it doesn’t get conflated. */ if (n_fds > 0) { @@ -1590,6 +1607,9 @@ do_exec (gint child_err_report_fd, } else { + if (target_fds[i] == child_err_report_fd) + child_err_report_fd = safe_dup (child_err_report_fd); + safe_dup2 (source_fds[i], target_fds[i]); (void) close (source_fds[i]); } |