From d8448636b4190080ff769c5d198f8f4f267ff6f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 8 Feb 2022 00:11:00 +0400 Subject: [PATCH] glib/spawn: check user source_fds doesn't contain private fds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the user provided source_fds set contains internal fds, this is a programmer mistake. We can avoid further damage by preventing this situation. Signed-off-by: Marc-André Lureau --- glib/gspawn-private.h | 22 ++++++++++++++++++++++ glib/gspawn-win32.c | 15 +++++++++++++++ glib/gspawn.c | 22 ++++++++++++++++++++-- 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/glib/gspawn-private.h b/glib/gspawn-private.h index 400c173cf..64d3c8150 100644 --- a/glib/gspawn-private.h +++ b/glib/gspawn-private.h @@ -24,6 +24,7 @@ #include +#include "glibintl.h" #include "gspawn.h" static inline gint @@ -115,3 +116,24 @@ _g_spawn_exec_err_to_g_error (gint en) return G_SPAWN_ERROR_FAILED; } } + +static inline gboolean +_g_spawn_invalid_source_fd (gint fd, + const gint *source_fds, + gsize n_fds, + GError **error) +{ + gsize i; + + for (i = 0; i < n_fds; i++) + if (fd == source_fds[i]) + { + g_set_error (error, + G_SPAWN_ERROR, + G_SPAWN_ERROR_INVAL, + _("Invalid source FDs argument")); + return TRUE; + } + + return FALSE; +} diff --git a/glib/gspawn-win32.c b/glib/gspawn-win32.c index cae4c288c..665d7313e 100644 --- a/glib/gspawn-win32.c +++ b/glib/gspawn-win32.c @@ -658,6 +658,9 @@ fork_exec (gint *exit_status, { if (!make_pipe (stdin_pipe, error)) goto cleanup_and_fail; + if (_g_spawn_invalid_source_fd (stdin_pipe[0], source_fds, n_fds, error) || + _g_spawn_invalid_source_fd (stdin_pipe[1], source_fds, n_fds, error)) + goto cleanup_and_fail; stdin_fd = stdin_pipe[0]; } @@ -665,6 +668,9 @@ fork_exec (gint *exit_status, { if (!make_pipe (stdout_pipe, error)) goto cleanup_and_fail; + if (_g_spawn_invalid_source_fd (stdout_pipe[0], source_fds, n_fds, error) || + _g_spawn_invalid_source_fd (stdout_pipe[1], source_fds, n_fds, error)) + goto cleanup_and_fail; stdout_fd = stdout_pipe[1]; } @@ -672,6 +678,9 @@ fork_exec (gint *exit_status, { if (!make_pipe (stderr_pipe, error)) goto cleanup_and_fail; + if (_g_spawn_invalid_source_fd (stderr_pipe[0], source_fds, n_fds, error) || + _g_spawn_invalid_source_fd (stderr_pipe[1], source_fds, n_fds, error)) + goto cleanup_and_fail; stderr_fd = stderr_pipe[1]; } @@ -703,9 +712,15 @@ fork_exec (gint *exit_status, if (!make_pipe (child_err_report_pipe, error)) goto cleanup_and_fail; + if (_g_spawn_invalid_source_fd (child_err_report_pipe[0], source_fds, n_fds, error) || + _g_spawn_invalid_source_fd (child_err_report_pipe[1], source_fds, n_fds, error)) + goto cleanup_and_fail; if (!make_pipe (helper_sync_pipe, error)) goto cleanup_and_fail; + if (_g_spawn_invalid_source_fd (helper_sync_pipe[0], source_fds, n_fds, error) || + _g_spawn_invalid_source_fd (helper_sync_pipe[1], source_fds, n_fds, error)) + goto cleanup_and_fail; new_argv = g_new (char *, argc + 1 + ARG_COUNT); if (might_be_console_process ()) diff --git a/glib/gspawn.c b/glib/gspawn.c index f491c12cf..298df314f 100644 --- a/glib/gspawn.c +++ b/glib/gspawn.c @@ -2334,6 +2334,9 @@ fork_exec (gboolean intermediate_child, { if (!g_unix_open_pipe (stdin_pipe, pipe_flags, error)) goto cleanup_and_fail; + if (_g_spawn_invalid_source_fd (stdin_pipe[0], source_fds, n_fds, error) || + _g_spawn_invalid_source_fd (stdin_pipe[1], source_fds, n_fds, error)) + goto cleanup_and_fail; child_close_fds[n_child_close_fds++] = stdin_pipe[1]; stdin_fd = stdin_pipe[0]; } @@ -2342,6 +2345,9 @@ fork_exec (gboolean intermediate_child, { if (!g_unix_open_pipe (stdout_pipe, pipe_flags, error)) goto cleanup_and_fail; + if (_g_spawn_invalid_source_fd (stdout_pipe[0], source_fds, n_fds, error) || + _g_spawn_invalid_source_fd (stdout_pipe[1], source_fds, n_fds, error)) + goto cleanup_and_fail; child_close_fds[n_child_close_fds++] = stdout_pipe[0]; stdout_fd = stdout_pipe[1]; } @@ -2350,6 +2356,9 @@ fork_exec (gboolean intermediate_child, { if (!g_unix_open_pipe (stderr_pipe, pipe_flags, error)) goto cleanup_and_fail; + if (_g_spawn_invalid_source_fd (stderr_pipe[0], source_fds, n_fds, error) || + _g_spawn_invalid_source_fd (stderr_pipe[1], source_fds, n_fds, error)) + goto cleanup_and_fail; child_close_fds[n_child_close_fds++] = stderr_pipe[0]; stderr_fd = stderr_pipe[1]; } @@ -2491,9 +2500,18 @@ fork_exec (gboolean intermediate_child, if (!g_unix_open_pipe (child_err_report_pipe, pipe_flags, error)) goto cleanup_and_fail; - - if (intermediate_child && !g_unix_open_pipe (child_pid_report_pipe, pipe_flags, error)) + if (_g_spawn_invalid_source_fd (child_err_report_pipe[0], source_fds, n_fds, error) || + _g_spawn_invalid_source_fd (child_err_report_pipe[1], source_fds, n_fds, error)) goto cleanup_and_fail; + + if (intermediate_child) + { + if (!g_unix_open_pipe (child_pid_report_pipe, pipe_flags, error)) + goto cleanup_and_fail; + if (_g_spawn_invalid_source_fd (child_pid_report_pipe[0], source_fds, n_fds, error) || + _g_spawn_invalid_source_fd (child_pid_report_pipe[1], source_fds, n_fds, error)) + goto cleanup_and_fail; + } pid = fork ();