OpenVAS Scanner  22.7.9
processes.c
Go to the documentation of this file.
1 /* SPDX-FileCopyrightText: 2023 Greenbone AG
2  * SPDX-FileCopyrightText: 2006 Software in the Public Interest, Inc.
3  * SPDX-FileCopyrightText: 1998-2006 Tenable Network Security, Inc.
4  *
5  * SPDX-License-Identifier: GPL-2.0-only
6  */
7 
13 #include "processes.h"
14 
15 #include "../misc/kb_cache.h"
16 #include "debug_utils.h" /* for init_sentry() */
17 #include "sighand.h"
18 
19 #include <errno.h> /* for errno() */
20 #include <glib.h> /* for g_error */
21 #include <gvm/base/logging.h> /* for gvm_log_lock/unlock() */
22 #include <gvm/util/mqtt.h> /* for mqtt_reset() */
23 #include <setjmp.h>
24 #include <signal.h> /* for kill() */
25 #include <stdlib.h> /* for exit() */
26 #include <string.h> /* for strerror() */
27 #include <sys/wait.h> /* for waitpid() */
28 #include <time.h> /* for time() */
29 #include <unistd.h> /* for fork() */
30 
31 #undef G_LOG_DOMAIN
32 
35 #define G_LOG_DOMAIN "sd main"
36 
37 // holds all used ipc_contexts; it will be initialized and managed by
38 // create_ipc_process.
39 static struct ipc_contexts *ipcc = NULL;
40 
46 int
48 {
49  int freed = 0, i, status;
50  pid_t pid;
51  if (ipcc == NULL)
52  return -1;
53  g_debug ("%s: checking %d ipc.", __func__, ipcc->len);
54  for (i = 0; i < ipcc->len; i++)
55  {
56  if (ipcc->ctxs[i].closed)
57  {
58  continue;
59  }
60  pid = waitpid (ipcc->ctxs[i].pid, &status, WNOHANG);
61  if ((pid < 0)
62  || ((pid == ipcc->ctxs[i].pid)
63  && (WIFEXITED (status) || WIFSTOPPED (status)
64  || WIFSIGNALED (status))))
65  {
66  freed++;
67  ipc_close (&ipcc->ctxs[i]);
68  }
69  }
70  return freed;
71 }
72 
78 static void
80 {
82  ipcc = NULL;
83 }
84 
95 int
97 {
98  kill (pid, SIGTERM);
99  usleep (10000);
100  if (waitpid (pid, NULL, WNOHANG))
101  kill (pid, SIGKILL);
102 
103  return 0;
104 }
105 
112 void
114 {
115  if (ipcc == NULL)
116  return;
117 
118  for (int i = 0; i < ipcc->len; i++)
119  {
120  if (!ipcc->ctxs[i].closed)
122  }
123 }
124 
125 static void
127 {
128  /* SIGHUP is only for reloading main scanner process. */
129  openvas_signal (SIGHUP, SIG_IGN);
130  openvas_signal (SIGTERM, make_em_die);
131  openvas_signal (SIGINT, make_em_die);
132  openvas_signal (SIGQUIT, make_em_die);
133  openvas_signal (SIGSEGV, sighand_segv);
134  openvas_signal (SIGPIPE, SIG_IGN);
135 }
136 
137 static void
138 pre_fn_call (struct ipc_context *ctx, void *args)
139 {
140  (void) ctx;
141  (void) args;
142  // in a chuld we clean up every preexisting context
144  ipcc = ipc_contexts_init (0);
145  g_debug ("%s: called", __func__);
146  usleep (1000);
148  clean_procs ();
149  mqtt_reset ();
150  init_sentry ();
151  srand48 (getpid () + getppid () + (long) time (NULL));
152 
153  g_debug ("%s: exit", __func__);
154 }
155 
156 static void
157 post_fn_call (struct ipc_context *ctx, void *args)
158 {
159  (void) ctx;
160  (void) args;
161  g_debug ("%s: called", __func__);
162  gvm_close_sentry ();
163 }
164 
165 static void
167 {
168  if (ipcc == NULL)
169  return;
170  for (int i = 0; i < ipcc->len; i++)
171  {
172  if (ipcc->ctxs[i].closed == 1)
173  {
174  ipcc->ctxs[i].context = ctx->context;
175  ipcc->ctxs[i].pid = ctx->pid;
176  ipcc->ctxs[i].relation = ctx->relation;
177  ipcc->ctxs[i].type = ctx->type;
178  ipcc->ctxs[i].closed = 0;
179  return;
180  }
181  }
182  ipc_add_context (ipcc, ctx);
183 }
184 
194 pid_t
196 {
197  struct ipc_context *pctx = NULL;
198  struct ipc_exec_context ec = {0};
199  pid_t child_pid;
200  // previously init call, we want to store the contexts without making
201  // assumptions about signal handlung
202  if (ipcc == NULL)
203  ipcc = ipc_contexts_init (10);
204 
207  ec.func = (ipc_process_func) func;
208  ec.func_arg = args;
209  // check for exited processes and clean file descriptor
210  // we do it twice, before forking and when forking fails with EMFILE or EAGAIN
211 retry:
212  g_debug ("%s: closed %d fd.", __func__, procs_cleanup_children ());
213  if ((pctx = ipc_exec_as_process (IPC_PIPE, ec)) == NULL)
214  {
215  if (errno == EMFILE || errno == EAGAIN)
216  {
217  g_debug (
218  "%s: could not fork: %s (%d) retrying after trying to close fd.",
219  __func__, strerror (errno), errno);
220  goto retry;
221  }
222  g_warning ("%s: could not fork: %s (%d)", __func__, strerror (errno),
223  errno);
224  return FORKFAILED;
225  }
226  reuse_or_add_context (pctx);
227  child_pid = pctx->pid;
228  // ipcc works uses copies of pctx therefore we free it
229  free (pctx);
230  return child_pid;
231 }
232 
238 const struct ipc_contexts *
240 {
241  return ipcc;
242 }
terminate_process
int terminate_process(pid_t pid)
Terminates a given process. If termination does not work, the process will get killed....
Definition: processes.c:96
processes.h
processes.c header.
ipc_contexts::len
int len
Definition: ipc.h:42
FORKFAILED
#define FORKFAILED
Definition: processes.h:20
ipc_add_context
struct ipc_contexts * ipc_add_context(struct ipc_contexts *ctxs, struct ipc_context *ctx)
adds a given context to contexts
Definition: ipc.c:274
IPC_PIPE
@ IPC_PIPE
Definition: ipc.h:13
ipc_context::pid
pid_t pid
Definition: ipc.h:36
pre_fn_call
static void pre_fn_call(struct ipc_context *ctx, void *args)
Definition: processes.c:138
ipcc
static struct ipc_contexts * ipcc
Definition: processes.c:39
sighand.h
headerfile for sighand.c.
procs_terminate_childs
void procs_terminate_childs(void)
This function terminates all processes spawned with create_process. Calls terminate_child for each pr...
Definition: processes.c:113
init_child_signal_handlers
static void init_child_signal_handlers(void)
Definition: processes.c:126
openvas_signal
void(*)(int) openvas_signal(int signum, void(*handler)(int))
Definition: sighand.c:79
make_em_die
void make_em_die(int sig)
Definition: sighand.c:40
init_sentry
int init_sentry(void)
Init sentry.
Definition: debug_utils.c:23
ipc_contexts_init
struct ipc_contexts * ipc_contexts_init(int cap)
initializes ipc_contexts with a given preallocated capacity.
Definition: ipc.c:248
sighand_segv
void sighand_segv(int given_signal)
Definition: sighand.c:123
ipc_context::closed
unsigned int closed
Definition: ipc.h:35
create_ipc_process
pid_t create_ipc_process(ipc_process_func func, void *args)
initializes a communication channels and calls a function with a new process
Definition: processes.c:195
ipc_context::type
enum ipc_protocol type
Definition: ipc.h:33
pid
static pid_t pid
Definition: nasl_cmd_exec.c:39
ipc_exec_context
Definition: ipc.h:50
ipc_exec_context::post_func
ipc_process_func post_func
Definition: ipc.h:56
procs_cleanup_children
int procs_cleanup_children(void)
iterates through ipcc and verify if a child is stopped or killed to free the file handler.
Definition: processes.c:47
ipc_destroy_contexts
int ipc_destroy_contexts(struct ipc_contexts *ctxs)
destroys given contexts
Definition: ipc.c:305
ipc_context::relation
enum ipc_relation relation
Definition: ipc.h:34
ipc_process_func
void(* ipc_process_func)(struct ipc_context *, void *)
Definition: ipc.h:47
reuse_or_add_context
static void reuse_or_add_context(struct ipc_context *ctx)
Definition: processes.c:166
ipc_contexts
Definition: ipc.h:41
ipc_context
Definition: ipc.h:32
debug_utils.h
debug_utils.c headerfile.
ipc_close
int ipc_close(struct ipc_context *context)
closes given context
Definition: ipc.c:116
ipc_exec_context::func
ipc_process_func func
Definition: ipc.h:54
ipc_exec_context::func_arg
void * func_arg
Definition: ipc.h:58
ipc_contexts::ctxs
struct ipc_context * ctxs
Definition: ipc.h:44
free
void free(void *)
ipc_exec_as_process
struct ipc_context * ipc_exec_as_process(enum ipc_protocol type, struct ipc_exec_context exec_ctx)
runs given functions with the given protocol type.
Definition: ipc.c:175
clean_procs
static void clean_procs(void)
Cleans the process list and frees memory. This will not terminate child processes....
Definition: processes.c:79
ipc_exec_context::pre_func
ipc_process_func pre_func
Definition: ipc.h:52
ipc_context::context
void * context
Definition: ipc.h:37
procs_get_ipc_contexts
const struct ipc_contexts * procs_get_ipc_contexts(void)
returns ipc_contexts.
Definition: processes.c:239
post_fn_call
static void post_fn_call(struct ipc_context *ctx, void *args)
Definition: processes.c:157