This is the mail archive of the libc-help@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Preloading a replacement uname is causing environment to be cleaned if libpthread is loaded


OK, I wouldn't be surprised that I'm doing something wrong, but this
is quite weird:

I want to be able to overload/wrap uname. So, I have a simple library
that I preload. Now, even though my test program does not call uname,
if I link the pthread library with it, the environment variables get
cleared. Here is a run of the test code linked with pthread:

[west@localhost test-ld]$
LD_PRELOAD=/home/west/test-ld/libfakeuname.so ./test_w_pthread
Calling old_uname
Return value was 0
Buffer values:
  sysname	=Linux
  nodename	=localhost.localdomain
  release	=2.6.32.9-70.fc12.i686
  version	=#1 SMP Wed Mar 3 05:14:32 UTC 2010
  machine	=i686
HOME=(null)

Here is a run when not linked with pthread:

[west@localhost test-ld]$ LD_PRELOAD=/home/west/test-ld/libfakeuname.so ./test
HOME=/home/west

What could be going on? It sort of seems like the filling out of the
uname struct is zeroing the environ pointer, but that's just a guess.

Here is the simple test code (test.c):

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
?? ?printf("HOME=%s\n", getenv("HOME"));
?? ?return 0;
}

And here is the replacement code (fakeuname.c):

#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <sys/utsname.h>

typedef int (*uname_t)(struct utsname *buf);
typedef int (*gethostname_t)(char *name, size_t len);

uname_t old_uname;
gethostname_t old_gethostname;

void fakeuname_init()
{
    void *libc;
    char *error;

    libc = dlopen("/lib/libc.so.6", RTLD_LAZY);
    if (!libc) {
        fputs(dlerror(), stderr);
        exit(1);
    }

    old_uname = dlsym(libc, "uname");
    if ((error = dlerror()) != NULL) {
        fprintf(stderr, "%s\n", error);
        exit(1);
    }
}

int uname(struct utsname *buf)
{
    int i;

    if (!old_uname)
        fakeuname_init();

    printf("Calling old_uname\n");
    i = old_uname(buf);
    printf("Return value was %d\n", i);
    if (!i) {
	printf("Buffer values:\n");
	printf("  sysname	=%s\n", buf->sysname);
	printf("  nodename	=%s\n", buf->nodename);
	printf("  release	=%s\n", buf->release);
	printf("  version	=%s\n", buf->version);
	printf("  machine	=%s\n", buf->machine);
    }
    return i;
}

This is the makefile:

all: libfakeuname.so test test_w_pthread

libfakeuname.so: fakeuname.c
	gcc -Wall -O2 -fpic -shared -ldl -o $@ $^

test: test.c
	gcc -Wall -O2 -o $@ $^

test_w_pthread: test.c
	gcc -Wall -O2 -o $@ $^ -lpthread

clean:
	rm -f libfakeuname.so test test_w_pthread



Thanks for any help,
Rob West


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]