libfaketime icon indicating copy to clipboard operation
libfaketime copied to clipboard

`fstatat()` not intercepted (with glibc >= 2.33?)

Open mgorny opened this issue 1 year ago • 1 comments

It looks like libfaketime does not intercept fstatat().

This can be reproduced with the following example:

#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>

int main() {
	struct stat st;

	stat("1", &st);
	printf("%ld\n", st.st_mtime);
	fstatat(AT_FDCWD, "1", &st, 0);
	printf("%ld\n", st.st_mtime);

	return 0;
}
$ touch 1
$ FAKETIME='2024-01-01 00:00:00' LD_PRELOAD=/tmp/libfaketime/src/libfaketime.so.1 ./a.out 
1704063600
1727378293

Apparently the code is referring to __fxstatat*() but it looks like glibc is using plain fstatat and fstatat64 since 2.33:

$ readelf -W -s /usr/lib64/libc.so.6  | grep f.*statat
   607: 00000000001043f0    50 FUNC    WEAK   DEFAULT   13 fstatat@@GLIBC_2.33
   725: 00000000001043f0    50 FUNC    WEAK   DEFAULT   13 fstatat64@@GLIBC_2.33
  2588: 00000000001163a0   100 FUNC    GLOBAL DEFAULT   13 __fxstatat@@GLIBC_2.4
  3033: 00000000001163a0   100 FUNC    GLOBAL DEFAULT   13 __fxstatat64@@GLIBC_2.4

mgorny avatar Sep 26 '24 19:09 mgorny

Just a small datapoint:

We may be seeing something similar on ubuntu jammy (glibc 2.35) -- we run a backport of dovecot-2.3.21.1 there, and use faketime ... dovecot-lda to antedate delivery timestamps, and are seeing spurious warnings coming from https://github.com/dovecot/core/blob/d492236fa077cba1222695ca3267afb767235672/src/lib/file-dotlock.c#L585 .

However, that dovecot code calls fstat() instead of fstatat(), and when running a modified version of your reproducer to call fstat, those calls are getting intercepted by libfaketime, so I don't get what's going on here yet.

Sample output here:

$ touch 1 ; ./faketime -f -1d  /tmp/henk
stat 1737468826
fstat 1737468826
fstatat 1737555226
time() 1737468826
$ cat /tmp/henk.c
#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>

int main() {
	struct stat st;

	stat("1", &st);
	printf("stat %ld\n", st.st_ctime);
	int fd = open("1", O_RDONLY);
	fstat(fd, &st);
	close(fd);
	printf("fstat %ld\n", st.st_ctime);
	fstatat(AT_FDCWD, "1", &st, 0);
	printf("fstatat %ld\n", st.st_ctime);

	time_t now = time(NULL);
	printf("time() %ld\n", now);

	return 0;
}

In our case this warning seems to be harmless so I'll just ignore it.

jap avatar Jan 22 '25 14:01 jap