Hide Forgot
I'm looking at kernel-4.18.0-305.el8.x86_64. get_timespec64 in kernel/time/time.c does not clear the padding, I think: /* Zero out the padding for 32 bit systems or in compat mode */ if (IS_ENABLED(CONFIG_64BIT_TIME) && (!IS_ENABLED(CONFIG_64BIT) || in_compat_syscall())) kts.tv_nsec &= 0xFFFFFFFFUL; In our kernels IS_ENABLED(CONFIG_64BIT_TIME) is false, so this code is not compiled in, I think: Dump of assembler code for function get_timespec64: 855 { 0xffffffff8116a2e0 <+0>: callq 0xffffffff81a01920 <__fentry__> 0xffffffff8116a2e5 <+5>: push %rbx 0xffffffff8116a2e6 <+6>: mov $0x10,%edx 0xffffffff8116a2eb <+11>: mov %rdi,%rbx 0xffffffff8116a2ee <+14>: sub $0x18,%rsp 0xffffffff8116a2f2 <+18>: mov %gs:0x28,%rax 0xffffffff8116a2fb <+27>: mov %rax,0x10(%rsp) 0xffffffff8116a300 <+32>: xor %eax,%eax 856 struct __kernel_timespec kts; 857 int ret; 858 859 ret = copy_from_user(&kts, uts, sizeof(kts)); 860 if (ret) 0xffffffff8116a30a <+42>: test %eax,%eax 0xffffffff8116a30c <+44>: jne 0xffffffff8116a334 <get_timespec64+84> 861 return -EFAULT; 862 863 ts->tv_sec = kts.tv_sec; 0xffffffff8116a30e <+46>: mov (%rsp),%rdx 0xffffffff8116a312 <+50>: mov %rdx,(%rbx) 864 865 /* Zero out the padding for 32 bit systems or in compat mode */ 866 if (IS_ENABLED(CONFIG_64BIT_TIME) && (!IS_ENABLED(CONFIG_64BIT) || in_compat_syscall())) 867 kts.tv_nsec &= 0xFFFFFFFFUL; 868 869 ts->tv_nsec = kts.tv_nsec; 0xffffffff8116a315 <+53>: mov 0x8(%rsp),%rdx 0xffffffff8116a31a <+58>: mov %rdx,0x8(%rbx) 870 871 return 0; 0xffffffff8116a31e <+62>: mov 0x10(%rsp),%rcx 0xffffffff8116a323 <+67>: xor %gs:0x28,%rcx 0xffffffff8116a32c <+76>: jne 0xffffffff8116a33b <get_timespec64+91> 0xffffffff8116a32e <+78>: add $0x18,%rsp 0xffffffff8116a332 <+82>: pop %rbx 0xffffffff8116a333 <+83>: retq 0xffffffff8116a334 <+84>: mov $0xfffffff2,%eax 0xffffffff8116a339 <+89>: jmp 0xffffffff8116a31e <get_timespec64+62> 0xffffffff8116a33b <+91>: callq 0xffffffff810e09b0 <__stack_chk_fail> End of assembler dump. As a result, our kernel does not have the right userspace ABI for system calls such as utimensat_time64. Upstream decided to ignore padding, and current glibc (e.g., glibc-2.33-13.el9.i686) depends on this.
Reproducer that can be built with gcc -m32 on Red Hat Enterprise Linux 8: #include <errno.h> #include <fcntl.h> #include <stdint.h> #include <stdio.h> #include <sys/syscall.h> #include <unistd.h> int main (void) { errno = 0; uint64_t times[4] = { 1, 2 | (3ULL << 32), 4, 5 | (6ULL << 32) }; long ret = syscall (412, AT_FDCWD, "/proc/self/exe", times, 0); printf ("%ld, %m\n", ret); } “/opt/rh/gcc-toolset-10/root/usr/bin/strace ./a.out” shows: utimensat_time64(AT_FDCWD, "/proc/self/exe", [{tv_sec=1, tv_nsec=12884901890}, {tv_sec=4, tv_nsec=25769803781}], 0) = -1 EINVAL (Invalid argument) strace does not mask the padding, either, so the tv_nsec values are expected, but the EINVAL result is not. The system call should succeed.
*** Bug 1965078 has been marked as a duplicate of this bug. ***
(In reply to Florian Weimer from comment #0) > I'm looking at kernel-4.18.0-305.el8.x86_64. > > get_timespec64 in kernel/time/time.c does not clear the padding, I think: > > /* Zero out the padding for 32 bit systems or in compat mode */ > if (IS_ENABLED(CONFIG_64BIT_TIME) && (!IS_ENABLED(CONFIG_64BIT) || > in_compat_syscall())) > kts.tv_nsec &= 0xFFFFFFFFUL; > > In our kernels IS_ENABLED(CONFIG_64BIT_TIME) is false, so this code is not > compiled in, I think: Another side effect of the backport of time related patches to support time namespace. I will remove CONFIG_64BIT_TIME from the kernel source. Thanks for looking into this problem. -Longman
Since the problem described in this bug report should be resolved in a recent advisory, it has been closed with a resolution of ERRATA. For information on the advisory (Moderate: kernel security, bug fix, and enhancement update), and where to find the updated files, follow the link below. If the solution does not work for you, open a new bug report. https://access.redhat.com/errata/RHSA-2021:4356