I was playing around with LD_PRELOAD to intercept libc calls, it appears that the write call doesn't get intercepted with wc, though it does seem to work with cat. A stripped down version of the problem appears below.
RedHat Linux 2.6.9-42.ELsmp
Makefile
writelib:
gcc -Wall -rdynamic -fPIC -c write.c
gcc -shared -Wl,-soname,libwrite.so -Wl,-export-dynamic -o libwrite.so write.o -ldl
write.c:
#include <stdio.h>
#include <string.h>
#ifndef __USE_GNU
#define __USE_GNU
#define __USE_GNU_DEFINED
#endif
#include <dlfcn.h>
#ifdef __USE_GNU_DEFINED
#undef __USE_GNU
#undef __USE_GNU_DEFINED
#endif
#include <unistd.h>
#include <stdlib.h>
static ssize_t (*libc_write)(int fd, const void *buf, size_t len);
ssize_t
write(int fd, const void *buf, size_t len)
{
static int already;
ssize_t ret;
if (!already) {
if ((libc_write = dlsym(RTLD_NEXT, "write")) == NULL) {
exit(1);
}
already = 1;
}
ret = (*libc_write)(fd,"LD_PRELOAD\n",11);
return len; // not ret so cat doesn't take forever
}
Output:
prompt: make
gcc -Wall -rdynamic -fPIC -c write.c
gcc -shared -Wl,-soname,libwrite.so -Wl,-export-dynamic -o libwrite.so write.o -ldl
prompt: LD_PRELOAD=./libwrite.so /bin/cat write.c
LD_PRELOAD
prompt: LD_PRELOAD=./libwrite.so /usr/bin/wc write.c
32 70 572 write.c
Any explanations ?
That's because while cat
uses write
, wc
uses printf
, which is probably using either an inlined version of write
, or its reference to write
is bound to libc
, so cannot be interposed.
This can easily be seen using ltrace
:
$ echo foo | ltrace wc 2>&1 | grep 'write\|print'
printf("%*s", 7, "1") = 7
printf(" %*s", 7, "1") = 8
printf(" %*s", 7, "4") = 8
$ echo foo | ltrace cat 2>&1 | grep 'write\|print'
write(1, "foo\n", 4foo
LD_PRELOAD
is really a very poor method for intercepting and redirecting calls. It only works with shared libraries, and depending on how the library was linked and what levels of optimization and inlining were being used, the calls you want to intercept may not be reliably interceptable.
A great alternative that avoids all these problems, especially when it's syscalls you want to intercept and rewrite, is using the ptrace
tracing/debugging interface. Unfortunately there doesn't seem to be any tool to automate this approach at this time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With