6

Methods of which I'm aware of intercepting system calls are the following.

  1. Using ptrace, but this seems to have a high overhead. According to my knowledge, tools like strace also use ptrace internally.
  2. Using a kernel module to change the system call table, but according to my knowledge, this method is no more possible in later linux kernels.
  3. Using LD_PRELOAD. But this won't work if for example you directly make a system call without using some wrapper library function for that system call.

So you see all the above mentioned methods have flaws. So my question is what is the way to intercept system calls without modifying the kernel and with minimal overhead.

pythonic
  • 20,589
  • 43
  • 136
  • 219
  • There is probably none, other than the ones already listed. Why can't you use `ptrace` syscall? Its overhead is often acceptable in practice (because most applications spend much more CPU time in user mode than in kernel mode doing syscalls). – Basile Starynkevitch Jul 02 '12 at 10:15
  • 1
    I would also put a code snippet here that illustrates how you are using ptrace. There might be ways to optimize it. – AndreasT Jul 02 '12 at 10:21
  • You can use `seccomp` to only ptrace certain syscalls, which will reduce the overhead. Example [here](https://www.alfonsobeato.net/tag/seccomp/). – Timmmm Nov 05 '21 at 13:41

3 Answers3

4

If you can't modify the kernel, you must modify the application. You need to somehow intercept the int/syscall/sysenter instructions, either by setting a break point there (if you can handle them within the application in Linux; you can in Windows by using SEH/VEH) or by hooking the instruction in a more intrusive way (changing it to jmp to the code that would get save the system call number and parameters, perform the original int/syscall/sysenter and jmp back).

EDIT: Oh, I've forgot to add that finding those instructions can be a challenge. You may be unable to correctly identify them in the compiled binary. You can miss some (especially those created at run time) and you can take some other instructions for int/syscall/sysenter (if your code analysis isn't perfect). OTOH, finding them at run time (by analyzing individual instructions (or blocks of them) prior to executing/emulating them) is going to incur a performance hit.

In any event, most likely the performance issues are directly related to the number of system calls being made and to the amount of logged/traced information. If you cut that down (i.e. select only the interesting system calls and parameters) and/or collect only the information about, say, the last 10000 system calls and keep the data in memory and save it to a file just once (at the end of the app), you'll have much better performance.

Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180
1

Look at using a dynamic instrumentation framework e.g. DTrace or SystemTap. One or both should be available for your platform.

ecatmur
  • 152,476
  • 27
  • 293
  • 366
1

Pintool might also help; it's available for Linux too.

Unknown
  • 5,722
  • 5
  • 43
  • 64