This is the mail archive of the
libc-help@sourceware.org
mailing list for the glibc project.
Preloading a replacement uname is causing environment to be cleaned if libpthread is loaded
- From: Rob West <robertfwest at gmail dot com>
- To: libc-help at sourceware dot org
- Date: Thu, 1 Apr 2010 18:03:45 -0400
- Subject: 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