Bug 169846 - nscd related functions not threadsafe
nscd related functions not threadsafe
Product: Red Hat Enterprise Linux 4
Classification: Red Hat
Component: glibc (Show other bugs)
All Linux
medium Severity medium
: ---
: ---
Assigned To: Jakub Jelinek
Brian Brock
Depends On:
  Show dependency treegraph
Reported: 2005-10-04 09:05 EDT by Bastien Nocera
Modified: 2016-11-24 11:15 EST (History)
3 users (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Last Closed: 2005-10-21 17:23:52 EDT
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---

Attachments (Terms of Use)
getpwuid_r.c (718 bytes, text/plain)
2005-10-04 09:05 EDT, Bastien Nocera
no flags Details
getpwuid_r_mt.c (1.24 KB, text/plain)
2005-10-04 09:06 EDT, Bastien Nocera
no flags Details
Cleaned getpwuid test program. (1.86 KB, text/x-c)
2005-10-14 11:56 EDT, Martin Poole
no flags Details

  None (edit)
Description Bastien Nocera 2005-10-04 09:05:30 EDT
Created attachment 119596 [details]
Comment 1 Bastien Nocera 2005-10-04 09:05:30 EDT

When using getpwuid_r in a multi-threaded application, invalid reads are
performed by __nscd_get_map_ref().

Single threaded and multi-threaded testcases attached.
Comment 2 Bastien Nocera 2005-10-04 09:06:26 EDT
Created attachment 119597 [details]
Comment 3 Bastien Nocera 2005-10-04 09:08:59 EDT
This is the valgrind output with the multi-threaded testcase. The single
threaded test case works fine in all cases.

==24604== Memcheck, a memory error detector for x86-linux.
==24604== Copyright (C) 2002-2004, and GNU GPL'd, by Julian Seward et al.
==24604== Using valgrind-2.2.0, a program supervision framework for x86-linux.
==24604== Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.
==24604== For more details, rerun with: -v
==24604== Thread 3:
==24604== Invalid read of size 4
==24604==    at 0x3FC910: __nscd_get_map_ref (in /lib/tls/libc-2.3.4.so)
==24604==    by 0x3FADB3: nscd_getpw_r (in /lib/tls/libc-2.3.4.so)
==24604==    by 0x3FB106: __nscd_getpwuid_r (in /lib/tls/libc-2.3.4.so)
==24604==    by 0x38E269: getpwuid_r@@GLIBC_2.1.2 (in /lib/tls/libc-2.3.4.so)
==24604==  Address 0xB is not stack'd, malloc'd or (recently) free'd
==24604== Process terminating with default action of signal 11 (SIGSEGV)
==24604==  Access not within mapped region at address 0xB
==24604==    at 0x3FC910: __nscd_get_map_ref (in /lib/tls/libc-2.3.4.so)
==24604==    by 0x3FADB3: nscd_getpw_r (in /lib/tls/libc-2.3.4.so)
==24604==    by 0x3FB106: __nscd_getpwuid_r (in /lib/tls/libc-2.3.4.so)
==24604==    by 0x38E269: getpwuid_r@@GLIBC_2.1.2 (in /lib/tls/libc-2.3.4.so)
==24604== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 15 from 1)
==24604== malloc/free: in use at exit: 29568 bytes in 23 blocks.
==24604== malloc/free: 33 allocs, 10 frees, 31088 bytes allocated.
==24604== For a detailed leak analysis,  rerun with: --leak-check=yes
==24604== For counts of detected errors, rerun with: -v
Comment 4 Jakub Jelinek 2005-10-08 06:14:46 EDT
The testcase provided in #2 has 2 fatal bugs in it:
1) pthread_create is called with &nIterations as last argument (i.e. address
of an integer variable), but in the thread function it is used as if it was an
integer variable: nIterations = (int) pArg.
Either pthread_create should be called with (void *) (long) nIterations as
last argument and thread function can stay as is, or main can stay as is
and thread function needs to do nIterations = *(int *) pArg; (that's the
variant I have tested).  If &nIterations is in the upper half of 32-bit virtual
address space (that will be usually the case, as stack on i?86 is usually
0xbf......) or if on 64-bit arches (int) &nIterations is negative or zero,
getpwuid_r is not called at all in the thread and therefore the subsequent
printf segfaults
2) _SC_GETPW_R_SIZE_MAX is just a magic cookie, not maximum size.
You want sysconf (_SC_GETPW_R_SIZE_MAX) instead.

If I correct these bugs, I couldn't reproduce any crashes.
Comment 6 Martin Poole 2005-10-14 11:56:32 EDT
Created attachment 119984 [details]
Cleaned getpwuid test program.

 Build with....

 cc -Wall  -o getpwuid_r_rc getpwuid_r_rc.c
 cc -Wall  -pthread -o getpwuid_r_rc_mt -DWITH_THREADS getpwuid_r_rc.c
Comment 11 Jakub Jelinek 2005-10-17 12:30:36 EDT
And where does it say that not finding the requested entry is necessarily
and error?  If there will be say disk read error while trying to find the
requested entry, an error obviously occurred.  But merely not finding it
because it isn't there isn't necessarily an error.

Do you have other explanation why:
"A NULL pointer shall be returned at the location pointed to by result on
error or if the requested entry is not found."
mentions explicitly if the requested entry is not found?  If that would be
always considered an error, it would be enough to say
"A NULL pointer shall be returned at the location pointed to by result on error."

BTW, if you look at man getpwuid_r:
       0 or ENOENT or ESRCH or EBADF or EPERM or ...
              The given name or uid was not found.
Comment 13 Ulrich Drepper 2005-10-17 12:54:21 EDT
The POSIX spec is very clear (you can also read the 3p man page for getpwuid_r):

A null pointer shall be returned if the requested entry is not found, or an
error    occurs. On error, errno shall be set to indicate the error.

And then

If  successful, the getpwuid_r() function shall return zero; otherwise, an error
number shall be returned to indicate the error.

So, it's clear that the correct return value in case no entry is found is zero.
 Not finding a result is no error.

Note You need to log in before you can comment on or make changes to this bug.