From 719ccf8f4bf4263b02c686f16f579fd6119bb52c Mon Sep 17 00:00:00 2001 From: Eugene Syromyatnikov Date: Mon, 23 Aug 2021 18:24:39 +0200 Subject: [PATCH] tests: call setsockopt directly in sockopt-timestamp While commit v5.13-10-g0211fdc "tests: change sockopt-timestamp test to use syscall(__NR_recvmsg)" has fixed issues with glibc-induced mangling on newer kernels, the combination of an older kernel and new glibc still causes issues, as glibc silently falls back to SO_TIMESTAMP{,NS}_OLD, as implemented in glibc-2.34~294 "linux: Add fallback for 64-bit time_t SO_TIMESTAMP{NS}". Avoid that by calling setsockopt directly as well. * tests/sockopt-timestamp.c (SC_setsockopt): New macro constant. (k_setsockopt): New function. (test_sockopt): Call k_setsockopt instead of setsockopt. Complements: v5.13-10-g0211fdc "tests: change sockopt-timestamp test to use syscall(__NR_recvmsg)" --- tests/sockopt-timestamp.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/tests/sockopt-timestamp.c b/tests/sockopt-timestamp.c index 34c4d89..4bd96fd 100644 --- a/tests/sockopt-timestamp.c +++ b/tests/sockopt-timestamp.c @@ -48,6 +48,30 @@ k_recvmsg(const unsigned int fd, const void *const ptr, const unsigned int flags return rc; } +#define SC_setsockopt 14 +static long +k_setsockopt(const unsigned int fd, const unsigned int level, + const unsigned int optname, const void *const optval, + const unsigned int len) +{ + const kernel_ulong_t fill = (kernel_ulong_t) 0xdefaced00000000ULL; +#ifdef __NR_setsockopt + const kernel_ulong_t bad = (kernel_ulong_t) 0xbadc0dedbadc0dedULL; +#endif + + return syscall( +#ifdef __NR_setsockopt + __NR_setsockopt, +#else /* socketcall */ + __NR_socketcall, SC_setsockopt, +#endif + fill | fd , fill | level, fill | optname, optval, fill | len +#ifdef __NR_setsockopt + , bad +#endif + ); +} + static void print_timestamp_old(const struct cmsghdr *c) { @@ -139,7 +163,12 @@ test_sockopt(int so_val, const char *str, void (*fun)(const struct cmsghdr *)) perror_msg_and_skip(data); const int opt_1 = 1; - if (setsockopt(sv[0], SOL_SOCKET, so_val, &opt_1, sizeof(opt_1))) { + /* + * glibc-2.34~294 adds fallsback for SO_TIMESTAMP{,NS}_NEW that calls + * SO_TIMESTAMP{,NS}_OLD, so we have to call the setsockopt directly + * in order to avoid unexpected recvmsg msg types. + */ + if (k_setsockopt(sv[0], SOL_SOCKET, so_val, &opt_1, sizeof(opt_1))) { perror(str); return 0; } diff --git a/tests-m32/sockopt-timestamp.c b/tests-m32/sockopt-timestamp.c index 34c4d89..4bd96fd 100644 --- a/tests-m32/sockopt-timestamp.c +++ b/tests-m32/sockopt-timestamp.c @@ -48,6 +48,30 @@ k_recvmsg(const unsigned int fd, const void *const ptr, const unsigned int flags return rc; } +#define SC_setsockopt 14 +static long +k_setsockopt(const unsigned int fd, const unsigned int level, + const unsigned int optname, const void *const optval, + const unsigned int len) +{ + const kernel_ulong_t fill = (kernel_ulong_t) 0xdefaced00000000ULL; +#ifdef __NR_setsockopt + const kernel_ulong_t bad = (kernel_ulong_t) 0xbadc0dedbadc0dedULL; +#endif + + return syscall( +#ifdef __NR_setsockopt + __NR_setsockopt, +#else /* socketcall */ + __NR_socketcall, SC_setsockopt, +#endif + fill | fd , fill | level, fill | optname, optval, fill | len +#ifdef __NR_setsockopt + , bad +#endif + ); +} + static void print_timestamp_old(const struct cmsghdr *c) { @@ -139,7 +163,12 @@ test_sockopt(int so_val, const char *str, void (*fun)(const struct cmsghdr *)) perror_msg_and_skip(data); const int opt_1 = 1; - if (setsockopt(sv[0], SOL_SOCKET, so_val, &opt_1, sizeof(opt_1))) { + /* + * glibc-2.34~294 adds fallsback for SO_TIMESTAMP{,NS}_NEW that calls + * SO_TIMESTAMP{,NS}_OLD, so we have to call the setsockopt directly + * in order to avoid unexpected recvmsg msg types. + */ + if (k_setsockopt(sv[0], SOL_SOCKET, so_val, &opt_1, sizeof(opt_1))) { perror(str); return 0; } diff --git a/tests-mx32/sockopt-timestamp.c b/tests-mx32/sockopt-timestamp.c index 34c4d89..4bd96fd 100644 --- a/tests-mx32/sockopt-timestamp.c +++ b/tests-mx32/sockopt-timestamp.c @@ -48,6 +48,30 @@ k_recvmsg(const unsigned int fd, const void *const ptr, const unsigned int flags return rc; } +#define SC_setsockopt 14 +static long +k_setsockopt(const unsigned int fd, const unsigned int level, + const unsigned int optname, const void *const optval, + const unsigned int len) +{ + const kernel_ulong_t fill = (kernel_ulong_t) 0xdefaced00000000ULL; +#ifdef __NR_setsockopt + const kernel_ulong_t bad = (kernel_ulong_t) 0xbadc0dedbadc0dedULL; +#endif + + return syscall( +#ifdef __NR_setsockopt + __NR_setsockopt, +#else /* socketcall */ + __NR_socketcall, SC_setsockopt, +#endif + fill | fd , fill | level, fill | optname, optval, fill | len +#ifdef __NR_setsockopt + , bad +#endif + ); +} + static void print_timestamp_old(const struct cmsghdr *c) { @@ -139,7 +163,12 @@ test_sockopt(int so_val, const char *str, void (*fun)(const struct cmsghdr *)) perror_msg_and_skip(data); const int opt_1 = 1; - if (setsockopt(sv[0], SOL_SOCKET, so_val, &opt_1, sizeof(opt_1))) { + /* + * glibc-2.34~294 adds fallsback for SO_TIMESTAMP{,NS}_NEW that calls + * SO_TIMESTAMP{,NS}_OLD, so we have to call the setsockopt directly + * in order to avoid unexpected recvmsg msg types. + */ + if (k_setsockopt(sv[0], SOL_SOCKET, so_val, &opt_1, sizeof(opt_1))) { perror(str); return 0; } -- 2.1.4