[LTP] [PATCH 1/1] pkey01: Add .test_variants

Petr Vorel pvorel@suse.cz
Wed Aug 7 11:00:43 CEST 2024


Test both pkey_{alloc,mprotect() raw syscall and libc wrapper.

Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
Hi,

not sure if testing libc wrappers makes ATM sense, because (if I read
glibc code correctly), there is only pkey_mprotect() very thin wrapper
in sysdeps/unix/sysv/linux/pkey_mprotect.c [1]:

int
pkey_mprotect (void *addr, size_t len, int prot, int pkey)
{
  if (pkey == -1)
    /* If the key is -1, the system call is precisely equivalent to
       mprotect.  */
    return __mprotect (addr, len, prot);
  return INLINE_SYSCALL_CALL (pkey_mprotect, addr, len, prot, pkey);
}

pkey_alloc() and others [2]:

	This adds system call wrappers for pkey_alloc, pkey_free, pkey_mprotect,
	and x86-64 implementations of pkey_get and pkey_set, which abstract over
	the PKRU CPU register and hide the actual number of memory protection
	keys supported by the CPU.  pkey_mprotect with a -1 key is implemented
	using mprotect, so it will work even if the kernel does not support the
	pkey_mprotect system call.

	The system call wrapers use unsigned int instead of unsigned long for
	parameters, so that no special treatment for x32 is needed.  The flags
	argument is currently unused, and the access rights bit mask is limited
	to two bits by the current PKRU register layout anyway.

Besides, something like SYSCALL_VARIANT could be added to include/tst_test_macros.h,
to be reused.

Kind regards,
Petr

[1] https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/pkey_mprotect.c;h=b7afa7946d016ddaa8d4dea5b000dfb04b45491e;hb=c2a05c99e34539d16ebf2bb6234c8d2f2fdaa1f9
[2] https://sourceware.org/git/?p=glibc.git;a=commit;h=446d22e91d3113be57a4b0d1151cf337458c3bec

 testcases/kernel/syscalls/pkeys/pkey01.c | 43 +++++++++++++++++++-----
 1 file changed, 34 insertions(+), 9 deletions(-)

diff --git a/testcases/kernel/syscalls/pkeys/pkey01.c b/testcases/kernel/syscalls/pkeys/pkey01.c
index f1ecfec0bb..52b29b1783 100644
--- a/testcases/kernel/syscalls/pkeys/pkey01.c
+++ b/testcases/kernel/syscalls/pkeys/pkey01.c
@@ -51,11 +51,40 @@ static struct tcase {
 	{0, PKEY_DISABLE_WRITE, "PKEY_DISABLE_WRITE"},
 };
 
+#define PKEY_ALLOC(...) \
+	SYSCALL_VARIANT(TST_EXP_POSITIVE, pkey_alloc, __VA_ARGS__)
+
+#define PKEY_MPROTECT(...) \
+	SYSCALL_VARIANT(TST_EXP_PASS_SILENT, pkey_mprotect, __VA_ARGS__)
+
+#define SYSCALL_VARIANT(TST, SCALL, ...)                                 \
+	({                                                                     \
+		if (tst_variant)                                    \
+			TST(SCALL(__VA_ARGS__));	\
+		else							\
+			TST(tst_syscall(__NR_ ## SCALL, __VA_ARGS__));	\
+		TST_RET;                                                       \
+	})
+
+static void variant_check(void)
+{
+	if (tst_variant) {
+		tst_res(TINFO, "Testing variant: libc pkey_{alloc,mprotect()");
+#ifndef HAVE_PKEY_MPROTECT
+		tst_brk(TCONF, "libc pkey_{alloc,mprotect() wrappers not available");
+#endif
+	} else {
+		tst_res(TINFO, "Testing variant: syscall __NR_pkey_{alloc,mprotect}");
+	}
+
+	check_pkey_support();
+}
+
 static void setup(void)
 {
 	int i, fd;
 
-	check_pkey_support();
+	variant_check();
 
 	if (tst_hugepages == test.hugepages.number)
 		size = SAFE_READ_MEMINFO("Hugepagesize:") * 1024;
@@ -146,14 +175,10 @@ static void pkey_test(struct tcase *tc, struct mmap_param *mpa)
 		fd = SAFE_OPEN(TEST_FILE, O_RDWR | O_CREAT, 0664);
 
 	buffer = SAFE_MMAP(NULL, size, mpa->prot, mpa->flags, fd, 0);
-
-	pkey = pkey_alloc(tc->flags, tc->access_rights);
-	if (pkey == -1)
-		tst_brk(TBROK | TERRNO, "pkey_alloc failed");
+	pkey = PKEY_ALLOC(tc->flags, tc->access_rights);
 
 	tst_res(TINFO, "Set %s on (%s) buffer", tc->name, flag_to_str(mpa->flags));
-	if (pkey_mprotect(buffer, size, mpa->prot, pkey) == -1)
-		tst_brk(TBROK | TERRNO, "pkey_mprotect failed");
+	PKEY_MPROTECT(buffer, size, mpa->prot, pkey);
 
 	pid = SAFE_FORK();
 	if (pid == 0) {
@@ -181,8 +206,7 @@ static void pkey_test(struct tcase *tc, struct mmap_param *mpa)
                 tst_res(TFAIL, "Child: %s", tst_strstatus(status));
 
 	tst_res(TINFO, "Remove %s from the buffer", tc->name);
-	if (pkey_mprotect(buffer, size, mpa->prot, 0x0) == -1)
-		tst_brk(TBROK | TERRNO, "pkey_mprotect failed");
+	PKEY_MPROTECT(buffer, size, mpa->prot, 0x0);
 
 	switch (mpa->prot) {
 	case PROT_READ:
@@ -230,4 +254,5 @@ static struct tst_test test = {
 	.test = verify_pkey,
 	.setup = setup,
 	.hugepages = {1, TST_REQUEST},
+	.test_variants = 2,
 };
-- 
2.45.2



More information about the ltp mailing list