From 6c20e8393eba4a9f330143b2158e28ea594cbadd Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 31 Oct 2022 11:07:57 +0900 Subject: spawn: Fix spawn_cb of gpgrt_spawn_process_fd. * src/gpg-error.def.in (gpgrt_close_all_fds): New. * src/gpg-error.vers (gpgrt_close_all_fds): New. * src/gpg-error.h.in (GPGRT_SPAWN_INHERIT_FILE): New. (gpgrt_spawn_process_fd): SPAWN_CB having return value. * src/gpgrt-int.h (_gpgrt_spawn_process_fd): SPAWN_CB change. * src/spawn-posix.c (_gpgrt_close_all_fds): Rename from close_all_fds, and export it. (do_exec): Support the case not closing fds. (_gpgrt_spawn_process_fd): Handle return value of SPAWN_CB to determine closing all fds or not. * src/spawn-w32.c (_gpgrt_spawn_process_fd): Run SPAWN_CB. (_gpgrt_close_all_fds): New. * src/visibility.c (gpgrt_close_all_fds): New. * src/visibility.h (gpgrt_close_all_fds): New. -- Now, we have the API of gpgrt_spawn_process_fd for POSIX and Windows. Giving portable semantics for spawning a process is difficult, and it is still difficult for users to writing a function for SPAWN_CB with portability, but gpgrt_spawn_process_fd gives the feature of spawning a process. GnuPG-bug-id: 6249 Signed-off-by: NIIBE Yutaka --- src/gpg-error.def.in | 2 ++ src/gpg-error.h.in | 12 +++++++++--- src/gpg-error.vers | 1 + src/gpgrt-int.h | 17 ++++++++++++----- src/spawn-posix.c | 19 +++++++++++-------- src/spawn-w32.c | 22 +++++++++++++++++----- src/visibility.c | 12 +++++++++--- src/visibility.h | 2 ++ 8 files changed, 63 insertions(+), 24 deletions(-) diff --git a/src/gpg-error.def.in b/src/gpg-error.def.in index ac8f2f6..f94c6f4 100644 --- a/src/gpg-error.def.in +++ b/src/gpg-error.def.in @@ -242,4 +242,6 @@ EXPORTS gpgrt_utf8_to_wchar @186 gpgrt_wchar_to_utf8 @187 + gpgrt_close_all_fds @188 + ;; end of file with public symbols for Windows. diff --git a/src/gpg-error.h.in b/src/gpg-error.h.in index b7cfdcf..ce5c76a 100644 --- a/src/gpg-error.h.in +++ b/src/gpg-error.h.in @@ -1084,6 +1084,9 @@ void _gpgrt_log_assert (const char *expr, const char *file, int line, /* * Spawn functions */ +/* Internal flag to ihnerit file descriptor/handle */ +#define GPGRT_SPAWN_INHERIT_FILE 1 + #define GPGRT_SPAWN_NONBLOCK 16 /* Set the streams to non-blocking. */ #define GPGRT_SPAWN_RUN_ASFW 64 /* Use AllowSetForegroundWindow on W32. */ #define GPGRT_SPAWN_DETACHED 128 /* Start the process in the background. */ @@ -1110,14 +1113,14 @@ gpg_err_code_t gpgrt_spawn_process (const char *pgmname, const char *argv[], /* Fork and exec PGNNAME and connect the process to the given FDs. */ gpg_err_code_t gpgrt_spawn_process_fd (const char *pgmname, const char *argv[], int infd, int outfd, int errfd, - void (*after_fork_cb)(void *), - void *after_fork_cb_arg, + int (*spawn_cb) (void *), + void *spawn_cb_arg, pid_t *pid); /* Fork and exec PGMNAME as a detached process. */ gpg_err_code_t gpgrt_spawn_process_detached (const char *pgmname, const char *argv[], - const char *envp[] ); + const char *envp[]); /* Wait for a single process. */ gpg_err_code_t gpgrt_wait_process (const char *pgmname, pid_t pid, int hang, @@ -1132,6 +1135,9 @@ void gpgrt_kill_process (pid_t pid); /* Release process resources identified by PID. */ void gpgrt_release_process (pid_t pid); + +/* Close all file resources (descriptors), except KEEP_FDS. */ +void gpgrt_close_all_fds (int from, int *keep_fds); /* * Option parsing. diff --git a/src/gpg-error.vers b/src/gpg-error.vers index 4182da0..8884e47 100644 --- a/src/gpg-error.vers +++ b/src/gpg-error.vers @@ -179,6 +179,7 @@ GPG_ERROR_1.0 { gpgrt_wait_processes; gpgrt_kill_process; gpgrt_release_process; + gpgrt_close_all_fds; gpgrt_argparse; gpgrt_argparser; diff --git a/src/gpgrt-int.h b/src/gpgrt-int.h index b95b44c..c414272 100644 --- a/src/gpgrt-int.h +++ b/src/gpgrt-int.h @@ -696,15 +696,19 @@ _gpgrt_spawn_process (const char *pgmname, const char *argv[], * The arguments for the process are expected in the NULL terminated * array ARGV. The program name itself should not be included there. * Calling gpgrt_wait_process and gpgrt_release_process is required. - * Returns 0 on success or an error code. If AFTER_FORK_CB is not - * NULL, the given function will be called right after the fork, by - * child process. + * Returns 0 on success or an error code. If SPAWN_CB is not NULL, + * the given function will be called with SPAWN_CB_ARG to determine if + * file descriptors/handles should be inherited or not. The callback + * function should return 1 to ask keeping file descriptors/handles. + * If SPAWN_CB is NULL, or it returns 0, all file descriptors (except + * INFD, OUTFD, and ERRFD) will be closed on POSIX machine. On POSIX + * machine, it is called right after the fork, by child process. */ gpg_err_code_t _gpgrt_spawn_process_fd (const char *pgmname, const char *argv[], int infd, int outfd, int errfd, - void (*after_fork_cb)(void *), - void *after_fork_cb_arg, + int (*spawn_cb) (void *), + void *spawn_cb_arg, pid_t *pid); /* Spawn a new process and immediately detach from it. The name of @@ -758,6 +762,9 @@ void _gpgrt_kill_process (pid_t pid); * It is a nop if PID is invalid. */ void _gpgrt_release_process (pid_t pid); +/* Close all file resources (descriptors), except KEEP_FDS. */ +void _gpgrt_close_all_fds (int from, int *keep_fds); + /* * Local prototypes for argparse. diff --git a/src/spawn-posix.c b/src/spawn-posix.c index 3ac79ff..6914b0b 100644 --- a/src/spawn-posix.c +++ b/src/spawn-posix.c @@ -163,8 +163,8 @@ get_max_fds (void) * EXCEPT is not NULL, it is expected to be a list of file descriptors * which shall not be closed. This list shall be sorted in ascending * order with the end marked by -1. */ -static void -close_all_fds (int first, int *except) +void +_gpgrt_close_all_fds (int first, int *except) { int max_fd = get_max_fds (); int fd, i, except_start; @@ -319,7 +319,8 @@ do_exec (const char *pgmname, const char *argv[], } /* Close all other files. */ - close_all_fds (3, except); + if (!(flags & GPGRT_SPAWN_INHERIT_FILE)) + _gpgrt_close_all_fds (3, except); execv (pgmname, arg_list); /* No way to print anything, as we have may have closed all streams. */ @@ -535,11 +536,12 @@ _gpgrt_spawn_process (const char *pgmname, const char *argv[], gpg_err_code_t _gpgrt_spawn_process_fd (const char *pgmname, const char *argv[], int infd, int outfd, int errfd, - void (*after_fork_cb)(void *), - void *after_fork_cb_arg, + int (*spawn_cb) (void *), + void *spawn_cb_arg, pid_t *pid) { gpg_error_t err; + int ask_inherit_fds = 0; _gpgrt_pre_syscall (); *pid = fork (); @@ -553,11 +555,12 @@ _gpgrt_spawn_process_fd (const char *pgmname, const char *argv[], if (!*pid) { - if (after_fork_cb) - (*after_fork_cb) (after_fork_cb_arg); + if (spawn_cb) + ask_inherit_fds = (*spawn_cb) (spawn_cb_arg); /* Run child. */ - do_exec (pgmname, argv, infd, outfd, errfd, NULL, 0); + do_exec (pgmname, argv, infd, outfd, errfd, NULL, + ask_inherit_fds? GPGRT_SPAWN_INHERIT_FILE : 0); /*NOTREACHED*/ } diff --git a/src/spawn-w32.c b/src/spawn-w32.c index 963b6a5..d17f971 100644 --- a/src/spawn-w32.c +++ b/src/spawn-w32.c @@ -642,8 +642,8 @@ _gpgrt_spawn_process (const char *pgmname, const char *argv[], gpg_err_code_t _gpgrt_spawn_process_fd (const char *pgmname, const char *argv[], int infd, int outfd, int errfd, - void (*after_fork_cb)(void *), - void *after_fork_cb_arg, + int (*spawn_cb) (void *), + void *spawn_cb_arg, pid_t *pid) { gpg_err_code_t err; @@ -653,9 +653,10 @@ _gpgrt_spawn_process_fd (const char *pgmname, const char *argv[], char *cmdline; int ret, i; HANDLE stdhd[3]; + int ask_inherit = 0; - (void)after_fork_cb; - (void)after_fork_cb_arg; + if (spawn_cb) + ask_inherit = (*spawn_cb) (spawn_cb_arg); /* Setup return values. */ *pid = (pid_t)INVALID_HANDLE_VALUE; @@ -663,7 +664,11 @@ _gpgrt_spawn_process_fd (const char *pgmname, const char *argv[], /* Prepare security attributes. */ memset (&sec_attr, 0, sizeof sec_attr ); sec_attr.nLength = sizeof sec_attr; - sec_attr.bInheritHandle = FALSE; + + if (ask_inherit) + sec_attr.bInheritHandle = TRUE; + else + sec_attr.bInheritHandle = FALSE; /* Build the command line. */ err = build_w32_commandline (pgmname, argv, &cmdline); @@ -926,3 +931,10 @@ _gpgrt_release_process (pid_t pid) CloseHandle (process); } } + +void +_gpgrt_close_all_fds (int from, int *keep_fds) +{ + (void)from; + (void)keep_fds; +} diff --git a/src/visibility.c b/src/visibility.c index dba48b8..577a2be 100644 --- a/src/visibility.c +++ b/src/visibility.c @@ -1112,12 +1112,12 @@ gpgrt_spawn_process (const char *pgmname, const char *argv[], gpg_err_code_t gpgrt_spawn_process_fd (const char *pgmname, const char *argv[], int infd, int outfd, int errfd, - void (*after_fork_cb)(void *), - void *after_fork_cb_arg, + int (*spawn_cb)(void *), + void *spawn_cb_arg, pid_t *pid) { return _gpgrt_spawn_process_fd (pgmname, argv, infd, outfd, errfd, - after_fork_cb, after_fork_cb_arg, pid); + spawn_cb, spawn_cb_arg, pid); } gpg_err_code_t @@ -1152,6 +1152,12 @@ gpgrt_release_process (pid_t pid) _gpgrt_release_process (pid); } +void +gpgrt_close_all_fds (int from, int *keep_fds) +{ + _gpgrt_close_all_fds (from, keep_fds); +} + int gpgrt_argparse (estream_t fp, gpgrt_argparse_t *arg, gpgrt_opt_t *opts) diff --git a/src/visibility.h b/src/visibility.h index 2819394..a3ed6fc 100644 --- a/src/visibility.h +++ b/src/visibility.h @@ -207,6 +207,7 @@ MARK_VISIBLE (gpgrt_wait_process) MARK_VISIBLE (gpgrt_wait_processes) MARK_VISIBLE (gpgrt_kill_process) MARK_VISIBLE (gpgrt_release_process) +MARK_VISIBLE (gpgrt_close_all_fds) MARK_VISIBLE (gpgrt_argparse) MARK_VISIBLE (gpgrt_argparser) @@ -394,6 +395,7 @@ MARK_VISIBLE (gpgrt_absfnameconcat) #define gpgrt_wait_processes _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_kill_process _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_release_process _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_close_all_fds _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_argparse _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_argparser _gpgrt_USE_UNDERSCORED_FUNCTION -- cgit v1.2.1