Message ID | 20221012215008.2918444-1-thomas.petazzoni@bootlin.com |
---|---|
State | Accepted |
Headers | show |
Series | Config.in: introduce BR2_TIME_BITS_64 option for Y2038 compatibility | expand |
On Wed, 2022-10-12 at 23:50 +0200, Thomas Petazzoni via buildroot wrote: > Y2038 is now almost only 15 years away, and embedded systems built > today are potentially going to still be operational in 15 years, and > even though they are supposed to receive updates by then, we all know > how things go, and potentially some of these embedded systems will > not > receive any update. > > In 2038, the signed 32-bit representation of time_t used on 32-bit > architectures will overflow, causing all time-related functions to go > back in time in a surprising way. > > The Linux kernel has already been modified to support a 64-bit > representation of time_t on 32-bit architectures, but from a C > library > perspective, the situation varies: > > - glibc uses this 64-bit time_t representation on 32-bit systems > since glibc 2.34, but only if -D_TIME_BITS=64 is > specified. Therefore, this commit adds an option to add this flag > globally to the build, when glibc is the C library and the > architecture is not 64-bit. > > - musl uses unconditionally a 64-bit time_t representation on 32-bit > systems since musl 1.2.0. So there is nothing to do here since > Buildroot has been using a musl >= 1.2.0, used since Buildroot > 2020.05. No Buildroot option is needed here. > > - uClibc-ng does not support a 64-bit time_t representation on 32- > bit > systems, so systems using uClibc-ng will not be Y2038 compliant, > at > least for now. No Buildroot option is needed here. > > It should be noted that being Y2038-compliant will only work if all > application/library code is correct. For example if an > application/library stores a timestamp in an "int" instead of using > the proper time_t type, then the mechanisms described above will not > fix this, and the application/library will continue to be broken in > terms of Y2038 support. > > Possible discussions points about this patch: > > - Should we have an option at all, or should we unconditionally pass > -D_TIME_BITS=64, like we have been doing for _FILE_OFFSET_BITS=64 > for quite some time. The reasoning for having an option is that > the mechanism is itself opt-in in glibc, and generally relatively > new, so it seemed logical for now to make it optional as well in > Buildroot. There's some chance of software being broken by enabling this, with either a compile or runtime failure. For example, applications that assume sizeof(time_t) == sizeof(long) would work on 32-bit platforms with a 32-bit time and 64-bit platforms with a 64-bit time, but fail with a 64-bit time on 32-bit. I believe I've seen this when trying to build software with that option, so turning this on unconditionally might be unwise, unless some build tests of the supported packages have been done.. > > - Should we show something (a Config.in comment?) in the musl and > uClibc-ng case to let the user know that the code is Y2038 > compliant (musl) or not Y2038 compliant (uClibc-ng). Or should > this > discussion be part of the Buildroot documentation? > > Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com> > --- > Config.in | 16 ++++++++++++++++ > package/Makefile.in | 3 +++ > 2 files changed, 19 insertions(+) > > diff --git a/Config.in b/Config.in > index 3c57c591a8..46c80fe2f0 100644 > --- a/Config.in > +++ b/Config.in > @@ -753,6 +753,22 @@ config BR2_PER_PACKAGE_DIRECTORIES > > endmenu > > +config BR2_TIME_BITS_64 > + bool "Build Y2038-ready code" > + depends on BR2_TOOLCHAIN_USES_GLIBC && !BR2_ARCH_IS_64 > + help > + This option will pass -D_TIME_BITS=64 in the compiler flags > + to ensure the glibc C library uses a 64-bit representation > + for time_t and other time types, which ensures that > + programs/libraries will correctly handle time past year > + 2038. > + > + Notes: > + - This option only has an effect with glibc >= 2.34. > + - The musl C library since its version 1.20 is > + unconditionally Y2038 compliant. > + - The uClibc-ng library is not Y2038 compliant. > + > comment "Security Hardening Options" > > config BR2_PIC_PIE_ARCH_SUPPORTS > diff --git a/package/Makefile.in b/package/Makefile.in > index 43d214bcbe..59d88bb97e 100644 > --- a/package/Makefile.in > +++ b/package/Makefile.in > @@ -163,6 +163,9 @@ TARGET_HARDENED += -D_FORTIFY_SOURCE=2 > endif > > TARGET_CPPFLAGS += -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE - > D_FILE_OFFSET_BITS=64 > +ifeq ($(BR2_TIME_BITS_64),y) > +TARGET_CPPFLAGS += -D_TIME_BITS=64 > +endif > TARGET_CFLAGS = $(TARGET_CPPFLAGS) $(TARGET_ABI) > $(TARGET_OPTIMIZATION) $(TARGET_DEBUGGING) $(TARGET_HARDENED) > TARGET_CXXFLAGS = $(TARGET_CFLAGS) > TARGET_FCFLAGS = $(TARGET_ABI) $(TARGET_OPTIMIZATION) > $(TARGET_DEBUGGING)
>>>>> "Thomas" == Thomas Petazzoni <thomas.petazzoni@bootlin.com> writes: > Y2038 is now almost only 15 years away, and embedded systems built > today are potentially going to still be operational in 15 years, and > even though they are supposed to receive updates by then, we all know > how things go, and potentially some of these embedded systems will not > receive any update. Thanks for picking this up! This has been on my todo list for a while as well!. > In 2038, the signed 32-bit representation of time_t used on 32-bit > architectures will overflow, causing all time-related functions to go > back in time in a surprising way. > The Linux kernel has already been modified to support a 64-bit > representation of time_t on 32-bit architectures, but from a C library > perspective, the situation varies: > - glibc uses this 64-bit time_t representation on 32-bit systems > since glibc 2.34, but only if -D_TIME_BITS=64 is > specified. Therefore, this commit adds an option to add this flag > globally to the build, when glibc is the C library and the > architecture is not 64-bit. > - musl uses unconditionally a 64-bit time_t representation on 32-bit > systems since musl 1.2.0. So there is nothing to do here since > Buildroot has been using a musl >= 1.2.0, used since Buildroot > 2020.05. No Buildroot option is needed here. > - uClibc-ng does not support a 64-bit time_t representation on 32-bit > systems, so systems using uClibc-ng will not be Y2038 compliant, at > least for now. No Buildroot option is needed here. > It should be noted that being Y2038-compliant will only work if all > application/library code is correct. For example if an > application/library stores a timestamp in an "int" instead of using > the proper time_t type, then the mechanisms described above will not > fix this, and the application/library will continue to be broken in > terms of Y2038 support. > Possible discussions points about this patch: > - Should we have an option at all, or should we unconditionally pass > -D_TIME_BITS=64, like we have been doing for _FILE_OFFSET_BITS=64 > for quite some time. The reasoning for having an option is that > the mechanism is itself opt-in in glibc, and generally relatively > new, so it seemed logical for now to make it optional as well in > Buildroot. I was hoping we could just do it unconditionally, given that musl does it already. Failing that, I would think we could at least make it default y. > - Should we show something (a Config.in comment?) in the musl and > uClibc-ng case to let the user know that the code is Y2038 > compliant (musl) or not Y2038 compliant (uClibc-ng). Or should this > discussion be part of the Buildroot documentation? Having a notice about this in the documentation certainly cannot harm. I'm not sure it makes sense to have it in Config.in.
On Wed, 12 Oct 2022 23:49:37 +0000 Robert Hancock <robert.hancock@calian.com> wrote: > There's some chance of software being broken by enabling this, with > either a compile or runtime failure. For example, applications that > assume sizeof(time_t) == sizeof(long) would work on 32-bit platforms > with a 32-bit time and 64-bit platforms with a 64-bit time, but fail > with a 64-bit time on 32-bit. I believe I've seen this when trying to > build software with that option, so turning this on unconditionally > might be unwise, unless some build tests of the supported packages > have been done.. There will definitely be build testing: our autobuilders are testing 24/7 random configurations of Buildroot. So as soon as we introduce this option, there would be builds with BR2_TIME_BITS_64=y enabled, which would raise build issues if there's any. Of course, the more tricky part are runtime issues, which are essentially impossible to detect until someone runs into the problem. Best regards, Thomas
Hello Thomas, Le 13/10/2022 à 16:39, Thomas Petazzoni via buildroot a écrit : > On Wed, 12 Oct 2022 23:49:37 +0000 > Robert Hancock <robert.hancock@calian.com> wrote: > >> There's some chance of software being broken by enabling this, with >> either a compile or runtime failure. For example, applications that >> assume sizeof(time_t) == sizeof(long) would work on 32-bit platforms >> with a 32-bit time and 64-bit platforms with a 64-bit time, but fail >> with a 64-bit time on 32-bit. I believe I've seen this when trying to >> build software with that option, so turning this on unconditionally >> might be unwise, unless some build tests of the supported packages >> have been done.. > > There will definitely be build testing: our autobuilders are testing > 24/7 random configurations of Buildroot. So as soon as we introduce > this option, there would be builds with BR2_TIME_BITS_64=y enabled, > which would raise build issues if there's any. > > Of course, the more tricky part are runtime issues, which are > essentially impossible to detect until someone runs into the problem. We already tried to enable BR2_TIME_BITS_64 back in March 2022 but we had to revert it due to build issues with packages like glibc: See: http://lists.busybox.net/pipermail/buildroot/2022-March/638105.html https://git.buildroot.net/buildroot/commit/?id=dd170f0cbad729dba4193b2b20e3de0a7010d485 I'll try to look again. Best regards, Romain > > Best regards, > > Thomas
Le 06/02/2023 à 21:25, Romain Naour a écrit : > Hello Thomas, > > Le 13/10/2022 à 16:39, Thomas Petazzoni via buildroot a écrit : >> On Wed, 12 Oct 2022 23:49:37 +0000 >> Robert Hancock <robert.hancock@calian.com> wrote: >> >>> There's some chance of software being broken by enabling this, with >>> either a compile or runtime failure. For example, applications that >>> assume sizeof(time_t) == sizeof(long) would work on 32-bit platforms >>> with a 32-bit time and 64-bit platforms with a 64-bit time, but fail >>> with a 64-bit time on 32-bit. I believe I've seen this when trying to >>> build software with that option, so turning this on unconditionally >>> might be unwise, unless some build tests of the supported packages >>> have been done.. >> >> There will definitely be build testing: our autobuilders are testing >> 24/7 random configurations of Buildroot. So as soon as we introduce >> this option, there would be builds with BR2_TIME_BITS_64=y enabled, >> which would raise build issues if there's any. >> >> Of course, the more tricky part are runtime issues, which are >> essentially impossible to detect until someone runs into the problem. > > We already tried to enable BR2_TIME_BITS_64 back in March 2022 but we had to > revert it due to build issues with packages like glibc: > > See: > http://lists.busybox.net/pipermail/buildroot/2022-March/638105.html > > https://git.buildroot.net/buildroot/commit/?id=dd170f0cbad729dba4193b2b20e3de0a7010d485 > > I'll try to look again. The issue has been reported to zlib upstream project back in 2019 [1] and a pull request has been sent by Khem Raj on 2 Jan 2023 [2]. Reading one of the comment about libreELEC project "2038 proof" [3] we can notice it requires a lot of patches in several packages: glibc: dont build target with _TIME_BITS or _FILE_OFFSET_BITS for arm… eventlircd: support -D_TIME_BITS=64 for 64-bit time lirc: support -D_TIME_BITS=64 for 64-bit time zlib: support -D_TIME_BITS=64 for 64-bit time dvb-apps: support-time-bits-64.patch tslib: support -D_TIME_BITS=64 for 64-bit time libretro-fbneo: dont build target with _TIME_BITS or _FILE_OFFSET_BIT… mariadb: dont build target with _TIME_BITS or _FILE_OFFSET_BITS for a… In the end, enabling -D_FILE_OFFSET_BITS=64 and -D_TIME_BITS=64" onto all packages has been reverted [4] since it introduced several regression. After making a lot of effort and spending a lot of time, the libreELEC maintainer just give up: "TBH I tink we should not pursue the 32bit userland Y2038 issue further until glibc comes up with a better solution that doesn't break ABIs. Moving to 64bit (rather realistic within the next 10 years) or to another libc (not so much realistic) are all better options than the mess glibc created - it purely worked for them but pretty much no one else and almost every distribution abandoned the glibc approach so I think we should do the same." Thoughts? [1] https://github.com/madler/zlib/issues/447 [2] https://github.com/madler/zlib/pull/764 [3] https://github.com/LibreELEC/LibreELEC.tv/pull/6727 [4] https://github.com/LibreELEC/LibreELEC.tv/pull/7173 Best regards, Romain > > Best regards, > Romain > > >> >> Best regards, >> >> Thomas >
On Wed, 12 Oct 2022 23:50:08 +0200 Thomas Petazzoni via buildroot <buildroot@buildroot.org> wrote: > Y2038 is now almost only 15 years away, and embedded systems built > today are potentially going to still be operational in 15 years, and > even though they are supposed to receive updates by then, we all know > how things go, and potentially some of these embedded systems will not > receive any update. > > In 2038, the signed 32-bit representation of time_t used on 32-bit > architectures will overflow, causing all time-related functions to go > back in time in a surprising way. > > The Linux kernel has already been modified to support a 64-bit > representation of time_t on 32-bit architectures, but from a C library > perspective, the situation varies: > > - glibc uses this 64-bit time_t representation on 32-bit systems > since glibc 2.34, but only if -D_TIME_BITS=64 is > specified. Therefore, this commit adds an option to add this flag > globally to the build, when glibc is the C library and the > architecture is not 64-bit. > > - musl uses unconditionally a 64-bit time_t representation on 32-bit > systems since musl 1.2.0. So there is nothing to do here since > Buildroot has been using a musl >= 1.2.0, used since Buildroot > 2020.05. No Buildroot option is needed here. > > - uClibc-ng does not support a 64-bit time_t representation on 32-bit > systems, so systems using uClibc-ng will not be Y2038 compliant, at > least for now. No Buildroot option is needed here. > > It should be noted that being Y2038-compliant will only work if all > application/library code is correct. For example if an > application/library stores a timestamp in an "int" instead of using > the proper time_t type, then the mechanisms described above will not > fix this, and the application/library will continue to be broken in > terms of Y2038 support. > > Possible discussions points about this patch: > > - Should we have an option at all, or should we unconditionally pass > -D_TIME_BITS=64, like we have been doing for _FILE_OFFSET_BITS=64 > for quite some time. The reasoning for having an option is that > the mechanism is itself opt-in in glibc, and generally relatively > new, so it seemed logical for now to make it optional as well in > Buildroot. > > - Should we show something (a Config.in comment?) in the musl and > uClibc-ng case to let the user know that the code is Y2038 > compliant (musl) or not Y2038 compliant (uClibc-ng). Or should this > discussion be part of the Buildroot documentation? > > Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com> > --- > Config.in | 16 ++++++++++++++++ > package/Makefile.in | 3 +++ > 2 files changed, 19 insertions(+) This was discussed/review during the current hackathon, and in the end we decided to apply it, so it was pushed to master. Thomas
diff --git a/Config.in b/Config.in index 3c57c591a8..46c80fe2f0 100644 --- a/Config.in +++ b/Config.in @@ -753,6 +753,22 @@ config BR2_PER_PACKAGE_DIRECTORIES endmenu +config BR2_TIME_BITS_64 + bool "Build Y2038-ready code" + depends on BR2_TOOLCHAIN_USES_GLIBC && !BR2_ARCH_IS_64 + help + This option will pass -D_TIME_BITS=64 in the compiler flags + to ensure the glibc C library uses a 64-bit representation + for time_t and other time types, which ensures that + programs/libraries will correctly handle time past year + 2038. + + Notes: + - This option only has an effect with glibc >= 2.34. + - The musl C library since its version 1.20 is + unconditionally Y2038 compliant. + - The uClibc-ng library is not Y2038 compliant. + comment "Security Hardening Options" config BR2_PIC_PIE_ARCH_SUPPORTS diff --git a/package/Makefile.in b/package/Makefile.in index 43d214bcbe..59d88bb97e 100644 --- a/package/Makefile.in +++ b/package/Makefile.in @@ -163,6 +163,9 @@ TARGET_HARDENED += -D_FORTIFY_SOURCE=2 endif TARGET_CPPFLAGS += -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 +ifeq ($(BR2_TIME_BITS_64),y) +TARGET_CPPFLAGS += -D_TIME_BITS=64 +endif TARGET_CFLAGS = $(TARGET_CPPFLAGS) $(TARGET_ABI) $(TARGET_OPTIMIZATION) $(TARGET_DEBUGGING) $(TARGET_HARDENED) TARGET_CXXFLAGS = $(TARGET_CFLAGS) TARGET_FCFLAGS = $(TARGET_ABI) $(TARGET_OPTIMIZATION) $(TARGET_DEBUGGING)
Y2038 is now almost only 15 years away, and embedded systems built today are potentially going to still be operational in 15 years, and even though they are supposed to receive updates by then, we all know how things go, and potentially some of these embedded systems will not receive any update. In 2038, the signed 32-bit representation of time_t used on 32-bit architectures will overflow, causing all time-related functions to go back in time in a surprising way. The Linux kernel has already been modified to support a 64-bit representation of time_t on 32-bit architectures, but from a C library perspective, the situation varies: - glibc uses this 64-bit time_t representation on 32-bit systems since glibc 2.34, but only if -D_TIME_BITS=64 is specified. Therefore, this commit adds an option to add this flag globally to the build, when glibc is the C library and the architecture is not 64-bit. - musl uses unconditionally a 64-bit time_t representation on 32-bit systems since musl 1.2.0. So there is nothing to do here since Buildroot has been using a musl >= 1.2.0, used since Buildroot 2020.05. No Buildroot option is needed here. - uClibc-ng does not support a 64-bit time_t representation on 32-bit systems, so systems using uClibc-ng will not be Y2038 compliant, at least for now. No Buildroot option is needed here. It should be noted that being Y2038-compliant will only work if all application/library code is correct. For example if an application/library stores a timestamp in an "int" instead of using the proper time_t type, then the mechanisms described above will not fix this, and the application/library will continue to be broken in terms of Y2038 support. Possible discussions points about this patch: - Should we have an option at all, or should we unconditionally pass -D_TIME_BITS=64, like we have been doing for _FILE_OFFSET_BITS=64 for quite some time. The reasoning for having an option is that the mechanism is itself opt-in in glibc, and generally relatively new, so it seemed logical for now to make it optional as well in Buildroot. - Should we show something (a Config.in comment?) in the musl and uClibc-ng case to let the user know that the code is Y2038 compliant (musl) or not Y2038 compliant (uClibc-ng). Or should this discussion be part of the Buildroot documentation? Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com> --- Config.in | 16 ++++++++++++++++ package/Makefile.in | 3 +++ 2 files changed, 19 insertions(+)