2
votes

I am currently writing a shared library that takes a UNIX username and returns a string with all of the groups that user belongs to in [group1, group2, group3...] format.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <utmp.h>
#include <sys/types.h>
#include <grp.h>
#include <pwd.h>

int num_groups = 0;
struct passwd *pwd;
gid_t *groups;
struct group *grp;

FILE *stream;
char *buff;
size_t length;

char *printGroups(char *arg)
{
    stream = open_memstream(&buff, &length);
    pwd = getpwnam(arg);
    getgrouplist(arg, pwd->pw_gid, groups, &num_groups);
    groups = malloc(num_groups * sizeof(gid_t));
    if (groups == NULL){
        perror("malloc");
        exit(EXIT_FAILURE);
    }
    getgrouplist(arg, pwd->pw_gid, groups, &num_groups);
    fprintf(stream, " [");
    for (int i = 0; i < num_groups; ++i){
        grp = getgrgid(groups[i]);
        if (i == num_groups - 1)
            fprintf(stream, "%s", grp->gr_name);
        else
            fprintf(stream, "%s ", grp->gr_name);
    }
    free(groups);
    fprintf(stream, "]");
    fclose(stream);
    return buff;
}

This is main function in my shared library that returns the string. I verified that the function is indeed correct - the same logic works in a standalone program using printf instead of open_memstream stringstream.

The library however segfaults and I can't pinpoint why. Valgrind does not output anything useful:

gcc -shared -fpic -g -Wall lib.c
valgrind ./a.out
==9916== Process terminating with default action of signal 11 (SIGSEGV)
==9916== Access not within mapped region at address 0x0
==9916== at 0x1: ???
==9916== by 0xFFF000672: ???

Same goes for gdb backtrace:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000000001 in ?? () (gdb) backtrace
#0 0x0000000000000001 in ?? ()
#1 0x00007fffffffe6e9 in ?? ()
#2 0x0000000000000000 in ?? ()

I am out of ideas. Could somebody point me to a solution, ethier an error in the .so source or the reason why both Valgrind and gdb print ??? despite using the -g flag when compiling?

1
Please post a minimal reproducible example. Most of the variables you use in the function are defined somewhere else. Also, could you please format this? - Michail
You should start checking return values from system calls. Also, gcc -shared -fpic -g3 -O0 -Wall lib.c (or use -O1 if running under Valgrind). - jww
just posted the whole source. Im not sure how I could improve formatting. - Karol Samujło
are you actually trying to execute the library? as opposed to linking it from an executable and running that? When I invoke the library function from an executable, it seems to perform reasonably. - Michail
If this is intentional, you might be interested in this - Michail

1 Answers

2
votes

It looks like you're attempting to run the shared library directly. That's not how shared libraries work. They're referenced by other programs that use them.

For example, this code would use your library:

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

char *printGroups(char *);

int main()
{
    char *groups = printGroups("root");
    printf("groups: %s\n", groups);
    free(groups);
    return 0;
}

If you first compile your library like this:

gcc -shared -fpic -g -Wall lib.c -o libmylib.so

Then, assuming this library lives in the same directory as the the above test code, you compile the test code like this:

gcc -g -Wall -Wextra -L. -o mytest mytest.c -lmylib

Then set an environment variable to find your library:

export LD_LIBRARY_PATH=.

You can then run the test program which will use your library.