OpenVAS Scanner  7.0.0~git
pluginlaunch.c
Go to the documentation of this file.
1 /* Portions Copyright (C) 2009-2019 Greenbone Networks GmbH
2  * Portions Copyright (C) 2006 Software in the Public Interest, Inc.
3  * Based on work Copyright (C) 1998 - 2006 Tenable Network Security, Inc.
4  *
5  * SPDX-License-Identifier: GPL-2.0-only
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
26 #include "pluginlaunch.h"
27 
28 #include "../misc/network.h"
29 #include "../misc/nvt_categories.h" /* for ACT_SCANNER */
30 #include "pluginload.h"
31 #include "pluginscheduler.h"
32 #include "plugs_req.h"
33 #include "processes.h"
34 #include "sighand.h"
35 #include "utils.h"
36 
37 #include <errno.h> /* for errno() */
38 #include <gvm/base/prefs.h> /* for prefs_get_bool() */
39 #include <gvm/util/nvticache.h>
40 #include <stdio.h> /* for perror() */
41 #include <stdlib.h> /* for atoi() */
42 #include <string.h>
43 #include <strings.h> /* for bzero() */
44 #include <sys/time.h> /* for gettimeofday() */
45 #include <sys/wait.h> /* for waitpid() */
46 #include <unistd.h> /* for close() */
47 
48 #undef G_LOG_DOMAIN
49 
52 #define G_LOG_DOMAIN "sd main"
53 
57 #define MAX_PROCESSES 32
58 
62 struct running
63 {
65  struct timeval start;
66  pid_t pid;
67  int timeout;
69 };
70 
75 static GSList *non_simult_ports = NULL;
76 const char *hostname = NULL;
77 
81 static void
83 {
84  int i;
85  struct timeval now;
86  int log_whole = prefs_get_bool ("log_whole_attack");
87 
88  if (num_running_processes == 0)
89  return;
90 
91  gettimeofday (&now, NULL);
92  for (i = 0; i < MAX_PROCESSES; i++)
93  {
94  if (processes[i].pid > 0)
95  {
96  int is_alive = process_alive (processes[i].pid);
97  int ret_terminate = 0;
98 
99  // If process dead or timed out
100  if (!is_alive
101  || (processes[i].timeout > 0
102  && ((now.tv_sec - processes[i].start.tv_sec)
103  > processes[i].timeout)))
104  {
105  char *oid = processes[i].plugin->oid;
106 
107  if (is_alive)
108  {
109  char msg[2048];
110 
111  if (log_whole)
112  g_message ("%s (pid %d) is slow to finish - killing it",
113  oid, processes[i].pid);
114 
115  sprintf (msg,
116  "ERRMSG||| |||general/tcp|||%s|||"
117  "NVT timed out after %d seconds.",
118  oid ?: " ", processes[i].timeout);
119  kb_item_push_str (kb, "internal/results", msg);
120 
121  ret_terminate = terminate_process (processes[i].pid);
122  if (ret_terminate == 0)
123  {
124  terminate_process (processes[i].pid * -1);
127  bzero (&(processes[i]), sizeof (processes[i]));
128  }
129  }
130  else
131  {
132  struct timeval old_now = now;
133  int e;
134  if (now.tv_usec < processes[i].start.tv_usec)
135  {
136  processes[i].start.tv_sec++;
137  now.tv_usec += 1000000;
138  }
139  if (log_whole)
140  {
141  char *name = nvticache_get_filename (oid);
142  g_message (
143  "%s (%s) [%d] finished its job in %ld.%.3ld seconds",
144  name, oid, processes[i].pid,
145  (long) (now.tv_sec - processes[i].start.tv_sec),
146  (long) ((now.tv_usec - processes[i].start.tv_usec)
147  / 1000));
148  g_free (name);
149  }
150  now = old_now;
151  do
152  {
153  e = waitpid (processes[i].pid, NULL, 0);
154  }
155  while (e < 0 && errno == EINTR);
156 
157  terminate_process (processes[i].pid * -1);
160  bzero (&(processes[i]), sizeof (processes[i]));
161  }
162  }
163  }
164  }
165 }
166 
167 static int
168 common (GSList *list1, GSList *list2)
169 {
170  if (!list1 || !list2)
171  return 0;
172 
173  while (list1)
174  {
175  GSList *tmp = list2;
176  while (tmp)
177  {
178  if (!strcmp (list1->data, tmp->data))
179  return 1;
180  tmp = tmp->next;
181  }
182  list1 = list1->next;
183  }
184  return 0;
185 }
186 
187 static GSList *
188 required_ports_in_list (const char *oid, GSList *list)
189 {
190  GSList *common_ports = NULL;
191  char **array, *ports;
192  int i;
193 
194  if (!oid || !list)
195  return 0;
196  ports = nvticache_get_required_ports (oid);
197  if (!ports)
198  return 0;
199  array = g_strsplit (ports, ", ", 0);
200  g_free (ports);
201  if (!array)
202  return 0;
203 
204  for (i = 0; array[i]; i++)
205  {
206  GSList *tmp = list;
207  while (tmp)
208  {
209  if (!strcmp (tmp->data, array[i]))
210  common_ports = g_slist_prepend (common_ports, g_strdup (tmp->data));
211  tmp = tmp->next;
212  }
213  }
214 
215  g_strfreev (array);
216  return common_ports;
217 }
218 
219 static int
220 simult_ports (const char *oid, const char *next_oid)
221 {
222  int ret = 0;
223  GSList *common_ports1 = NULL, *common_ports2 = NULL;
224 
225  common_ports1 = required_ports_in_list (oid, non_simult_ports);
226  if (common_ports1)
227  common_ports2 = required_ports_in_list (next_oid, non_simult_ports);
228  if (common_ports1 && common_ports2 && common (common_ports1, common_ports2))
229  ret = 1;
230  g_slist_free_full (common_ports1, g_free);
231  g_slist_free_full (common_ports2, g_free);
232  return ret;
233 }
234 
241 static int
242 next_free_process (kb_t kb, struct scheduler_plugin *upcoming)
243 {
244  int r;
245 
246  for (r = 0; r < MAX_PROCESSES; r++)
247  {
248  if (processes[r].pid > 0
249  && simult_ports (processes[r].plugin->oid, upcoming->oid))
250  {
251  while (process_alive (processes[r].pid))
252  {
254  usleep (250000);
255  }
256  }
257  }
258  for (r = 0; r < MAX_PROCESSES; r++)
259  if (processes[r].pid <= 0)
260  return r;
261  return -1;
262 }
263 
264 void
265 pluginlaunch_init (const char *host)
266 {
267  int i;
268 
269  char **split = g_strsplit (prefs_get ("non_simult_ports"), ", ", 0);
270  for (i = 0; split[i]; i++)
271  non_simult_ports = g_slist_prepend (non_simult_ports, g_strdup (split[i]));
272  g_strfreev (split);
275  hostname = host;
276 
278  {
279  g_debug ("max_checks (%d) > MAX_PROCESSES (%d) - modify "
280  "openvas/openvas/pluginlaunch.c",
283  }
284 
286  bzero (&(processes), sizeof (processes));
287 }
288 
289 void
291 {
293 }
294 
295 void
297 {
299 }
300 
301 void
303 {
304  int i;
305 
306  for (i = 0; i < MAX_PROCESSES; i++)
307  {
308  if (processes[i].pid > 0)
309  {
310  terminate_process (processes[i].pid * -1);
313  bzero (&(processes[i]), sizeof (struct running));
314  }
315  }
316 }
317 
318 static int
319 plugin_timeout (nvti_t *nvti)
320 {
321  int timeout;
322 
323  assert (nvti);
324  timeout = prefs_nvt_timeout (nvti_oid (nvti));
325  if (timeout == 0)
326  timeout = nvti_timeout (nvti);
327  if (timeout == 0)
328  {
329  if (nvti_category (nvti) == ACT_SCANNER)
330  timeout =
331  atoi (prefs_get ("scanner_plugins_timeout")) ?: SCANNER_NVT_TIMEOUT;
332  else
333  timeout = atoi (prefs_get ("plugins_timeout")) ?: NVT_TIMEOUT;
334  }
335  return timeout;
336 }
337 
342 int
343 plugin_launch (struct scan_globals *globals, struct scheduler_plugin *plugin,
344  struct in6_addr *ip, GSList *vhosts, kb_t kb, nvti_t *nvti)
345 {
346  int p;
347 
348  /* Wait for a free slot */
350  p = next_free_process (kb, plugin);
351  if (p < 0)
352  return -1;
353  processes[p].plugin = plugin;
354  processes[p].timeout = plugin_timeout (nvti);
355  gettimeofday (&(processes[p].start), NULL);
356  processes[p].pid = nasl_plugin_launch (globals, ip, vhosts, kb, plugin->oid);
357 
358  if (processes[p].pid > 0)
360  else
362 
363  return processes[p].pid;
364 }
365 
369 void
371 {
372  while (num_running_processes)
373  {
376  waitpid (-1, NULL, 0);
377  }
378 }
379 
383 static int
385 {
386  int i, timeout = 0;
387 
388  for (i = 0; i < MAX_PROCESSES; i++)
389  {
390  if (processes[i].pid <= 0)
391  continue;
392  if (!timeout || processes[i].timeout < timeout)
393  timeout = processes[i].timeout;
394  }
395  return timeout;
396 }
397 
402 void
404 {
406  return;
408  /* Max number of processes are still running, wait for a child to exit or
409  * to timeout. */
411  {
412  sigset_t mask;
413  struct timespec ts = {0, 0};
414 
415  ts.tv_sec = timeout_running_processes ();
416  assert (ts.tv_sec);
417  sigemptyset (&mask);
418  sigaddset (&mask, SIGCHLD);
419  if (sigtimedwait (&mask, NULL, &ts) < 0 && errno != EAGAIN)
420  g_warning ("%s: %s", __FUNCTION__, strerror (errno));
422  }
423 }
terminate_process
int terminate_process(pid_t pid)
Send SIGTERM to the pid process. Try to wait the the process. In case of the process has still not ch...
Definition: processes.c:58
processes.h
processes.c header.
plugin_timeout
static int plugin_timeout(nvti_t *nvti)
Definition: pluginlaunch.c:319
non_simult_ports
static GSList * non_simult_ports
Definition: pluginlaunch.c:75
simult_ports
static int simult_ports(const char *oid, const char *next_oid)
Definition: pluginlaunch.c:220
running::timeout
int timeout
Definition: pluginlaunch.c:67
scheduler_plugin
Definition: pluginscheduler.h:40
pluginlaunch_disable_parallel_checks
void pluginlaunch_disable_parallel_checks(void)
Definition: pluginlaunch.c:290
running
Structure to represent a process in the sense of a running NVT.
Definition: pluginlaunch.c:62
sighand.h
headerfile for sighand.c.
timeval
struct timeval timeval(unsigned long val)
Definition: nasl_builtin_synscan.c:105
pid
static pid_t pid
Definition: nasl_builtin_nmap.c:499
running::start
struct timeval start
Definition: pluginlaunch.c:65
num_running_processes
static int num_running_processes
Definition: pluginlaunch.c:72
common
static int common(GSList *list1, GSList *list2)
Definition: pluginlaunch.c:168
PLUGIN_STATUS_DONE
@ PLUGIN_STATUS_DONE
Definition: pluginscheduler.h:37
name
const char * name
Definition: nasl_init.c:377
pluginload.h
pluginload.c header.
oid
const char * oid
Definition: nasl_builtin_find_service.c:57
scheduler_plugin::running_state
enum plugin_status running_state
Definition: pluginscheduler.h:44
next_free_process
static int next_free_process(kb_t kb, struct scheduler_plugin *upcoming)
Definition: pluginlaunch.c:242
utils.h
utils.c headerfile.
required_ports_in_list
static GSList * required_ports_in_list(const char *oid, GSList *list)
Definition: pluginlaunch.c:188
pluginlaunch_init
void pluginlaunch_init(const char *host)
Definition: pluginlaunch.c:265
MAX_PROCESSES
#define MAX_PROCESSES
'Hard' limit of the max. number of concurrent plugins per host.
Definition: pluginlaunch.c:57
pluginlaunch_wait
void pluginlaunch_wait(kb_t kb)
Waits and 'pushes' processes until num_running_processes is 0.
Definition: pluginlaunch.c:370
running::pid
pid_t pid
Definition: pluginlaunch.c:66
update_running_processes
static void update_running_processes(kb_t kb)
Definition: pluginlaunch.c:82
process_alive
int process_alive(pid_t pid)
Definition: utils.c:204
scan_globals
Definition: scanneraux.h:32
scheduler_plugin::oid
char * oid
Definition: pluginscheduler.h:42
PLUGIN_STATUS_UNRUN
@ PLUGIN_STATUS_UNRUN
Definition: pluginscheduler.h:35
plugin_launch
int plugin_launch(struct scan_globals *globals, struct scheduler_plugin *plugin, struct in6_addr *ip, GSList *vhosts, kb_t kb, nvti_t *nvti)
Definition: pluginlaunch.c:343
host
Host information, implemented as doubly linked list.
Definition: hosts.c:46
get_max_checks_number
int get_max_checks_number(void)
Definition: utils.c:174
ACT_SCANNER
@ ACT_SCANNER
Definition: nvt_categories.h:39
pluginlaunch_wait_for_free_process
void pluginlaunch_wait_for_free_process(kb_t kb)
Waits and 'pushes' processes until the number of running processes has changed.
Definition: pluginlaunch.c:403
pluginscheduler.h
header for pluginscheduler.c
hostname
const char * hostname
Definition: pluginlaunch.c:76
pluginlaunch.h
pluginlaunch.c header.
running::plugin
struct scheduler_plugin * plugin
Definition: pluginlaunch.c:64
timeout_running_processes
static int timeout_running_processes()
Return shortest timeout of the running processes.
Definition: pluginlaunch.c:384
pluginlaunch_stop
void pluginlaunch_stop()
Definition: pluginlaunch.c:302
nasl_plugin_launch
int nasl_plugin_launch(struct scan_globals *globals, struct in6_addr *ip, GSList *vhosts, kb_t kb, const char *oid)
Launch a NASL plugin.
Definition: nasl_plugins.c:151
pluginlaunch_enable_parallel_checks
void pluginlaunch_enable_parallel_checks(void)
Definition: pluginlaunch.c:296
plugs_req.h
plugs_req.c header.
max_running_processes
static int max_running_processes
Definition: pluginlaunch.c:73
list
Definition: nasl_builtin_synscan.c:259
processes
static struct running processes[MAX_PROCESSES]
Definition: pluginlaunch.c:71
old_max_running_processes
static int old_max_running_processes
Definition: pluginlaunch.c:74