utimensat truncates timestamp to whole second granularity

Bug #1890486 reported by Stephan Wacker
14
This bug affects 3 people
Affects Status Importance Assigned to Milestone
eCryptfs
Confirmed
Undecided
Unassigned

Bug Description

The utimensat(2) system call should set a file's modification timestamp with nanosecond resolution (or the best resolution supported by the filesystem).

With a Linux kernel 5.4 and ecryptfs, the resolution is actually one second, i.e. the fractions of a second are truncted when the touch(1) utility is used with a reference file

$ touch foo
$ touch -m -r foo bar

The result is

$ ls -l --full-time foo bar
-rw-rw-r-- 1 stephan stephan 0 2020-08-03 11:26:13.000000000 -0400 bar
-rw-rw-r-- 1 stephan stephan 0 2020-08-03 11:26:13.272034647 -0400 foo

which also shows that the first "touch foo" did the right thing.

This happens only
 * in an ecryptfs directory
 * with a Linux kernel >= 5.4

The bug does not occur
 * on the same ext4 filesystem (outside the ecryptfs directory)
 * or with ecryptfs but with a kernel version below 5.4

I also verified it in a freshly created ecryptfs directory: with encryption I get a truncated timestamp; without encryption everything is fine.

Other commands, like "cp -a" and "rsync -a" are affected, as well.

$ cp -a foo baz
$ ls -l --full-time foo bar baz
-rw-rw-r-- 1 stephan stephan 0 2020-08-03 11:26:13.000000000 -0400 bar
-rw-rw-r-- 1 stephan stephan 0 2020-08-03 11:26:13.000000000 -0400 baz
-rw-rw-r-- 1 stephan stephan 0 2020-08-03 11:26:13.272034647 -0400 foo

The strace(1) utility shows that utimensat() was called with correct values.

$ strace touch -m -r foo bar
...
utimensat(0, NULL, [UTIME_OMIT, {tv_sec=1596468373, tv_nsec=272034647} /* 2020-08-03T11:26:13.272034647-0400 */], 0) = 0

Note: I found this Changelog entry on https://kernelnewbies.org/Linux_5.4

"VFS: adds a per-superblock minimum/maximum timestamp limit for a file system, and clamps timestamps as they are written, to avoid random behavior from integer overflow as well as having different time stamps on disk vs in memory. This helps futimens(), utimensat() and utimes() syscalls to conform to POSIX defined behavior when the time being set is outside of the corresponding filesystem's supported limits"

My best guess is that ecryptfs does not correctly report 1 ns as the "supported limit".

Revision history for this message
Jason Harvey (jason-alioth) wrote (last edit ):

Can confirm and I am able to repro on Linux 5.4 on ecryptfs. Interestingly if you pass `NULL` in both of the time fields to `utimensat`, as `touch` does, full timestamp resolution is maintained.

This causes breakage with utilities such as `rclone`, which try to synchronize partly based on information such as mtime.

Changed in ecryptfs:
status: New → Confirmed
Revision history for this message
Koichi Murase (akinomyoga) wrote :

Are there any updates to this bug? I've received a report [1] in my project caused by this bug. It seems `cargo`, the Rust package manager, is also affected [2] by this bug.

- [1] https://github.com/akinomyoga/ble.sh/issues/347
- [2] https://github.com/rust-lang/cargo/issues/7775

Revision history for this message
Koichi Murase (akinomyoga) wrote :

FYI, the `rclone` breakage mentioned by Jason Harvey can be found in Ref. [3]:

- [3] https://forum.rclone.org/t/rclone-sync-does-not-properly-preserve-modification-times-when-syncing-to-ecryptfs-mounts/25841/5

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.