How do I intercept system calls?
Use something like Linux Trace Toolkit probably.
There is also a horrible hack based on modifying entries in the system call table. This is strongly unrecommended - it is not safe against module unloading, it is not architecture independent, and it is just ugly anyway.
Having said that, it seems it's a common task for those learning their way around kernel hacking. Checkout syscalltrack module for some code that actually does this.
Basically each point value in the global sys_call_table is modified to point to a new address supplied by the kernel module. In this way when the process calls a system call, it will end up in your routine. You can then call the old value saved from the system call table to actually process the meat of the request after collecting whatever info you need.
This fails horribly for the execve system call, and there's a very good reason for this. Let's look at the prototype of sys_execve() :
asmlinkage int sys_execve(struct pt_regs regs)
Note the argument - that is not a pointer! Your attempt to intercept sys_execve in the same is not going to work. This argument indicates that the process's registers have been saved on the stack. Code inside sys_execve actually modifies these stack locations to place the PC value register at the start of the new executable - so you must let the code access the original point in the stack!
For example code that does the modification of the registers, see start_thread() called from load_elf_binary().
The simplest way to get around this problem is by calling do_execve() instead of the saved old sys_execve pointer value, duplicating the kernel's sys_execve() code. Ugly huh? Please don't ever do this in real code. If you want to provide some code in a module that kernel code needs to call, provide a hook in the kernel code as a patch, then a module on top of that (an example of this is sys_nfsservctl()).
Note that Linus removed the export of sys_call_table in 2.5 kernels.