summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <smcv@collabora.com>2023-08-07 20:19:17 +0100
committerSimon McVittie <smcv@collabora.com>2023-08-14 14:18:25 +0000
commit3072109b1122ed8ec02e1fa92bb04290a373f73d (patch)
tree240ba67dcba2042ebae76effdc11afdbbcbb5d70
parent91b59ea792c67cdf088c6b1970b436ab3fb891a6 (diff)
On 32-bit glibc, define _TIME_BITS to 64 if not already defined
On older 32-bit architectures such as i386, this redefines time_t to be 64-bit, and correspondingly increases the size of all system data structures that contain a time_t, such as struct timeval and struct stat. This is necessary to allow timestamps beyond January 2038 to be represented; as well as things that obviously deal with timestamps, this affects functions like stat() (and therefore our wrapper _dbus_stat()), which will fail with EOVERFLOW if asked to inspect a file whose correct timestamp does not fit in time_t. In particular, if the modification or access timestamp on /etc/machine-id has somehow been set to a post-2038 time, libdbus will consider the inability to stat() that file to be an installation error, and when using the deprecated dbus_get_local_machine_id(), that can cause third-party i386 software such as the Steam client to crash. Using 64-bit timestamps avoids that failure mode. Using 64-bit timestamps in glibc is an opt-in and not the default, because if done carelessly it can change libraries' ABIs. However, libdbus is careful not to include system headers and system data types in its own headers, with the only exceptions being extremely basic ISO C headers like <stddef.h> and <stdarg.h>; so we can safely do this without it breaking our ABI. This is similar to the reasoning for why commit 96ffc2a0 "configure.ac: support large-file for stat64" was a safe change. This change only affects glibc. Some non-GNU operating system libraries (such as musl) are less concerned with binary backwards compatibility than glibc, and therefore have incompatibly changed their ABI on 32-bit platforms to switch to 64-bit timestamps throughout; no action is needed on those platforms. If other non-GNU OS libraries have taken a route similar to GNU's, then maintainers of those operating systems are welcome to send tested merge requests similar to this one. An extra subtlety here is that _TIME_BITS=64 requires _FILE_OFFSET_BITS=64. In the Meson build, Meson unconditionally enables _FILE_OFFSET_BITS=64 where appropriate, and in the Autotools build, we already had that via AC_SYS_LARGEFILE, but in the CMake build we did not necessarily have this; so we also define _FILE_OFFSET_BITS=64 there if necessary, as a continuation of commit 96ffc2a0 "configure.ac: support large-file for stat64". On newer 32-bit architectures like x32, time_t is always 64-bit and so this has no practical effect. On 64-bit, setting these would have no practical effect, but to minimize risk I'm only doing this for 32-bit architectures. Resolves: https://gitlab.freedesktop.org/dbus/dbus/-/issues/465 Signed-off-by: Simon McVittie <smcv@collabora.com>
-rw-r--r--cmake/ConfigureChecks.cmake16
-rw-r--r--cmake/config.h.cmake2
-rw-r--r--configure.ac25
-rw-r--r--meson.build11
4 files changed, 54 insertions, 0 deletions
diff --git a/cmake/ConfigureChecks.cmake b/cmake/ConfigureChecks.cmake
index 737913ba..b138b367 100644
--- a/cmake/ConfigureChecks.cmake
+++ b/cmake/ConfigureChecks.cmake
@@ -72,6 +72,22 @@ check_symbol_exists(socketpair "sys/socket.h" HAVE_SOCKETPAIR) #
check_symbol_exists(unsetenv "stdlib.h" HAVE_UNSETENV) # dbus-sysdeps.c
check_symbol_exists(writev "sys/uio.h" HAVE_WRITEV) # dbus-sysdeps.c, dbus-sysdeps-win.c
+# It doesn't really matter which specific header we use for these, as long as
+# we include at least one glibc-provided header. time.h is suitable.
+check_symbol_exists(__GLIBC__ "time.h" HAVE___GLIBC__)
+check_symbol_exists(_FILE_OFFSET_BITS "time.h" HAVE__FILE_OFFSET_BITS)
+check_symbol_exists(_TIME_BITS "time.h" HAVE__TIME_BITS)
+
+# Opt-in to large inode number and timestamp support, which we know doesn't
+# break libdbus ABI: https://gitlab.freedesktop.org/dbus/dbus/-/issues/465
+if(HAVE___GLIBC__ AND CMAKE_SIZEOF_VOID_P EQUAL 4 AND NOT HAVE__FILE_OFFSET_BITS)
+ set(_FILE_OFFSET_BITS 64)
+endif()
+
+if(HAVE___GLIBC__ AND CMAKE_SIZEOF_VOID_P EQUAL 4 AND NOT HAVE__TIME_BITS)
+ set(_TIME_BITS 64)
+endif()
+
check_struct_member(cmsgcred cmcred_pid "sys/types.h;sys/socket.h" HAVE_CMSGCRED) # dbus-sysdeps.c
CHECK_C_SOURCE_COMPILES("
diff --git a/cmake/config.h.cmake b/cmake/config.h.cmake
index e16d2247..16e737f3 100644
--- a/cmake/config.h.cmake
+++ b/cmake/config.h.cmake
@@ -13,6 +13,8 @@
# define __USE_MINGW_ANSI_STDIO 0
#endif
+#cmakedefine _FILE_OFFSET_BITS @_FILE_OFFSET_BITS@
+#cmakedefine _TIME_BITS @_TIME_BITS@
#cmakedefine WORDS_BIGENDIAN
/* Opt-in to modern APIs and thread-safety for Solaris. In the Autotools
diff --git a/configure.ac b/configure.ac
index b1809e75..389b2796 100644
--- a/configure.ac
+++ b/configure.ac
@@ -546,6 +546,31 @@ fi
AC_SUBST(DBUS_INT16_TYPE)
+# Opt-in to large timestamp support, which we know doesn't break libdbus ABI:
+# https://gitlab.freedesktop.org/dbus/dbus/-/issues/465
+# Currently we only know how to do this for GNU libc.
+AC_CHECK_DECL(
+ [__GLIBC__], [
+ AC_CHECK_DECL(
+ [_TIME_BITS],
+ [time_bits_defined=yes],
+ [time_bits_defined=no],
+ [[#include <time.h>]]
+ )
+ ],
+ [],
+ [[#include <time.h>]]
+)
+AS_IF(
+ [test "$time_bits_defined" = no && test "$DBUS_SIZEOF_VOID_P" = 4],
+ [
+ AC_DEFINE(
+ [_TIME_BITS], [64],
+ [Define to 64 if using 32-bit glibc and not already defined]
+ )
+ ]
+)
+
## byte order
case $host_os in
darwin*)
diff --git a/meson.build b/meson.build
index 9bfcb4a8..4fef6100 100644
--- a/meson.build
+++ b/meson.build
@@ -627,6 +627,17 @@ endif
config.set('DBUS_BUILD_X11', use_x11_autolaunch)
config.set('DBUS_ENABLE_X11_AUTOLAUNCH', use_x11_autolaunch)
+# Opt-in to large timestamp support, which we know doesn't break libdbus ABI:
+# https://gitlab.freedesktop.org/dbus/dbus/-/issues/465
+# Meson does the equivalent for large offsets and inode numbers automatically.
+if (
+ cc.has_header_symbol('time.h', '__GLIBC__', args: compile_args_c)
+ and not cc.has_header_symbol('time.h', '_TIME_BITS', args: compile_args_c)
+ and cc.sizeof('void *') == 4
+)
+ config.set('_TIME_BITS', '64')
+endif
+
# keep CMakeLists.txt in sync
check_functions = [
'accept4',