# Frequent segfaults of vsftpd with glibc >= 2.7 [Solved]

## natrij

Since the upgrade to glibc-2.17, I was seeing frequent segfaults of vsftpd on my server. Strangely enough, they did not seem to affect the functionality of the FTP service, but dmesg was flooded with such lines:

```

[1038524.541043] vsftpd[20031]: segfault at 8 ip 00007fa13548d79a sp 00007fff4f4f9268 error 4 in libc-2.19.so[7fa1353f7000+19e000]

[1038842.131133] vsftpd[21099]: segfault at 8 ip 00007fa13548d79a sp 00007fff4f4f9268 error 4 in libc-2.19.so[7fa1353f7000+19e000]

[1039188.617834] vsftpd[23432]: segfault at 8 ip 00007ffff700a79a sp 00007fffffffd598 error 4 in libc-2.19.so[7ffff6f74000+19e000]

[1039516.888385] vsftpd[24389]: segfault at 8 ip 00007ffff700a79a sp 00007fffffffd598 error 4 in libc-2.19.so[7ffff6f74000+19e000]

```

After chasing this problem for almost a day, I finally found its cause. The behaviour of the crypt() function has changed in glibc >= 2.17: it can now return NULL in some circumstances. Vsftpd does not expect this to happen and promptly passes the pointer returned by crypt() to strcmp(), producing a segfault.

It appears that the bug affects only systems where vsftpd directly accesses the shadow password database (i.e., no PAM). Although the majority of the systems nowadays use PAM, thus avoiding this bug, I thought that there might be someone else out there hitting upon the same problem - especially now that glibc-2.17 is marked stable in the portage tree.

The cure to the disease:

```

--- sysdeputil.c.orig   2014-07-07 16:18:34.000000000 +0200

+++ sysdeputil.c        2014-07-07 16:19:30.000000000 +0200

@@ -285,7 +285,7 @@

         return 0;

       }

       p_crypted = crypt(str_getbuf(p_pass_str), p_spwd->sp_pwdp);

-      if (!vsf_sysutil_strcmp(p_crypted, p_spwd->sp_pwdp))

+      if (p_crypted != NULL && !vsf_sysutil_strcmp(p_crypted, p_spwd->sp_pwdp))

       {

         return 1;

       }

@@ -293,7 +293,7 @@

   }

   #endif /* VSF_SYSDEP_HAVE_SHADOW */

   p_crypted = crypt(str_getbuf(p_pass_str), p_pwd->pw_passwd);

-  if (!vsf_sysutil_strcmp(p_crypted, p_pwd->pw_passwd))

+  if (p_crypted != NULL && !vsf_sysutil_strcmp(p_crypted, p_pwd->pw_passwd))

   {

     return 1;

   }

```

Upstream has been notified. I am posting this message here in hope that it will spare those stumbling upon the same problem some time and nerves.

----------

