Bugzilla will be upgraded to version 5.0 on a still to be determined date in the near future. The original upgrade date has been delayed.
Bug 621959 - getlogin() segfaults if NSS module returns NSS_STATUS_UNAVAIL with an errnop
getlogin() segfaults if NSS module returns NSS_STATUS_UNAVAIL with an errnop
Status: CLOSED CURRENTRELEASE
Product: Red Hat Enterprise Linux 6
Classification: Red Hat
Component: glibc (Show other bugs)
6.0
All Linux
low Severity medium
: rc
: ---
Assigned To: Andreas Schwab
qe-baseos-tools
: Regression
Depends On:
Blocks:
  Show dependency treegraph
 
Reported: 2010-08-06 11:51 EDT by Stephen Gallagher
Modified: 2016-11-24 10:54 EST (History)
10 users (show)

See Also:
Fixed In Version: glibc-2.12-1.6.el6
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2010-11-10 15:29:41 EST
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)

  None (edit)
Description Stephen Gallagher 2010-08-06 11:51:20 EDT
Description of problem:
Any application making the getlogin() call is at risk of a segfault if any installed NSS module (e.g. SSSD) ever returns NSS_STATUS_UNAVAIL and sets the errnop value as described in http://www.gnu.org/s/libc/manual/html_node/NSS-Modules-Interface.html

As described in that page, NSS modules should set the correct error in *errnop if anything but NSS_STATUS_SUCCESS is returned (errnop's value is undefined in that case).

Version-Release number of selected component (if applicable):
glibc-2.12-1.4.el6

How reproducible:
Every time

Steps to Reproduce:
1. Configure nsswitch.conf with an NSS module that will return NSS_STATUS_UNAVAIL with a set errnop. One example would be to configure SSSD for network authentications and then turn off the daemon (leaving sss in the nsswitch.conf file).
2. Run the sample code below
  
Actual results:
getlogin() segfaults

Expected results:
getlogin() should not segfault

Additional info:
Note when testing: use an account from the same NSS module or later in the nsswitch.conf passwd list, or else the earlier module (e.g. files) will return successfully and this bug will not be visible.

Useful test program:

#include <unistd.h>
#include <stdio.h>

int main(int argc, char **argv)
{
    char *username = getlogin();

    printf("[%s]\n", username);
    return 0;
}
Comment 1 Stephen Gallagher 2010-08-06 11:53:55 EDT
Additional comments: If I forcibly set errnop to zero (in defiance of the specification) it does not segfault.


The specific function that is being called in the module is
_nss_XXX_getpwuid_r()  (in my case, _nss_sss_getpwuid_r)
Comment 2 Stephen Gallagher 2010-08-06 12:07:00 EDT
This was discovered while tracking down SSSD's upstream bug https://fedorahosted.org/sssd/ticket/598
Comment 4 Andreas Schwab 2010-08-06 13:25:42 EDT
Please provide a backtrace.  I'm unable to reproduce that.
Comment 5 Ulrich Drepper 2010-08-06 13:27:59 EDT
(In reply to comment #1)
> Additional comments: If I forcibly set errnop to zero (in defiance of the
> specification) it does not segfault.

What errno number did you use?  Why don't you just provide all the details instead of letting people guess?
Comment 6 Stephen Gallagher 2010-08-06 13:33:58 EDT
#0  internal_getent (uid=13041, result=0x7fffffffe040, buffer=0x7fffffffdc10 "exim", buflen=8192, errnop=0x7ffff7fe56a8)
    at nss_files/files-XXX.c:206
        p = <value optimized out>
        data = 0x7fffffffdc10
        linebuflen = 8192
        parse_result = <value optimized out>
#1  _nss_files_getpwuid_r (uid=13041, result=0x7fffffffe040, buffer=0x7fffffffdc10 "exim", buflen=8192, errnop=0x7ffff7fe56a8)
    at nss_files/files-pwd.c:40
        status = <value optimized out>
#2  0x000000344aea5dfd in __getpwuid_r (uid=13041, resbuf=0x7fffffffe040, buffer=0x7fffffffdc10 "exim", buflen=8192, 
    result=0x7fffffffe080) at ../nss/getXXbyYY_r.c:253
        startp_initialized = true
        startp = 0x49afd29e18a6d9f3
        start_fct = 0xb6503de58066d9f3
        nip = 0x601310
        fct = {l = 0x7ffff7dddf70 <_nss_files_getpwuid_r>, ptr = 0x7ffff7dddf70}
        no_more = <value optimized out>
        status = <value optimized out>
        nscd_status = <value optimized out>
        res = <value optimized out>
#3  0x000000344aea80cd in __getlogin_r_loginuid (name=0x344b17be40 "", namesize=33) at ../sysdeps/unix/sysv/linux/getlogin_r.c:63
        fd = <value optimized out>
        uidbuf = "13041\000\000\000\060\004@"
        n = <value optimized out>
        uid = 13041
        endp = 0x7fffffffe075 ""
        buflen = 8192
        buf = 0x7fffffffdc10 "exim"
        use_malloc = false
        pwd = {pw_name = 0x7fffffffdc10 "exim", pw_passwd = 0x7fffffffdc15 "x", pw_uid = 93, pw_gid = 93, 
          pw_gecos = 0x7fffffffdc1d "", pw_dir = 0x7fffffffdc1e "/var/spool/exim", pw_shell = 0x7fffffffdc2e "/sbin/nologin"}
        tpwd = <value optimized out>
        res = <value optimized out>
        result = <value optimized out>
        needed = <value optimized out>
#4  0x000000344aea7dd5 in getlogin () at ../sysdeps/unix/sysv/linux/getlogin.c:35
No locals.
#5  0x0000000000400528 in main (argc=1, argv=0x7fffffffe1e8) at getlogin.c:6
        username = 0x0



Originally I was leaving errno alone, but apparently getlogin() wasn't setting it to zero before calling us, so I tried setting it to ENOENT as recommended in http://www.gnu.org/s/libc/manual/html_node/NSS-Modules-Interface.html and that did not work either.

Only when I forcibly set it to zero did it stop segfaulting.

I'm currently trying to set up a test environment on RHEL5 to test whether it's a regression. I will get back to you on that shortly.
Comment 7 Stephen Gallagher 2010-08-06 13:43:05 EDT
More detailed steps to reproduce.

1) yum install sssd
2) authconfig-gtk
Set up LDAP user account database, LDAP or Kerberos authentication
3) Sign in at the console with an account from that database you just set up
4) shut down the sssd daemon (service sssd stop)
5) Run the example program in the original description

