2

The source gets printed, but no open: or open64: gets printed. How to fix this? Thanks!

/*
gcc -o emload emload.c -ldl
./emload
*/

// emload.c

#define _GNU_SOURCE

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <stdarg.h>

typedef int   (*orig_open_func_type)(const char *__file, int flags, ...);
typedef int   (*orig_openat_func_type)(int dirfd, const char *__file, int flags, ...);


int open(const char *__file, int __oflag, ...)
{
    orig_open_func_type orig_func;
    orig_func = (orig_open_func_type)dlsym(RTLD_NEXT, "open");
    int res = 0;

    if (__oflag & O_CREAT) {
        va_list ap;
        va_start(ap, __oflag);
        int mode = va_arg(ap, unsigned);
        res = orig_func(__file, __oflag, mode);
        va_end(ap);
    }
    else
        res = orig_func(__file, __oflag);

    printf("open: %d (%s)\n", res, __file);
    return res;
}

int open64(const char *__file, int __oflag, ...)
{
    orig_open_func_type orig_func;
    orig_func = (orig_open_func_type)dlsym(RTLD_NEXT, "open64");
    int res = 0;

    if (__oflag & O_CREAT) {
        va_list ap;
        va_start(ap, __oflag);
        int mode = va_arg(ap, unsigned);
        res = orig_func(__file, __oflag, mode);
        va_end(ap);
    }
    else
        res = orig_func(__file, __oflag);

    printf("open64: %d (%s)\n", res, __file);
    return res;
}

int openat(int dirfd, const char *__file, int __oflag, ...)
{
    orig_openat_func_type orig_func = (orig_openat_func_type)dlsym(RTLD_NEXT, "openat");
    int res = 0;

    if (__oflag & O_CREAT) {
        va_list ap;
        va_start(ap, __oflag);
        int mode = va_arg(ap, unsigned);
        res = orig_func(dirfd, __file, __oflag, mode);
        va_end(ap);
    }
    else
        res = orig_func(dirfd, __file, __oflag);

    printf("openat: %d (%s)\n", res, __file);
    return res;
}

char source[2 << 20];

int main(int argc, char **argv, char **env)
{
    FILE* f = fopen("emload.c", "r");
    fread(source, sizeof(source), 1, f);
    puts(source);
    fclose(f);
    return 0;
}
2
  • Does it actually work with LD_PRELOAD? glibc seems to use its internal __open explicitly inside an internal file opening function, and this gets resolved to __GI___libc_open. I don't think you'll be able to override it even with LD_PRELOAD, since it's not a call to open. Commented Oct 8, 2021 at 22:04
  • Just tried, it also does not work :( It seems that it's impossible to override open at the syscall level with this simple trick :( Was it changed only in recent versions of glibc? Because there are plenty of questions / repos online that showcase these sort of overrides - those would be useless if it doesn't even work for a simple fopen usage. Commented Oct 8, 2021 at 22:20

1 Answer 1

1

GLIBC's fopen calls the syscall wrapper directly, without any address resolution, so you're out of luck here. Your other options are:

  • Use ptrace(2) from a separate process, tracing syscalls via PTRACE_SYSCALL requests. This will stop on any syscall, not just the ones you need, so may potentially degrade performance.
  • Patch the wrapper in memory to a jump to your override. This may make it harder to execute the original code, though, because you'd need to analyze its first several instructions (that you overwrite) to reproduce their effect. Or, you can just reimplement the wrapper completely, avoiding the return to the original version.
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.