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.
signature.asc
Description: This is a digitally signed message part