Bug 1213603 - glibc: nss_db: get*ent crashes without preceding set*ent
Summary: glibc: nss_db: get*ent crashes without preceding set*ent
Alias: None
Product: Red Hat Enterprise Linux 7
Classification: Red Hat
Component: glibc
Version: 7.2
Hardware: All
OS: Linux
Target Milestone: rc
: ---
Assignee: Florian Weimer
QA Contact: Sergey Kolosov
Depends On: 1344480
Blocks: 1203710 1390370 1388635
TreeView+ depends on / blocked
Reported: 2015-04-20 21:39 UTC by Frank Hirtz
Modified: 2020-02-14 17:29 UTC (History)
11 users (show)

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.
Clone Of:
: 1344480 1388635 (view as bug list)
Last Closed: 2017-08-01 18:06:55 UTC
Target Upstream Version:

Attachments (Terms of Use)

System ID Private Priority Status Summary Last Updated
Red Hat Bugzilla 1318890 0 urgent CLOSED glibc: nss_db: long group entries are skipped 2021-02-22 00:41:40 UTC
Red Hat Bugzilla 1370630 0 high CLOSED glibc: nss_db: Endless loop in services database processing 2021-02-22 00:41:40 UTC
Red Hat Bugzilla 1698015 0 medium CLOSED glibc: Calling getpwent after endpwent should not crash? 2021-02-22 00:41:40 UTC
Red Hat Product Errata RHSA-2017:1916 0 normal SHIPPED_LIVE Moderate: glibc security, bug fix, and enhancement update 2017-08-01 18:05:43 UTC
Sourceware 20237 0 None None None 2019-06-13 20:41:09 UTC

Internal Links: 1318890 1370630 1698015

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:

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 ~]# 

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

[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@garabaldi ~]# perl -e getservent
Segmentation fault
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 ()

Version-Release number of selected component (if applicable):

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:

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;
   254		  goto out;
   255		}
   256	    }

While _nss_db_set* has:

    72	  status = internal_setent (DBFILE, &state);
    74	  if (status == NSS_STATUS_SUCCESS)
    75	    {
    76	      /* Remember STAYOPEN flag.  */
    77	      keep_db |= stayopen;
    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:


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.


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