Commit Graph

684 Commits

Author SHA1 Message Date
Wolfgang Hommel
75d91ea726 Merge pull request #533 from GeneralDisarray/implement-faketime-follow-absolute
Implement FAKETIME_FOLLOW_ABSOLUTE feature
2026-02-18 07:49:19 +01:00
Mike Rushe
6c7aa3966c Implement FAKETIME_FOLLOW_ABSOLUTE feature
See README for feature intent.
Simple regression test at test_follow_absolute.sh.
2026-02-17 12:17:48 -05:00
Wolfgang Hommel
3062fb2004 Merge pull request #530 from drolevar/fix_master
Fix several multi-arch-related issues
2026-02-01 12:17:06 +01:00
Andrij Abyzov
b687b165b2 Replace POSIX semaphore with flock() for cross-arch safety
POSIX named semaphores (sem_t) have architecture-dependent internal
layout in glibc: 32 bytes on 64-bit, 16 bytes on 32-bit. When a
64-bit faketime wrapper creates a semaphore and spawns a 32-bit child,
the child misinterprets the counter and hangs on sem_wait forever.

Extract ft_sem_* abstraction into shared ft_sem.h/ft_sem.c with three
backends: FT_POSIX (existing), FT_SYSV (existing), FT_FLOCK (new
default). The flock backend uses kernel-mediated file locking on
/dev/shm/faketime_lock_<pid>, which is architecture-independent and
auto-releases on process death.

Both libfaketime.so and the faketime wrapper now use the same shared
abstraction, ensuring protocol agreement regardless of backend.
2026-01-26 14:43:43 +01:00
Andrij Abyzov
e21bf3017a Fix cross-arch shared memory struct layout and ftruncate/munmap sizes
Replace struct timespec (arch-dependent long/time_t) with fixed-width
int64_t pairs in ft_shared_s so that 32-bit and 64-bit processes
interpret the same shared memory layout identically.

Fix ftruncate calls that allocated sizeof(uint64_t) (8 bytes) instead
of sizeof(struct ft_shared_s) (64-80 bytes) for the shared memory
region. Fix munmap in ft_cleanup using the wrong size.

Add struct layout test and cross-process shared memory functional test.
2026-01-26 13:31:55 +01:00
Wolfgang Hommel
13d47210d5 Merge pull request #528 from ppisar/gcc16
tests: Silence an unused-but-set-variable warning with GCC 16
2026-01-06 20:20:46 +01:00
Petr Písař
712733e5f0 tests: Silence an unused-but-set-variable warning with GCC 16
Compiling tests with GCC 16 results into this warning:

    gcc -shared -o libmallocintercept.so -fpic -std=gnu99 -Wall -DFAKE_STAT -Werror -Wextra  -U_FILE_OFFSET_BITS -U_TIME_BITS libmallocintercept.c
    libmallocintercept.c: In function ‘free’:
    libmallocintercept.c:79:12: error: variable ‘ptr2’ set but not used [-Werror=unused-but-set-variable=]
       79 |   long int ptr2 = (long int) ptr; ptr2 -= (long int) ptr;
	  |            ^~~~
    cc1: all warnings being treated as errors

The ptr2 variable was added in the past to silence compiler warnings,
probably for the very same reason (commits
75cbe8e507 and
2bfbe19f71). GCC 16 is smarter and
discovers that the ptr2 variables is not needed.

