How getpwnam() works?

-2

I met a problem with (0xC0000005) by using below code, I saw this code in Duo Security source code, Duo can run this code successfully , but when I run this code it will fail with this code the same as them. I tried to debug, seems it failed when *iter = '\0' happen.

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

char *
duo_split_at(char *s, char delimiter, unsigned int position)
{
    unsigned int count = 0;
    char *iter = NULL;
    char *result = s;

    for (iter = s; *iter; iter++) {
        if (*iter == delimiter) {
            if (count < position) {
                result = iter + 1;
                count++;
            }
            *iter = '\0';
        }
    }

    if (count < position) {
        return NULL;
    }

    return result;
}

int main()
{
    char* pw_gecos = "code1/code2/code3//textField/usergecosparsed";
    const int delimited_position = 5;
    char delimiter = '/';
    char* user = NULL;
    user = duo_split_at(pw_gecos, delimiter, delimited_position);
    printf("%s",user);
    return 0;
}

Below code works perfectly by using getpwnam() to get user's gecos part:

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

char *
duo_split_at( char *s, char delimiter, unsigned int position )
{
    unsigned int    count   = 0;
    char        *iter   = NULL;
    char        *result = s;

    for ( iter = s; *iter; iter++ )
    {
        if ( *iter == delimiter )
        {
            if ( count < position )
            {
                result = iter + 1;
                count++;
            }
            *iter = '\0';
        }
    }

    if ( count < position )
    {
        return(NULL);
    }

    return(result);
}


int
main()
{
    char        * user = "daijwei";
    struct passwd   *pw;
    if ( (pw = getpwnam( user ) ) == NULL )
    {
        printf( "error" );
        return(-1);
    }
    const char      delimiter       = '/';
    const unsigned int  delimited_position  = 5;
    user = duo_split_at( pw->pw_gecos, delimiter, delimited_position );

    printf( "%s\n%s\n", user, pw->pw_gecos );

    return(0);
}

But now new question came to me , I have downloaded the glibc from GNU website , try to find how getpwnam work , but I failed. Does anyone know how getpwnam work or the source code for it ?

I only find a file named by getpwnam.c but inside the file , I can't understand what is it.

#include <pwd.h>


#define LOOKUP_TYPE struct passwd
#define FUNCTION_NAME   getpwnam
#define DATABASE_NAME   passwd
#define ADD_PARAMS  const char *name
#define ADD_VARIABLES   name
#define BUFLEN      NSS_BUFLEN_PASSWD

#include "../nss/getXXbyYY.c"
c
linux
asked on Stack Overflow Aug 24, 2018 by Jiawei • edited Aug 27, 2018 by dbush

1 Answer

1

The problem is that pw_gecos points to a string literal, and attempting to modify the contents of a string literal leads to undefined behavior (in your case, a runtime error).

If you change the declaration of pw_gecos to

char pw_gecos[] = "code1/code2/code3//textField/usergecosparsed";

your code should work. In this case you're creating an array for pw_gecos and copying the contents of the string literal into it.

answered on Stack Overflow Aug 24, 2018 by John Bode

User contributions licensed under CC BY-SA 3.0