@@ -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,
};
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(-)