From the debugging I did, I'm sure that this would be the case for any other NSS module that can return NSS_STATUS_UNAVAIL, but I only have this one handy to test with.
Comment 8 Ulrich Drepper 2010-08-06 13:52:07 EDT
(In reply to comment #7)
> More detailed steps to reproduce.
> 
> 1) yum install sssd

No no.  If the problem is as you described it a simple function with the appropriate name which sets errno and returns NSS_STATUS_UNAVAIL must be sufficient to reproduce the problem.  If this is not the case then your code does something else.  We need a self-contained test case.
Comment 9 Stephen Gallagher 2010-08-06 14:28:50 EDT
Ok, here are some very simple steps to reproduce it.

1) Start up a RHEL 6 machine/VM
2) Yum install sssd-client (this is an easy example, I can write a separate module if you REALLY need it, but the source for sssd-client is very simple, it's just a message-passer)
2) As root, useradd a new user
3) Log in on a new console (or SSH) with that user
4) As root on the first console, remove that user from /etc/passwd
5) As root on the first console, add 'sss' to the passwd line of /etc/nsswitch.conf
6) As the still logged-in but no-longer-valid user on the second console, run the test program above that calls getlogin()

Witness the crash.

Also, it is worth noting that I have just finished testing this on RHEL5 and it IS a regression. (RHEL5 does not experience this segfault)
Comment 10 Stephen Gallagher 2010-08-06 14:31:26 EDT
The source of sssd-client, so you can see what it's doing.

http://git.fedorahosted.org/git/?p=sssd.git;a=tree;f=src/sss_client;h=ac94d6ff485d96560432e5fc66599878eba1c44a;hb=8fb2b985f83c0d37d4c0119fa20538bfb1c17c55


The relevant code is that sss_nss_make_request() returns NSS_STATUS_UNAVAIL when sss_cli_check_socket() returns an error (because the daemon wasn't running and we can't ask it for any information)
Comment 11 Ulrich Drepper 2010-08-06 22:20:55 EDT
(In reply to comment #9)
> Ok, here are some very simple steps to reproduce it.
> 
> 1) Start up a RHEL 6 machine/VM
> 2) Yum install sssd-client

Again, this is not self-contained.  So I cannot test this.  I don't have a spare machine to ruin by installing RHEL6 and sssd.


 I did fix a problem in getlogin.  It's committed upstream and Andreas can backport it easily.  It's 100% safe.