This patch changes the work around to "(void) unused_variable;" idiom
recommended by GCC manual and already used in print_msg().
2026-01-06 10:34:39 +01:00
Wolfgang Hommel
1e931cb4cd Merge pull request #527 from totoroyyb/master
fix: broken futex syscall when FUTEX_WAIT is used
2025-12-23 11:22:48 +01:00
Yibo Yan
026a2627af nits: remove warnings 2025-12-23 02:48:55 +00:00
Yibo Yan
7295f20288 mod: better error handling for edge cases 2025-12-23 01:26:35 +00:00
Yibo Yan
92bf909d95 fix: broken futex syscall when FUTEX_WAIT is used 2025-12-22 12:23:01 +00:00
Wolfgang Hommel
ebe76e26b0 Merge pull request #526 from rgacogne/fix-preload-hang-521
Fix: Better detection of recursive initialisation problems
2025-12-19 06:20:21 +01:00
Remi Gacogne
c0aa6189f7 Refactor ft_shm_init and ftpl_init to remove duplication
Signed-off-by: Remi Gacogne <remi.gacogne@powerdns.com>
2025-12-16 16:30:25 +01:00
Remi Gacogne
7ba95f4cb0 Fix: Better detection of recursive initialisation problems
Signed-off-by: Remi Gacogne <remi.gacogne@powerdns.com>
2025-12-16 11:50:40 +01:00
Wolfgang Hommel
aabe141783 Merge pull request #525 from TomasKorbar/master
Add const qualifiers to fix build with ISO C23
2025-12-15 12:51:49 +01:00
Tomas Korbar
dbe865dfdb Add const qualifiers to fix build with ISO C23
Fix https://github.com/wolfcw/libfaketime/issues/524
2025-12-15 11:03:21 +01:00
Wolfgang Hommel
1231a002e0 Merge pull request #522 from rbalint/fake-syscall-clock-nanosleep
Fake the clock_nanosleep syscall
2025-11-09 10:02:16 +01:00
Balint Reczey
3109728f45 Fake the clock_nanosleep syscall 2025-11-08 17:28:48 +01:00
Wolfgang Hommel
949b36e6a2 Merge pull request #519 from bjornfor/fix-semaphore-deletion
Only let the owner clean up semaphore and shared memory
2025-09-29 20:41:22 +02:00
Bjørn Forsman
0c76f27777 Only let the owner clean up semaphore and shared memory
I noticed a bug in the semaphore handling, when using the System V semaphore
backend:

  $ LD_PRELOAD=./src/libfaketime.so.1 bash -c "echo foo | sed s/foo/bar/"
  libfaketime: In lock_for_stat(), ft_sem_lock failed: Invalid argument
  [...exited with error...]

(Beware, the above command-line is not 100% deterministic; sometimes it
succeeds.)

Looking at the strace for the above command-line, it seems the bash echo
builtin process (or thread?) decides to remove the semaphore upon
exiting, while it's still in use by the sed process. sed then gets
EINVAL error ("Invalid argument") on its next semop call.

The root cause is a semantic difference between POSIX sem_unlink and
SysV semop(..., IPC_RMID), the two implementations for ft_sem_unlink:

* sem_unlink allows the semaphore to be used afterwards, as long as a
  process has a reference to the semaphore.
* semop(..., IPC_RMID) removes the semaphore immediately, and further
  use results in EINVAL error.

AFAICT, the simplest fix is to only let the owner of the semaphore (and
shared memory) do the clean up, which is what this patch does. Both
semaphore backends pass the tests with this change.
2025-09-29 13:41:57 +02:00
Wolfgang Hommel
7bfe6566b3 Merge pull request #516 from bjornfor/fix-dangling-pointer
Fix dangling pointer via ft_sem_t name field
2025-09-27 11:47:48 +02:00
Wolfgang Hommel
c2a9bc1878 Merge pull request #517 from bjornfor/portable-shebang
Use portable shebang
2025-09-27 11:47:19 +02:00
Bjørn Forsman
4d0f0b7426 doc: refer to commands by name, not absolute path
For simplicity and portability.

I left some instances in README.OSX as is, because I'm worried about
invalidating the docs.
2025-09-24 15:06:44 +02:00
Bjørn Forsman
9d63a80062 tests: replace /bin/bash with bash
For portability.
2025-09-24 15:03:34 +02:00
Bjørn Forsman
cccce3bf23 Replace #!/bin/bash shebangs with #!/usr/bin/env bash
For portability. E.g. /bin/bash doesn't exist on NixOS.
2025-09-24 15:02:44 +02:00
Bjørn Forsman
f33dda8022 Fix dangling pointer via ft_sem_t name field
ft_sem_create() is called with an argument located on the stack, which
means it's a bad idea to keep a reference to it in the 'name' field of
ft_sem_t -- the pointed to data goes out of scope and results in
unpredictable behaviour.

Fix it by making a copy of the semaphore name. Allocate a 256 char
buffer, to match existing code.

