Getpwuid() breaks when using nix store libc instead of system libc?

I am on an Ubuntu system where my Linux user is managed by LDAP. I am using nix as a package manager in single-user mode.

Here is a simple C program to test the functionality of getpwuid:

#include <pwd.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char* argv[]) {
        uid_t uid = getuid();
        printf("%d\n", uid);
        struct passwd* pwuid = getpwuid(uid);
        if (pwuid == NULL) {
                printf("struct is null!\n");
                return 1;
        }
        printf("%s\n", pwuid->pw_name);
        return 0;
}

If I compile this in my normal shell and run it, I get the following output:

170636273
brasswood

ldd output:

        linux-vdso.so.1 (0x00007ffe6dbf8000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x0000733c62200000)
        /lib64/ld-linux-x86-64.so.2 (0x0000733c6260f000)

If I nix-shell -p gcc and recompile the same file, I get the following output:

170636273
struct is null!

ldd output:

        linux-vdso.so.1 (0x00007fff8010f000)
        libc.so.6 => /nix/store/maxa3xhmxggrc5v2vc0c3pjb79hjlkp9-glibc-2.40-66/lib/libc.so.6 (0x00007ed582407000)
        /nix/store/maxa3xhmxggrc5v2vc0c3pjb79hjlkp9-glibc-2.40-66/lib/ld-linux-x86-64.so.2 => /nix/store/maxa3xhmxggrc5v2vc0c3pjb79hjlkp9-glibc-2.40-66/lib64/ld-linux-x86-64.so.2 (0x00007ed582601000)

In summary, linking against my Ubuntu system’s libc works fine, while linking against the nix store’s libc breaks the functionality of getpwuid(). Why is this happening?

You cant mix and match glibc versions like this im afraid. The nss module of ldap gets loaded into the memory of nix’s glibc but they might not be abi compatible due to being built against different versions of glibc.

In nixos we work around this by piping all name requests through nscd which then loads the nss modules. So that we have a stable API interface for name lookups

In other distros we don’t have that luxury. You’re basically out of luck if your glibc version in Nixpkgs doesn’t match your distros. Expect undefined behaviour and segfaults.

See

For context

And

For a possible solution

1 Like

Ok, let me check if I understand the problem correctly.

The call to getpwuid resolves to the function in the nix store glibc.

That glibc then looks in /etc/nsswitch.conf to find out how to query the passwd entry.

/etc/nsswitch.conf directs glibc to, for example, run a subroutine defined in /usr/lib/x86_64-linux-gnu/libnss_sss.so.2.

glibc then dlopens this file and tries to call the subroutine.

But the problem is, /usr/lib/x86_64-linux-gnu/libnss_sss.so.2 was written for my distro’s glibc and presents a different ABI than what nix’s glibc is expecting. Segfault. Is this correct?

Would simply running nsncd on the host system solve the problem? Specifically, a version of nsncd that was built against the same version of glibc that is running on the host system?

Yes, that’s a valid fix for this, and why we worked on getting everything into nsncd upstream.

1 Like

Follow-up question: Why not automatically install and run nsncd as part of the installation process for nix as a package manager on top of another distro?

I think one of the main reasons is that it’s complicated. Everything that interacts with the existing distro might look slightly different on different distros. It should probably at least be documented more prominently.