Skip to content

Commit

Permalink
Merge pull request #834 from greenbone/mergify/bp/master/pr-832
Browse files Browse the repository at this point in the history
Fix interrupted scans (backport #832)
  • Loading branch information
jjnicola authored Aug 9, 2021
2 parents 142cd7c + 893f743 commit 920e63d
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 19 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Deprecated
### Removed
### Fixed
Fix interrupted scan, when the process table is full. [#832](https://github.com/greenbone/openvas-scanner/pull/832)

[21.4.3]: https://github.com/greenbone/openvas-scanner/compare/v21.4.2...gvmd-21.04

Expand Down
34 changes: 25 additions & 9 deletions src/attack.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@
#include <unistd.h> /* for close() */

#define ERR_HOST_DEAD -1
#define ERR_CANT_FORK -2

#define MAX_FORK_RETRIES 10
/**
Expand Down Expand Up @@ -385,13 +384,14 @@ check_new_vhosts (void)
* Does not launch a plugin twice if !save_kb_replay.
*
* @return ERR_HOST_DEAD if host died, ERR_CANT_FORK if forking failed,
* 0 otherwise.
* ERR_NO_FREE_SLOT if the process table is full, 0 otherwise.
*/
static int
launch_plugin (struct scan_globals *globals, struct scheduler_plugin *plugin,
struct in6_addr *ip, GSList *vhosts, kb_t kb, kb_t main_kb)
{
int optimize = prefs_get_bool ("optimize_test"), pid, ret = 0;
int optimize = prefs_get_bool ("optimize_test");
int launch_error, pid, ret = 0;
char *oid, *name, *error = NULL, ip_str[INET6_ADDRSTRLEN];
nvti_t *nvti;

Expand Down Expand Up @@ -467,11 +467,13 @@ launch_plugin (struct scan_globals *globals, struct scheduler_plugin *plugin,

/* Update vhosts list and start the plugin */
check_new_vhosts ();
pid = plugin_launch (globals, plugin, ip, vhosts, kb, main_kb, nvti);
if (pid < 0)
launch_error = 0;
pid = plugin_launch (globals, plugin, ip, vhosts, kb, main_kb, nvti,
&launch_error);
if (launch_error == ERR_NO_FREE_SLOT || launch_error == ERR_CANT_FORK)
{
plugin->running_state = PLUGIN_STATUS_UNRUN;
ret = ERR_CANT_FORK;
ret = launch_error;
goto finish_launch_plugin;
}

Expand Down Expand Up @@ -554,19 +556,33 @@ attack_host (struct scan_globals *globals, struct in6_addr *ip, GSList *vhosts,
comm_send_status_host_dead (main_kb, ip_str);
goto host_died;
}
else if (e == ERR_NO_FREE_SLOT)
{
if (forks_retry < MAX_FORK_RETRIES)
{
forks_retry++;
g_warning ("Launch failed for %s. No free slot available "
"in the internal process table for starting a "
"plugin.",
plugin->oid);
fork_sleep (forks_retry);
goto again;
}
}
else if (e == ERR_CANT_FORK)
{
if (forks_retry < MAX_FORK_RETRIES)
{
forks_retry++;
g_debug ("fork() failed - sleeping %d seconds (%s)",
forks_retry, strerror (errno));
g_warning (
"fork() failed for %s - sleeping %d seconds (%s)",
plugin->oid, forks_retry, strerror (errno));
fork_sleep (forks_retry);
goto again;
}
else
{
g_debug ("fork() failed too many times - aborting");
g_warning ("fork() failed too many times - aborting");
goto host_died;
}
}
Expand Down
41 changes: 32 additions & 9 deletions src/pluginlaunch.c
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,8 @@ simult_ports (const char *oid, const char *next_oid)
/**
* If another NVT with same port requirements is running, wait.
*
* @return -1 if MAX_PROCESSES are running, the index of the first free "slot"
* in the processes array otherwise.
* @return ERR_NO_FREE_SLOT if MAX_PROCESSES are running, the index of the first
* free "slot" in the processes array otherwise.
*/
static int
next_free_process (kb_t main_kb, kb_t kb, struct scheduler_plugin *upcoming)
Expand All @@ -311,7 +311,7 @@ next_free_process (kb_t main_kb, kb_t kb, struct scheduler_plugin *upcoming)
for (r = 0; r < MAX_PROCESSES; r++)
if (processes[r].pid <= 0)
return r;
return -1;
return ERR_NO_FREE_SLOT;
}

void
Expand Down Expand Up @@ -437,21 +437,35 @@ check_sysload ()
}

/**
* @brief Start a plugin.
*
* Check for free slots available in the process table. Set error with
* ERR_NO_FREE_SLOT if the process table is full. Set error with ERR_CANT_FORK
* if was not possible to fork() a new child.
*
* @return PID of process that is connected to the plugin as returned by plugin
* classes pl_launch function (<=0 means there was a problem).
* classes pl_launch function. Less than 0 means there was a problem,
* but error param should be checked.
*/
int
plugin_launch (struct scan_globals *globals, struct scheduler_plugin *plugin,
struct in6_addr *ip, GSList *vhosts, kb_t kb, kb_t main_kb,
nvti_t *nvti)
nvti_t *nvti, int *error)
{
int p;

/* Wait for a free slot */
pluginlaunch_wait_for_free_process (main_kb, kb);
p = next_free_process (main_kb, kb, plugin);
if (p < 0)
return -1;
{
g_warning ("%s. There is currently no free slot available for starting a "
"new plugin.",
__func__);
*error = ERR_NO_FREE_SLOT;
return -1;
}

processes[p].plugin = plugin;
processes[p].timeout = plugin_timeout (nvti);
gettimeofday (&(processes[p].start), NULL);
Expand All @@ -461,8 +475,10 @@ plugin_launch (struct scan_globals *globals, struct scheduler_plugin *plugin,
if (processes[p].pid > 0)
num_running_processes++;
else
processes[p].plugin->running_state = PLUGIN_STATUS_UNRUN;

{
processes[p].plugin->running_state = PLUGIN_STATUS_UNRUN;
*error = ERR_CANT_FORK;
}
return processes[p].pid;
}

Expand Down Expand Up @@ -510,8 +526,15 @@ pluginlaunch_wait_for_free_process (kb_t main_kb, kb_t kb)
update_running_processes (main_kb, kb);
/* Max number of processes are still running, wait for a child to exit or
* to timeout. */

if (num_running_processes >= max_running_processes)
g_debug ("%s. Number of running processes >= maximum running processes (%d "
">= %d). "
"Waiting for free slot for processes.",
__func__, num_running_processes, max_running_processes);

while (
(num_running_processes == max_running_processes)
(num_running_processes >= max_running_processes)
|| (num_running_processes > 0 && (check_memory () || check_sysload ())))
{
sigset_t mask;
Expand Down
11 changes: 10 additions & 1 deletion src/pluginlaunch.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@
#include "pluginload.h" /* for struct pl_class_t */
#include "pluginscheduler.h" /* for struct plugins_scheduler_t */

/**
* @brief Error for when it is not possible to fork a new plugin process.
*/
#define ERR_CANT_FORK -2
/**
* @brief Error for when the process table is full
*/
#define ERR_NO_FREE_SLOT -99

void
pluginlaunch_init (const char *);
void pluginlaunch_wait (kb_t, kb_t);
Expand All @@ -39,7 +48,7 @@ pluginlaunch_stop (void);

int
plugin_launch (struct scan_globals *, struct scheduler_plugin *,
struct in6_addr *, GSList *, kb_t, kb_t, nvti_t *);
struct in6_addr *, GSList *, kb_t, kb_t, nvti_t *, int *);

void
pluginlaunch_disable_parallel_checks (void);
Expand Down

0 comments on commit 920e63d

Please sign in to comment.