From c77d461cddb898f77137cbe2fbb19da1e94e064d Mon Sep 17 00:00:00 2001 From: Marc Rittinghaus Date: Mon, 24 Apr 2023 17:12:07 +0200 Subject: [PATCH] lib/vfscore: Exit sys_utimensat on all UTIME_OMIT This commit restructures the sanity checks of the input timespecs to come before all other checks and to include an early exit of both times are UTIME_OMIT. This is inline with the behavior on Linux. Signed-off-by: Marc Rittinghaus Reviewed-by: Stefan Jumarea Reviewed-by: Rares Miculescu Approved-by: Razvan Deaconescu Tested-by: Unikraft CI GitHub-Closes: #865 --- lib/vfscore/syscalls.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/lib/vfscore/syscalls.c b/lib/vfscore/syscalls.c index d85c08f55..f02c12333 100644 --- a/lib/vfscore/syscalls.c +++ b/lib/vfscore/syscalls.c @@ -1401,19 +1401,31 @@ sys_utimensat(int dirfd, const char *pathname, const struct timespec times[2], i struct dentry *dp = NULL; struct vfscore_file *fp = NULL; + if (times) { + /* Make the behavior compatible with Linux */ + if (unlikely(times[0].tv_nsec == UTIME_OMIT && + times[1].tv_nsec == UTIME_OMIT)) + return 0; + + if (unlikely(!is_timespec_valid(×[0]) || + !is_timespec_valid(×[1]))) + return EINVAL; + + init_timespec(×pec_times[0], times + 0); + init_timespec(×pec_times[1], times + 1); + } else { + init_timespec(×pec_times[0], NULL); + init_timespec(×pec_times[1], NULL); + } + /* utimensat should return ENOENT when pathname is empty */ if(pathname && pathname[0] == 0) return ENOENT; + /* Only the AT_SYMLINK_NOFOLLOW is allowed */ if (flags && !(flags & AT_SYMLINK_NOFOLLOW)) return EINVAL; - if (times && (!is_timespec_valid(×[0]) || !is_timespec_valid(×[1]))) - return EINVAL; - - init_timespec(×pec_times[0], times ? times + 0 : NULL); - init_timespec(×pec_times[1], times ? times + 1 : NULL); - if (pathname && pathname[0] == '/') { ap = strdup(pathname); if (!ap) -- 2.39.5