----- Forwarded message from Andrew Tridgell ----- Subject: tip of the day (LD_PRELOAD) Date: Sun, 26 Sep 1999 20:25:40 +1000 I know it's been a while since the last tip of the day, so I thought I'd make this one an entertaining one, at least for those of you who don't mind a bit of low-level hacking. If you've never used a C compiler then maybe you should just delete this one now. On the other hand, reading on my save you from being caught by a little programming prank at the end of this tip ... Yesterday a friend in Canberra wanted help getting q3test running on his Debian box with a Banshee board. The problem was that the proprietry Glide libraries were calling __bzero but the glibc version he was using on his Debian box only exported bzero(). This is a common sort of problem given the recent changes in what symbols glibc supports. The quick solution was a preloaded library that provided the required __bzero() function. The code looks like this: void __bzero(void *s, int n) { bzero(s, n); } put that in bzero.c then compile like this: gcc -fPIC -c bzero.c ld -shared -o bzero.so bzero.o now we can run quake3 like this: LD_PRELOAD=./bzero.so linuxquake3 and it happily runs as it now has the required __bzero() symbol. The loader preloads the little bzero.so shared library that we have built and provides the included function to the application. Those of you with devious minds (generally a requirement of a Unix programmer!) will realise that this trick is useful for a lot more than getting your daily dose of quake on a Debian system. Here is a bit of code that can be used to really confuse people: #include #include #include struct passwd *getpwuid(uid_t uid) { static void *h; static struct passwd * (*getpwuid_orig)(uid_t uid); if (!h) { /* get the original function pointer from the C library */ h = dlopen("/lib/libc.so.6", RTLD_LAZY); getpwuid_orig = dlsym(h, "getpwuid"); } return getpwuid_orig(uid+1); } notice the +1 at the end? It means that getpwuid(), which is used to map user IDs to usernames, now returns the identity of the user with the next highest uid, rather than the user that is being asked for. Try putting the above in prank.c then compile like this: gcc -fPIC -c prank.c ld -shared -o prank.so prank.o -ldl finally, add this to the victims .profile or equivalent: export LD_PRELOAD=/tmp/preload.so and see the confusion next time they use "ls -l" to look at who owns a file. Unless they know about this prank it will take them a long time to work out whats going on. Of course, there are lots of less prankish uses for LD_PRELOAD. Just let your imagination loose and I'm sure you'll find it an essential tool for getting out of tight spots. Cheers, Tridge ----- End forwarded message -----