|
|
905b4d |
From 6468d9f2bb30147967a724075c504afb3481d465 Mon Sep 17 00:00:00 2001
|
|
|
905b4d |
From: Jakub Hrozek <jhrozek@redhat.com>
|
|
|
905b4d |
Date: Mon, 1 Dec 2014 12:25:24 +0100
|
|
|
905b4d |
Subject: [PATCH 127/128] Add extra_args to exec_child()
|
|
|
905b4d |
|
|
|
905b4d |
Related:
|
|
|
905b4d |
https://fedorahosted.org/sssd/ticket/2503
|
|
|
905b4d |
|
|
|
905b4d |
Currently all child processes use the same arguments, the construction
|
|
|
905b4d |
of argv[] is even hardcoded in exec_child(). Add an extra_args[] array
|
|
|
905b4d |
that extends the common set of argvs so that we can have child-specific
|
|
|
905b4d |
arguments. Also adds a unit test.
|
|
|
905b4d |
|
|
|
905b4d |
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
|
|
905b4d |
---
|
|
|
905b4d |
src/providers/ad/ad_gpo.c | 2 +-
|
|
|
905b4d |
src/providers/ipa/ipa_selinux.c | 3 ++-
|
|
|
905b4d |
src/providers/krb5/krb5_child_handler.c | 3 ++-
|
|
|
905b4d |
src/providers/ldap/sdap_child_helpers.c | 3 ++-
|
|
|
905b4d |
src/tests/cmocka/test_child.c | 31 ++++++++++++----------
|
|
|
905b4d |
src/tests/cmocka/test_child_common.c | 47 ++++++++++++++++++++++++++++++++-
|
|
|
905b4d |
src/util/child_common.c | 23 ++++++++++++++--
|
|
|
905b4d |
src/util/child_common.h | 3 ++-
|
|
|
905b4d |
8 files changed, 93 insertions(+), 22 deletions(-)
|
|
|
905b4d |
|
|
|
905b4d |
diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c
|
|
|
905b4d |
index 83edbe4fb5a7e617cab95c0330ceae31392b18b2..62715861c91484fa2a57e7cc13ba403c9096d9a7 100644
|
|
|
905b4d |
--- a/src/providers/ad/ad_gpo.c
|
|
|
905b4d |
+++ b/src/providers/ad/ad_gpo.c
|
|
|
905b4d |
@@ -3960,7 +3960,7 @@ gpo_fork_child(struct tevent_req *req)
|
|
|
905b4d |
if (pid == 0) { /* child */
|
|
|
905b4d |
err = exec_child(state,
|
|
|
905b4d |
pipefd_to_child, pipefd_from_child,
|
|
|
905b4d |
- GPO_CHILD, gpo_child_debug_fd);
|
|
|
905b4d |
+ GPO_CHILD, gpo_child_debug_fd, NULL);
|
|
|
905b4d |
DEBUG(SSSDBG_CRIT_FAILURE, "Could not exec gpo_child: [%d][%s].\n",
|
|
|
905b4d |
err, strerror(err));
|
|
|
905b4d |
return err;
|
|
|
905b4d |
diff --git a/src/providers/ipa/ipa_selinux.c b/src/providers/ipa/ipa_selinux.c
|
|
|
905b4d |
index 30ad6f0a7c4622ca5eb9a75ae4f57183543515c6..531258dac5c033b5896598e44e28a373d6cf5e3b 100644
|
|
|
905b4d |
--- a/src/providers/ipa/ipa_selinux.c
|
|
|
905b4d |
+++ b/src/providers/ipa/ipa_selinux.c
|
|
|
905b4d |
@@ -1036,7 +1036,8 @@ static errno_t selinux_fork_child(struct selinux_child_state *state)
|
|
|
905b4d |
if (pid == 0) { /* child */
|
|
|
905b4d |
ret = exec_child(state,
|
|
|
905b4d |
pipefd_to_child, pipefd_from_child,
|
|
|
905b4d |
- SELINUX_CHILD, selinux_child_debug_fd);
|
|
|
905b4d |
+ SELINUX_CHILD, selinux_child_debug_fd,
|
|
|
905b4d |
+ NULL);
|
|
|
905b4d |
DEBUG(SSSDBG_CRIT_FAILURE, "Could not exec selinux_child: [%d][%s].\n",
|
|
|
905b4d |
ret, sss_strerror(ret));
|
|
|
905b4d |
return ret;
|
|
|
905b4d |
diff --git a/src/providers/krb5/krb5_child_handler.c b/src/providers/krb5/krb5_child_handler.c
|
|
|
905b4d |
index 93961172c7a3a5d8f2a4fb320370037f188b5909..9bb61f65437694d8aa2109513b5f061dfc9ee21c 100644
|
|
|
905b4d |
--- a/src/providers/krb5/krb5_child_handler.c
|
|
|
905b4d |
+++ b/src/providers/krb5/krb5_child_handler.c
|
|
|
905b4d |
@@ -299,7 +299,8 @@ static errno_t fork_child(struct tevent_req *req)
|
|
|
905b4d |
if (pid == 0) { /* child */
|
|
|
905b4d |
err = exec_child(state,
|
|
|
905b4d |
pipefd_to_child, pipefd_from_child,
|
|
|
905b4d |
- KRB5_CHILD, state->kr->krb5_ctx->child_debug_fd);
|
|
|
905b4d |
+ KRB5_CHILD, state->kr->krb5_ctx->child_debug_fd,
|
|
|
905b4d |
+ NULL);
|
|
|
905b4d |
if (err != EOK) {
|
|
|
905b4d |
DEBUG(SSSDBG_CRIT_FAILURE, "Could not exec KRB5 child: [%d][%s].\n",
|
|
|
905b4d |
err, strerror(err));
|
|
|
905b4d |
diff --git a/src/providers/ldap/sdap_child_helpers.c b/src/providers/ldap/sdap_child_helpers.c
|
|
|
905b4d |
index 40010989021eb7cf77b96876b2d1c4119ed39163..b60891d2b41f9a359856eb22174128d7f07559fb 100644
|
|
|
905b4d |
--- a/src/providers/ldap/sdap_child_helpers.c
|
|
|
905b4d |
+++ b/src/providers/ldap/sdap_child_helpers.c
|
|
|
905b4d |
@@ -108,7 +108,8 @@ static errno_t sdap_fork_child(struct tevent_context *ev,
|
|
|
905b4d |
if (pid == 0) { /* child */
|
|
|
905b4d |
err = exec_child(child,
|
|
|
905b4d |
pipefd_to_child, pipefd_from_child,
|
|
|
905b4d |
- LDAP_CHILD, ldap_child_debug_fd);
|
|
|
905b4d |
+ LDAP_CHILD, ldap_child_debug_fd,
|
|
|
905b4d |
+ NULL);
|
|
|
905b4d |
DEBUG(SSSDBG_CRIT_FAILURE, "Could not exec LDAP child: [%d][%s].\n",
|
|
|
905b4d |
err, strerror(err));
|
|
|
905b4d |
return err;
|
|
|
905b4d |
diff --git a/src/tests/cmocka/test_child.c b/src/tests/cmocka/test_child.c
|
|
|
905b4d |
index a857afce1fe7c4f3949fe77fe4e0a24e15961a4f..0bb50a4e005a26b1fbd332b17558d1284de77ea1 100644
|
|
|
905b4d |
--- a/src/tests/cmocka/test_child.c
|
|
|
905b4d |
+++ b/src/tests/cmocka/test_child.c
|
|
|
905b4d |
@@ -35,13 +35,9 @@ int main(int argc, const char *argv[])
|
|
|
905b4d |
int opt;
|
|
|
905b4d |
int debug_fd = -1;
|
|
|
905b4d |
poptContext pc;
|
|
|
905b4d |
- const char *action;
|
|
|
905b4d |
- ssize_t len = 0;
|
|
|
905b4d |
- ssize_t written;
|
|
|
905b4d |
- errno_t ret;
|
|
|
905b4d |
- uint8_t *buf[IN_BUF_SIZE];
|
|
|
905b4d |
- uid_t uid;
|
|
|
905b4d |
- gid_t gid;
|
|
|
905b4d |
+ const char *action = NULL;
|
|
|
905b4d |
+ const char *guitar;
|
|
|
905b4d |
+ const char *drums;
|
|
|
905b4d |
|
|
|
905b4d |
struct poptOption long_options[] = {
|
|
|
905b4d |
POPT_AUTOHELP
|
|
|
905b4d |
@@ -54,8 +50,9 @@ int main(int argc, const char *argv[])
|
|
|
905b4d |
{"debug-fd", 0, POPT_ARG_INT, &debug_fd, 0,
|
|
|
905b4d |
_("An open file descriptor for the debug logs"), NULL},
|
|
|
905b4d |
{"debug-to-stderr", 0, POPT_ARG_NONE | POPT_ARGFLAG_DOC_HIDDEN, &debug_to_stderr, 0, \
|
|
|
905b4d |
- _("Send the debug output to stderr directly."), NULL }, \
|
|
|
905b4d |
- SSSD_SERVER_OPTS(uid, gid)
|
|
|
905b4d |
+ _("Send the debug output to stderr directly."), NULL },
|
|
|
905b4d |
+ {"guitar", 0, POPT_ARG_STRING, &guitar, 0, _("Who plays guitar"), NULL },
|
|
|
905b4d |
+ {"drums", 0, POPT_ARG_STRING, &drums, 0, _("Who plays drums"), NULL },
|
|
|
905b4d |
POPT_TABLEEND
|
|
|
905b4d |
};
|
|
|
905b4d |
|
|
|
905b4d |
@@ -73,11 +70,17 @@ int main(int argc, const char *argv[])
|
|
|
905b4d |
}
|
|
|
905b4d |
}
|
|
|
905b4d |
|
|
|
905b4d |
+ action = getenv("TEST_CHILD_ACTION");
|
|
|
905b4d |
+ if (action) {
|
|
|
905b4d |
+ if (strcasecmp(action, "check_extra_args") == 0) {
|
|
|
905b4d |
+ if (!(strcmp(guitar, "george") == 0 \
|
|
|
905b4d |
+ && strcmp(drums, "ringo") == 0)) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE, "This band sounds weird\n");
|
|
|
905b4d |
+ _exit(1);
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
DEBUG(SSSDBG_TRACE_FUNC, "test_child completed successfully\n");
|
|
|
905b4d |
_exit(0);
|
|
|
905b4d |
-
|
|
|
905b4d |
-fail:
|
|
|
905b4d |
- DEBUG(SSSDBG_TRACE_FUNC, "test_child completed successfully\n");
|
|
|
905b4d |
- close(STDOUT_FILENO);
|
|
|
905b4d |
- _exit(-1);
|
|
|
905b4d |
}
|
|
|
905b4d |
diff --git a/src/tests/cmocka/test_child_common.c b/src/tests/cmocka/test_child_common.c
|
|
|
905b4d |
index f2cd8c0081c2e85432db1c9696102780dc990e75..112ed0ad97294bc45eac7c2124155e6b1908ad92 100644
|
|
|
905b4d |
--- a/src/tests/cmocka/test_child_common.c
|
|
|
905b4d |
+++ b/src/tests/cmocka/test_child_common.c
|
|
|
905b4d |
@@ -89,7 +89,49 @@ void test_exec_child(void **state)
|
|
|
905b4d |
ret = exec_child(child_tctx,
|
|
|
905b4d |
child_tctx->pipefd_to_child,
|
|
|
905b4d |
child_tctx->pipefd_from_child,
|
|
|
905b4d |
- CHILD_DIR"/"TEST_BIN, 2);
|
|
|
905b4d |
+ CHILD_DIR"/"TEST_BIN, 2, NULL);
|
|
|
905b4d |
+ assert_int_equal(ret, EOK);
|
|
|
905b4d |
+ } else {
|
|
|
905b4d |
+ do {
|
|
|
905b4d |
+ errno = 0;
|
|
|
905b4d |
+ ret = waitpid(child_pid, &status, 0);
|
|
|
905b4d |
+ } while (ret == -1 && errno == EINTR);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ if (ret > 0) {
|
|
|
905b4d |
+ ret = EIO;
|
|
|
905b4d |
+ if (WIFEXITED(status)) {
|
|
|
905b4d |
+ ret = WEXITSTATUS(status);
|
|
|
905b4d |
+ assert_int_equal(ret, 0);
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ } else {
|
|
|
905b4d |
+ DEBUG(SSSDBG_FUNC_DATA,
|
|
|
905b4d |
+ "Failed to wait for children %d\n", child_pid);
|
|
|
905b4d |
+ ret = EIO;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+}
|
|
|
905b4d |
+
|
|
|
905b4d |
+/* Just make sure the exec works. The child does nothing but exits */
|
|
|
905b4d |
+void test_exec_child_extra_args(void **state)
|
|
|
905b4d |
+{
|
|
|
905b4d |
+ errno_t ret;
|
|
|
905b4d |
+ pid_t child_pid;
|
|
|
905b4d |
+ int status;
|
|
|
905b4d |
+ struct child_test_ctx *child_tctx = talloc_get_type(*state,
|
|
|
905b4d |
+ struct child_test_ctx);
|
|
|
905b4d |
+ const char *extra_args[] = { "--guitar=george",
|
|
|
905b4d |
+ "--drums=ringo",
|
|
|
905b4d |
+ NULL };
|
|
|
905b4d |
+
|
|
|
905b4d |
+ setenv("TEST_CHILD_ACTION", "check_extra_args", 1);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ child_pid = fork();
|
|
|
905b4d |
+ assert_int_not_equal(child_pid, -1);
|
|
|
905b4d |
+ if (child_pid == 0) {
|
|
|
905b4d |
+ ret = exec_child(child_tctx,
|
|
|
905b4d |
+ child_tctx->pipefd_to_child,
|
|
|
905b4d |
+ child_tctx->pipefd_from_child,
|
|
|
905b4d |
+ CHILD_DIR"/"TEST_BIN, 2, extra_args);
|
|
|
905b4d |
assert_int_equal(ret, EOK);
|
|
|
905b4d |
} else {
|
|
|
905b4d |
do {
|
|
|
905b4d |
@@ -126,6 +168,9 @@ int main(int argc, const char *argv[])
|
|
|
905b4d |
unit_test_setup_teardown(test_exec_child,
|
|
|
905b4d |
child_test_setup,
|
|
|
905b4d |
child_test_teardown),
|
|
|
905b4d |
+ unit_test_setup_teardown(test_exec_child_extra_args,
|
|
|
905b4d |
+ child_test_setup,
|
|
|
905b4d |
+ child_test_teardown),
|
|
|
905b4d |
};
|
|
|
905b4d |
|
|
|
905b4d |
/* Set debug level to invalid value so we can deside if -d 0 was used. */
|
|
|
905b4d |
diff --git a/src/util/child_common.c b/src/util/child_common.c
|
|
|
905b4d |
index cc6a8fa758bfa6efa511c28cd9121e759b590342..9710630f9773ae02258e4f0dd609a3d74978c8f4 100644
|
|
|
905b4d |
--- a/src/util/child_common.c
|
|
|
905b4d |
+++ b/src/util/child_common.c
|
|
|
905b4d |
@@ -623,6 +623,7 @@ static void child_invoke_callback(struct tevent_context *ev,
|
|
|
905b4d |
static errno_t prepare_child_argv(TALLOC_CTX *mem_ctx,
|
|
|
905b4d |
int child_debug_fd,
|
|
|
905b4d |
const char *binary,
|
|
|
905b4d |
+ const char *extra_argv[],
|
|
|
905b4d |
char ***_argv)
|
|
|
905b4d |
{
|
|
|
905b4d |
/*
|
|
|
905b4d |
@@ -632,6 +633,7 @@ static errno_t prepare_child_argv(TALLOC_CTX *mem_ctx,
|
|
|
905b4d |
uint_t argc = 5;
|
|
|
905b4d |
char ** argv;
|
|
|
905b4d |
errno_t ret = EINVAL;
|
|
|
905b4d |
+ size_t i;
|
|
|
905b4d |
|
|
|
905b4d |
/* Save the current state in case an interrupt changes it */
|
|
|
905b4d |
bool child_debug_to_file = debug_to_file;
|
|
|
905b4d |
@@ -642,6 +644,10 @@ static errno_t prepare_child_argv(TALLOC_CTX *mem_ctx,
|
|
|
905b4d |
if (child_debug_to_file) argc++;
|
|
|
905b4d |
if (child_debug_stderr) argc++;
|
|
|
905b4d |
|
|
|
905b4d |
+ if (extra_argv) {
|
|
|
905b4d |
+ for (i = 0; extra_argv[i]; i++) argc++;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
/*
|
|
|
905b4d |
* program name, debug_level, debug_to_file, debug_timestamps,
|
|
|
905b4d |
* debug_microseconds and NULL
|
|
|
905b4d |
@@ -654,6 +660,17 @@ static errno_t prepare_child_argv(TALLOC_CTX *mem_ctx,
|
|
|
905b4d |
|
|
|
905b4d |
argv[--argc] = NULL;
|
|
|
905b4d |
|
|
|
905b4d |
+ /* Add extra_attrs first */
|
|
|
905b4d |
+ if (extra_argv) {
|
|
|
905b4d |
+ for (i = 0; extra_argv[i]; i++) {
|
|
|
905b4d |
+ argv[--argc] = talloc_strdup(argv, extra_argv[i]);
|
|
|
905b4d |
+ if (argv[argc] == NULL) {
|
|
|
905b4d |
+ ret = ENOMEM;
|
|
|
905b4d |
+ goto fail;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
argv[--argc] = talloc_asprintf(argv, "--debug-level=%#.4x",
|
|
|
905b4d |
debug_level);
|
|
|
905b4d |
if (argv[argc] == NULL) {
|
|
|
905b4d |
@@ -714,7 +731,8 @@ fail:
|
|
|
905b4d |
|
|
|
905b4d |
errno_t exec_child(TALLOC_CTX *mem_ctx,
|
|
|
905b4d |
int *pipefd_to_child, int *pipefd_from_child,
|
|
|
905b4d |
- const char *binary, int debug_fd)
|
|
|
905b4d |
+ const char *binary, int debug_fd,
|
|
|
905b4d |
+ const char *extra_argv[])
|
|
|
905b4d |
{
|
|
|
905b4d |
int ret;
|
|
|
905b4d |
errno_t err;
|
|
|
905b4d |
@@ -739,7 +757,8 @@ errno_t exec_child(TALLOC_CTX *mem_ctx,
|
|
|
905b4d |
}
|
|
|
905b4d |
|
|
|
905b4d |
ret = prepare_child_argv(mem_ctx, debug_fd,
|
|
|
905b4d |
- binary, &argv);
|
|
|
905b4d |
+ binary, extra_argv,
|
|
|
905b4d |
+ &argv);
|
|
|
905b4d |
if (ret != EOK) {
|
|
|
905b4d |
DEBUG(SSSDBG_CRIT_FAILURE, "prepare_child_argv.\n");
|
|
|
905b4d |
return ret;
|
|
|
905b4d |
diff --git a/src/util/child_common.h b/src/util/child_common.h
|
|
|
905b4d |
index e159719a2fca70a4ea044d79530a0d21cb3577e8..e659388ece3677b7746c159d7de3e86171bb4146 100644
|
|
|
905b4d |
--- a/src/util/child_common.h
|
|
|
905b4d |
+++ b/src/util/child_common.h
|
|
|
905b4d |
@@ -114,7 +114,8 @@ void child_sig_handler(struct tevent_context *ev,
|
|
|
905b4d |
/* Never returns EOK, ether returns an error, or doesn't return on success */
|
|
|
905b4d |
errno_t exec_child(TALLOC_CTX *mem_ctx,
|
|
|
905b4d |
int *pipefd_to_child, int *pipefd_from_child,
|
|
|
905b4d |
- const char *binary, int debug_fd);
|
|
|
905b4d |
+ const char *binary, int debug_fd,
|
|
|
905b4d |
+ const char *extra_argv[]);
|
|
|
905b4d |
|
|
|
905b4d |
void child_cleanup(int readfd, int writefd);
|
|
|
905b4d |
|
|
|
905b4d |
--
|
|
|
905b4d |
1.9.3
|
|
|
905b4d |
|