How does sanitizer_common_syscalls.inc work?

In rtsan, we want to detect any call of a system call, and abort if we are in a real-time context.

This led me to sanitizer_common_syscalls, which (it appears) tries to implement pre and post system call hooks for all syscalls.

Can anyone help me understand how this works, and if this is the right mechanism to use to implement an “all system calls” interceptor?

Some questions:

  • When are these functions invoked? Do I need to configure rtsan to call them?

__sanitizer_syscall_pre_impl_##name
__sanitizer_syscall_post_impl_##name

  • Do these intercept the libc functions, or actually just interpose when the syscall is called? By what mechanism does that work?

  • Is there any similar mechanism on darwin systems?

Polite ping to @eugenis and @vitalybuka as it appears you’ve done a lot of work in this file.

These are meant to handle Linux system calls, but the actual interception mechanism is not included. They are also quite incomplete, as they were implemented only as needed - typically for system calls that do not have libc wrappers or are called raw for other reasons.

There is nothing for Darwin.

For interception, I’d look at ptrace or seccomp-bpf. It would also make sense to use these handlers in the interception of syscall() function, but that would require reverse-mapping syscall numbers to names.

1 Like

sanitizer_common_syscall provides hooks to implement wrappers around syscalls, e.g. in one of the tests:

int mypipe(int pipefd[2]) {
  __sanitizer_syscall_pre_pipe(pipefd);
  int res = syscall(SYS_pipe2, pipefd, 0);
  __sanitizer_syscall_post_pipe(res, pipefd);
  return res;
}

So libraries that do raw syscalls should use these pre/post callbacks.

But the interceptors provided by the runtimes out of the box all override libc functions.

If you want a guaranteed way to intercept all syscalls on Linux, seccomp is a much more reliable way to do that. You could enable and disable seccomp filters for real-time contexts. Example: Using simple seccomp filters

Sandboxes use seccomp to do syscall filtering, and in your case it sounds like you want to set up regions where you “sandbox” all syscalls to simply abort the program. For one-off experiments sandbox2 might be useful and provide some inspiration. But if you want similar functionality in rtsan, you need to re-implement the sandboxing logic using plain seccomp.

1 Like

Thank you both for the info. Really helpful. I had not heard of seccomp.

@melver do you know if it is possible to do a custom action such as calling a method when seccomp detects a system call? In my brief research, it seems like you can only do some pre-defined actions (or sigtrap, which may be too much overhead for us)

Your best option is probably receiving a signal, and then doing something from there. Also note there’s ptrace()'s PTRACE_SYSCALL. But not sure that’s easier or better for the rtsan runtime.

Overhead-wise, if you only need to enable the seccomp filter for some region of code, it should be tolerable.

Great, thanks again for this info!