The bug is originally reported by Guillermo D. H. at https://bugs.gentoo.org/688246. Here is the reproducer: $ cat /etc/nsswitch.conf passwd: files #group: files #https://bugs.gentoo.org/688246 group: db files initgroups: files shadow: files gshadow: files hosts: files dns networks: files dns protocols: db files services: db files ethers: db files rpc: db files netgroup: db files $ cat a.c #include <errno.h> #include <stdio.h> #include <string.h> #include <grp.h> int main() { int saved_errno; for (;;) { errno = 0; struct group *gr = getgrent(); saved_errno = errno; if (!gr) break; } printf("(errno = %s)\n", strerror(saved_errno)); printf("errno before endgrent() = %s\n", strerror(errno)); endgrent(); printf("errno after endgrent() = %s\n", strerror(errno)); } $ gcc a.c -o a $ ./a (errno = Success) errno before endgrent() = Success errno after endgrent() = Invalid argument <- the bug The following workaround seems to be enough: --- a/nss/nss_db/db-open.c +++ b/nss/nss_db/db-open.c @@ -63,5 +63,9 @@ internal_setent (const char *file, struct nss_db_map *mapping) void internal_endent (struct nss_db_map *mapping) { - munmap (mapping->header, mapping->len); + /* Avoid clobbering errno if 'header' was never allocated. */ + if (mapping->header != NULL) + { + munmap (mapping->header, mapping->len); + } }
Created attachment 11843 [details] a.c
Any library function is allowed to modify errno unless explicitly documented otherwise.
Yes, I agree that this is not a bug.
Actually, endgrent *is* one of those exceptions: The setgrent() and endgrent() functions shall not change the setting of errno if successful.
The master branch has been updated by DJ Delorie <dj@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=99135114ba23c3110b7e4e650fabdc5e639746b7 commit 99135114ba23c3110b7e4e650fabdc5e639746b7 Author: DJ Delorie <dj@redhat.com> Date: Fri Jun 28 18:30:00 2019 -0500 nss_db: fix endent wrt NULL mappings [BZ #24695] [BZ #24696] nss_db allows for getpwent et al to be called without a set*ent, but it only works once. After the last get*ent a set*ent is required to restart, because the end*ent did not properly reset the module. Resetting it to NULL allows for a proper restart. If the database doesn't exist, however, end*ent erroniously called munmap which set errno. The test case runs "makedb" inside the testroot, so needs selinux DSOs installed.
Fix committed.
The release/2.28/master branch has been updated by DJ Delorie <dj@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=cef4c840a80372fe084effec0da1177d44b40bc0 commit cef4c840a80372fe084effec0da1177d44b40bc0 Author: DJ Delorie <dj@redhat.com> Date: Fri Jun 28 18:30:00 2019 -0500 nss_db: fix endent wrt NULL mappings [BZ #24695] [BZ #24696] nss_db allows for getpwent et al to be called without a set*ent, but it only works once. After the last get*ent a set*ent is required to restart, because the end*ent did not properly reset the module. Resetting it to NULL allows for a proper restart. If the database doesn't exist, however, end*ent erroniously called munmap which set errno. The test case runs "makedb" inside the testroot, so needs selinux DSOs installed. (cherry picked from commit 99135114ba23c3110b7e4e650fabdc5e639746b7) (note: tests excluded as test-in-container infrastructure missing)
The release/2.29/master branch has been updated by DJ Delorie <dj@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=f1f24cdebafff0c372611801cc8dbe504c3ecfff commit f1f24cdebafff0c372611801cc8dbe504c3ecfff Author: DJ Delorie <dj@redhat.com> Date: Fri Jun 28 18:30:00 2019 -0500 nss_db: fix endent wrt NULL mappings [BZ #24695] [BZ #24696] nss_db allows for getpwent et al to be called without a set*ent, but it only works once. After the last get*ent a set*ent is required to restart, because the end*ent did not properly reset the module. Resetting it to NULL allows for a proper restart. If the database doesn't exist, however, end*ent erroniously called munmap which set errno. The test case runs "makedb" inside the testroot, so needs selinux DSOs installed. (cherry picked from commit 99135114ba23c3110b7e4e650fabdc5e639746b7)