From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46188) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bO79h-0003Ie-1Z for qemu-devel@nongnu.org; Fri, 15 Jul 2016 13:44:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bO79f-0004FQ-5J for qemu-devel@nongnu.org; Fri, 15 Jul 2016 13:44:04 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:58320) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bO79e-0004EV-Ti for qemu-devel@nongnu.org; Fri, 15 Jul 2016 13:44:03 -0400 From: Peter Maydell Date: Fri, 15 Jul 2016 18:43:54 +0100 Message-Id: <1468604634-23758-1-git-send-email-peter.maydell@linaro.org> Subject: [Qemu-devel] [PATCH] linux-user: fix "really futimens" condition in sys_utimensat() List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Riku Voipio , patches@linaro.org In some configurations we implement sys_utimensat() via a wrapper that calls either futimens() or utimensat(), depending on the arguments (to handle a case where the Linux syscall API diverges from the glibc API). Fix a corner case in this handling: if the syscall is passed a NULL pathname and dirfd == AT_FDCWD, then it must fail with EFAULT. We can't handle this by passing it to glibc utimensat() because at the libc level a NULL pathname is failed with EINVAL, and we can't handle it by passing to futimens() because that would fail with EBADF. So special case it and return EFAULT directly from the wrapper. This means that if the guest calls utimes() with a NULL pathname and guest glibc converts that into a syscall utimensat(AT_FDCWD, NULL, ...) then we correctly fail it with EFAULT. Signed-off-by: Peter Maydell --- linux-user/syscall.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 0e87157..61ea58b 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -367,10 +367,15 @@ static int sys_getcwd1(char *buf, size_t size) static int sys_utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags) { - if (pathname == NULL) + if (pathname == NULL) { + if (dirfd == AT_FDCWD) { + errno = EFAULT; + return -1; + } return futimens(dirfd, times); - else + } else { return utimensat(dirfd, pathname, times, flags); + } } #elif defined(__NR_utimensat) #define __NR_sys_utimensat __NR_utimensat -- 1.9.1