c and LD_PRELOAD. open and open64 calls intercepted, but not stat64 - c

I've done a little shared library that tries to intercept open, open64, stat and stat64 sys calls.
When I export LD_PRELOAD and run oracle's sqlplus, I can see the traces of the open and open64 calls, but no traces of the stat and stat64 calls.
The shared library is a single c file with all the definitions of the sys calls in it.
Why does it happen that some syscalls are intercepted and others don't?
thanks for your help.

Because the GNU libc implements open() and open64() as you'd expect (i.e. they're just dynamically linked symbols that you can hook into with LD_PRELOAD), but does something special with stat() and stat64().
If you look at the symbols exported by libc (e.g. with nm -D /libc/libc.so.6), you'll see that it doesn't actually provide the symbols stat or stat64!
Calls to these functions are wrapped - either at compile time (if possible) by inline functions in <sys/stat.h>, or (failing that) statically linked definitions provided by libc_nonshared.a.
The actual dynamically linked functions which are called are __xstat() or __xstat64(); and these take an additional first argument, an integer, which is a version number indicating the layout of struct stat that is expected by the caller. Try hooking these instead.
(The point of all this is to allow the dynamically linked libc to support binaries which use various incompatible layouts of struct stat and definitions of bits in mode_t; if you look in /usr/include/sys/stat.h you'll find a comment to this effect. fstat(), fstat64(), lstat(), lstat64() and mknod() are also affected in the same way.)

Related

Linux bare system calls, not glibc

I'm reading an article that explains how to call bare syscalls without passing through glibc. To call chmod and exit, use:
#include <linux/unistd.h>
_syscall2(int,chmod,char*,f,int,m)
_syscall1(int,exit,int,r)
My gcc complains about them. What are their use, how do they work?
$ gcc --version
gcc (Ubuntu 7.4.0-1ubuntu1~18.04) 7.4.0
$ gcc e.c
e.c:2:15: error: unknown type name ‘setresuid’; did you mean ‘__NR_setresuid’?
_syscall3(int,setresuid,int,r,int,e,int,s)
^~~~~~~~~
__NR_setresuid
e.c:2:29: error: unknown type name ‘r’
_syscall3(int,setresuid,int,r,int,e,int,s)
^
e.c:2:35: error: unknown type name ‘e’
_syscall3(int,setresuid,int,r,int,e,int,s)
^
e.c:2:41: error: unknown type name ‘s’
_syscall3(int,setresuid,int,r,int,e,int,s)
^
Your article is probably obsolete.
If you code in C, there is no reason to avoid using the syscalls(2) (notice the plural) as documented. Be also aware of the vdso(7). You could use some other C standard library than the glibc (e.g. musl-libc, dietlibc, etc...) and you might (but that is not recommended) statically link it.
You might use syscall(2) (notice the singular) instead. I see no reason to do that, e.g. use read(2) or mmap(2) without syscall.
The Assembly HowTo might be an interesting read (beware, it might be too 32 bits centric, most Linux PCs today are 64 bits x86-64).
See also osdev.org
BTW, some old Unixes (e.g. Solaris) had a libsys providing just the syscalls, and their libc linked to it. I would like a libsys too! But on current Linux systems, it does not really matter, since almost every process (running some dynamically linked ELF executable) is mmap(2)-ing, after ld-linux.so(8), several segments and sections of your libc.so.6; for details, read Drepper's How to write a shared library (since it also explains in details how shared libraries actually work). Use also pmap(1) on some running process (e.g. pmap $$ in a shell).
Some rare syscalls (e.g. userfaultfd(2) today 2Q2019) are not known by the glibc. They are an exception, because most system calls are wrapped by your libc (the wrapping usually just deals with errno(3) setting on failure). Be aware of strace(1).
And you also should read Operating Systems: Three Easy Pieces (it is a freely downloadable book, explaining the role of, and reason for, system calls)

Force specified function to be linked to a specified lib when compiling/linking

I am wondering whether it is possible to force the linker to use some specified function to link to when compiling/linking.
I am using the LD_PRELOAD environment variable to hook some specified functions but I am not so familiar with linker so there are some troubles. I am hooking the standard open() system call to add some functionalities so that when users use the open() system call, I can collect some data. Basically, I am doing something like this:
int open(int fd, int flags, ...) //(1)
{
// add some functionalities here
return open(...); // (2), return the original open system call
}
Obviously, this cannot work, as it would call into an infinite loop... So I am wondering whether I can force the linker to link some function to some specified dynamic library so that it would not cause an infinite loop. In the example above, it would be perfect for the "open()" system call at (2) to be linked to the standard library.
As for now, because I set the LD_PRELOAD as:
export LD_PRELOAD=/path/to/my_open.so
whenever a program that has an open() function inside is loaded, the dynamic linker would link that open() to my my_open.so. And that is the same for my open(): when the linker tries to link the open() at (2), it would also try to link that to my open() at (1), resulting in an infinite loop.
Any idea?
The detailed algorithm about linking dynamic symbols can be found in man ld.so.
The ELF format allows to insert a symbol open##VERSION. This is useful to keep different versions of libc in the same time. Probably you want to keep your own .so library in LD_LIBRARY_PATH.
See here for details.
You can retrieve the original implementation of open using dlsym (RTLD_NEXT, "open"). There is no other reliable way to reach the original definition of open from an LD_PRELOAD library.
It might be instructive to look at projects such as fakeroot and cwrap, to see how they handle this.

Where is the definition of the POSIX function "stat" on Linux?

On Windows, stat and pretty much all other C/POSIX functions Windows supplies are defined in msvcrt.dll, which is the C runtime library.
On Linux, I know a lot of POSIX C functions are system calls. I also know when linking a program, you can't have undefined references. I have searched all so files in /lib and /usr/lib for the symbol stat or "mangled/prefixed" form but have not found anything. This is the command I used:
objdump -T /lib/*.so* /usr/lib/*.so* | grep "stat"
It didn't turn up the stat I was looking for.
So my question becomes: where is it, and any other "system calls" defined?
On my Linux machine, I can find the stat (weak) symbol and __stat (non-weak) in /usr/lib/libc.a
You might make linux kernel system calls without even using the libc (but this is probably a bad practice). The Linux Assembly Howto explains (in its chapters 5 & 6) how to do that (on x86 Linux 32 bits at least).
But I think it is a bad idea. Going thru the libc is good practice, and might even be faster (because e.g. of VDSO), and is more portable.
First of all stat is ambiguous; there's a stat syscall and there is a function stat that can be called from user space which calls the syscall. That last function is (on my system at least) defined in /usr/include/sys/stat.h (that's right, it's in the header file). It actually has several definitions (all one liners that call a different function, like e.g. __fxstat) of which one is chosen depending on compiler and system and whatnots.
Anyhow, stat (and other syscalls) are just wrappers that call the kernel (usually with a lot of orchestration). That is why I was initially confused about what you meant. I hope though, I could help despite my unhelpful first comment.
You can call it with syscall(2)
#include <sys/syscall.h>
...
syscall(SYS_stat, path, buf);
see also Linux syscall reference: http://syscalls.kernelgrok.com/

Question about overriding C standard library functions and how to link everything together

I made my own implementation of _init , malloc , free ( and others ).
Inside these functions I use the dlfcn.h (dlopen , dlsym etc) library to call the actual standard versions. I put then in a single file and compile them as a shared library ( memory.so ). When I wish to run an executable and make it call my versions of these functions I simply set LD_PRELOAD=memory.so .
The problem is that I have a number of other modules which memory.c depends on. These include a file containing functions to scan elf files ( symbols.c ) and my own implementation of a hash table ( hashtable.c ) which I use to keep track of memory leaks among others.
My question is if there is a way to separately compile hashtable.c & symbols.c so any malloc references are resolved with the standard library and not with the ones included on memory.c. I could of course use the dlfcn.h libraries on everything that memory.c depends on but I would prefer it if there was a way to avoid that.
I still haven't completely figured out how linking works so any help would be appreciated.
Thank you
If you are working with glibc you can use alternative non-overriden function names:
[max#truth ~]$ nm --defined-only --dynamic /lib64/libc.so.6 | egrep "malloc\b"
0000003e56079540 T __libc_malloc
0000003e56079540 T malloc
Note the same function address in the above. In other words, malloc() function is given two names, so that the original malloc() version is available under __libc_malloc() name in case malloc() has been interposed.
A quick grep on glibc sources reveals the only caller of __libc_malloc() is mcheck. These function aliases are a glibc implementation detail and there is no header for them. malloc/mcheck.c declares the internal functions as below:
extern __typeof (malloc) __libc_malloc;
extern __typeof (free) __libc_free;
extern __typeof (realloc) __libc_realloc;
Other C libraries may have differently named aliases, so using dlsym() to get the original malloc() address is more portable.
First it is important to note there is no need to do what you want to do for memory debuggers in Linux as glibc provides specific hook functions for memory functions (see: http://www.gnu.org/s/libc/manual/html_node/Allocation-Debugging.html)
But disregarding this, the general solution is to NOT use dlopen() to get a reference to glibc for dlsym() but rather use the magical handle RTLD_NEXT. Here is the relevant part from the dlopen() man page:
"There are two special pseudo-handles, RTLD_DEFAULT and RTLD_NEXT. The former will find the first occurrence of the desired symbol using the default library search order. The latter will find the next occurrence of a function in the search order after the current library. This allows one to provide a wrapper around a function in another shared library."
See for example: http://developers.sun.com/solaris/articles/lib_interposers_code.html
You could take a look at electric fence. It overrides a lot of standard functions to do various memory debugging.

Function interposition in Linux without dlsym

I'm currently working on a project where I need to track the usage of several system calls and low-level functions like mmap, brk, sbrk. So far, I've been doing this using function interposition: I write a wrapper function with the same name as the function I'm replacing (mmap for example), and I load it in a program by setting the LD_PRELOAD environment variable. I call the real function through a pointer that I load with dlsym.
Unfortunately, one of the functions I want to wrap, sbrk, is used internally by dlsym, so the program crashes when I try to load the symbol. sbrk is not a system call in Linux, so I can't simply use syscall to call it indirectly.
So my question is, how can I call a library function from a wrapper function of the same name without using dlsym? Is there any compiler trick (using gcc) that lets me refer to the original function?
see ld's option --wrap symbol. From the man page:
--wrap symbol Use a wrapper function for symbol. Any undefined
reference to symbol will be resolved
to "__wrap_symbol". Any undefined
reference to "__real_symbol" will
be resolved to symbol.
This can be used to provide a
wrapper for a system function. The
wrapper function should be called
"__wrap_symbol". If it wishes to call
the system function, it should call
"__real_symbol".
Here is a trivial example:
void *
__wrap_malloc (size_t c)
{
printf ("malloc called with %zu\n", c);
return __real_malloc (c);
}
If you link other code with this
file using --wrap malloc, then all
calls to "malloc" will call the
function "__wrap_malloc" instead. The
call to "__real_malloc" in
"__wrap_malloc" will call the real
"malloc" function.
You may wish to provide a
"__real_malloc" function as well, so
that links without the --wrap option
will succeed. If you do this, you
should not put the definition of
"__real_malloc" in the same file as
"__wrap_malloc"; if you do, the
assembler may resolve the call before
the linker has a chance to wrap it to
"malloc".
The other option is to possibly look at the source for ltrace, it is more or less does the same thing :-P.
Here's an idea though. You could have your LD_PRELOAD'ed library change the PLT entries to point to your code. This you technically the sbrk() function is still callable from your code nativly.
You can examine function invocation unobtrusively using tools such as:
gdb
ltrace
systemtap
These tools allow a monitor program to inform you when a function is called, and allow you to interrogate the arguments.
The main differences are:
gdb is interactive, but powerful
ltrace simple to use, but you can only print the function name
systemtap is not interactive, but it can be very fast, and is powerful.
If you are running a host system with glibc, the libc has some internal back end to the runtime dynamic linker that I used some time ago. If I recall correctly, I think it's called '__libc_dlsym'. (To check, "$ readelf -s /usr/lib/libc.a | grep dlsym" should help.) Declare it as an externally linked function with the same arguments and return value that dlsym has and use it to wrap dlsym itself.
Does truss not work on your system? It works perfectly for this kind of things here on Solaris.

Resources