Fixes: 2649cdb156 ("Add semaphore abstraction layer")
2025-09-24 14:55:15 +02:00
Wolfgang Hommel
4fc06b90df Merge pull request #512 from sammytranGeo/correct-use-of-real-monotonic-clock
Use real clock monotonic when not faking
2025-08-23 19:33:26 +02:00
Sammy Tran
75e130c4f1 Use real clock monotonic when not faking 2025-08-13 15:15:12 -04:00
Wolfgang Hommel
066f38baac Merge pull request #510 from bjornfor/fix-musl-build
Only define stat64 when building with glibc
2025-08-07 13:14:29 +02:00
Bjørn Forsman
4de86c2145 Only define stat64 when building with glibc
musl defines stat64 as stat, leading to this build error:

  gcc -o libfaketime.o -c -std=gnu99 -Wall -Wextra -Werror -DFAKE_PTHREAD -DFAKE_STAT -DFAKE_UTIME -DFAKE_SLEEP -DFAKE_TIMERS -DFAKE_INTERNAL_CALLS -fPIC -DPREFIX='"'/nix/store/qpyvvrcas950da98mssw6ixlw7ckvyrb-libfaketime-0.9.11'"' -DLIBDIRNAME='"'/lib'"'  -Wno-nonnull-compare   libfaketime.c
  In file included from libfaketime.c:55:
  libfaketime.c:1276:5: error: redefinition of ‘stat’
   1276 | int stat64 (const char *path, struct stat64 *buf)
        |     ^~~~~~
  /nix/store/g9cgi4yyn5vrd1f9axj8gxdvwzv5ssvk-musl-1.2.5-dev/include/sys/stat.h:80:5: note: previous definition of ‘stat’ with type ‘int(const char *, struct stat *)’
     80 | int stat(const char *__restrict, struct stat *__restrict);
        |     ^~~~
  make[1]: *** [Makefile:161: libfaketime.o] Error 1

Fix it by only defining stat64 when building against glibc, since it's
not straight forward to detect musl, and it's the safest approach; there
might be other libc implementations that behave like musl.

Fixes: 53ba71e547 ("Handle stat64() call")
2025-08-07 09:19:13 +02:00
Wolfgang Hommel
ffdb51bc30 Merge pull request #507 from bjornfor/add-stat64
Handle stat64() call
2025-08-05 20:51:42 +02:00
Wolfgang Hommel
3aa2028174 Merge pull request #509 from lisanet/master
fixes issue #506 - build arch64 and arch64e separately
2025-08-03 14:27:27 +02:00
Simone Karin Lehmann
6566162e7e fix for issue #506 - build arch64 and arch64e separately and then lipo them. 2025-08-03 13:48:41 +02:00
Bjørn Forsman
53ba71e547 Handle stat64() call
This fixes missing modification of timestamps in stat() calls for
programs built with large file support (-D_FILE_OFFSET_BITS=64), both
32- and 64-bit.

Demo code:

  $ cat <<EOF >test.c
  #include <sys/stat.h>
  int main()
  {
      struct stat buf;
      return stat("/", &buf);
  }
  EOF

