ecore exe - add an "isolate io"f lag for sending io to /dev/null
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>
Sat, 23 Sep 2017 13:44:17 +0000 (22:44 +0900)
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>
Sat, 23 Sep 2017 13:44:17 +0000 (22:44 +0900)
this is useful for security to disallow child processes access to
stdio/err of the parent process.

@feature

src/lib/ecore/ecore_exe.eo
src/lib/ecore/ecore_exe_posix.c

index 78a1da9..100f5b3 100644 (file)
@@ -35,7 +35,8 @@ enum Ecore.Exe_Flags
    respawn = 64, [[FIXME: Exe is restarted if it dies]]
    use_sh = 128, [[Use /bin/sh to run the command.]]
    not_leader = 256, [[Do not use setsid() to have the executed process be its own session leader]]
-   term_with_parent = 512 [[Makes child receive SIGTERM when parent dies.]]
+   term_with_parent = 512, [[Makes child receive SIGTERM when parent dies.]]
+   isolate_io = 1024, [[Try and isolate stdin/out and err of the process so it isn't shared with the parent.]]
 }
 
 class Ecore.Exe (Efl.Object, Efl.Control)
index 2a240a2..3cbba20 100644 (file)
@@ -317,24 +317,58 @@ _impl_ecore_exe_efl_object_finalize(Eo *obj, Ecore_Exe_Data *exe)
 #warning "Have support for this"
 #endif
          }
-         /* dup2 STDERR, STDIN, and STDOUT.  dup2() allegedly closes the
-          * second pipe if it's open. On the other hand, there was the
-          * Great FD Leak Scare of '06, so let's be paranoid. */
-         if (ok && (flags & ECORE_EXE_PIPE_ERROR))
-         {
-            E_NO_ERRNO(result, close(STDERR_FILENO), ok);
-            E_NO_ERRNO(result, dup2(errorPipe[1], STDERR_FILENO), ok);
-         }
-         if (ok && (flags & ECORE_EXE_PIPE_READ))
-         {
-            E_NO_ERRNO(result, close(STDOUT_FILENO), ok);
-            E_NO_ERRNO(result, dup2(readPipe[1], STDOUT_FILENO), ok);
-         }
-         if (ok && (flags & ECORE_EXE_PIPE_WRITE))
-         {
-            E_NO_ERRNO(result, close(STDIN_FILENO), ok);
-            E_NO_ERRNO(result, dup2(writePipe[0], STDIN_FILENO), ok);
-         }
+         if (ok && (flags & ECORE_EXE_ISOLATE_IO))
+           {
+              int devnull;
+
+              /* we want to isolatie the stdin/out/err of the process so
+               * it can't share those of the parent, so close and replace with
+               * /dev/null */
+              devnull = open("/dev/null", O_RDONLY);
+              if (devnull >= 0)
+                {
+                   E_NO_ERRNO(result, close(STDIN_FILENO), ok);
+                   E_NO_ERRNO(result, dup2(devnull, STDIN_FILENO), ok);
+                   E_NO_ERRNO(result, close(devnull), ok);
+                }
+
+              devnull = open("/dev/null", O_WRONLY);
+              if (devnull >= 0)
+                {
+                   E_NO_ERRNO(result, close(STDOUT_FILENO), ok);
+                   E_NO_ERRNO(result, dup2(devnull, STDOUT_FILENO), ok);
+                   E_NO_ERRNO(result, close(devnull), ok);
+                }
+
+              devnull = open("/dev/null", O_WRONLY);
+              if (devnull >= 0)
+                {
+                   E_NO_ERRNO(result, close(STDERR_FILENO), ok);
+                   E_NO_ERRNO(result, dup2(devnull, STDERR_FILENO), ok);
+                   E_NO_ERRNO(result, close(devnull), ok);
+                }
+           }
+         else
+           {
+              /* dup2 STDERR, STDIN, and STDOUT.  dup2() allegedly closes the
+               * second pipe if it's open. On the other hand, there was the
+               * Great FD Leak Scare of '06, so let's be paranoid. */
+              if (ok && (flags & ECORE_EXE_PIPE_ERROR))
+                {
+                   E_NO_ERRNO(result, close(STDERR_FILENO), ok);
+                   E_NO_ERRNO(result, dup2(errorPipe[1], STDERR_FILENO), ok);
+                }
+              if (ok && (flags & ECORE_EXE_PIPE_READ))
+                {
+                   E_NO_ERRNO(result, close(STDOUT_FILENO), ok);
+                   E_NO_ERRNO(result, dup2(readPipe[1], STDOUT_FILENO), ok);
+                }
+              if (ok && (flags & ECORE_EXE_PIPE_WRITE))
+                {
+                   E_NO_ERRNO(result, close(STDIN_FILENO), ok);
+                   E_NO_ERRNO(result, dup2(writePipe[0], STDIN_FILENO), ok);
+                }
+           }
 
          if (ok)
          {