[LTP] [PATCH] Fix Valgrind warnings in ioctl_pidfd02
Martin Cermak
mcermak@redhat.com
Fri Apr 17 10:29:20 CEST 2026
When ioctl_pidfd02 runs under valgrind, it fails to use clone3()
in lib/tst_clone.c:27, because valgrind doesn't implement clone3.
So, tst_clone.c resorts to a raw clone() syscall a few lines later.
Manual page clone(2) says that In Linux 2.4 and earlier, clone()
does not take arguments parent_tid, tls, and child_tid. That pre-
dates valgrind itself though. In reasonably recent history, the
raw clone() syscall takes 5 args.
The clone() syscall is notorious for having different "Calling
Conventions" depending on the CPU architecture. The following
valgrind source demonstrates that mess:
|| defined(VGP_ppc32_linux) \
|| defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
|| defined(VGP_arm_linux) || defined(VGP_mips32_linux) \
|| defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
|| defined(VGP_nanomips_linux) || defined(VGP_riscv64_linux)
// And s390x is even more special, and inverts flags and child stack args
The ARG3 (parent_tidptr) - this patch actually is about - actually is
the only arg having identical position across various arches, hooray :)
The ioctl_pidfd02.c testcase calls clone() with CLONE_PIDFD.
In that case ARG3 becomes mandatory (ftr. kernel/fork.c:2669) and
valgrind checks its validity. Without this patch, Valgrind fails:
ioctl_pidfd02.c:64: TPASS: WEXITSTATUS(info1->exit_code) == 100 (100)
==2227408== Syscall param clone(parent_tidptr) points to unaddressable byte(s)
==2227408== at 0x496215D: syscall (syscall.S:38)
==2227408== by 0x420E73: tst_clone (tst_clone.c:41)
[ ... stuff deleted ... ]
==2227408== by 0x404E9A: main (tst_test.h:755)
==2227408== Address 0xffffffffffffffa0 is not stack'd, malloc'd or (recently) free'd
This patch sets ARG3 explicitly, making valgrind happy. With this
update, ioctl_pidfd02 tests fine on all the rhel supported arches both
with and without valgrind, e.g.:
el10 s390x # valgrind --exit-on-first-error=yes --error-exitcode=-3 --quiet ./testcases/kernel/syscalls/ioctl/ioctl_pidfd02
tst_kconfig.c:90: TINFO: Parsing kernel config '/lib/modules/6.12.0-218.el10.s390x/build/.config'
tst_buffers.c:57: TINFO: Test is using guarded buffers
[ ... stuff deleted ... ]
ioctl_pidfd02.c:62: TPASS: info1->exit_code == status (25600)
ioctl_pidfd02.c:64: TPASS: WEXITSTATUS(info1->exit_code) == 100 (100)
Summary:
passed 10
failed 0
broken 0
skipped 0
warnings 0
el10 s390x #
This patch also sets ARG4 and ARG5. Luckily in this case both are NULL.
That's a win, because otherwise we'd need to look into the messy clone()
calling convention and handle individual arches separately, see above.
diff --git a/lib/tst_clone.c b/lib/tst_clone.c
index 8638052e2..296cd40ac 100644
--- a/lib/tst_clone.c
+++ b/lib/tst_clone.c
@@ -36,9 +36,9 @@ pid_t tst_clone(const struct tst_clone_args *tst_args)
flags = args.exit_signal | args.flags;
#ifdef __s390x__
- pid = syscall(__NR_clone, NULL, flags);
+ pid = syscall(__NR_clone, NULL, flags, args.pidfd, NULL, NULL);
#else
- pid = syscall(__NR_clone, flags, NULL);
+ pid = syscall(__NR_clone, flags, NULL, args.pidfd, NULL, NULL);
#endif
if (pid == -1)
--
2.53.0
More information about the ltp
mailing list