[glib: 5/15] gspawn: Avoid custom FDs conflicting with the child_err_report_fd




commit f20f0d385ef0729653340477cd578ce721a486b2
Author: Philip Withnall <pwithnall endlessos org>
Date:   Tue Oct 13 13:25:21 2020 +0100

    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

 glib/gspawn.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
---
diff --git a/glib/gspawn.c b/glib/gspawn.c
index db4f5ad02..aae0be2e9 100644
--- a/glib/gspawn.c
+++ b/glib/gspawn.c
@@ -1407,6 +1407,20 @@ safe_closefrom (int lowfd)
 #endif
 }
 
+/* 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
@@ -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]);
             }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]