Two problems getting user and group info from /etc/{passwd,group}

q q miska0000@yahoo.com
Fri Apr 11 20:41:00 GMT 2014



Dear Cygwin developers,

Can you please take a look? - We came across a couple problems (times two, because they're identical for /etc/group as well):

1.  When '/etc/passwd' gets reloaded, it can't add the last (default) line for uid=-1 because pretty_ls[] has already been parsed (':'s replaced with '\0'), and can't be parsed again.

2.  When there's fork(), a fresh copy of the pretty_ls seems to be loaded, which does not have '\0's in place of ':'s, while the parsed addressed are kept on heap and are still valid.

NOTE.  The default entry (uid=-1) is needed in case when code runs from a service account(NT SERVICE\...), which can't map to any POSIX UID/GID, so they fail back to -1.

The exposition is below, for each bug (WARNING: BUG1 will cause /etc/passwd to be "touch"ed):

$ gcc -DBUG1 pwd.c

$ ./a.exe
pw_name   = (0x6118ad2c)????????
pw_passwd = (0x6118ad35)*
pw_uid    = 4294967295
pw_gid    = 4294967295
pw_gecos  = (0x6118ad3d)
pw_dir    = (0x6118ad3e)
pw_shell  = (0x6118ad3f)

pwd = NULL


$ gcc -DBUG2 pwd.c

$ ./a.exe
pw_name   = (0x6118ad2c)????????
pw_passwd = (0x6118ad35)*
pw_uid    = 4294967295
pw_gid    = 4294967295
pw_gecos  = (0x6118ad3d)
pw_dir    = (0x6118ad3e)
pw_shell  = (0x6118ad3f)

pw_name   = (0x6118ad2c)????????:*:-1:-1:::
pw_passwd = (0x6118ad35)*:-1:-1:::
pw_uid    = 4294967295
pw_gid    = 4294967295
pw_gecos  = (0x6118ad3d)::
pw_dir    = (0x6118ad3e):
pw_shell  = (0x6118ad3f)


Best regards,
Q.



---------------------------------------


#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <utime.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>


//#define BUG1
//#define BUG2


static void s_GetPwUid(uid_t uid)
{
    const struct passwd* pwd = getpwuid(uid);
    if (pwd) {
        printf("pw_name   = (%p)%s\n"
                "pw_passwd = (%p)%s\n"
                "pw_uid    = %u\n"
                "pw_gid    = %u\n"
                "pw_gecos  = (%p)%s\n"
                "pw_dir    = (%p)%s\n"
                "pw_shell  = (%p)%s\n\n",
                pwd->pw_name,   pwd->pw_name   ? pwd->pw_name   : "NULL",
                pwd->pw_passwd, pwd->pw_passwd ? pwd->pw_passwd : "NULL",
                (unsigned int) pwd->pw_uid,
                (unsigned int) pwd->pw_gid,
                pwd->pw_gecos,  pwd->pw_gecos  ? pwd->pw_gecos  : "NULL",
                pwd->pw_dir,    pwd->pw_dir    ? pwd->pw_dir    : "NULL",
                pwd->pw_shell, pwd->pw_shell   ? pwd->pw_shell  : "NULL");
    } else {
      printf("pwd = NULL\n\n");
    }
}


int main(void)
{
    s_GetPwUid(-1);

#ifdef BUG1
    {
    time_t t;
    struct timeval tv[2];
    sleep(2);

    t = time(0);
    memset(tv, 0, sizeof(tv));
    tv[0].tv_sec = t;
    tv[1].tv_sec = t;
    utimes("/etc/passwd", tv);

    s_GetPwUid(-1);
    }
#endif

#ifdef BUG2
    if (fork())
       return 0;

    s_GetPwUid(-1);
#endif

    return 0;
}

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple



More information about the Cygwin mailing list