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.
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:
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.
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
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: