getpwnam on Ubuntu behaves differently if compiled in 32-bit

1.7k views Asked by At

I'm setting up a ZABBIX agent (written in C) on a couple of Ubuntu 64-bit servers. I usually compile everything in 32-bit unless I specifically need 64-bit (such as database servers.) The servers in question will be hosting virtual servers and have 8GB RAM, hence why I've kept them 64-bit.

If the ZABBIX agent starts as root, it tries to drop-down to the permission level of the zabbix user, which it looks up using the C getpwnam() function.

On a pure 32-bit system, this function behaves. However, when compiled in 32-bit on a 64-bit system, getpwnam() returns NULL when a user does exist. If compiled in 64-bit on a 64-bit system it works fine.

I've mocked up a little application that proves this, but I'm hopeful it's more my setup than a bug in GCC or the STL - the zabbix user is in an LDAP directory.

Firstly here's the output of this program:

root@sydney:/tmp# getent passwd|grep zabbix
zabbix:x:1500:1500:Zabbix Service:/home/zabbix:/bin/bash

root@sydney:/tmp# gcc main.c
root@sydney:/tmp# ./a.out
User zabbix exists with UID 1500.

root@sydney:/tmp# gcc -m32 main.c
root@sydney:/tmp# ./a.out
User zabbix does not exist.

Here's the code for my little program which I've adapted using the ZABBIX agent source code.

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

int main(int num_args, char** args)
{
        struct passwd           *pwd;
        char                    user[7] = "zabbix";

        pwd = getpwnam(user);
        if (NULL == pwd)
        {
                fprintf(stdout, "User %s does not exist.\r\n", user);
                return 1;
        }
        else
        {
                fprintf(stdout, "User %s exists with UID %d.\r\n", user, pwd->pw_uid);
        }

        return 0;
}

If this turns out to be an issue with my setup I'll gladly ask on serverfault.com, but I thought as it centres around the getpwnam() function it was more programming-related. I've also Google'd but not found anything useful which is why I'm inclined to think it's my setup.

2

There are 2 answers

1
ephemient On BEST ANSWER

In order to support non-traditional name lookups (i.e. LDAP instead of just /etc/{passwd,shadow}), libc uses the Name Service Switch. Some methods are not built into libc and must be loaded separately: /lib/libnss_ldap.so.2, for example. This is actually quite problematic when statically linking – you aren't doing that, are you?

Obviously the same module cannot be used for both 64-bit and 32-bit. Ubuntu Karmic ships /lib32/libnss_ldap.so.2 in package ia32-libs – is this installed?

0
rickfoosusa On

Both multilib, and ia32 libs must be installed.

sudo apt-get install ia32-libs gcc-multilib

Similar answer here: gcc cannot find bits/predefs.h on i686