--- /dev/null
+Fix CVE-2015-1419 - config option deny_file is not handled correctly.
+From SUSE: https://bugzilla.suse.com/show_bug.cgi?id=915522
+
+Signed-off-by: Gustavo Zacarias <gustavo@zacarias.com.ar>
+
+Index: vsftpd-3.0.2/ls.c
+===================================================================
+--- vsftpd-3.0.2.orig/ls.c
++++ vsftpd-3.0.2/ls.c
+@@ -7,6 +7,7 @@
+ * Would you believe, code to handle directory listing.
+ */
+
++#include <stdlib.h>
+ #include "ls.h"
+ #include "access.h"
+ #include "defs.h"
+@@ -243,11 +244,42 @@ vsf_filename_passes_filter(const struct
+ struct mystr temp_str = INIT_MYSTR;
+ struct mystr brace_list_str = INIT_MYSTR;
+ struct mystr new_filter_str = INIT_MYSTR;
++ struct mystr normalize_filename_str = INIT_MYSTR;
++ const char *normname;
++ const char *path;
+ int ret = 0;
+ char last_token = 0;
+ int must_match_at_current_pos = 1;
++
+ str_copy(&filter_remain_str, p_filter_str);
+- str_copy(&name_remain_str, p_filename_str);
++
++ /* normalize filepath */
++ path = str_strdup(p_filename_str);
++ normname = realpath(path, NULL);
++ if (normname == NULL)
++ goto out;
++ str_alloc_text(&normalize_filename_str, normname);
++
++ if (!str_isempty (&filter_remain_str) && !str_isempty(&normalize_filename_str)) {
++ if (str_get_char_at(p_filter_str, 0) == '/') {
++ if (str_get_char_at(&normalize_filename_str, 0) != '/') {
++ str_getcwd (&name_remain_str);
++
++ if (str_getlen(&name_remain_str) > 1) /* cwd != root dir */
++ str_append_char (&name_remain_str, '/');
++
++ str_append_str (&name_remain_str, &normalize_filename_str);
++ }
++ else
++ str_copy (&name_remain_str, &normalize_filename_str);
++ } else {
++ if (str_get_char_at(p_filter_str, 0) != '{')
++ str_basename (&name_remain_str, &normalize_filename_str);
++ else
++ str_copy (&name_remain_str, &normalize_filename_str);
++ }
++ } else
++ str_copy(&name_remain_str, &normalize_filename_str);
+
+ while (!str_isempty(&filter_remain_str) && *iters < VSFTP_MATCHITERS_MAX)
+ {
+@@ -360,6 +392,9 @@ vsf_filename_passes_filter(const struct
+ ret = 0;
+ }
+ out:
++ free(normname);
++ free(path);
++ str_free(&normalize_filename_str);
+ str_free(&filter_remain_str);
+ str_free(&name_remain_str);
+ str_free(&temp_str);
+Index: vsftpd-3.0.2/str.c
+===================================================================
+--- vsftpd-3.0.2.orig/str.c
++++ vsftpd-3.0.2/str.c
+@@ -770,3 +770,14 @@ str_replace_unprintable(struct mystr* p_
+ }
+ }
+
++void
++str_basename (struct mystr* d_str, const struct mystr* path)
++{
++ static struct mystr tmp;
++
++ str_copy (&tmp, path);
++ str_split_char_reverse(&tmp, d_str, '/');
++
++ if (str_isempty(d_str))
++ str_copy (d_str, path);
++}
+Index: vsftpd-3.0.2/str.h
+===================================================================
+--- vsftpd-3.0.2.orig/str.h
++++ vsftpd-3.0.2/str.h
+@@ -101,6 +101,7 @@ void str_replace_unprintable(struct myst
+ int str_atoi(const struct mystr* p_str);
+ filesize_t str_a_to_filesize_t(const struct mystr* p_str);
+ unsigned int str_octal_to_uint(const struct mystr* p_str);
++void str_basename (struct mystr* d_str, const struct mystr* path);
+
+ /* PURPOSE: Extract a line of text (delimited by \n or EOF) from a string
+ * buffer, starting at character position 'p_pos'. The extracted line will
--- /dev/null
+From 1e65a0a15f819b8bf1b551bd84f71d0da1f5a00c Mon Sep 17 00:00:00 2001
+From: Martin Sehnoutka <msehnout@redhat.com>
+Date: Thu, 17 Nov 2016 13:02:27 +0100
+Subject: [PATCH] Prevent hanging in SIGCHLD handler.
+
+vsftpd can now handle pam_exec.so in pam.d config without hanging
+in SIGCHLD handler.
+
+[Abdelmalek:
+Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1198259
+Fetched from:
+https://src.fedoraproject.org/cgit/rpms/vsftpd.git/plain/0026-Prevent-hanging-in-SIGCHLD-handler.patch]
+Signed-off-by: Abdelmalek Benelouezzane <abdelmalek.benelouezzane@savoirfairelinux.com>
+---
+ sysutil.c | 4 ++--
+ sysutil.h | 2 +-
+ twoprocess.c | 13 +++++++++++--
+ 3 files changed, 14 insertions(+), 5 deletions(-)
+
+diff --git a/sysutil.c b/sysutil.c
+index 6d7cb3f..099748f 100644
+--- a/sysutil.c
++++ b/sysutil.c
+@@ -608,13 +608,13 @@ vsf_sysutil_exit(int exit_code)
+ }
+
+ struct vsf_sysutil_wait_retval
+-vsf_sysutil_wait(void)
++vsf_sysutil_wait(int hang)
+ {
+ struct vsf_sysutil_wait_retval retval;
+ vsf_sysutil_memclr(&retval, sizeof(retval));
+ while (1)
+ {
+- int sys_ret = wait(&retval.exit_status);
++ int sys_ret = waitpid(-1, &retval.exit_status, hang ? 0 : WNOHANG);
+ if (sys_ret < 0 && errno == EINTR)
+ {
+ vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0);
+diff --git a/sysutil.h b/sysutil.h
+index c145bdf..13153cd 100644
+--- a/sysutil.h
++++ b/sysutil.h
+@@ -177,7 +177,7 @@ struct vsf_sysutil_wait_retval
+ int PRIVATE_HANDS_OFF_syscall_retval;
+ int PRIVATE_HANDS_OFF_exit_status;
+ };
+-struct vsf_sysutil_wait_retval vsf_sysutil_wait(void);
++struct vsf_sysutil_wait_retval vsf_sysutil_wait(int hang);
+ int vsf_sysutil_wait_reap_one(void);
+ int vsf_sysutil_wait_get_retval(
+ const struct vsf_sysutil_wait_retval* p_waitret);
+diff --git a/twoprocess.c b/twoprocess.c
+index 33d84dc..b1891e7 100644
+--- a/twoprocess.c
++++ b/twoprocess.c
+@@ -47,8 +47,17 @@ static void
+ handle_sigchld(void* duff)
+ {
+
+- struct vsf_sysutil_wait_retval wait_retval = vsf_sysutil_wait();
++ struct vsf_sysutil_wait_retval wait_retval = vsf_sysutil_wait(0);
+ (void) duff;
++ if (!vsf_sysutil_wait_get_exitcode(&wait_retval) &&
++ !vsf_sysutil_wait_get_retval(&wait_retval))
++ /* There was nobody to wait for, possibly caused by underlying library
++ * which created a new process through fork()/vfork() and already picked
++ * it up, e.g. by pam_exec.so or integrity check routines for libraries
++ * when FIPS mode is on (nss freebl), which can lead to calling prelink
++ * if the prelink package is installed.
++ */
++ return;
+ /* Child died, so we'll do the same! Report it as an error unless the child
+ * exited normally with zero exit code
+ */
+@@ -390,7 +399,7 @@ common_do_login(struct vsf_session* p_sess, const struct mystr* p_user_str,
+ priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_OK);
+ if (!p_sess->control_use_ssl)
+ {
+- (void) vsf_sysutil_wait();
++ (void) vsf_sysutil_wait(1);
+ }
+ else
+ {
+--
+2.14.4
+
+++ /dev/null
-Fix CVE-2015-1419 - config option deny_file is not handled correctly.
-From SUSE: https://bugzilla.suse.com/show_bug.cgi?id=915522
-
-Signed-off-by: Gustavo Zacarias <gustavo@zacarias.com.ar>
-
-Index: vsftpd-3.0.2/ls.c
-===================================================================
---- vsftpd-3.0.2.orig/ls.c
-+++ vsftpd-3.0.2/ls.c
-@@ -7,6 +7,7 @@
- * Would you believe, code to handle directory listing.
- */
-
-+#include <stdlib.h>
- #include "ls.h"
- #include "access.h"
- #include "defs.h"
-@@ -243,11 +244,42 @@ vsf_filename_passes_filter(const struct
- struct mystr temp_str = INIT_MYSTR;
- struct mystr brace_list_str = INIT_MYSTR;
- struct mystr new_filter_str = INIT_MYSTR;
-+ struct mystr normalize_filename_str = INIT_MYSTR;
-+ const char *normname;
-+ const char *path;
- int ret = 0;
- char last_token = 0;
- int must_match_at_current_pos = 1;
-+
- str_copy(&filter_remain_str, p_filter_str);
-- str_copy(&name_remain_str, p_filename_str);
-+
-+ /* normalize filepath */
-+ path = str_strdup(p_filename_str);
-+ normname = realpath(path, NULL);
-+ if (normname == NULL)
-+ goto out;
-+ str_alloc_text(&normalize_filename_str, normname);
-+
-+ if (!str_isempty (&filter_remain_str) && !str_isempty(&normalize_filename_str)) {
-+ if (str_get_char_at(p_filter_str, 0) == '/') {
-+ if (str_get_char_at(&normalize_filename_str, 0) != '/') {
-+ str_getcwd (&name_remain_str);
-+
-+ if (str_getlen(&name_remain_str) > 1) /* cwd != root dir */
-+ str_append_char (&name_remain_str, '/');
-+
-+ str_append_str (&name_remain_str, &normalize_filename_str);
-+ }
-+ else
-+ str_copy (&name_remain_str, &normalize_filename_str);
-+ } else {
-+ if (str_get_char_at(p_filter_str, 0) != '{')
-+ str_basename (&name_remain_str, &normalize_filename_str);
-+ else
-+ str_copy (&name_remain_str, &normalize_filename_str);
-+ }
-+ } else
-+ str_copy(&name_remain_str, &normalize_filename_str);
-
- while (!str_isempty(&filter_remain_str) && *iters < VSFTP_MATCHITERS_MAX)
- {
-@@ -360,6 +392,9 @@ vsf_filename_passes_filter(const struct
- ret = 0;
- }
- out:
-+ free(normname);
-+ free(path);
-+ str_free(&normalize_filename_str);
- str_free(&filter_remain_str);
- str_free(&name_remain_str);
- str_free(&temp_str);
-Index: vsftpd-3.0.2/str.c
-===================================================================
---- vsftpd-3.0.2.orig/str.c
-+++ vsftpd-3.0.2/str.c
-@@ -770,3 +770,14 @@ str_replace_unprintable(struct mystr* p_
- }
- }
-
-+void
-+str_basename (struct mystr* d_str, const struct mystr* path)
-+{
-+ static struct mystr tmp;
-+
-+ str_copy (&tmp, path);
-+ str_split_char_reverse(&tmp, d_str, '/');
-+
-+ if (str_isempty(d_str))
-+ str_copy (d_str, path);
-+}
-Index: vsftpd-3.0.2/str.h
-===================================================================
---- vsftpd-3.0.2.orig/str.h
-+++ vsftpd-3.0.2/str.h
-@@ -101,6 +101,7 @@ void str_replace_unprintable(struct myst
- int str_atoi(const struct mystr* p_str);
- filesize_t str_a_to_filesize_t(const struct mystr* p_str);
- unsigned int str_octal_to_uint(const struct mystr* p_str);
-+void str_basename (struct mystr* d_str, const struct mystr* path);
-
- /* PURPOSE: Extract a line of text (delimited by \n or EOF) from a string
- * buffer, starting at character position 'p_pos'. The extracted line will
+++ /dev/null
-From 1e65a0a15f819b8bf1b551bd84f71d0da1f5a00c Mon Sep 17 00:00:00 2001
-From: Martin Sehnoutka <msehnout@redhat.com>
-Date: Thu, 17 Nov 2016 13:02:27 +0100
-Subject: [PATCH] Prevent hanging in SIGCHLD handler.
-
-vsftpd can now handle pam_exec.so in pam.d config without hanging
-in SIGCHLD handler.
-
-[Abdelmalek:
-Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1198259
-Fetched from:
-https://src.fedoraproject.org/cgit/rpms/vsftpd.git/plain/0026-Prevent-hanging-in-SIGCHLD-handler.patch]
-Signed-off-by: Abdelmalek Benelouezzane <abdelmalek.benelouezzane@savoirfairelinux.com>
----
- sysutil.c | 4 ++--
- sysutil.h | 2 +-
- twoprocess.c | 13 +++++++++++--
- 3 files changed, 14 insertions(+), 5 deletions(-)
-
-diff --git a/sysutil.c b/sysutil.c
-index 6d7cb3f..099748f 100644
---- a/sysutil.c
-+++ b/sysutil.c
-@@ -608,13 +608,13 @@ vsf_sysutil_exit(int exit_code)
- }
-
- struct vsf_sysutil_wait_retval
--vsf_sysutil_wait(void)
-+vsf_sysutil_wait(int hang)
- {
- struct vsf_sysutil_wait_retval retval;
- vsf_sysutil_memclr(&retval, sizeof(retval));
- while (1)
- {
-- int sys_ret = wait(&retval.exit_status);
-+ int sys_ret = waitpid(-1, &retval.exit_status, hang ? 0 : WNOHANG);
- if (sys_ret < 0 && errno == EINTR)
- {
- vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0);
-diff --git a/sysutil.h b/sysutil.h
-index c145bdf..13153cd 100644
---- a/sysutil.h
-+++ b/sysutil.h
-@@ -177,7 +177,7 @@ struct vsf_sysutil_wait_retval
- int PRIVATE_HANDS_OFF_syscall_retval;
- int PRIVATE_HANDS_OFF_exit_status;
- };
--struct vsf_sysutil_wait_retval vsf_sysutil_wait(void);
-+struct vsf_sysutil_wait_retval vsf_sysutil_wait(int hang);
- int vsf_sysutil_wait_reap_one(void);
- int vsf_sysutil_wait_get_retval(
- const struct vsf_sysutil_wait_retval* p_waitret);
-diff --git a/twoprocess.c b/twoprocess.c
-index 33d84dc..b1891e7 100644
---- a/twoprocess.c
-+++ b/twoprocess.c
-@@ -47,8 +47,17 @@ static void
- handle_sigchld(void* duff)
- {
-
-- struct vsf_sysutil_wait_retval wait_retval = vsf_sysutil_wait();
-+ struct vsf_sysutil_wait_retval wait_retval = vsf_sysutil_wait(0);
- (void) duff;
-+ if (!vsf_sysutil_wait_get_exitcode(&wait_retval) &&
-+ !vsf_sysutil_wait_get_retval(&wait_retval))
-+ /* There was nobody to wait for, possibly caused by underlying library
-+ * which created a new process through fork()/vfork() and already picked
-+ * it up, e.g. by pam_exec.so or integrity check routines for libraries
-+ * when FIPS mode is on (nss freebl), which can lead to calling prelink
-+ * if the prelink package is installed.
-+ */
-+ return;
- /* Child died, so we'll do the same! Report it as an error unless the child
- * exited normally with zero exit code
- */
-@@ -390,7 +399,7 @@ common_do_login(struct vsf_session* p_sess, const struct mystr* p_user_str,
- priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_OK);
- if (!p_sess->control_use_ssl)
- {
-- (void) vsf_sysutil_wait();
-+ (void) vsf_sysutil_wait(1);
- }
- else
- {
---
-2.14.4
-