----- 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 -----