OpenVAS Scanner 23.32.3
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
12
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
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.
39static struct ipc_contexts *ipcc = NULL;
40
46int
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
78static void
80{
82 ipcc = NULL;
83}
84
95int
97{
98 kill (pid, SIGTERM);
99 usleep (10000);
100 if (waitpid (pid, NULL, WNOHANG))
101 kill (pid, SIGKILL);
102
103 return 0;
104}
105
112void
114{
115 if (ipcc == NULL)
116 return;
117
118 for (int i = 0; i < ipcc->len; i++)
119 {
120 if (!ipcc->ctxs[i].closed)
121 terminate_process (ipcc->ctxs[i].pid);
122 }
123}
124
125static 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
137static void
138pre_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
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
156static void
157post_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
165static 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
194pid_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
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
211retry:
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 }
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
238const struct ipc_contexts *
240{
241 return ipcc;
242}
int init_sentry(void)
Init sentry.
Definition debug_utils.c:23
debug_utils.c headerfile.
int ipc_close(struct ipc_context *context)
closes given context
Definition ipc.c:116
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
struct ipc_contexts * ipc_contexts_init(int cap)
initializes ipc_contexts with a given preallocated capacity.
Definition ipc.c:248
struct ipc_contexts * ipc_add_context(struct ipc_contexts *ctxs, struct ipc_context *ctx)
adds a given context to contexts
Definition ipc.c:274
int ipc_destroy_contexts(struct ipc_contexts *ctxs)
destroys given contexts
Definition ipc.c:305
void(* ipc_process_func)(struct ipc_context *, void *)
Definition ipc.h:47
@ IPC_PIPE
Definition ipc.h:13
Header file to cache main_kb.
static pid_t pid
void free(void *)
const struct ipc_contexts * procs_get_ipc_contexts(void)
returns ipc_contexts.
Definition processes.c:239
static void post_fn_call(struct ipc_context *ctx, void *args)
Definition processes.c:157
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
static void reuse_or_add_context(struct ipc_context *ctx)
Definition processes.c:166
static struct ipc_contexts * ipcc
Definition processes.c:39
void procs_terminate_childs(void)
This function terminates all processes spawned with create_process. Calls terminate_child for each pr...
Definition processes.c:113
int terminate_process(pid_t pid)
Terminates a given process. If termination does not work, the process will get killed....
Definition processes.c:96
static void init_child_signal_handlers(void)
Definition processes.c:126
static void pre_fn_call(struct ipc_context *ctx, void *args)
Definition processes.c:138
static void clean_procs(void)
Cleans the process list and frees memory. This will not terminate child processes....
Definition processes.c:79
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
processes.c header.
#define FORKFAILED
Definition processes.h:20
void(*)(int) openvas_signal(int signum, void(*handler)(int))
Definition sighand.c:79
void sighand_segv(int given_signal)
Definition sighand.c:123
void make_em_die(int sig)
Definition sighand.c:40
headerfile for sighand.c.
void * context
Definition ipc.h:37
enum ipc_protocol type
Definition ipc.h:33
enum ipc_relation relation
Definition ipc.h:34
pid_t pid
Definition ipc.h:36
ipc_process_func pre_func
Definition ipc.h:52
void * func_arg
Definition ipc.h:58
ipc_process_func post_func
Definition ipc.h:56
ipc_process_func func
Definition ipc.h:54