diff --git a/NEWS b/NEWS index 982e3ec82..c79d77509 100644 --- a/NEWS +++ b/NEWS @@ -143,6 +143,7 @@ where XXXXXX is the bug number as listed below. 396475 valgrind OS-X build: config.h not found (out-of-tree macOS builds) 396887 arch_prctl should return EINVAL on unknown option 397012 glibc ld.so uses arch_prctl on i386 +397354 utimensat should ignore timespec tv_sec if tv_nsec is UTIME_NOW/OMIT 397424 glibc 2.27 and gdb_server tests n-i-bz Fix missing workq_ops operations (macOS) diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c index 2c96fedf0..90d4a8586 100644 --- a/coregrind/m_syswrap/syswrap-linux.c +++ b/coregrind/m_syswrap/syswrap-linux.c @@ -5303,8 +5303,25 @@ PRE(sys_utimensat) int, dfd, char *, filename, struct timespec *, utimes, int, flags); if (ARG2 != 0) PRE_MEM_RASCIIZ( "utimensat(filename)", ARG2 ); - if (ARG3 != 0) - PRE_MEM_READ( "utimensat(tvp)", ARG3, 2 * sizeof(struct vki_timespec) ); + if (ARG3 != 0) { + /* If timespec.tv_nsec has the special value UTIME_NOW or UTIME_OMIT + then the tv_sec field is ignored. */ + struct vki_timespec *times = (struct vki_timespec *)(Addr)ARG3; + PRE_MEM_READ( "utimensat(times[0].tv_nsec)", + (Addr)×[0].tv_nsec, sizeof(times[0].tv_nsec)); + PRE_MEM_READ( "utimensat(times[1].tv_nsec)", + (Addr)×[1].tv_nsec, sizeof(times[1].tv_nsec)); + if (ML_(safe_to_deref)(times, 2 * sizeof(struct vki_timespec))) { + if (times[0].tv_nsec != VKI_UTIME_NOW + && times[0].tv_nsec != VKI_UTIME_OMIT) + PRE_MEM_READ( "utimensat(times[0].tv_sec)", + (Addr)×[0].tv_sec, sizeof(times[0].tv_sec)); + if (times[1].tv_nsec != VKI_UTIME_NOW + && times[1].tv_nsec != VKI_UTIME_OMIT) + PRE_MEM_READ( "utimensat(times[1].tv_sec)", + (Addr)×[1].tv_sec, sizeof(times[1].tv_sec)); + } + } } PRE(sys_newfstatat) diff --git a/include/vki/vki-linux.h b/include/vki/vki-linux.h index 815f658e1..b4c60854a 100644 --- a/include/vki/vki-linux.h +++ b/include/vki/vki-linux.h @@ -285,6 +285,10 @@ struct vki_timespec { long tv_nsec; /* nanoseconds */ }; +/* Special values for vki_timespec.tv_nsec when used with utimensat. */ +#define VKI_UTIME_NOW ((1l << 30) - 1l) +#define VKI_UTIME_OMIT ((1l << 30) - 2l) + struct vki_timeval { vki_time_t tv_sec; /* seconds */ vki_suseconds_t tv_usec; /* microseconds */