Summary: | sys-libs/glibc-2.29-r2: endgrent() sets errno if service 'db' is in nsswitch.conf, even if successful; breaks sys-apps/s6 | ||
---|---|---|---|
Product: | Gentoo Linux | Reporter: | Guillermo D. H. <gdiazhartusch> |
Component: | Current packages | Assignee: | Gentoo Toolchain Maintainers <toolchain> |
Status: | RESOLVED FIXED | ||
Severity: | normal | ||
Priority: | Normal | ||
Version: | unspecified | ||
Hardware: | AMD64 | ||
OS: | Linux | ||
URL: | https://sourceware.org/PR24696 | ||
Whiteboard: | |||
Package list: | Runtime testing required: | --- | |
Attachments: | test-program.c |
Description
Guillermo D. H.
2019-06-17 18:51:19 UTC
Debugging the test program reveals that the setting of errno happens in function internal_endent() of file nss/nss_db/db-open.c. This function makes a munmap(2) call with a NULL argument (mapping->header). Function argument 'mapping' points to static variable 'state' defined in nss/nss_db/db-XXX.c), which is initialized to {.header = NULL, .len = 0}, and never modified if file /var/db/group.db does not exist and previously called function internal_setent() returned NSS_STATUS_UNAVAIL. Relevant lines of strace output when executing the test program: openat(AT_FDCWD, "/var/db/group.db", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) openat(AT_FDCWD, "/etc/group", O_RDONLY|O_CLOEXEC) = 3 ... write(1, "End of file or error (errno = Su"..., 39) = 39 write(1, "errno before endgrent() = Succes"..., 34) = 34 munmap(NULL, 0) = -1 EINVAL (Invalid argument) close(3) = 0 write(1, "errno after endgrent() = Invalid"..., 42) = 42 exit_group(0) = ? +++ exited with 0 +++ Relevant output of a GDB session for debugging the test program, showing backtraces, and variable and function argument values, when executing getgrent() for the first time, and when executing endgrent(): (gdb) bt #0 __GI___open64_nocancel (file=0x7ffff7def03a "/var/db/group.db", oflag=oflag@entry=524288) at ../sysdeps/unix/sysv/linux/open64_nocancel.c:34 #1 0x00007ffff7dee013 in internal_setent (file=<optimized out>, mapping=0x7ffff7df1230 <state>) at nss_db/db-open.c:39 #2 0x00007ffff7deb573 in _nss_db_getgrent_r (result=0x7ffff7fbed40 <resbuf>, buffer=0x555555559260 "", buflen=1024, errnop=0x7ffff7fc3480) at ./nss_files/../nss_db/db-XXX.c:249 #3 0x00007ffff7f1f1da in __nss_getent_r (getent_func_name=getent_func_name@entry=0x7ffff7f8698b "getgrent_r", setent_func_name=setent_func_name@entry=0x7ffff7f86996 "setgrent", lookup_fct=<optimized out>, nip=nip@entry=0x7ffff7fbee08 <nip>, startp=startp@entry=0x7ffff7fbedf8 <startp>, last_nip=last_nip@entry=0x7ffff7fbee00 <last_nip>, stayopen_tmp=0x0, res=0, resbuf=0x7ffff7fbed40 <resbuf>, buffer=0x555555559260 "", buflen=1024, result=0x7fffffffe070, h_errnop=0x0) at getnssent_r.c:194 #4 0x00007ffff7ebf6d6 in __getgrent_r (resbuf=<optimized out>, buffer=<optimized out>, buflen=<optimized out>, result=<optimized out>) at ../nss/getXXent_r.c:160 #5 0x00007ffff7f1ecb3 in __nss_getent (func=0x7ffff7ebf640 <__getgrent_r>, resbuf=resbuf@entry=0x7ffff7fbed40 <resbuf>, buffer=buffer@entry=0x7ffff7fbd898 <buffer>, buflen=buflen@entry=1024, buffer_size=buffer_size@entry=0x7ffff7fbed20 <buffer_size>, h_errnop=h_errnop@entry=0x0) at getnssent.c:50 #6 0x00007ffff7ebedba in getgrent () at ../nss/getXXent.c:83 #7 0x00005555555551ad in main () at prueba.c:10 ... (gdb) next _nss_db_getgrent_r (result=0x7ffff7fbed40 <resbuf>, buffer=0x555555559260 "", buflen=1024, errnop=0x7ffff7fc3480) at ./nss_files/../nss_db/db-XXX.c:250 (gdb) print status $2 = NSS_STATUS_UNAVAIL (gdb) print state $3 = {header = 0x0, len = 0} ... (gdb) bt #0 internal_endent (mapping=0x7ffff7df1230 <state>) at nss_db/db-open.c:65 #1 0x00007ffff7deb396 in _nss_db_endgrent () at ./nss_files/../nss_db/db-XXX.c:95 #2 0x00007ffff7f1f043 in __nss_endent (func_name=func_name@entry=0x7ffff7f8699f "endgrent", lookup_fct=0x7ffff7f1feb0 <__GI___nss_group_lookup2>, nip=nip@entry=0x7ffff7fbee08 <nip>, startp=startp@entry=0x7ffff7fbedf8 <startp>, last_nip=last_nip@entry=0x7ffff7fbee00 <last_nip>, res=res@entry=0) at getnssent_r.c:139 #3 0x00007ffff7ebf5da in endgrent () at ../nss/getXXent_r.c:143 #4 0x000055555555527e in main () at prueba.c:24 (gdb) next 66 in nss_db/db-open.c (gdb) print *mapping $5 = {header = 0x0, len = 0} (gdb) next 0x00007ffff7dea120 in munmap@plt () from /lib64/libnss_db.so.2 Confirmed, will try to reproduce on vanilla glibc and try to bisect. Do you know which last version of glibc worked for you if ever? (In reply to Sergei Trofimovich from comment #2) > Confirmed, will try to reproduce on vanilla glibc and try to bisect. > > Do you know which last version of glibc worked for you if ever? Thanks. Last version that worked for me was the last sys-libs/glibc-2.27 package that was in the stable amd64 branch before it was masked. I think last upgrade on May 25th went straight from 2.27 to 2.29. (In reply to Guillermo D. H. from comment #3) > (In reply to Sergei Trofimovich from comment #2) > > Confirmed, will try to reproduce on vanilla glibc and try to bisect. > > > > Do you know which last version of glibc worked for you if ever? > > Thanks. Last version that worked for me was the last sys-libs/glibc-2.27 > package that was in the stable amd64 branch before it was masked. I think > last upgrade on May 25th went straight from 2.27 to 2.29. Aha! I tried vanilla glibc for master, 2.29, 2.28, 2.27, 2.26. All have the same EINVAL. Could it be that you (or glibc) updated /etc/nsswitch.conf at the same time? I think glibc added munmap() call to glibc-2.25 in 2666d441c2d8107b1987b869714189af64b954c6. This fix seems to be enough to preserve errno. I'll file upstream bug. --- 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); + } } Reported as https://sourceware.org/PR24696 (In reply to Sergei Trofimovich from comment #4) > I tried vanilla glibc for master, 2.29, 2.28, 2.27, 2.26. All have the same > EINVAL. Could it be that you (or glibc) updated /etc/nsswitch.conf at the > same time? I think I know what happened. My /var/log/emerge.log says I had sys-libs/glibc-2.27-r6 before the upgrade. The corresponding patch set, glibc-2.27-patches-3.tar.bz2, shipped with an /etc/nsswitch.conf (in directory extra/etc) that said: group: compat files (i.e. no 'db' service), whereas the patch set for sys-libs/glibc-2.29-r2, glibc-2.29-patches-3.tar.xz, does not, so the ebuild installs upstream's example file, nss/nsswitch.conf. This EINVAL thing might have been present since version 2.26, but Gentoo's default nsswitch.conf did not expose it. Let's see what upstream says about it. I don't remember ever modifying that file. Upstream applied a patch to 2.30 as: https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=99135114ba23c3110b7e4e650fabdc5e639746b7 >=sys-libs/gcc-2.30 contain upstream's fix. sys-libs/gcc-2.29-r7 pulls glibc-2.29-patches-8.tar.xz, with upstream's fix backported to 2.29 (patches/0053-nss_db-fix-endent-wrt-NULL-mappings-BZ-24695-BZ-2469.patch). I guess that when bug #702484 is done, this one can be considered fixed. Let's just declare it done. Most of arches are past stabilization. |