From 8739472d8f6e996c18abde951d39038d015cdf2c Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Sun, 24 Mar 2024 10:35:49 +0100 Subject: [PATCH 1/4] Make pointer-to-int-cast warnings non-fatal Latest gcc on Debian unstable i386 starts to fail with > tests/test-umockdev-vala.vala:714:19: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast] > xfer[0].tx_buf = (uint64) tx_buf; It's right -- this *is* an evil and wrong cast, but unfortunately Linux defines the struct precisely as that -- `u64`, on all platforms. As we can't selectively `#pragma` these away, disable the fatal warning globally. --- meson.build | 2 ++ tests/test-umockdev-vala.vala | 1 + 2 files changed, 3 insertions(+) diff --git a/meson.build b/meson.build index 8e3b287..8411749 100644 --- a/meson.build +++ b/meson.build @@ -41,6 +41,8 @@ add_project_arguments( cc.get_supported_arguments( # Vala doesn't have `const void*`, or a way to selectively #pragma these in the code '-Wno-error=discarded-qualifiers', + # spi_ioc_transfer.[rx]x_buf are pointers, but declared u64 everywhere; Vala can't selectively #pragma these + '-Wno-error=pointer-to-int-cast', # mostly const dropping and dropped "volatile" in fully autogenerated code; # upstream Vala does not support fixing this warning '-Wno-error=incompatible-pointer-types', diff --git a/tests/test-umockdev-vala.vala b/tests/test-umockdev-vala.vala index c68cefa..524c777 100644 --- a/tests/test-umockdev-vala.vala +++ b/tests/test-umockdev-vala.vala @@ -710,6 +710,7 @@ t_spidev_ioctl () tx_buf[1] = 0xff; Posix.memset (xfer, 0, sizeof (Ioctl.spi_ioc_transfer) * 2); + /* these casts are evil, bad, and wrong -- but that's how Linux defines them, even 32 bit platforms have u64 */ xfer[0].tx_buf = (uint64) tx_buf; xfer[0].len = 2; xfer[1].rx_buf = (uint64) rx_buf; From b947c513b95e84ffbe36180b6d48731f677108d8 Mon Sep 17 00:00:00 2001 From: Zixing Liu Date: Sun, 24 Mar 2024 10:52:15 +0100 Subject: [PATCH 2/4] preload: Fix building with _FILE_OFFSET_BITS Unsetting `_FILE_OFFSET_BITS` causes time_t to be treated as 32-bit instead of the 64-bit that we want with `-D_TIME_BITS=64`. Fixes #216 Co-Authored-By: Steve Langasek Co-Authored-By: Martin Pitt --- src/libumockdev-preload.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/libumockdev-preload.c b/src/libumockdev-preload.c index 7e1ea6f..bed4774 100644 --- a/src/libumockdev-preload.c +++ b/src/libumockdev-preload.c @@ -22,12 +22,30 @@ * along with umockdev; If not, see . */ -/* override -D_FILE_OFFSET_BITS, it breaks us */ -#undef _FILE_OFFSET_BITS - /* for getting stat64 */ #define _GNU_SOURCE +#include + +#ifdef __GLIBC__ +/* Remove gcc asm aliasing so that our interposed symbols work as expected */ +#include + +#include +extern int __REDIRECT_NTH (__ttyname_r_alias, (int __fd, char *__buf, + size_t __buflen), ttyname_r); + +#ifdef __REDIRECT +#undef __REDIRECT +#endif +#define __REDIRECT(name, proto, alias) name proto +#ifdef __REDIRECT_NTH +#undef __REDIRECT_NTH +#endif +#define __REDIRECT_NTH(name, proto, alias) name proto __THROW + +#endif /* __GLIBC__ */ + #include #include #include @@ -63,6 +81,14 @@ #include "utils.h" #include "ioctl_tree.h" +#ifdef __GLIBC__ +/* Fixup for making a mess with __REDIRECT above */ +#ifdef __USE_TIME_BITS64 +#define clock_gettime __clock_gettime64 +extern int clock_gettime(clockid_t clockid, struct timespec *tp); +#endif +#endif + /* fix missing O_TMPFILE on some systems */ #ifndef O_TMPFILE #define O_TMPFILE (__O_TMPFILE | O_DIRECTORY) From 2396055f6e5dda1f95a5ed3ee39f94515b45d1de Mon Sep 17 00:00:00 2001 From: Steve Langasek Date: Sun, 24 Mar 2024 10:56:51 +0100 Subject: [PATCH 3/4] tests: Make input_event handling compatible with 64-bit time_t The structure of struct input_event varies depending on whether 64-bit `time_t` is in use. --- tests/test-umockdev.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/test-umockdev.c b/tests/test-umockdev.c index bf6268a..70763dc 100644 --- a/tests/test-umockdev.c +++ b/tests/test-umockdev.c @@ -1578,7 +1578,12 @@ t_testbed_script_replay_evdev_event_framing(UMockdevTestbedFixture * fixture, UN int fd; char buf[1024]; +#if __BITS_PER_LONG != 32 || !defined(__USE_TIME_BITS64) struct timeval dummy = {0}; +#else + __kernel_ulong_t dummy = 0; +#endif + /* Simple evdev stream - x coordinate followed by SYN, times 2 */ struct input_event dummy_events[] = { {dummy, 0003, 0000, 2534}, From 51675449827828280a4b20e22a9b6eb0a23c7493 Mon Sep 17 00:00:00 2001 From: Steve Langasek Date: Sun, 24 Mar 2024 10:59:15 +0100 Subject: [PATCH 4/4] preload: Provide wrappers for functions specific to 64-bit time_t See https://bugs.debian.org/1067208 --- src/libumockdev-preload.c | 58 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/src/libumockdev-preload.c b/src/libumockdev-preload.c index bed4774..f73ee2f 100644 --- a/src/libumockdev-preload.c +++ b/src/libumockdev-preload.c @@ -1239,6 +1239,8 @@ rettype name(const char *path, arg2t arg2, arg3t arg3, arg4t arg4) \ * the emulated /dev to indicate a block device (the sticky bit has no * real functionality for device nodes) */ #define WRAP_STAT(prefix, suffix) \ +extern int prefix ## stat ## suffix (const char *path, \ + struct stat ## suffix *st); \ int prefix ## stat ## suffix (const char *path, struct stat ## suffix *st) \ { \ const char *p; \ @@ -1259,6 +1261,8 @@ int prefix ## stat ## suffix (const char *path, struct stat ## suffix *st) \ /* wrapper template for fstatat family */ #define WRAP_FSTATAT(prefix, suffix) \ +extern int prefix ## fstatat ## suffix (int dirfd, const char *path, \ + struct stat ## suffix *st, int flags); \ int prefix ## fstatat ## suffix (int dirfd, const char *path, struct stat ## suffix *st, int flags) \ { \ const char *p; \ @@ -1416,6 +1420,12 @@ WRAP_STAT(,64); WRAP_STAT(l,64); WRAP_FSTATAT(,64); WRAP_FOPEN(,64); +#if defined(__USE_FILE_OFFSET64) && defined(__USE_TIME_BITS64) +#define stat64_time64 stat64 +WRAP_STAT(__,64_time64); +WRAP_STAT(__l,64_time64); +WRAP_FSTATAT(__,64_time64); +#endif #endif WRAP_3ARGS(ssize_t, -1, readlink, char *, size_t); @@ -1785,6 +1795,18 @@ recvmsg(int sockfd, struct msghdr * msg, int flags) return ret; } +extern ssize_t __recvmsg64(int sockfd, struct msghdr * msg, int flags); +ssize_t +__recvmsg64(int sockfd, struct msghdr * msg, int flags) +{ + libc_func(__recvmsg64, int, int, struct msghdr *, int); + ssize_t ret = ___recvmsg64(sockfd, msg, flags); + + netlink_recvmsg(sockfd, msg, ret); + + return ret; +} + int socket(int domain, int type, int protocol) { @@ -1902,6 +1924,42 @@ ioctl(int d, IOCTL_REQUEST_TYPE request, ...) return result; } +#ifdef __GLIBC__ + +extern int __ioctl_time64 (int __fd, unsigned long int __request, ...) __THROW; +int +__ioctl_time64(int d, IOCTL_REQUEST_TYPE request, ...) +{ + libc_func(__ioctl_time64, int, int, IOCTL_REQUEST_TYPE, ...); + int result; + va_list ap; + void* arg; + + /* one cannot reliably forward arbitrary varargs + * (http://c-faq.com/varargs/handoff.html), but we know that ioctl gets at + * most one extra argument, and almost all of them are pointers or ints, + * both of which fit into a void*. + */ + va_start(ap, request); + arg = va_arg(ap, void*); + va_end(ap); + + result = remote_emulate(d, IOCTL_REQ_IOCTL, (unsigned int) request, (long) arg); + if (result != UNHANDLED) { + DBG(DBG_IOCTL, "ioctl fd %i request %X: emulated, result %i\n", d, (unsigned) request, result); + return result; + } + + /* fallback to call original ioctl */ + result = ___ioctl_time64(d, request, arg); + DBG(DBG_IOCTL, "ioctl fd %i request %X: original, result %i\n", d, (unsigned) request, result); + + return result; +} + +#endif /* __GLIBC__ */ + + int isatty(int fd) {