Preloading a replacement uname is causing environment to be cleaned if libpthread is loaded
Rob West
robertfwest@gmail.com
Thu Apr 1 22:04:00 GMT 2010
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
More information about the Libc-help
mailing list