]> git.itanic.dy.fi Git - rrdd/blobdiff - process.c
jobcontrol: Fork bomb prevental
[rrdd] / process.c
index 070b5f0920091ac393908e3fbd7e516f2f90f0fd..27e940050aa6804d10c2cb74bb903779b1ccefa4 100644 (file)
--- a/process.c
+++ b/process.c
@@ -19,6 +19,7 @@ static int epoll_fd;
 static unsigned int max_jobs;
 static unsigned int job_count;
 static unsigned int jobs_pending;
+static unsigned int max_jobs_pending;
 
 int get_child_count(void)
 {
@@ -70,6 +71,24 @@ static int grant_new_job(void)
        return 0;
 }
 
+static int deny_job(void)
+{
+       int ret;
+       char byte = -1;
+
+       pr_info("Denying new job. %d jobs currently and %d pending, "
+               "limit of pending jobs is %d\n",
+               job_count, jobs_pending, max_jobs_pending);
+
+       ret = write(job_get_permission_fd[1], &byte, 1);
+       if (ret != 1) {
+               pr_err("Failed to write 1 byte: %m\n");
+               return -1;
+       }
+
+       return 0;
+}
+
 static int handle_job_request(struct event_handler *h)
 {
        int ret, pid;
@@ -87,7 +106,10 @@ static int handle_job_request(struct event_handler *h)
 
        if (pid > 0) {
                if (job_count >= max_jobs) {
-                       jobs_pending++;
+                       if (jobs_pending < max_jobs_pending)
+                               jobs_pending++;
+                       else
+                               deny_job();
                } else {
                        ret = grant_new_job();
                        return 0;
@@ -208,6 +230,9 @@ read_fail:
 no_count_cpus:
        pr_info("Set maximum number of parallel jobs to %d\n", max_jobs);
 
+       max_jobs_pending = max_jobs * 50 + 25;
+       pr_info("Set maximum number of pending jobs to %d\n", max_jobs_pending);
+
        return 0;
 }
 
@@ -370,6 +395,17 @@ int do_fork_limited(void)
        if (ret < 0)
                pr_err("Job control request failure: %m\n");
 
+       if (byte < 0) {
+               pr_info("Did not get permission to execute. Terminating\n");
+
+               /*
+                * Avoid running exit handler, that would tell the
+                * parent we died normally and decrement the job
+                * counters.
+                */
+               raise(SIGKILL);
+       }
+
        pr_info("Continuing\n");
        return child;
 }