This patch should provide the necessary kernel version check, but I
haven't tested it.

Ben.

--- vsftpd-2.3.2.orig/sysdeputil.c
+++ vsftpd-2.3.2/sysdeputil.c
@@ -25,6 +25,11 @@
   #define _LARGEFILE64_SOURCE 1
 #endif
 
+#ifdef __linux__
+  #include <stdio.h>
+  #include <sys/utsname.h>
+#endif
+
 /* For INT_MAX */
 #include <limits.h>
 
@@ -1261,11 +1266,36 @@
 #endif
 }
 
+#ifdef VSF_SYSDEP_HAVE_LINUX_CLONE
+/* On Linux versions <2.6.35, netns cleanup may be so slow that
+ * creating a netns per connection allows a remote denial-of-service.
+ * We therefore do not use CLONE_NEWNET on these versions.
+ */
+static int
+vsf_sysutil_netns_cleanup_is_fast(void)
+{
+#ifdef __linux__
+  struct utsname utsname;
+  int r1, r2, r3 = 0;
+  return (uname(&utsname) == 0 &&
+         sscanf(utsname.release, "%d.%d.%d", &r1, &r2, &r3) >= 2 &&
+         ((r1 << 16) | (r2 << 8) | r3) >= ((2 << 16) | (6 << 8) | 35));
+#else
+  /* Assume any other kernel that has the feature don't have this problem */
+  return 1;
+#endif
+}
+#endif
+
 int
 vsf_sysutil_fork_isolate_all_failok()
 {
 #ifdef VSF_SYSDEP_HAVE_LINUX_CLONE
-  static int cloneflags_work = 1;
+  static int cloneflags_work = -1;
+  if (cloneflags_work < 0)
+  {
+    cloneflags_work = vsf_sysutil_netns_cleanup_is_fast();
+  }
   if (cloneflags_work)
   {
     int ret = syscall(__NR_clone,
@@ -1311,7 +1341,11 @@
 vsf_sysutil_fork_newnet()
 {
 #ifdef VSF_SYSDEP_HAVE_LINUX_CLONE
-  static int cloneflags_work = 1;
+  static int cloneflags_work = -1;
+  if (cloneflags_work < 0)
+  {
+    cloneflags_work = vsf_sysutil_netns_cleanup_is_fast();
+  }
   if (cloneflags_work)
   {
     int ret = syscall(__NR_clone, CLONE_NEWNET | SIGCHLD, NULL);
--- END ---

-- 
Ben Hutchings
Once a job is fouled up, anything done to improve it makes it worse.

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to