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]

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


On Fri, Apr 2, 2010 at 12:09 AM, Rob West <robertfwest@gmail.com> wrote:
> Sorry, I forgot to mention that I'm running Fedora 12 on i686:
>
> [west@localhost test-ld]$ rpm -q glibc
> glibc-2.11.1-1.i686
> [west@localhost test-ld]$ uname -a
> Linux localhost.localdomain 2.6.32.9-70.fc12.i686 #1 SMP Wed Mar 3
> 05:14:32 UTC 2010 i686 i686 i386 GNU/Linux
>
> Not an April Fool's joke...
>
>
>
> On Thu, Apr 1, 2010 at 6:03 PM, Rob West <robertfwest@gmail.com> wrote:
>> 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
>>
>


hi,

I found out uname is being called on x86 in is_smp_system function,
which is called within libpthread _init.

I did some debuging and found out that:
 - after calling _init for libthread  (functions _dl_init and
call_init from elf/dl-init.c)
 - the stack is changed and the env argument changes to NULL before
calling libc _init

I tried to follow the stack during the libpthread _init calls,
but there's sooo many resolvings and I got lost :)

The is_smp_system function was not allways calling uname,
when I put the old version (using sysctl) the issue is gone..

So I'm guessing that there's some issue when you actually
need to resolve a function in another library during libpthread
_init call... ? but thats just the guess

I'm attaching the workaround change that works for me (latest git source).
Maybe somebody will be able to track the real issue... I'll wait for
some answers
before I dig in to that again ;)

cc-ing libc-alpha..

thanks,
jirka

Attachment: glibc.patch
Description: Binary data


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