Comment 12 Andreas Schwab 2010-08-09 07:56:31 EDT
There is nothing to backport in that commit.
Comment 13 Andreas Schwab 2010-08-09 08:13:20 EDT
Please test: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=2666742
Comment 14 Jakub Hrozek 2010-08-09 14:16:04 EDT
(In reply to comment #13)
> Please test: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=2666742    

I'm still able to reproduce the crash with 2.12-1.4 using the steps in comment #9.
Comment 15 Jakub Hrozek 2010-08-09 15:10:28 EDT
(In reply to comment #14)
> (In reply to comment #13)
> > Please test: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=2666742    
> 
> I'm still able to reproduce the crash with 2.12-1.4 using the steps in comment
> #9.    

I am sorry, I spoke too soon. With the packages grabbed from brew, I can no longer reproduce the crash. Thank you!
Comment 16 Ulrich Drepper 2010-08-09 15:14:50 EDT
The patch Andreas added isn't what I meant.  My git use was sub-optimal again and the ChangeLog and patch went into different commits.  This is why he missed it, I guess.

Andreas, please add commit c86434ccb576a3ce35b5a74f72b9f03bd45b522a

diff --git a/sysdeps/unix/sysv/linux/getlogin_r.c b/sysdeps/unix/sysv/linux/getlogin_r.c
index 7d4d6c0..42041ee 100644
--- a/sysdeps/unix/sysv/linux/getlogin_r.c
+++ b/sysdeps/unix/sysv/linux/getlogin_r.c
@@ -81,7 +81,7 @@ __getlogin_r_loginuid (name, namesize)
        use_malloc = true;
       }
 
-  if (res != 0)
+  if (res != 0 || tpwd == NULL)
     {
       result = -1;
       goto out;
Comment 17 Andreas Schwab 2010-08-10 04:34:07 EDT
There is nothing to add here.  I know much better what to do here.
Comment 20 Petr Muller 2010-08-19 10:51:41 EDT
By following steps in comment 9, I'm still seeing this issue on s390x, ppc and x86_64. The issue seems fixed on i686, though


[mullernew@testbox ~]$ rpm -q glibc
glibc-2.12-1.5.el6.x86_64
glibc-2.12-1.5.el6.i686

[mullernew@testbox ~]$ /tmp/suxor
Segmentation fault (core dumped)

[mullernew@testbox ~]$ gdb /tmp/suxor --quiet
Reading symbols from /tmp/suxor...done.
(gdb) r
Starting program: /tmp/suxor 

Program received signal SIGSEGV, Segmentation fault.
internal_getent (uid=503, result=0x7fffffffe3a0, buffer=0x7ffef7843010 "dovenull", buflen=2147483648, errnop=0x7ffff7fe26a8)
    at nss_files/files-XXX.c:206
206           ((unsigned char *) data->linebuffer)[linebuflen - 1] = '\xff';
Missing separate debuginfos, use: debuginfo-install sssd-client-1.2.1-27.el6.x86_64
(gdb) bt
#0  internal_getent (uid=503, result=0x7fffffffe3a0, buffer=0x7ffef7843010 "dovenull", buflen=2147483648, 
    errnop=0x7ffff7fe26a8) at nss_files/files-XXX.c:206
#1  _nss_files_getpwuid_r (uid=503, result=0x7fffffffe3a0, buffer=0x7ffef7843010 "dovenull", buflen=2147483648, 
    errnop=0x7ffff7fe26a8) at nss_files/files-pwd.c:40
#2  0x00007ffff7b04e1d in __getpwuid_r (uid=503, resbuf=0x7fffffffe3a0, buffer=0x7ffef7843010 "dovenull", 
    buflen=2147483648, result=0x7fffffffe3e0) at ../nss/getXXbyYY_r.c:253
#3  0x00007ffff7b070ea in __getlogin_r_loginuid (name=0x7ffff7ddae40 "", namesize=33)
    at ../sysdeps/unix/sysv/linux/getlogin_r.c:63
#4  0x00007ffff7b06df5 in getlogin () at ../sysdeps/unix/sysv/linux/getlogin.c:35
#5  0x0000000000400528 in main (argc=1, argv=0x7fffffffe548) at suxor.c:6
Comment 25 Kashyap Chamarthy 2010-09-01 02:49:30 EDT
Verified using comment #9 on RHEL6 newest compose(as of writing this) 

Compiled the program from Comment#1 and ran it with old glibc
========================================
[root@el6test ~]# rpm -q glibc
glibc-2.12-1.2.el6.x86_64
[foo1@el6test ~]$ 
[foo1@el6test ~]$ /export/./getlogincrash 
Segmentation fault
=========================================

After updating glibc to "glibc-2.12-1.6.el6.x86_64", NO segfault can be seen.
==========================================
[foo1@el6test ~]$ /export/./getlogincrash 
[foo1]
[foo1@el6test ~]$ 
==========================================
Comment 26 releng-rhel@redhat.com 2010-11-10 15:29:41 EST
Red Hat Enterprise Linux 6.0 is now available and should resolve
the problem described in this bug report. This report is therefore being closed
with a resolution of CURRENTRELEASE. You may reopen this bug report if the
solution does not work for you.

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