sssd  2.2.3
About: SSSD provides a set of daemons to manage access to remote directories and authentication mechanisms such as LDAP, Kerberos or FreeIPA. It provides also an NSS and PAM interface toward the system.
  Fossies Dox: sssd-2.2.3.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

child_common.c
Go to the documentation of this file.
1 /*
2  SSSD
3 
4  Common helper functions to be used in child processes
5 
6  Authors:
7  Sumit Bose <sbose@redhat.com>
8 
9  Copyright (C) 2009 Red Hat
10 
11  This program is free software; you can redistribute it and/or modify
12  it under the terms of the GNU General Public License as published by
13  the Free Software Foundation; either version 3 of the License, or
14  (at your option) any later version.
15 
16  This program is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with this program. If not, see <http://www.gnu.org/licenses/>.
23 */
24 
25 #include <sys/types.h>
26 #include <fcntl.h>
27 #include <signal.h>
28 #include <tevent.h>
29 #include <sys/wait.h>
30 #include <errno.h>
31 
32 #include "util/util.h"
33 #include "util/find_uid.h"
34 #include "db/sysdb.h"
35 #include "util/child_common.h"
36 
38  struct tevent_context *ev;
39  hash_table_t *children;
40  int options;
41 };
42 
43 struct sss_child_ctx {
44  pid_t pid;
46  void *pvt;
48 };
49 
50 static void sss_child_handler(struct tevent_context *ev,
51  struct tevent_signal *se,
52  int signum,
53  int count,
54  void *siginfo,
55  void *private_data);
56 
57 errno_t sss_sigchld_init(TALLOC_CTX *mem_ctx,
58  struct tevent_context *ev,
59  struct sss_sigchild_ctx **child_ctx)
60 {
61  errno_t ret;
62  struct sss_sigchild_ctx *sigchld_ctx;
63  struct tevent_signal *tes;
64 
65  sigchld_ctx = talloc_zero(mem_ctx, struct sss_sigchild_ctx);
66  if (!sigchld_ctx) {
68  "fatal error initializing sss_sigchild_ctx\n");
69  return ENOMEM;
70  }
71  sigchld_ctx->ev = ev;
72 
73  ret = sss_hash_create(sigchld_ctx, 10, &sigchld_ctx->children);
74  if (ret != EOK) {
76  "fatal error initializing children hash table: [%s]\n",
77  strerror(ret));
78  talloc_free(sigchld_ctx);
79  return ret;
80  }
81 
82  BlockSignals(false, SIGCHLD);
83  tes = tevent_add_signal(ev, sigchld_ctx, SIGCHLD, SA_SIGINFO,
84  sss_child_handler, sigchld_ctx);
85  if (tes == NULL) {
86  talloc_free(sigchld_ctx);
87  return EIO;
88  }
89 
90  *child_ctx = sigchld_ctx;
91  return EOK;
92 }
93 
94 static int sss_child_destructor(void *ptr)
95 {
96  struct sss_child_ctx *child_ctx;
97  hash_key_t key;
98  int error;
99 
100  child_ctx = talloc_get_type(ptr, struct sss_child_ctx);
101  key.type = HASH_KEY_ULONG;
102  key.ul = child_ctx->pid;
103 
104  error = hash_delete(child_ctx->sigchld_ctx->children, &key);
105  if (error != HASH_SUCCESS && error != HASH_ERROR_KEY_NOT_FOUND) {
107  "failed to delete child_ctx from hash table [%d]: %s\n",
108  error, hash_error_string(error));
109  }
110 
111  return 0;
112 }
113 
114 errno_t sss_child_register(TALLOC_CTX *mem_ctx,
116  pid_t pid,
118  void *pvt,
119  struct sss_child_ctx **child_ctx)
120 {
121  struct sss_child_ctx *child;
122  hash_key_t key;
123  hash_value_t value;
124  int error;
125 
126  child = talloc_zero(mem_ctx, struct sss_child_ctx);
127  if (child == NULL) {
128  return ENOMEM;
129  }
130 
131  child->pid = pid;
132  child->cb = cb;
133  child->pvt = pvt;
134  child->sigchld_ctx = sigchld_ctx;
135 
136  key.type = HASH_KEY_ULONG;
137  key.ul = pid;
138 
139  value.type = HASH_VALUE_PTR;
140  value.ptr = child;
141 
142  error = hash_enter(sigchld_ctx->children, &key, &value);
143  if (error != HASH_SUCCESS) {
144  talloc_free(child);
145  return ENOMEM;
146  }
147 
148  talloc_set_destructor((TALLOC_CTX *) child, sss_child_destructor);
149 
150  *child_ctx = child;
151  return EOK;
152 }
153 
157 };
158 
159 static void sss_child_invoke_cb(struct tevent_context *ev,
160  struct tevent_immediate *imm,
161  void *pvt)
162 {
163  struct sss_child_cb_pvt *cb_pvt;
164  struct sss_child_ctx *child_ctx;
165  hash_key_t key;
166  int error;
167 
168  cb_pvt = talloc_get_type(pvt, struct sss_child_cb_pvt);
169  child_ctx = cb_pvt->child_ctx;
170 
171  key.type = HASH_KEY_ULONG;
172  key.ul = child_ctx->pid;
173 
174  error = hash_delete(child_ctx->sigchld_ctx->children, &key);
175  if (error != HASH_SUCCESS && error != HASH_ERROR_KEY_NOT_FOUND) {
177  "failed to delete child_ctx from hash table [%d]: %s\n",
178  error, hash_error_string(error));
179  }
180 
181  if (child_ctx->cb) {
182  child_ctx->cb(child_ctx->pid, cb_pvt->wait_status, child_ctx->pvt);
183  }
184 
185  talloc_free(imm);
186 }
187 
188 static void sss_child_handler(struct tevent_context *ev,
189  struct tevent_signal *se,
190  int signum,
191  int count,
192  void *siginfo,
193  void *private_data)
194 {
195  struct sss_sigchild_ctx *sigchld_ctx;
196  struct tevent_immediate *imm;
197  struct sss_child_cb_pvt *invoke_pvt;
198  struct sss_child_ctx *child_ctx;
199  hash_key_t key;
200  hash_value_t value;
201  int error;
202  int wait_status;
203  pid_t pid;
204 
205  sigchld_ctx = talloc_get_type(private_data, struct sss_sigchild_ctx);
206  key.type = HASH_KEY_ULONG;
207 
208  do {
209  do {
210  errno = 0;
211  pid = waitpid(-1, &wait_status, WNOHANG | sigchld_ctx->options);
212  } while (pid == -1 && errno == EINTR);
213 
214  if (pid == -1) {
216  "waitpid failed [%d]: %s\n", errno, strerror(errno));
217  return;
218  } else if (pid == 0) continue;
219 
220  key.ul = pid;
221  error = hash_lookup(sigchld_ctx->children, &key, &value);
222  if (error == HASH_SUCCESS) {
223  child_ctx = talloc_get_type(value.ptr, struct sss_child_ctx);
224 
225  imm = tevent_create_immediate(child_ctx);
226  if (imm == NULL) {
228  "Out of memory invoking SIGCHLD callback\n");
229  return;
230  }
231 
232  invoke_pvt = talloc_zero(child_ctx, struct sss_child_cb_pvt);
233  if (invoke_pvt == NULL) {
235  "out of memory invoking SIGCHLD callback\n");
236  return;
237  }
238  invoke_pvt->child_ctx = child_ctx;
239  invoke_pvt->wait_status = wait_status;
240 
241  tevent_schedule_immediate(imm, sigchld_ctx->ev,
242  sss_child_invoke_cb, invoke_pvt);
243  } else if (error == HASH_ERROR_KEY_NOT_FOUND) {
245  "BUG: waitpid() returned [%d] but it was not in the table. "
246  "This could be due to a linked library creating processes "
247  "without registering them with the sigchld handler\n",
248  pid);
249  /* We will simply ignore this and return to the loop
250  * This will prevent a zombie, but may cause unexpected
251  * behavior in the code that was trying to handle this
252  * pid.
253  */
254  } else {
256  "SIGCHLD hash table error [%d]: %s\n",
257  error, hash_error_string(error));
258  /* This is bad, but we should try to check for other
259  * children anyway, to avoid potential zombies.
260  */
261  }
262  } while (pid != 0);
263 }
264 
266  struct tevent_signal *sige;
267  pid_t pid;
270  void *pvt;
271 };
272 
273 static void child_sig_handler(struct tevent_context *ev,
274  struct tevent_signal *sige, int signum,
275  int count, void *__siginfo, void *pvt);
276 
277 int child_handler_setup(struct tevent_context *ev, int pid,
278  sss_child_callback_t cb, void *pvt,
279  struct sss_child_ctx_old **_child_ctx)
280 {
281  struct sss_child_ctx_old *child_ctx;
282 
284  "Setting up signal handler up for pid [%d]\n", pid);
285 
286  child_ctx = talloc_zero(ev, struct sss_child_ctx_old);
287  if (child_ctx == NULL) {
288  return ENOMEM;
289  }
290 
291  child_ctx->sige = tevent_add_signal(ev, child_ctx, SIGCHLD, SA_SIGINFO,
292  child_sig_handler, child_ctx);
293  if(!child_ctx->sige) {
294  /* Error setting up signal handler */
295  talloc_free(child_ctx);
296  return ENOMEM;
297  }
298 
299  child_ctx->pid = pid;
300  child_ctx->cb = cb;
301  child_ctx->pvt = pvt;
302 
303  DEBUG(SSSDBG_TRACE_INTERNAL, "Signal handler set up for pid [%d]\n", pid);
304 
305  if (_child_ctx != NULL) {
306  *_child_ctx = child_ctx;
307  }
308 
309  return EOK;
310 }
311 
313 {
314  errno_t ret;
315 
316  /* We still want to wait for the child to finish, but the caller is not
317  * interested in the result anymore (e.g. timeout was reached). */
318  ctx->cb = NULL;
319  ctx->pvt = NULL;
320 
321  ret = kill(ctx->pid, SIGKILL);
322  if (ret == -1) {
323  ret = errno;
324  DEBUG(SSSDBG_MINOR_FAILURE, "kill failed [%d][%s].\n", ret, strerror(ret));
325  }
326 }
327 
328 /* Async communication with the child process via a pipe */
329 
331  int fd;
332  uint8_t *buf;
333  size_t len;
334  ssize_t written;
335 };
336 
337 static void write_pipe_handler(struct tevent_context *ev,
338  struct tevent_fd *fde,
339  uint16_t flags, void *pvt);
340 
341 struct tevent_req *write_pipe_send(TALLOC_CTX *mem_ctx,
342  struct tevent_context *ev,
343  uint8_t *buf, size_t len, int fd)
344 {
345  struct tevent_req *req;
346  struct write_pipe_state *state;
347  struct tevent_fd *fde;
348 
349  req = tevent_req_create(mem_ctx, &state, struct write_pipe_state);
350  if (req == NULL) return NULL;
351 
352  state->fd = fd;
353  state->buf = buf;
354  state->len = len;
355  state->written = 0;
356 
357  fde = tevent_add_fd(ev, state, fd, TEVENT_FD_WRITE,
358  write_pipe_handler, req);
359  if (fde == NULL) {
360  DEBUG(SSSDBG_CRIT_FAILURE, "tevent_add_fd failed.\n");
361  goto fail;
362  }
363 
364  return req;
365 
366 fail:
367  talloc_zfree(req);
368  return NULL;
369 }
370 
371 static void write_pipe_handler(struct tevent_context *ev,
372  struct tevent_fd *fde,
373  uint16_t flags, void *pvt)
374 {
375  struct tevent_req *req = talloc_get_type(pvt, struct tevent_req);
376  struct write_pipe_state *state = tevent_req_data(req,
377  struct write_pipe_state);
378  errno_t ret;
379 
380  if (flags & TEVENT_FD_READ) {
382  "write_pipe_done called with TEVENT_FD_READ,"
383  " this should not happen.\n");
384  tevent_req_error(req, EINVAL);
385  return;
386  }
387 
388  errno = 0;
389  state->written = sss_atomic_write_s(state->fd, state->buf, state->len);
390  if (state->written == -1) {
391  ret = errno;
393  "write failed [%d][%s].\n", ret, strerror(ret));
394  tevent_req_error(req, ret);
395  return;
396  }
397 
398  if (state->len != state->written) {
399  DEBUG(SSSDBG_CRIT_FAILURE, "Wrote %zd bytes, expected %zu\n",
400  state->written, state->len);
401  tevent_req_error(req, EIO);
402  return;
403  }
404 
405  DEBUG(SSSDBG_TRACE_FUNC, "All data has been sent!\n");
406  tevent_req_done(req);
407  return;
408 }
409 
410 int write_pipe_recv(struct tevent_req *req)
411 {
413 
414  return EOK;
415 }
416 
418  int fd;
419  uint8_t *buf;
420  size_t len;
421 };
422 
423 static void read_pipe_handler(struct tevent_context *ev,
424  struct tevent_fd *fde,
425  uint16_t flags, void *pvt);
426 
427 struct tevent_req *read_pipe_send(TALLOC_CTX *mem_ctx,
428  struct tevent_context *ev, int fd)
429 {
430  struct tevent_req *req;
431  struct read_pipe_state *state;
432  struct tevent_fd *fde;
433 
434  req = tevent_req_create(mem_ctx, &state, struct read_pipe_state);
435  if (req == NULL) return NULL;
436 
437  state->fd = fd;
438  state->buf = NULL;
439  state->len = 0;
440 
441  fde = tevent_add_fd(ev, state, fd, TEVENT_FD_READ,
442  read_pipe_handler, req);
443  if (fde == NULL) {
444  DEBUG(SSSDBG_CRIT_FAILURE, "tevent_add_fd failed.\n");
445  goto fail;
446  }
447 
448  return req;
449 
450 fail:
451  talloc_zfree(req);
452  return NULL;
453 }
454 
455 static void read_pipe_handler(struct tevent_context *ev,
456  struct tevent_fd *fde,
457  uint16_t flags, void *pvt)
458 {
459  struct tevent_req *req = talloc_get_type(pvt, struct tevent_req);
460  struct read_pipe_state *state = tevent_req_data(req,
461  struct read_pipe_state);
462  ssize_t size;
463  errno_t err;
464  uint8_t buf[CHILD_MSG_CHUNK];
465 
466  if (flags & TEVENT_FD_WRITE) {
467  DEBUG(SSSDBG_CRIT_FAILURE, "read_pipe_done called with TEVENT_FD_WRITE,"
468  " this should not happen.\n");
469  tevent_req_error(req, EINVAL);
470  return;
471  }
472 
473  size = sss_atomic_read_s(state->fd,
474  buf,
476  if (size == -1) {
477  err = errno;
479  "read failed [%d][%s].\n", err, strerror(err));
480  tevent_req_error(req, err);
481  return;
482 
483  } else if (size > 0) {
484  state->buf = talloc_realloc(state, state->buf, uint8_t,
485  state->len + size);
486  if(!state->buf) {
487  tevent_req_error(req, ENOMEM);
488  return;
489  }
490 
491  safealign_memcpy(&state->buf[state->len], buf,
492  size, &state->len);
493  return;
494 
495  } else if (size == 0) {
496  DEBUG(SSSDBG_TRACE_FUNC, "EOF received, client finished\n");
497  tevent_req_done(req);
498  return;
499 
500  } else {
502  "unexpected return value of read [%zd].\n", size);
503  tevent_req_error(req, EINVAL);
504  return;
505  }
506 }
507 
508 int read_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
509  uint8_t **buf, ssize_t *len)
510 {
511  struct read_pipe_state *state;
512  state = tevent_req_data(req, struct read_pipe_state);
513 
515 
516  *buf = talloc_steal(mem_ctx, state->buf);
517  *len = state->len;
518 
519  return EOK;
520 }
521 
522 static void child_invoke_callback(struct tevent_context *ev,
523  struct tevent_immediate *imm,
524  void *pvt);
525 static void child_sig_handler(struct tevent_context *ev,
526  struct tevent_signal *sige, int signum,
527  int count, void *__siginfo, void *pvt)
528 {
529  int ret, err;
530  struct sss_child_ctx_old *child_ctx;
531  struct tevent_immediate *imm;
532 
533  if (count <= 0) {
535  "SIGCHLD handler called with invalid child count\n");
536  return;
537  }
538 
539  child_ctx = talloc_get_type(pvt, struct sss_child_ctx_old);
540  DEBUG(SSSDBG_TRACE_LIBS, "Waiting for child [%d].\n", child_ctx->pid);
541 
542  errno = 0;
543  ret = waitpid(child_ctx->pid, &child_ctx->child_status, WNOHANG);
544 
545  if (ret == -1) {
546  err = errno;
548  "waitpid failed [%d][%s].\n", err, strerror(err));
549  } else if (ret == 0) {
551  "waitpid did not found a child with changed status.\n");
552  } else {
553  if (WIFEXITED(child_ctx->child_status)) {
554  if (WEXITSTATUS(child_ctx->child_status) != 0) {
556  "child [%d] failed with status [%d].\n", ret,
557  WEXITSTATUS(child_ctx->child_status));
558  } else {
560  "child [%d] finished successfully.\n", ret);
561  }
562  } else if (WIFSIGNALED(child_ctx->child_status)) {
564  "child [%d] was terminated by signal [%d].\n", ret,
565  WTERMSIG(child_ctx->child_status));
566  } else {
567  if (WIFSTOPPED(child_ctx->child_status)) {
569  "child [%d] was stopped by signal [%d].\n", ret,
570  WSTOPSIG(child_ctx->child_status));
571  }
572  if (WIFCONTINUED(child_ctx->child_status) == true) {
574  "child [%d] was resumed by delivery of SIGCONT.\n",
575  ret);
576  }
577 
578  return;
579  }
580 
581  /* Invoke the callback in a tevent_immediate handler
582  * so that it is safe to free the tevent_signal *
583  */
584  imm = tevent_create_immediate(child_ctx);
585  if (imm == NULL) {
587  "Out of memory invoking sig handler callback\n");
588  return;
589  }
590 
591  tevent_schedule_immediate(imm, ev, child_invoke_callback,
592  child_ctx);
593  }
594 
595  return;
596 }
597 
598 static void child_invoke_callback(struct tevent_context *ev,
599  struct tevent_immediate *imm,
600  void *pvt)
601 {
602  struct sss_child_ctx_old *child_ctx =
603  talloc_get_type(pvt, struct sss_child_ctx_old);
604  if (child_ctx->cb) {
605  child_ctx->cb(child_ctx->child_status, child_ctx->sige, child_ctx->pvt);
606  }
607 
608  /* Stop monitoring for this child */
609  talloc_free(child_ctx);
610 }
611 
612 static errno_t prepare_child_argv(TALLOC_CTX *mem_ctx,
613  int child_debug_fd,
614  const char *binary,
615  const char *extra_argv[],
616  bool extra_args_only,
617  char ***_argv)
618 {
619  /*
620  * program name, debug_level, debug_timestamps,
621  * debug_microseconds and NULL
622  */
623  uint_t argc = 5;
624  char ** argv = NULL;
625  errno_t ret = EINVAL;
626  size_t i;
627 
628  if (extra_args_only) {
629  argc = 2; /* program name and NULL */
630  }
631 
632  /* Save the current state in case an interrupt changes it */
633  bool child_debug_timestamps = debug_timestamps;
634  bool child_debug_microseconds = debug_microseconds;
635 
636  if (!extra_args_only) {
637  argc++;
638  }
639 
640  if (extra_argv) {
641  for (i = 0; extra_argv[i]; i++) argc++;
642  }
643 
644  /*
645  * program name, debug_level, debug_to_file, debug_timestamps,
646  * debug_microseconds and NULL
647  */
648  argv = talloc_array(mem_ctx, char *, argc);
649  if (argv == NULL) {
650  DEBUG(SSSDBG_CRIT_FAILURE, "talloc_array failed.\n");
651  return ENOMEM;
652  }
653 
654  argv[--argc] = NULL;
655 
656  /* Add extra_attrs first */
657  if (extra_argv) {
658  for (i = 0; extra_argv[i]; i++) {
659  argv[--argc] = talloc_strdup(argv, extra_argv[i]);
660  if (argv[argc] == NULL) {
661  ret = ENOMEM;
662  goto fail;
663  }
664  }
665  }
666 
667  if (!extra_args_only) {
668  argv[--argc] = talloc_asprintf(argv, "--debug-level=%#.4x",
669  debug_level);
670  if (argv[argc] == NULL) {
671  ret = ENOMEM;
672  goto fail;
673  }
674 
675  if (sss_logger == FILES_LOGGER) {
676  argv[--argc] = talloc_asprintf(argv, "--debug-fd=%d",
677  child_debug_fd);
678  if (argv[argc] == NULL) {
679  ret = ENOMEM;
680  goto fail;
681  }
682  } else {
683  argv[--argc] = talloc_asprintf(argv, "--logger=%s",
685  if (argv[argc] == NULL) {
686  ret = ENOMEM;
687  goto fail;
688  }
689  }
690 
691  argv[--argc] = talloc_asprintf(argv, "--debug-timestamps=%d",
692  child_debug_timestamps);
693  if (argv[argc] == NULL) {
694  ret = ENOMEM;
695  goto fail;
696  }
697 
698  argv[--argc] = talloc_asprintf(argv, "--debug-microseconds=%d",
699  child_debug_microseconds);
700  if (argv[argc] == NULL) {
701  ret = ENOMEM;
702  goto fail;
703  }
704  }
705 
706  argv[--argc] = talloc_strdup(argv, binary);
707  if (argv[argc] == NULL) {
708  ret = ENOMEM;
709  goto fail;
710  }
711 
712  if (argc != 0) {
713  ret = EINVAL;
714  goto fail;
715  }
716 
717  *_argv = argv;
718 
719  return EOK;
720 
721 fail:
722  talloc_free(argv);
723  return ret;
724 }
725 
726 void exec_child_ex(TALLOC_CTX *mem_ctx,
727  int *pipefd_to_child, int *pipefd_from_child,
728  const char *binary, int debug_fd,
729  const char *extra_argv[], bool extra_args_only,
730  int child_in_fd, int child_out_fd)
731 {
732  int ret;
733  errno_t err;
734  char **argv;
735 
736  close(pipefd_to_child[1]);
737  ret = dup2(pipefd_to_child[0], child_in_fd);
738  if (ret == -1) {
739  err = errno;
741  "dup2 failed [%d][%s].\n", err, strerror(err));
742  exit(EXIT_FAILURE);
743  }
744 
745  close(pipefd_from_child[0]);
746  ret = dup2(pipefd_from_child[1], child_out_fd);
747  if (ret == -1) {
748  err = errno;
750  "dup2 failed [%d][%s].\n", err, strerror(err));
751  exit(EXIT_FAILURE);
752  }
753 
754  ret = prepare_child_argv(mem_ctx, debug_fd,
755  binary, extra_argv, extra_args_only,
756  &argv);
757  if (ret != EOK) {
758  DEBUG(SSSDBG_CRIT_FAILURE, "prepare_child_argv.\n");
759  exit(EXIT_FAILURE);
760  }
761 
762  execv(binary, argv);
763  err = errno;
764  DEBUG(SSSDBG_OP_FAILURE, "execv failed [%d][%s].\n", err, strerror(err));
765  exit(EXIT_FAILURE);
766 }
767 
768 void exec_child(TALLOC_CTX *mem_ctx,
769  int *pipefd_to_child, int *pipefd_from_child,
770  const char *binary, int debug_fd)
771 {
772  exec_child_ex(mem_ctx, pipefd_to_child, pipefd_from_child,
773  binary, debug_fd, NULL, false,
774  STDIN_FILENO, STDOUT_FILENO);
775 }
776 
777 int child_io_destructor(void *ptr)
778 {
779  int ret;
780  struct child_io_fds *io = talloc_get_type(ptr, struct child_io_fds);
781  if (io == NULL) return EOK;
782 
783  if (io->write_to_child_fd != -1) {
784  ret = close(io->write_to_child_fd);
785  io->write_to_child_fd = -1;
786  if (ret != EOK) {
787  ret = errno;
789  "close failed [%d][%s].\n", ret, strerror(ret));
790  }
791  }
792 
793  if (io->read_from_child_fd != -1) {
794  ret = close(io->read_from_child_fd);
795  io->read_from_child_fd = -1;
796  if (ret != EOK) {
797  ret = errno;
799  "close failed [%d][%s].\n", ret, strerror(ret));
800  }
801  }
802 
803  return EOK;
804 }
805 
806 errno_t child_debug_init(const char *logfile, int *debug_fd)
807 {
808  int ret;
809  FILE *debug_filep;
810 
811  if (debug_fd == NULL) {
812  return EOK;
813  }
814 
815  if (sss_logger == FILES_LOGGER && *debug_fd == -1) {
816  ret = open_debug_file_ex(logfile, &debug_filep, false);
817  if (ret != EOK) {
818  DEBUG(SSSDBG_FATAL_FAILURE, "Error setting up logging (%d) [%s]\n",
819  ret, sss_strerror(ret));
820  return ret;
821  }
822 
823  *debug_fd = fileno(debug_filep);
824  if (*debug_fd == -1) {
825  ret = errno;
827  "fileno failed [%d][%s]\n", ret, strerror(ret));
828  return ret;
829  }
830  }
831 
832  return EOK;
833 }
write_pipe_handler
static void write_pipe_handler(struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags, void *pvt)
Definition: child_common.c:371
sss_child_cb_pvt::child_ctx
struct sss_child_ctx * child_ctx
Definition: child_common.c:155
sss_strerror
const char * sss_strerror(errno_t error)
return a string describing the error number like strerror()
Definition: util_errors.c:150
read_pipe_state::len
size_t len
Definition: child_common.c:420
SSSDBG_TRACE_INTERNAL
#define SSSDBG_TRACE_INTERNAL
Definition: debug.h:82
EOK
#define EOK
Definition: hbac_evaluator.c:40
prepare_child_argv
static errno_t prepare_child_argv(TALLOC_CTX *mem_ctx, int child_debug_fd, const char *binary, const char *extra_argv[], bool extra_args_only, char ***_argv)
Definition: child_common.c:612
safealign_memcpy
static void safealign_memcpy(void *dest, const void *src, size_t n, size_t *counter)
Definition: safealign.h:48
sss_child_ctx::cb
sss_child_fn_t cb
Definition: child_common.c:45
sss_logger_str
const char * sss_logger_str[]
Definition: debug.c:50
child_io_fds::read_from_child_fd
int read_from_child_fd
Definition: child_common.h:52
find_uid.h
read_pipe_recv
int read_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, uint8_t **buf, ssize_t *len)
Definition: child_common.c:508
exec_child_ex
void exec_child_ex(TALLOC_CTX *mem_ctx, int *pipefd_to_child, int *pipefd_from_child, const char *binary, int debug_fd, const char *extra_argv[], bool extra_args_only, int child_in_fd, int child_out_fd)
Definition: child_common.c:726
child_io_fds::write_to_child_fd
int write_to_child_fd
Definition: child_common.h:53
sss_child_ctx
Definition: child_common.c:43
write_pipe_state::buf
uint8_t * buf
Definition: child_common.c:332
exec_child
void exec_child(TALLOC_CTX *mem_ctx, int *pipefd_to_child, int *pipefd_from_child, const char *binary, int debug_fd)
Definition: child_common.c:768
sss_child_invoke_cb
static void sss_child_invoke_cb(struct tevent_context *ev, struct tevent_immediate *imm, void *pvt)
Definition: child_common.c:159
read_pipe_state
Definition: child_common.c:417
read_pipe_handler
static void read_pipe_handler(struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags, void *pvt)
Definition: child_common.c:455
sss_child_ctx::pid
pid_t pid
Definition: child_common.c:44
DEBUG
#define DEBUG(level, format,...)
macro to generate debug messages
Definition: debug.h:123
sss_child_fn_t
void(* sss_child_fn_t)(int pid, int wait_status, void *pvt)
Definition: child_common.h:57
SSSDBG_TRACE_FUNC
#define SSSDBG_TRACE_FUNC
Definition: debug.h:80
child_handler_setup
int child_handler_setup(struct tevent_context *ev, int pid, sss_child_callback_t cb, void *pvt, struct sss_child_ctx_old **_child_ctx)
Definition: child_common.c:277
debug_level
int debug_level
Definition: sss_certmap.c:35
debug_microseconds
int debug_microseconds
Definition: debug.c:43
sss_child_cb_pvt
Definition: child_common.c:154
child_common.h
write_pipe_state::len
size_t len
Definition: child_common.c:333
errno_t
int errno_t
Definition: hbac_evaluator.c:36
BlockSignals
void BlockSignals(bool block, int signum)
Block sigs.
Definition: signal.c:35
sss_atomic_write_s
#define sss_atomic_write_s(fd, buf, n)
Definition: atomic_io.h:38
SSSDBG_FATAL_FAILURE
#define SSSDBG_FATAL_FAILURE
Definition: debug.h:74
sss_child_ctx_old::pvt
void * pvt
Definition: child_common.c:270
sss_child_destructor
static int sss_child_destructor(void *ptr)
Definition: child_common.c:94
sss_child_ctx_old::cb
sss_child_callback_t cb
Definition: child_common.c:269
read_pipe_send
struct tevent_req * read_pipe_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, int fd)
Definition: child_common.c:427
FILES_LOGGER
@ FILES_LOGGER
Definition: debug.h:38
sss_sigchild_ctx::children
hash_table_t * children
Definition: child_common.c:39
sss_child_ctx::pvt
void * pvt
Definition: child_common.c:46
sss_child_ctx_old::sige
struct tevent_signal * sige
Definition: child_common.c:266
sss_logger
enum sss_logger_t sss_logger
Definition: debug.c:46
child_io_fds
Definition: child_common.h:51
read_pipe_state::fd
int fd
Definition: child_common.c:418
write_pipe_recv
int write_pipe_recv(struct tevent_req *req)
Definition: child_common.c:410
SSSDBG_TRACE_LIBS
#define SSSDBG_TRACE_LIBS
Definition: debug.h:81
ctx
struct nss_ops_ctx * ctx
Definition: wbc_pwd_sssd.c:61
sss_sigchild_ctx
Definition: child_common.c:37
SSSDConfigTest.error
int error
Definition: SSSDConfigTest.py:2129
SSSDBG_CONF_SETTINGS
#define SSSDBG_CONF_SETTINGS
Definition: debug.h:78
sysdb.h
child_sig_handler
static void child_sig_handler(struct tevent_context *ev, struct tevent_signal *sige, int signum, int count, void *__siginfo, void *pvt)
Definition: child_common.c:525
read_pipe_state::buf
uint8_t * buf
Definition: child_common.c:419
sss_sigchld_init
errno_t sss_sigchld_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sss_sigchild_ctx **child_ctx)
Definition: child_common.c:57
write_pipe_send
struct tevent_req * write_pipe_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, uint8_t *buf, size_t len, int fd)
Definition: child_common.c:341
sss_child_callback_t
void(* sss_child_callback_t)(int child_status, struct tevent_signal *sige, void *pvt)
Definition: child_common.h:78
write_pipe_state::written
ssize_t written
Definition: child_common.c:334
sss_child_ctx::sigchld_ctx
struct sss_sigchild_ctx * sigchld_ctx
Definition: child_common.c:47
sss_sigchild_ctx::ev
struct tevent_context * ev
Definition: child_common.c:38
sss_sigchild_ctx::options
int options
Definition: child_common.c:40
write_pipe_state
Definition: child_common.c:330
talloc_zfree
#define talloc_zfree(ptr)
Definition: util.h:121
debug_timestamps
int debug_timestamps
Definition: debug.c:42
child_handler_destroy
void child_handler_destroy(struct sss_child_ctx_old *ctx)
Definition: child_common.c:312
sss_child_ctx_old::pid
pid_t pid
Definition: child_common.c:267
SSSDBG_MINOR_FAILURE
#define SSSDBG_MINOR_FAILURE
Definition: debug.h:77
open_debug_file_ex
int open_debug_file_ex(const char *filename, FILE **filep, bool want_cloexec)
Definition: debug.c:408
CHILD_MSG_CHUNK
#define CHILD_MSG_CHUNK
Definition: child_common.h:36
sss_child_cb_pvt::wait_status
int wait_status
Definition: child_common.c:156
write_pipe_state::fd
int fd
Definition: child_common.c:331
sss_atomic_read_s
#define sss_atomic_read_s(fd, buf, n)
Definition: atomic_io.h:37
SSSDBG_CRIT_FAILURE
#define SSSDBG_CRIT_FAILURE
Definition: debug.h:75
sss_child_ctx_old
Definition: child_common.c:265
TEVENT_REQ_RETURN_ON_ERROR
#define TEVENT_REQ_RETURN_ON_ERROR(req)
Definition: util.h:132
NULL
#define NULL
Definition: util.h:67
SSSDBG_OP_FAILURE
#define SSSDBG_OP_FAILURE
Definition: debug.h:76
child_io_destructor
int child_io_destructor(void *ptr)
Definition: child_common.c:777
sss_child_handler
static void sss_child_handler(struct tevent_context *ev, struct tevent_signal *se, int signum, int count, void *siginfo, void *private_data)
Definition: child_common.c:188
child_debug_init
errno_t child_debug_init(const char *logfile, int *debug_fd)
Definition: child_common.c:806
sss_child_ctx_old::child_status
int child_status
Definition: child_common.c:268
util.h
sss_child_register
errno_t sss_child_register(TALLOC_CTX *mem_ctx, struct sss_sigchild_ctx *sigchld_ctx, pid_t pid, sss_child_fn_t cb, void *pvt, struct sss_child_ctx **child_ctx)
Definition: child_common.c:114
sss_hash_create
errno_t sss_hash_create(TALLOC_CTX *mem_ctx, unsigned long count, hash_table_t **tbl)
Definition: util.c:433
ret
errno_t ret
Definition: sbus_errors.c:31
child_invoke_callback
static void child_invoke_callback(struct tevent_context *ev, struct tevent_immediate *imm, void *pvt)
Definition: child_common.c:598