[glib: 6/15] gspawn: Avoid merged FDs being closed on exec()




commit c5f3ba7f01a04921828e39b02624b64f59a3559a
Author: Philip Withnall <pwithnall endlessos org>
Date:   Fri Dec 4 18:28:08 2020 +0000

    gspawn: Avoid merged FDs being closed on exec()
    
    If `stdout_fd` was set to (say) 6, and `stderr_fd` was set to 1, the
    `set_cloexec()` call for setting up `stderr` would set the new `stdout`
    for the forked process to be closed in the pending `exec()`.
    
    This would cause the child process to error when writing to `stdout`.
    
    This situation happens when using `G_SUBPROCESS_FLAGS_STDERR_MERGE`.
    
    Add some conditions to prevent setting `CLOEXEC` in such cases.
    
    Signed-off-by: Philip Withnall <pwithnall endlessos org>
    
    Helps: #2097

 glib/gspawn.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)
---
diff --git a/glib/gspawn.c b/glib/gspawn.c
index aae0be2e9..5e7c58700 100644
--- a/glib/gspawn.c
+++ b/glib/gspawn.c
@@ -1497,7 +1497,9 @@ do_exec (gint                  child_err_report_fd,
         write_err_and_exit (child_err_report_fd,
                             CHILD_DUP2_FAILED);
 
-      set_cloexec (GINT_TO_POINTER(0), stdin_fd);
+      if (!((stdout_fd >= 0 || stdout_to_null) && stdin_fd == 1) &&
+          !((stderr_fd >= 0 || stderr_to_null) && stdin_fd == 2))
+        set_cloexec (GINT_TO_POINTER(0), stdin_fd);
     }
   else if (!child_inherits_stdin)
     {
@@ -1517,7 +1519,9 @@ do_exec (gint                  child_err_report_fd,
         write_err_and_exit (child_err_report_fd,
                             CHILD_DUP2_FAILED);
 
-      set_cloexec (GINT_TO_POINTER(0), stdout_fd);
+      if (!((stdin_fd >= 0 || !child_inherits_stdin) && stdout_fd == 0) &&
+          !((stderr_fd >= 0 || stderr_to_null) && stdout_fd == 2))
+        set_cloexec (GINT_TO_POINTER(0), stdout_fd);
     }
   else if (stdout_to_null)
     {
@@ -1536,7 +1540,9 @@ do_exec (gint                  child_err_report_fd,
         write_err_and_exit (child_err_report_fd,
                             CHILD_DUP2_FAILED);
 
-      set_cloexec (GINT_TO_POINTER(0), stderr_fd);
+      if (!((stdin_fd >= 0 || !child_inherits_stdin) && stderr_fd == 0) &&
+          !((stdout_fd >= 0 || stdout_to_null) && stderr_fd == 1))
+        set_cloexec (GINT_TO_POINTER(0), stderr_fd);
     }
   else if (stderr_to_null)
     {


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