lksctp-tools: fix sctp_connectx() and ptests on musl

Three func_tests failed on musl:

- test_1_to_1_sendmsg and test_1_to_1_recvmsg died with SIGSEGV. They
  pass (struct msghdr *)-1 and expect EFAULT, but on 64-bit musl the
  sendmsg()/recvmsg() wrappers copy the msghdr to clear its padding
  before making the syscall. Issue those two calls with syscall(2) so
  they test the kernel's handling of the bad pointer.

- test_connectx reported "Association id mismatch: connectx returned 3,
  notification returned:240". libsctp exports an unversioned
  sctp_connectx alias of the original API next to the VERS_1..VERS_3
  versions. musl's dynamic linker does not implement symbol versioning
  and binds that alias, so every sctp_connectx() call on musl ran the old
  API, which never returns the association id. The alias only serves
  binaries linked before libsctp was versioned, so only emit it on
  glibc; sctp_connectx@@VERS_3 is then the one musl resolves.

Tested with meta-networking-image-ptest-lksctp-tools on qemux86-64 with
yoe-musl-systemd-wayland: TOTAL: 1 FAIL: 0.

AI-Generated: Uses Claude Code
Signed-off-by: Khem Raj <khem.raj@oss.qualcomm.com>
This commit is contained in:
Khem Raj committed 2026-09-28 06:57:40 -07:00
1 parent 6bbc65fd7a
commit f5b8366ede
3 files changed
+123

No files matched your search

