cvariadic-functionsdlopeninterception

Intercepting and redirecting fcntl calls


fcntl is defined as a vararg function int fcntl(int fd, int action, ...) which sometimes takes an int arg and sometimes void* arg.

I'd like to write a logging interceptor for this libc function (using dlsym(RTLD_NEXT, "fcntl")).

The culprit is that the arg type sizeof for int and void* might not match - so we can't just va_arg and pass it down. How to write such an interceptor correctly and properly and redirect to the libc's underlying orig_fcntl (loaded with dlsym)?

Thanks!


Solution

  • How to write such an interceptor correctly and properly and redirect to the libc's underlying orig_fcntl (loaded with dlsym)?

    The actual implementation has to accept either argument. On most systems it will be passed in the same register (or the same stack slot) for either type, and so you can use Andrew Henle's solution: pretend that the last argument is a void *arg, and pass that to the original fcntl.

    If you are on a system where the ABI specifies different way to pass an argument to variadic function depending on its type, you'll have to read the ABI specification closely and do what it says.