Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Libfaketime not working on MacOS 12 Monterey #357

Closed
ronrother opened this issue Dec 9, 2021 · 1 comment
Closed

Libfaketime not working on MacOS 12 Monterey #357

ronrother opened this issue Dec 9, 2021 · 1 comment

Comments

@ronrother
Copy link

Hi @wolfcw

I'm having trouble getting libfaketime to work with MacOS 12, possibly due to changes in how dyld works. I am using an M1 mac, but it doesn't seem to be related to the architecture.
Repro (from libfaketime repo root):

make

cat <<EOF > monterepro.c
#include <stdio.h>
#include <time.h>
#include <dlfcn.h>

static int (*next_clock_gettime) (clockid_t clk_id, struct timespec *tp);

int main()
{
    // This will print 2021
    struct timespec now;
    clock_gettime(CLOCK_REALTIME, &now);
    printf(ctime(&now));

    // clock_gettime was loaded from /usr/lib/system/libsystem_c.dylib
    Dl_info dl_info;
    dladdr((void *)clock_gettime, &dl_info);
    printf("%s\n", dl_info.dli_fname);

    // Libfaketime itself works -- the block below prints 2029
    void* handle = dlopen("./src/libfaketime.1.dylib", RTLD_LAZY);
    next_clock_gettime = dlsym(handle, "clock_gettime");
    next_clock_gettime(CLOCK_REALTIME, &now);
    printf(ctime(&now));
}
EOF

clang -o monterepro monterepro.c

DYLD_INSERT_LIBRARIES=./src/libfaketime.1.dylib DYLD_FORCE_FLAT_NAMESPACE=YES FAKETIME='@2029-08-14 21:59:54' ./monterepro

At the end of the output, you should see:

Thu Dec  9 xx:xx:xx 2021
/usr/lib/system/libsystem_c.dylib
Tue Aug 14 21:59:54 2029

It looks like not matter what I do, the clock functions are loaded from libsystem_c.dylib. Running with DYLD_PRINT_LIBRARIES=YES shows that libfaketime is indeed being loaded:

>  libfaketime(master): DYLD_INSERT_LIBRARIES=./src/libfaketime.1.dylib DYLD_PRINT_LIBRARIES=YES DYLD_FORCE_FLAT_NAMESPACE=YES FAKETIME='@2029-08-14 21:59:54' ./monterepro
dyld[70537]: <31AA8C31-5441-300A-8FA6-F2000B296E25> /Users/ronrother/libfaketime/monterepro
dyld[70537]: <9905DE48-8EA9-3106-966C-E80EC7BA33B9> /Users/ronrother/libfaketime/src/libfaketime.1.dylib
...

But DYLD_PRINT_BINDINGS suggests libfaketime is not taking precedence:

>  libfaketime(master): DYLD_INSERT_LIBRARIES=./src/libfaketime.1.dylib DYLD_PRINT_BINDINGS=YES DYLD_FORCE_FLAT_NAMESPACE=YES FAKETIME='@2029-08-14 21:59:54' ./monterepro
...
dyld[77121]: <monterepro/bind#0> -> 0x1bc324d3c (libsystem_c.dylib/_clock_gettime)
...

This style of interposition still works with functions from other libraries, but doesn't seem to work with functions from libsystem.

For the record:
I had success using this approach: http://toves.freeshell.org/interpose/. By copying this DYLD_INTERPOSE macro from https://opensource.apple.com/source/dyld/dyld-97.1/include/mach-o/dyld-interposing.h.auto.html, renaming clock_gettime in libfaketime.c to interposed_clock_gettime, applying DYLD_INTERPOSE to it and calling clock_gettime directly instead of using real_clock_gettime, I got it to work (as a POC):

...
#define DYLD_INTERPOSE(_replacment,_replacee) \
   __attribute__((used)) static struct{ const void* replacment; const void* replacee; } _interpose_##_replacee \
            __attribute__ ((section ("__DATA,__interpose"))) = { (const void*)(unsigned long)&_replacment, (const void*)(unsigned long)&_replacee };

# renamed from clock_gettime
int interposed_clock_gettime(clockid_t clk_id, struct timespec *tp)
{
...
DONT_FAKE_TIME(result = (*clock_gettime)(clk_id, tp));
...
}

DYLD_INTERPOSE(interposed_clock_gettime, clock_gettime);

But it looks like this approach would require a large refactor, and I'm not sure how far it would be in terms of backwards-compatibility.

@wolfcw
Copy link
Owner

wolfcw commented Feb 20, 2022

Basic functionality should work on Monterey meanwhile again. I'm open for any improvements.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants