Bug 11770 - Syscall.getpwuid_r() crashes for non-existing UIDs when nscd is running
Summary: Syscall.getpwuid_r() crashes for non-existing UIDs when nscd is running
Alias: None
Product: Runtime
Classification: Mono
Component: Interop ()
Version: unspecified
Hardware: PC Linux
: --- normal
Target Milestone: ---
Assignee: Bugzilla
Depends on:
Reported: 2013-04-13 16:45 UTC by Steffen Kieß
Modified: 2013-04-18 14:36 UTC (History)
3 users (show)

Is this bug a regression?: ---
Last known good build:

Output of executing test case (4.72 KB, text/plain)
2013-04-13 16:45 UTC, Steffen Kieß

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Steffen Kieß 2013-04-13 16:45:18 UTC
Created attachment 3812 [details]
Output of executing test case

When Syscall.getpwuid_r() is called for a UID without an entry in /etc/passwd and nscd is installed and running getpwuid_r() will crash.

Test case:

class A {
  public static void Main () {
    Mono.Unix.Native.Passwd pw = null;
    Mono.Unix.Native.Syscall.getpwuid_r (60123 /* a non-existing UID */, new Mono.Unix.Native.Passwd (), out pw);

This crashes with a SIGSEGV on my system (see crash.txt).

The problem seems to be that Mono_Posix_Syscall_getpwuid_r() is invoking copy_passwd() even if getpwuid_r() sets result to NULL.

On linux getpwuid_r() will return 0 if the uid is not found and will set result to NULL. When nscd is not running it also sets all fields of pwd (with the values of the last line of /etc/passwd), which means that copy_passwd() won't crash. When nscd is running pwd isn't touched at all, meaning copy_passwd() will try to copy an uninitialized string.

The solution probably is to add a check whether *pwbufp is NULL before calling copy_passwd(), similar to Mono_Posix_Syscall_getpwnam_r(), Mono_Posix_Syscall_getgrnam_r() and Mono_Posix_Syscall_getgrgid_r():

diff --git a/support/pwd.c b/support/pwd.c
index 4bb6ad6..6e3b68a 100644
--- a/support/pwd.c
+++ b/support/pwd.c
@@ -183,6 +183,10 @@ Mono_Posix_Syscall_getpwuid_r (mph_uid_t uid,
        } while ((r = getpwuid_r (uid, &_pwbuf, buf, buflen, (struct passwd**) pwbufp)) && 
                        recheck_range (r));
+       if (r == 0 && !(*pwbufp))
+               /* On solaris, this function returns 0 even if the entry was not found */
+               r = errno = ENOENT;
        if (r == 0 && copy_passwd (pwbuf, &_pwbuf) == -1)
                r = errno = ENOMEM;
        free (buf);
Comment 1 Zoltan Varga 2013-04-18 14:36:59 UTC
Applied the patch to master/2.10.