[PATCH] y2038: linux: Provide __recvmmsg_time64 implementation

Lukasz Majewski lukma@denx.de
Thu Apr 9 13:30:41 GMT 2020


Hi Stepan,

> 08.04.2020 в 13:51:15 +0200 Lukasz Majewski написал:
> > This patch provides new __recvmmsg_time64 explicit 64 bit function
> > for receiving messages from a socket with absolute timeout.
> > Moreover, a 32 bit version - __recvmmsg has been refactored to
> > internally use __recvmmsg_time64.
> > 
> > The __recvmmsg is now supposed to be used on systems still
> > supporting 32 bit time (__TIMESIZE != 64) - hence the necessary
> > conversion to 64 bit struct __timespec64 from struct timespec.
> > 
> > The new recvmmsg_time64 syscall available from Linux 5.1+ has been
> > used, when applicable.
> > 
> > Build tests:
> > - ./src/scripts/build-many-glibcs.py glibcs
> > 
> > Run-time tests:
> > - Run specific tests on ARM/x86 32bit systems (qemu):
> >   https://github.com/lmajewski/meta-y2038 and run tests:
> >   https://github.com/lmajewski/y2038-tests/commits/master
> > 
> > Linux kernel, headers and minimal kernel version for glibc build
> > test matrix:
> > - Linux v5.1 (with recvmmsg_time64) and glibc built with v5.1 as
> >   minimal kernel version (--enable-kernel="5.1.0")
> >   The __ASSUME_TIME64_SYSCALLS flag defined.
> > 
> > - Linux v5.1 and default minimal kernel version
> >   The __ASSUME_TIME64_SYSCALLS not defined, but kernel supports
> > recvmmsg_time64 syscall.
> > 
> > - Linux v4.19 (no recvmmsg_time64 support) with default minimal
> > kernel version for contemporary glibc (3.2.0)
> >   This kernel doesn't support recvmmsg_time64 syscall, so the
> > fallback to recvmmsg is tested.
> > 
> > Above tests were performed with Y2038 redirection applied as well
> > as without (so the __TIMESIZE != 64 execution path is checked as
> > well).  
> 
> Note that this patch is broken for m68k and s390.  And future
> revisions of the patch have potential to break s390x running on
> kernels older than 4.3.
> 
> >  int
> > -recvmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen,
> > int flags,
> > -	  struct timespec *tmo)
> > +__recvmmsg_time64 (int fd, struct mmsghdr *vmessages, unsigned int
> > vlen,
> > +                   int flags, struct __timespec64 *tmo)
> >  {
> >  #ifdef __ASSUME_RECVMMSG_SYSCALL
> > -  return SYSCALL_CANCEL (recvmmsg, fd, vmessages, vlen, flags,
> > tmo); +# ifdef __ASSUME_TIME64_SYSCALLS
> > +#  ifndef __NR_recvmmsg_time64
> > +#   define __NR_recvmmsg_time64 __NR_recvmmsg
> > +#  endif
> > +  return SYSCALL_CANCEL (recvmmsg_time64, fd, vmessages, vlen,
> > flags, tmo); +# else
> > +  int ret = SYSCALL_CANCEL (recvmmsg_time64, fd, vmessages, vlen,
> > flags, tmo);
> > +  if (ret == 0 || errno != ENOSYS)
> > +    return ret;
> > +
> > +  struct timespec ts32;
> > +  if (tmo != NULL)
> > +    {
> > +      if (! in_time_t_range (tmo->tv_sec))
> > +        {
> > +          __set_errno (EOVERFLOW);
> > +          return -1;
> > +        }
> > +
> > +      ts32 = valid_timespec64_to_timespec (*tmo);
> > +    }
> > +
> > +  return SYSCALL_CANCEL (recvmmsg, fd, vmessages, vlen, flags,
> > +                         tmo != NULL ? &ts32 : NULL);
> > +# endif
> >  #else
> >    return SOCKETCALL_CANCEL (recvmmsg, fd, vmessages, vlen, flags,
> > tmo); #endif
> >  }  
> 
> !defined __ASSUME_RECVMMSG_SYSCALL case is broken for 32-bit
> architectures.  It can be done like this:
> 
> #ifdef __ASSUME_TIME64_SYSCALLS
> # ifdef __ASSUME_RECVMMSG_SYSCALL
> #  ifndef __NR_recvmmsg_time64
> #   define __NR_recvmmsg_time64 __NR_recvmmsg
> #  endif
>   SYSCALL_CANCEL (recvmmsg_time64, …
> # else
>   SOCKETCALL_CANCEL (recvmmsg, …
> # endif
> #else
>   SYSCALL_CANCEL (recvmmsg_time64, …
>   convert input
> # ifdef __ASSUME_RECVMMSG_SYSCALL
>   SYSCALL_CANCEL (recvmmsg, …
> # else
>   SOCKETCALL_CANCEL (recvmmsg, …
> # endif
>   convert output
> #endif
> 
> but I think Joseph opposed to __ASSUME_TIME64_SYSCALLS being used
> here (and comment near __ASSUME_TIME64_SYSCALLS does not mention
> recvmmsg).
> 
> Note that there are 5 relevant cases:
> 
> 1. recvmmsg syscall always exists and uses 64-bit time_t.
> 2. recvmmsg_time64 syscall always exists.
> 3. socketcall always exists and uses 64-bit time_t.
> 4. recvmmsg syscall with 32-bit time_t and recvmmsg_time64 exist but
> one of them may be unavailable at runtime (due to old or
> !COMPAT_32BIT_TIME kernel).
> 5. socketcall with 32-bit time_t and recvmmsg_time64 exist but one of
> them may be unavailable at runtime (due to old or !COMPAT_32BIT_TIME
> kernel).

I've grepped the sources and it seems like the
__ASSUME_RECVMMSG_SYSCALL is undefined only for m68k and s390 when the
kernel is less than 4.3 (as you pointed out above).

IMHO, there is no hurry to accept this patch and I think that it would
be better to wait for glibc minimal supported kernel is bumped above
4.3 and apply this patch then.

The same situation is with statx being always available (for all
supported archs) after 4.13 Linux.


Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <https://sourceware.org/pipermail/libc-alpha/attachments/20200409/f471f812/attachment.sig>


More information about the Libc-alpha mailing list