Blame SOURCES/0059-Fix-SEGFAULT-when-running-in-a-container-as-PID-1.patch

d7fdbd
From 970711fde95bee3de1e4a5e0b557c3132d0c3e3f Mon Sep 17 00:00:00 2001
d7fdbd
From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= <olysonek@redhat.com>
d7fdbd
Date: Tue, 6 Feb 2018 11:39:01 +0100
d7fdbd
Subject: [PATCH 59/59] Fix SEGFAULT when running in a container as PID 1
d7fdbd
d7fdbd
When vsftpd is running in a container as PID 1, it is possible
d7fdbd
that it will get SIGCHILD for processes, which were not directly
d7fdbd
created by it, but by some of its children. These processes will
d7fdbd
not be in the s_p_pid_ip_hash hash table, and thus trying to
d7fdbd
delete the entry from the hash table in standalone.c:handle_sigchld()
d7fdbd
will result in segmentation fault.
d7fdbd
d7fdbd
I can quite easily reproduce it with the upstream vsftpd and default
d7fdbd
configuration, except for isolate=NO and isolate_network=NO being set
d7fdbd
(it seems to me that network namespaces take a long time to create
d7fdbd
and destroy, which hides the race condition), on a quad-core machine.
d7fdbd
When connecting to vsftpd in a loop like this:
d7fdbd
$ while true; do echo -en '' | nc localhost 21; done
d7fdbd
d7fdbd
vsftpd crashes after a couple of seconds.
d7fdbd
---
d7fdbd
 standalone.c | 18 +++++++++++++-----
d7fdbd
 1 file changed, 13 insertions(+), 5 deletions(-)
d7fdbd
d7fdbd
diff --git a/standalone.c b/standalone.c
d7fdbd
index 3b65ea2..3f35e9e 100644
d7fdbd
--- a/standalone.c
d7fdbd
+++ b/standalone.c
d7fdbd
@@ -270,13 +270,21 @@ handle_sigchld(void* duff)
d7fdbd
     if (reap_one)
d7fdbd
     {
d7fdbd
       struct vsf_sysutil_ipaddr* p_ip;
d7fdbd
-      /* Account total number of instances */
d7fdbd
-      --s_children;
d7fdbd
-      /* Account per-IP limit */
d7fdbd
       p_ip = (struct vsf_sysutil_ipaddr*)
d7fdbd
         hash_lookup_entry(s_p_pid_ip_hash, (void*)&reap_one);
d7fdbd
-      drop_ip_count(p_ip);      
d7fdbd
-      hash_free_entry(s_p_pid_ip_hash, (void*)&reap_one);
d7fdbd
+      /* If we are running in a container as PID 1, it is possible
d7fdbd
+       * that we will get SIGCHILD for processes, which were not
d7fdbd
+       * created directly by our process and which are not in the
d7fdbd
+       * s_p_pid_ip_hash hash table.
d7fdbd
+       */
d7fdbd
+      if (p_ip)
d7fdbd
+      {
d7fdbd
+        /* Account total number of instances */
d7fdbd
+        --s_children;
d7fdbd
+        /* Account per-IP limit */
d7fdbd
+        drop_ip_count(p_ip);
d7fdbd
+        hash_free_entry(s_p_pid_ip_hash, (void*)&reap_one);
d7fdbd
+      }
d7fdbd
     }
d7fdbd
   }
d7fdbd
 }
d7fdbd
-- 
d7fdbd
2.14.4
d7fdbd