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

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