strange behavior when intercepting read() with LD_PRELOAD
hi, ive been playing with LD_PRELOAD for a little while now (its so cool isnt it lol) and ive managed to do fun stuff like replace gettimeofday() with one that always returns 0 and run xclock. now i want to go a step further and intercept all calls to read(). I wrote a quick hackup of my library and this is what it looks like.
Code:
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
ssize_t read (int __fd, void *__buf, size_t __nbytes) __wur
{
//printf ("start\n");
ssize_t ret;
void * handle;
handle = dlopen ("/lib/libc.so.6", RTLD_LAZY);
if (!handle) {
fputs (dlerror (), stderr);
exit (EXIT_FAILURE);
}
ssize_t (*orig_read)(int, void *, size_t);
orig_read = dlsym (handle, "read");
char * error;
if ((error = dlerror()) != NULL) {
fprintf (stderr, "%s\n", error);
exit (EXIT_FAILURE);
}
ret = (*orig_read)(__fd, __buf, __nbytes);
//printf ("%d bytes\n %s end\n", __nbytes, (char *)__buf);
return ret;
}
i know that my library is being used because when the printfs are uncommented i get output, however programs that use this library always crash with annoying error codes, often times 0 (success).
running xclock for example with strace gives
Code:
read(3, "Z\261\236\0\0\0`\3\377\377\37\0\0\1\0\0\24\0\377\377\1"..., 2220) = 2220
select(4, [3], [3], NULL, NULL) = 1 (out [3])
writev(3, [{"7\0\5\0\0\0`\3;\1\0\0\10\0\0\0\377\377\377\0b\0\5\0\f\0"..., 40}], 1) = 40
select(4, [3], [], NULL, NULL) = 1 (in [3])
read(3, "\1p\2\0\0\0\0\0\1\203\0\0\250\236\346\277\213\4\25\10<"..., 4096) = 32
select(4, [3], [3], NULL, NULL) = 1 (out [3])
writev(3, [{"\203\0\1\0", 4}], 1) = 4
select(4, [3], [], NULL, NULL) = 1 (in [3])
read(3, "\1\10\3\0\0\0\0\0\377\377?\0\213\4\25\10<c \10\200\236"..., 4096) = 32
select(4, [3], [3], NULL, NULL) = 1 (out [3])
writev(3, [{"\24\0\6\0;\1\0\0\27\0\0\0\37\0\0\0\0\0\0\0\0\341\365\5"..., 24}], 1) = 24
select(4, [3], [], NULL, NULL) = 1 (in [3])
read(3, "\1\10\4\0\327\r\0\0\37\0\0\0\0\0\0\0\\7\0\0\213\4\25\10"..., 4096) = 4096
read(3, "SelectionBox.foreground:\t#000000"..., 10108) = 10108
read(3, 0x805ab64, 4096) = -1 EAGAIN (Resource temporarily unavailable)
open("/usr/share/locale/en_AU.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_AU.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_AU/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/en_AU.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/en_AU.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/en_AU/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/en.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/en.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, "XIO: fatal IO error 2 (No such "..., 71XIO: fatal IO error 2 (No such file or directory) on X server ":0.0"
) = 71
write(2, " after 4 requests (0 known "..., 69 after 4 requests (0 known processed) with 0 events remaining.
) = 69
exit_group(1) = ?
Process 21745 detached
now without ld_preload the same section looks like
Code:
read(3, "Z\261\236\0\0\0`\3\377\377\37\0\0\1\0\0\24\0\377\377\1"..., 2220) = 2220
select(4, [3], [3], NULL, NULL) = 1 (out [3])
writev(3, [{"7\0\5\0\0\0`\3;\1\0\0\10\0\0\0\377\377\377\0b\0\5\0\f\0"..., 40}], 1) = 40
select(4, [3], [], NULL, NULL) = 1 (in [3])
read(3, "\1p\2\0\0\0\0\0\1\203\0\0\250\236\346\277\213\4\25\10<"..., 4096) = 32
select(4, [3], [3], NULL, NULL) = 1 (out [3])
writev(3, [{"\203\0\1\0", 4}], 1) = 4
select(4, [3], [], NULL, NULL) = 1 (in [3])
read(3, "\1`\3\0\0\0\0\0\377\377?\0\213\4\25\10<c \10\200\236\346"..., 4096) = 32
select(4, [3], [3], NULL, NULL) = 1 (out [3])
writev(3, [{"\24\0\6\0;\1\0\0\27\0\0\0\37\0\0\0\0\0\0\0\0\341\365\5"..., 24}], 1) = 24
select(4, [3], [], NULL, NULL) = 1 (in [3])
read(3, "\1\10\4\0\327\r\0\0\37\0\0\0\0\0\0\0\\7\0\0\213\4\25\10"..., 4096) = 4096
read(3, "SelectionBox.foreground:\t#000000"..., 10108) = 10108
read(3, 0x805ab64, 4096) = -1 EAGAIN (Resource temporarily unavailable)
select(4, [3], [3], NULL, NULL) = 1 (out [3])
writev(3, [{"b\0\5\0\t\0\0\0XKEYBOARD\0\0\0", 20}], 1) = 20
select(4, [3], [], NULL, NULL) = 1 (in [3])
read(3, "\1s\5\0\0\0\0\0\1\226q\255\250\236\346\277\213\4\25\10"..., 4096) = 32
read(3, 0x805ab64, 4096) = -1 EAGAIN (Resource temporarily unavailable)
select(4, [3], [3], NULL, NULL) = 1 (out [3])
writev(3, [{"\226\0\2\0\1\0\0\0", 8}], 1) = 8
select(4, [3], [], NULL, NULL) = 1 (in [3])
read(3, "\1\1\6\0\0\0\0\0\1\0\0\0\250\236\346\277\rs\33\10\200`"..., 4096) = 32
read(3, 0x805ab64, 4096) = -1 EAGAIN (Resource temporarily unavailable)
select(4, [3], [3], NULL, NULL) = 1 (out [3])
writev(3, [{"\20\0\5\0\v\0\0\0Custom Init\0", 20}], 1) = 20
select(4, [3], [], NULL, NULL) = 1 (in [3])
read(3, "\1s\7\0\0\0\0\0G\2\0\0\250\236\346\277\213\4\25\10<c \10"..., 4096) = 32
read(3, 0x805ab64, 4096) = -1 EAGAIN (Resource temporarily unavailable)
select(4, [3], [3], NULL, NULL) = 1 (out [3])
writev(3, [{"\20\0\5\0\v\0\0\0Custom Data\0", 20}], 1) = 20
select(4, [3], [], NULL, NULL) = 1 (in [3])
read(3, "\1s\10\0\0\0\0\0H\2\0\0\250\236\346\277\213\4\25\10<c "..., 4096) = 32
read(3, 0x805ab64, 4096) = -1 EAGAIN (Resource temporarily unavailable)
open("/usr/share/X11/locale/locale.alias", O_RDONLY) = 4
fstat64(4, {st_mode=S_IFREG|0644, st_size=78744, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb79f6000
read(4, "#\t$XdotOrg: lib/X11/nls/locale.a"..., 4096) = 4096
read(4, "br_FR.iso88591\t\t\t\t\tbr_FR.ISO8859"..., 4096) = 4096
read(4, "iso88597\t\t\t\t\tel_GR.ISO8859-7\nel_"..., 4096) = 4096
read(4, "es_DO.ISO8859-1\nes_DO.utf8\t\t\t\t\te"..., 4096) = 4096
these are only the sections relevant to the crash, ie they start to differ, but from just looking at these two you can see that read is acting differently in my implementation
finally, i should point out that when the dynamic linker uses my read it seems to work, i can see many successful syscalls which look like this.
Code:
open("/usr/lib/libXaw.so.7", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0@\330\0"..., 512) = 512
any ideas
thx in advance