Bug 1213603

Summary: glibc: nss_db: get*ent crashes without preceding set*ent
Product: Red Hat Enterprise Linux 7 Reporter: Frank Hirtz <fhirtz>
Component: glibcAssignee: Florian Weimer <fweimer>
Status: CLOSED ERRATA QA Contact: Sergey Kolosov <skolosov>
Severity: medium Docs Contact:
Priority: urgent    
Version: 7.2CC: alanm, ashankar, codonell, cww, fkrska, fweimer, mcermak, mnewsome, mpetlan, pfrankli, skolosov
Target Milestone: rcKeywords: Patch, ZStream
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: glibc-2.17-158.el7 Doc Type: Bug Fix
Doc Text:
Cause: The nss_db Name Service Switch module incorrectly initializes itself. Consequence: If nss_db is enabled and any of the get*ent functions (such as getservent) are called before a corresponding set*ent call, the application crashes. Fix: The nss_db initialization sequence was updated to support this call sequence. Result: It is possible to call get*ent functions without calling set*ent first.
Story Points: ---
Clone Of:
: 1344480 1388635 (view as bug list) Environment:
Last Closed: 2017-08-01 18:06:55 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On: 1344480    
Bug Blocks: 1203710, 1388635, 1390370    

Description Frank Hirtz 2015-04-20 21:39:15 UTC
Description of problem:
Baseline, with nsswitch set to use db, but no .db files. This works:

<snip>
root@garabaldi ~]# grep services /etc/nsswitch.conf | grep -v '^#'
services:   db files sss
[root@garabaldi ~]# rm -f /var/db/*
rm: cannot remove ‘/var/db/sudo’: Is a directory
[root@garabaldi ~]# perl -e getservent
[root@garabaldi ~]# 
<snip>

Now let;s build a default db file set (this is a clean install):

<snip>
[root@garabaldi ~]# perl -e getservent
[root@garabaldi ~]# cd /var/db/; make; cd -
passwd... done.
group... done.
protocols... done.
rpc... done.
services... done.
shadow... done.

Warning: The shadow password database /var/db/shadow.db
has been set to be readable only by root.  You may want
to make it readable by the `shadow' group depending
on your configuration.

gshadow... done.

Warning: The shadow group database /var/db/gshadow.db
has been set to be readable only by root.  You may want
to make it readable by the `shadow' group depending
on your configuration.

/root
[root@garabaldi ~]# perl -e getservent
Segmentation fault
<snip>
Core was generated by `perl -e getservent'.
Program terminated with signal 11, Segmentation fault.
#0  0x00007f90955685bf in __rawmemchr_sse2 () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install perl-5.16.3-285.el7.x86_64
(gdb) bt
#0  0x00007f90955685bf in __rawmemchr_sse2 () from /lib64/libc.so.6
#1  0x00007f908eba81c1 in _nss_db_getservent_r () from /lib64/libnss_db.so.2
#2  0x00007f90955e0c11 in __nss_getent_r () from /lib64/libc.so.6
#3  0x00007f90955e983a in getservent_r@@GLIBC_2.2.5 () from /lib64/libc.so.6
#4  0x00007f9096931a96 in Perl_pp_gservent () from /usr/lib64/perl5/CORE/libperl.so
#5  0x00007f90968dca46 in Perl_runops_standard ()
   from /usr/lib64/perl5/CORE/libperl.so
#6  0x00007f9096879855 in perl_run () from /usr/lib64/perl5/CORE/libperl.so
#7  0x0000000000400d99 in main ()
<snip>

Version-Release number of selected component (if applicable):
glibc-2.17-78.el7.x86_64

How reproducible:


Steps to Reproduce:
1. Set nsswitch to use 'db' for services
    > grep services /etc/nsswitch.conf | grep -v '^#'
    > services:   db files sss
2. cd /var/db/; make; cd -
3. perl -e getservent

Actual results:
Segfault

Expected results:
No Segfault

Additional info:

Comment 3 Florian Weimer 2015-12-15 18:14:49 UTC
It appears the cause is that that implicit initialization of the service by get*ent (without a preceding set*ent) does not cause initialization of the entidex variable.  _nss_db_get*_r does this:

   247	  if (state.header == NULL)
   248	    {
   249	      status = internal_setent (DBFILE, &state);
   250	      if (status != NSS_STATUS_SUCCESS)
   251		{
   252		  *errnop = errno;
   253		  H_ERRNO_SET (NETDB_INTERNAL);
   254		  goto out;
   255		}
   256	    }

While _nss_db_set* has:

    72	  status = internal_setent (DBFILE, &state);
    73	
    74	  if (status == NSS_STATUS_SUCCESS)
    75	    {
    76	      /* Remember STAYOPEN flag.  */
    77	      keep_db |= stayopen;
    78	
    79	      /* Reset the sequential index.  */
    80	      entidx  = (const char *) state.header + state.header->valstroffset;
    81	    }

As far as I can see, the bug is present upstream as well.

Comment 5 Florian Weimer 2016-06-10 08:56:08 UTC
Patch posted upstream:

  https://sourceware.org/ml/libc-alpha/2016-06/msg00346.html

Comment 25 errata-xmlrpc 2017-08-01 18:06:55 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHSA-2017:1916