Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linux getpwnam() library dependencies

Tags:

c

linux

I had a program whose system call getpwnam() was failing at runtime. To debug this, I decided to run getpwnam() in isolation with this code (it came from a forum):

#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
struct passwd *pw;

if (argc != 2) {
    printf("usage: %s username\n", argv[0]);
    exit(0);
}
pw = getpwnam(argv[1]);
if (pw == NULL)
    printf("getpwnam failed\n");
else
    printf("home dir = %s\n", pw->pw_dir);
    exit(0);
}

Oddly it seems to depend on libnss_compat-2.3.5.so being present:

With libnss_compat:

./pwnam root home dir = /root

Without libnss_compat:

./pwnam root getpwnam failed

So my question is; why is getpwnam() dependent on libnss_compat*.so? I found out with the nm -D command that libc-2.3.5.so is the lib which provides getpwnam().

readelf -d shows me that libc in turn only depends on ld.so.1. That in turn depends on nothing. So why on earth is libnss_compat having an impact?

Thanks for your help everyone!!

like image 890
Andy J Avatar asked May 07 '26 18:05

Andy J


1 Answers

NSS is the Name Service Switch, a library that can look up user information in various sources (traditional password files, Network Information Service, LDAP). getpwnam may be defined in libc, but that will load the actual NSS library at runtime. Looking inside libc, I find

$ strings /lib/x86_64-linux-gnu/libc.so.6 | grep libnss
libnss_
libnss_
libnss_%s.so.%d.%d

The last line is clearly a format string for snprintf that is used to construct the name of the actual implementation library to load using dlopen. The implementation is determined using /etc/nsswitch.conf.

EDIT I found the place in the Glibc sources where the library is loaded. It's not (no longer?) using snprintf, but the principle is still the same.

like image 140
Fred Foo Avatar answered May 09 '26 09:05

Fred Foo