32-bit build:

  $ nix-shell -p gcc --argstr system i686-linux

  nix-shell$ gcc test.c && ltrace ./a.out
  __libc_start_main([ "./a.out" ] <unfinished ...>
  stat(0x804a008, 0xffa4b644, 895, 0) = 0
  +++ exited (status 0) +++

  nix-shell$ gcc -D_FILE_OFFSET_BITS=64 test.c && ltrace ./a.out
  __libc_start_main([ "./a.out" ] <unfinished ...>
  stat64(0x804a008, 0xffdcf61c, 100, 0xffdcfaeb) = 0
  +++ exited (status 0) +++

  nix-shell$ file a.out
  a.out: ELF 32-bit LSB executable, Intel 80386, [...]

64-bit build:

  $ nix-shell -p gcc

  nix-shell$ gcc test.c && ltrace ./a.out
  stat(0x402004, 0x7ffc50a9d740, 0x7ffc50a9d908, 0x403db0) = 0
  +++ exited (status 0) +++

  nix-shell$ gcc -D_FILE_OFFSET_BITS=64 test.c && ltrace ./a.out
  stat64(0x402004, 0x7ffd5cbafba0, 0x7ffd5cbafd68, 0x403db0) = 0
  +++ exited (status 0) +++

  nix-shell$ file a.out
  a.out: ELF 64-bit LSB executable, x86-64, [...]
2025-07-09 17:32:54 +02:00
Wolfgang Hommel
6404d81f63 Merge pull request #504 from bjornfor/system-v-semaphores
Add optional System V semaphores
2025-06-27 19:33:14 +02:00
Bjørn Forsman
44c578c6d6 Add optional System V semaphore backend
By building with -DFT_SEMAPHORE_BACKEND=FT_SYSV, the System V semaphore
API is unsed instead of POSIX. This works around a glibc bug[1] and
fixes https://github.com/wolfcw/libfaketime/issues/427
("libfaketime hangs forever when 32-bit process is executed within 64-bit process").
The default backend is still POSIX, in case there are regressions in the
new code.

[1] https://sourceware.org/bugzilla/show_bug.cgi?id=17980

Ref https://github.com/wolfcw/libfaketime/issues/427
2025-06-23 21:00:21 +02:00
Bjørn Forsman
2649cdb156 Add semaphore abstraction layer
Add ft_sem_*() functions that use the POSIX semaphore API.

In preparation for adding System V semaphores as an alternative to POSIX
semaphores, because glibc breaks POSIX semaphores when operating in
mixed 32- and 64-bit environments[1].

[1] https://sourceware.org/bugzilla/show_bug.cgi?id=17980
2025-06-23 16:42:49 +02:00
Bjørn Forsman
71b31e908d Add missing newline to error message 2025-06-23 16:19:26 +02:00
Wolfgang Hommel
523584abd4 Merge pull request #503 from sammytranGeo/fix-monotonic-timedwait
Fix MONOTONIC pthread_cond_timedwait when REALTIME is set
2025-06-14 13:04:11 +02:00
Sammy Tran
a2e406c669 Fix MONOTONIC pthread_cond_timedwait when REALTIME is set 2025-06-13 17:13:43 -04:00
Wolfgang Hommel
3ccdd344aa Preparations for v0.9.12 release v0.9.12 2025-06-09 14:31:15 +02:00
Wolfgang Hommel
f63569e422 Merge pull request #502 from usertam/patch/fix-fake-stat64buf-on-linux
Fix fake_stat64buf() again
2025-06-09 14:26:48 +02:00
usertam
d276658b74 libfaketime.c: fix fake_stat64buf() again
I got the logic wrong in PR #501 in the inner `#ifndef __APPLE__`.
This broke building on linux. This should fix it.
2025-06-09 19:19:37 +08:00
Wolfgang Hommel
cb48e454be Merge pull request #501 from usertam/patch/clean-up-and-readme
Fix compiler warnings and update README.OSX
2025-06-09 10:24:59 +02:00
usertam
77ae25f529 README.OSX: document about the new arm64e ABI 2025-06-08 23:23:50 +08:00
usertam
30d7defcf5 libfaketime.c: get rid of stat64 things on aarch64-darwin
To give more context, stat64 is a child of large-file support (LFS)
back in 1996, during the transition from 32-bit to 64-bit. People
wanted 64-bit inodes in 32-bit systems, hence stat and stat64.

Nowadays where everything is 64-bit, stat64 is mostly just an alias
to stat, as stat is already native 64-bit. On modern implementations
like musl, stat64 is even dropped entirely as a sane default. We
observe the same in darwin's stat.h:

  #if !__DARWIN_ONLY_64_BIT_INO_T
  struct stat64 __DARWIN_STRUCT_STAT64;
  #endif /* !__DARWIN_ONLY_64_BIT_INO_T */

Because struct stat64 doesn't ever exist on aarch64-darwin, and we
don't have to worry about people using stat64 calls, we can safely
remove all stat64 bloat, according to __DARWIN_ONLY_64_BIT_INO_T.

I nuked fake_stat64buf because only STAT64_HANDLER is using it, and
only non-darwin stat64 things use that handler. I didn't do more
because people might still use stat64 things on x86_64 (on glibc)
and other older 32-bit platforms, and we still need to hook those.

A loose follow up to PR #453. Fixes the remaining clang warnings on
aarch64-darwin.
2025-06-08 19:34:48 +08:00
Wolfgang Hommel
9f7b304dbe Merge pull request #500 from usertam/patch/fix-darwin-and-arm64e
Fix darwin and arm64e
2025-06-07 23:03:01 +02:00
usertam
0277016bb5 Makefile.OSX: add -fptrauth-* flags for arm64e to work properly
Particularly we need -fptrauth-calls, so when pthread_once indirectly
calls ftpl_really_init, it won't fail PAC.
2025-06-07 20:51:07 +08:00
usertam
0e2dbe4ae1 libfaketime.c: correct macro from __APPLEOSX__ to __APPLE__
This fixes the recursive pthread_once deadlock on darwin platforms.
It looks something like this:

  Trace/BPT trap: 5

  BUG IN CLIENT OF LIBPLATFORM: Trying to recursively lock an os_once_t

The macro __APPLEOSX__ is never defined, instead __APPLE__ should be used.
This mistake inadvertently caused system_time_from_system() to always take
the linux code path on darwin, leading to recursive calls during ftpl_init().

This was exposed by PR #488 which removed the ad-hoc recursion detection
that previously masked this issue.
2025-06-07 20:51:06 +08:00
Wolfgang Hommel
45d29c8256 Merge pull request #497 from usertam/patch/compile-both-arm64-arm64e
Compile for arm64 on darwin again
2025-06-03 21:48:40 +02:00