s6-envuidgid: Weird errors with GNU libc's getgrent() and endgrent()

From: Guillermo <gdiazhartusch_at_gmail.com>
Date: Sat, 1 Jun 2019 23:55:57 -0300

Hello,

I hereby present to you a weird error report.

Short version: For recent libc releases, and at least on Gentoo,
getgrent() and endgrent() seem to magically set errno to EINVAL (I
think), except when errno's value is actually meaningful. That is,
when getgrent() returns a null pointer. I don't know if this behaviour
is in the upstream package or in Gentoo's patched one. s6-envuidgid
makes a getgrent() call but checks errno only after it has called
endgrent(), so it fails with a strange "invalid argument" error
whenever it tries to set GIDLIST. s6-setuidgid invokes s6-envuidgid,
so it also fails.

Longer version:

After performing the usual, periodic package upgrades on my Gentoo
machine, which included an upgrade of GNU libc from 2.27 to 2.29, I
was surprised to find that s6-setuidgid suddenly and consistently
failed with a mysterious error:

# s6-setuidgid daemon printf Nope\\n
s6-envuidgid: fatal: unable to get supplementary groups for daemon:
Invalid argument

Nothing like this happened before the upgrade. I checked
s6-envuidgid's code, ran some tests, used strace without getting any
meaningful results, and finally came to the conclusion I mentioned
before after compiling and running the following test program:

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <grp.h>

int main() {
   struct group *gr;
   int saved_errno;
   for (;;) {
      errno = 0;
      gr = getgrent();
      saved_errno = errno;
      if (gr) {
         printf("name: %s members: ", gr->gr_name);
      }
      else {
         printf ("End of file or error ");
         break;
      }
      for (char **p = gr->gr_mem; *p; p++) printf ("%s ", *p);
      printf("(errno = %s)\n", strerror(saved_errno));
   }
   printf("(errno = %s)\n", strerror(saved_errno));
   endgrent();
   printf("errno = %s\n", strerror(errno));
}

Results:

name: root members: root (errno = Invalid argument)
name: bin members: root bin daemon (errno = Invalid argument)
name: daemon members: root bin daemon (errno = Invalid argument)
...
name: messagebus members: (errno = Invalid argument)
name: nullmail members: (errno = Invalid argument)
End of file or error (errno = Success)
errno = Invalid argument

strace says the program loads libnss_files.so.2 (provided by the libc)
and reads /etc/group, but doesn't make that many system calls.

Sooo... thoughts? Does anyone else use a sufficiently recent version
of GNU libc and experience the same?

G:
Received on Sun Jun 02 2019 - 02:55:57 UTC

This archive was generated by hypermail 2.3.0 : Sun May 09 2021 - 19:38:49 UTC