@@ -0,0 +1,72 @@
From 5402bce533c3ba8dae022eded7c6ffe7967b7248 Mon Sep 17 00:00:00 2001
From: Khem Raj <khem.raj@oss.qualcomm.com>
Date: Sun, 27 Sep 2026 15:52:39 -0700
Subject: [PATCH 2/3] func_tests: pass invalid msghdr pointers straight to the
kernel
test_1_to_1_sendmsg TEST6 and test_1_to_1_recvmsg TEST4 hand
(struct msghdr *)-1 to sendmsg()/recvmsg() and expect EFAULT from the
kernel. Passing an invalid pointer to a libc function is undefined, and
on 64-bit musl both wrappers copy the msghdr first to clear its padding
fields, so the tests die with SIGSEGV before reaching the syscall.
Use syscall(2) for these two cases so they test what they mean to: the
kernel's handling of a bad msghdr pointer.
Upstream-Status: Pending
Signed-off-by: Khem Raj <khem.raj@oss.qualcomm.com>
---
src/func_tests/test_1_to_1_recvmsg.c | 7 ++++++-
src/func_tests/test_1_to_1_sendmsg.c | 7 ++++++-
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/src/func_tests/test_1_to_1_recvmsg.c b/src/func_tests/test_1_to_1_recvmsg.c
index 962b7b5..0ccf087 100644
--- a/src/func_tests/test_1_to_1_recvmsg.c
+++ b/src/func_tests/test_1_to_1_recvmsg.c
@@ -56,6 +56,7 @@
#include <sys/uio.h>
#include <linux/socket.h>
#include <sctputil.h>
+#include <sys/syscall.h>
char *TCID = __FILE__;
int TST_TOTAL = 8;
@@ -158,7 +159,11 @@ main(int argc, char *argv[])
inmessage.msg_iov = &iov_rcv;
/*recvmsg () TEST4: Invalid msghdr pointer EFAULT, Expected error*/
- count = recvmsg(acpt_sk, (struct msghdr *)-1, flag);
+ /* Call the kernel directly: libc wrappers may read the msghdr
+ * themselves (musl copies it to clear padding on 64-bit), which
+ * crashes instead of returning EFAULT.
+ */
+ count = syscall(SYS_recvmsg, acpt_sk, (struct msghdr *)-1, flag);
if (count != -1 || errno != EFAULT)
tst_brkm(TBROK, tst_exit, "recvmsg with invalid msghdr "
"pointer count:%d, errno:%d", count, errno);
diff --git a/src/func_tests/test_1_to_1_sendmsg.c b/src/func_tests/test_1_to_1_sendmsg.c
index f2949e7..4f46c78 100644
--- a/src/func_tests/test_1_to_1_sendmsg.c
+++ b/src/func_tests/test_1_to_1_sendmsg.c
@@ -63,6 +63,7 @@
#include <sys/uio.h>
#include <linux/socket.h>
#include <sctputil.h>
+#include <sys/syscall.h>
char *TCID = __FILE__;
int TST_TOTAL = 14;
@@ -200,7 +201,11 @@ main(int argc, char *argv[])
outmessage.msg_iovlen = 1;
/*sendmsg () TEST6: Invalid msghdr pointer EFAULT, Expected error*/
- count = sendmsg(sk, (struct msghdr *)-1, flag);
+ /* Call the kernel directly: libc wrappers may read the msghdr
+ * themselves (musl copies it to clear padding on 64-bit), which
+ * crashes instead of returning EFAULT.
+ */
+ count = syscall(SYS_sendmsg, sk, (struct msghdr *)-1, flag);
if (count != -1 || errno != EFAULT)
tst_brkm(TBROK, tst_exit, "sendmsg with invalid msghdr "
"pointer count:%d, errno:%d", count, errno);
@@ -0,0 +1,49 @@
From fb2fa4a7af169878f7e7cb2fbf3dba00639d73ed Mon Sep 17 00:00:00 2001
From: Khem Raj <khem.raj@oss.qualcomm.com>
Date: Sun, 27 Sep 2026 15:52:39 -0700
Subject: [PATCH 3/3] connectx: only export the unversioned sctp_connectx alias
on glibc
libsctp exports sctp_connectx four times: an unversioned alias of the
original three-argument API plus the VERS_1, VERS_2 and default VERS_3
versions. glibc honours the version recorded in the caller, but musl's
dynamic linker does not implement symbol versioning: it skips the
hidden VERS_1/VERS_2 entries yet accepts both the unversioned alias and
sctp_connectx@@VERS_3, and whichever comes first in the hash chain wins.
That is the unversioned alias, so on musl every sctp_connectx() call
runs the old API, which ignores the association id argument. The caller
then reads an uninitialised id, e.g. test_connectx:
test_connectx.c 3 BROK : Association id mismatch: connectx returned 3,
notification returned:240
The alias only exists for binaries linked before libsctp was versioned,
which is a glibc concern. Emit it only when building against glibc, so
sctp_connectx@@VERS_3 is the only visible definition elsewhere.
Upstream-Status: Pending
Signed-off-by: Khem Raj <khem.raj@oss.qualcomm.com>
---
src/lib/connectx.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/lib/connectx.c b/src/lib/connectx.c
index 2a21e3a..119f6c9 100644
--- a/src/lib/connectx.c
+++ b/src/lib/connectx.c
@@ -76,7 +76,15 @@ static int __connectx_addrsize(const struct sockaddr *addrs,
}
+/* The unversioned alias lets glibc resolve references from binaries
+ * built before libsctp had symbol versions. Dynamic linkers without
+ * symbol versioning, such as musl's, pick the first matching name
+ * instead and would bind every sctp_connectx() call to this old API,
+ * which never reports the association id.
+ */
+#ifdef __GLIBC__
SYMVER(__sctp_connectx, sctp_connectx@)
+#endif
int __sctp_connectx(int fd, struct sockaddr *addrs, int addrcnt)
{
int addrs_size = __connectx_addrsize(addrs, addrcnt);
@@ -13,6 +13,8 @@ SRCREV = "37d5f1225573b91d706a5e547d081f79963a9deb"
SRC_URI = " \
git://github.com/sctp/lksctp-tools.git;branch=master;protocol=https \
file://0001-func_tests-disable-FORTIFY_SOURCE-for-test_1_to_1_re.patch \
file://0002-func_tests-pass-invalid-msghdr-pointers-straight-to-.patch \
file://0003-connectx-only-export-the-unversioned-sctp_connectx-a.patch \
file://run-ptest \
file://v4test.sh \
file://v6test.sh \