From: Mark Wielaard Date: Mon, 3 Sep 2018 09:54:38 +0000 (+0200) Subject: Bug 397354 utimensat should ignore tv_sec if tv_nsec is UTIME_NOW/OMIT. X-Git-Tag: VALGRIND_3_14_0~40 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=790f5f3018f807153339e441e7aea1414f4b5c8d;p=thirdparty%2Fvalgrind.git Bug 397354 utimensat should ignore tv_sec if tv_nsec is UTIME_NOW/OMIT. When code uses utimensat with UTIME_NOW or UTIME_OMIT valgrind memcheck would generate a warning. But as the utimensat manpage says: If the tv_nsec field of one of the timespec structures has the special value UTIME_NOW, then the corresponding file timestamp is set to the current time. If the tv_nsec field of one of the timespec structures has the special value UTIME_OMIT, then the corresponding file timestamp is left unchanged. In both of these cases, the value of the corre‐ sponding tv_sec field is ignored. So ignore the timespec tv_sec when tv_nsec is set to UTIME_NOW or UTIME_OMIT. --- diff --git a/NEWS b/NEWS index 982e3ec829..c79d775092 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 2c96fedf0c..90d4a8586f 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 815f658e12..b4c60854a3 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 */