Re: [PATCH] y2038: uapi: use 64-bit __kernel_old_timespec::tv_nsec on x32

From: Thomas Weißschuh

Date: Tue Apr 14 2026 - 06:23:24 EST


On Fri, Feb 27, 2026 at 10:53:52AM +0100, Thomas Weißschuh wrote:
> On Fri, Feb 27, 2026 at 10:05:25AM +0100, Arnd Bergmann wrote:
> > On Fri, Feb 27, 2026, at 08:18, Thomas Weißschuh wrote:
> > > 'struct __kernel_old_timespec' represents the 'native' time ABI of the
> > > kernel. On 32-bit systems it uses 32-bit fields and on 64-bit systems
> > > it uses 64-bit fields.
> > > However the x86 x32 ABI uses the 64-bit time ABI natively.
> > > This is correctly handled for the 'tv_sec' fields, through the typedefs
> > > of '__kernel_old_time_t' -> '__kernel_long_t' -> 'long long'. The same
> > > treatment was missed for 'tv_nsec'.
> >
> > Not sure about this patch, the choice of 'long' was clearly deliberate
> > here because that is what POSIX mandates for 'struct timespec', and what
> > glibc uses as well. Any access to an actual userspec timespec
> > is supposed to go through get_timespec64(), which handles the padding
> > like this

Actually, glibc does *not* use 'long' for tv_nsec on x32.
Instead it uses 'long long', as proposed in this patch.

> Do we need to follow POSIX here? This is not a POSIX type.
> POSIX also specifies 'tv_sec' to be 'time_t', which it isn't here.
>
> Weirdly enough timespec(3type) says this:
>
> tv_nsec is of an implementation-defined signed type capable of
> holding the specified range. Under glibc, this is usually long,
> and long long on X32. It can be safely down-cast to any concrete
> 32-bit integer type for processing.
>
> Which does make sense, as x32 uses the time ABI from x86_64, and there
> tv_nsec is a 64-bit value.

(...)

> > > @@ -30,7 +30,7 @@ struct __kernel_old_timeval {
> > >
> > > struct __kernel_old_timespec {
> > > __kernel_old_time_t tv_sec; /* seconds */
> > > - long tv_nsec; /* nanoseconds */
> > > + __kernel_long_t tv_nsec; /* nanoseconds */
> > > };
> >
> > I think the hidden padding is an actual problem here, but I
> > would address that with extra padding, similar to what glibc
> > has, e.g.
> >
> > struct __kernel_old_timespec {
> > __kernel_old_time_t tv_sec; /* seconds */
> > long tv_nsec; /* nanoseconds */
> > #if defined(__x86_64__) && defined(__ILP32__)
> > long :32; /* pad to alignment */
> > #endif
> > };
>
> This patch is a fallout of [0]. With it the type assertions become simpler.
> The additional padding would not solve this "issue".
>
> > It may be better to duplicate the structure definition and keep
> > the x32 hack in arch/x86/uapi/asm/posix_types.h, the same way
> > we do for the sparc64 __kernel_old_timeval, which has a very
> > similar issue.

I am not a fan of complicating this through a new x86/posix_types.h
definition. The semantics of __kernel_long_t match perfectly and it is
also used elsewhere in this file.


Thomas