* [LTP] [PATCH] pkey: Add test for memory protection keys
@ 2019-06-20 9:55 Li Wang
2019-06-20 13:05 ` Jan Stancek
0 siblings, 1 reply; 3+ messages in thread
From: Li Wang @ 2019-06-20 9:55 UTC (permalink / raw)
To: ltp
Signed-off-by: Li Wang <liwang@redhat.com>
---
configure.ac | 1 +
include/lapi/syscalls/aarch64.in | 3 +
include/lapi/syscalls/arm.in | 3 +
include/lapi/syscalls/i386.in | 3 +
include/lapi/syscalls/ia64.in | 3 +
include/lapi/syscalls/powerpc.in | 3 +
include/lapi/syscalls/powerpc64.in | 3 +
include/lapi/syscalls/s390.in | 3 +
include/lapi/syscalls/s390x.in | 3 +
include/lapi/syscalls/sh.in | 3 +
include/lapi/syscalls/sparc.in | 3 +
include/lapi/syscalls/sparc64.in | 3 +
include/lapi/syscalls/x86_64.in | 3 +
runtest/syscalls | 2 +
testcases/kernel/syscalls/pkeys/.gitignore | 1 +
testcases/kernel/syscalls/pkeys/Makefile | 8 ++
testcases/kernel/syscalls/pkeys/pkey.h | 44 +++++++++
testcases/kernel/syscalls/pkeys/pkey01.c | 105 +++++++++++++++++++++
18 files changed, 197 insertions(+)
create mode 100644 testcases/kernel/syscalls/pkeys/.gitignore
create mode 100644 testcases/kernel/syscalls/pkeys/Makefile
create mode 100644 testcases/kernel/syscalls/pkeys/pkey.h
create mode 100644 testcases/kernel/syscalls/pkeys/pkey01.c
diff --git a/configure.ac b/configure.ac
index 5ecc92781..35997699f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -76,6 +76,7 @@ AC_CHECK_FUNCS([ \
profil \
pwritev \
pwritev2 \
+ pkey_mprotect \
readlinkat \
renameat \
renameat2 \
diff --git a/include/lapi/syscalls/aarch64.in b/include/lapi/syscalls/aarch64.in
index 177dd0115..4232defbe 100644
--- a/include/lapi/syscalls/aarch64.in
+++ b/include/lapi/syscalls/aarch64.in
@@ -266,3 +266,6 @@ copy_file_range 285
preadv2 286
pwritev2 287
_sysctl 1078
+pkey_mprotect 394
+pkey_alloc 395
+pkey_free 396
diff --git a/include/lapi/syscalls/arm.in b/include/lapi/syscalls/arm.in
index f4adedb2c..48b55b5ff 100644
--- a/include/lapi/syscalls/arm.in
+++ b/include/lapi/syscalls/arm.in
@@ -350,3 +350,6 @@ copy_file_range (__NR_SYSCALL_BASE+391)
preadv2 (__NR_SYSCALL_BASE+392)
pwritev2 (__NR_SYSCALL_BASE+393)
statx (__NR_SYSCALL_BASE+397)
+pkey_mprotect (__NR_SYSCALL_BASE+394)
+pkey_alloc (__NR_SYSCALL_BASE+395)
+pkey_free (__NR_SYSCALL_BASE+396)
diff --git a/include/lapi/syscalls/i386.in b/include/lapi/syscalls/i386.in
index af5254f77..c54573547 100644
--- a/include/lapi/syscalls/i386.in
+++ b/include/lapi/syscalls/i386.in
@@ -348,3 +348,6 @@ copy_file_range 377
preadv2 378
pwritev2 379
statx 383
+pkey_mprotect 380
+pkey_alloc 381
+pkey_free 382
diff --git a/include/lapi/syscalls/ia64.in b/include/lapi/syscalls/ia64.in
index c0aeed08b..56bfd7928 100644
--- a/include/lapi/syscalls/ia64.in
+++ b/include/lapi/syscalls/ia64.in
@@ -305,3 +305,6 @@ mlock2 1346
copy_file_range 1347
preadv2 1348
pwritev2 1349
+pkey_mprotect 330
+pkey_alloc 331
+pkey_free 332
diff --git a/include/lapi/syscalls/powerpc.in b/include/lapi/syscalls/powerpc.in
index 6b6be58a7..eaf8d45ed 100644
--- a/include/lapi/syscalls/powerpc.in
+++ b/include/lapi/syscalls/powerpc.in
@@ -355,3 +355,6 @@ copy_file_range 379
preadv2 380
pwritev2 381
statx 383
+pkey_mprotect 386
+pkey_alloc 384
+pkey_free 385
diff --git a/include/lapi/syscalls/powerpc64.in b/include/lapi/syscalls/powerpc64.in
index 6b6be58a7..eaf8d45ed 100644
--- a/include/lapi/syscalls/powerpc64.in
+++ b/include/lapi/syscalls/powerpc64.in
@@ -355,3 +355,6 @@ copy_file_range 379
preadv2 380
pwritev2 381
statx 383
+pkey_mprotect 386
+pkey_alloc 384
+pkey_free 385
diff --git a/include/lapi/syscalls/s390.in b/include/lapi/syscalls/s390.in
index 2a2ffe223..3ee5547f1 100644
--- a/include/lapi/syscalls/s390.in
+++ b/include/lapi/syscalls/s390.in
@@ -338,3 +338,6 @@ mlock2 374
copy_file_range 375
preadv2 376
pwritev2 377
+pkey_mprotect 384
+pkey_alloc 385
+pkey_free 386
diff --git a/include/lapi/syscalls/s390x.in b/include/lapi/syscalls/s390x.in
index 4c36ce17c..92e882aae 100644
--- a/include/lapi/syscalls/s390x.in
+++ b/include/lapi/syscalls/s390x.in
@@ -337,3 +337,6 @@ mlock2 374
copy_file_range 375
preadv2 376
pwritev2 377
+pkey_mprotect 384
+pkey_alloc 385
+pkey_free 386
diff --git a/include/lapi/syscalls/sh.in b/include/lapi/syscalls/sh.in
index a942fb506..00726c1cc 100644
--- a/include/lapi/syscalls/sh.in
+++ b/include/lapi/syscalls/sh.in
@@ -369,3 +369,6 @@ mlock2 390
copy_file_range 391
preadv2 392
pwritev2 393
+pkey_mprotect 384
+pkey_alloc 385
+pkey_free 386
diff --git a/include/lapi/syscalls/sparc.in b/include/lapi/syscalls/sparc.in
index 20dc37b01..1b34ab489 100644
--- a/include/lapi/syscalls/sparc.in
+++ b/include/lapi/syscalls/sparc.in
@@ -343,3 +343,6 @@ mlock2 356
copy_file_range 357
preadv2 358
pwritev2 359
+pkey_mprotect 362
+pkey_alloc 363
+pkey_free 364
diff --git a/include/lapi/syscalls/sparc64.in b/include/lapi/syscalls/sparc64.in
index c100b8e3e..f3142fbdd 100644
--- a/include/lapi/syscalls/sparc64.in
+++ b/include/lapi/syscalls/sparc64.in
@@ -319,3 +319,6 @@ mlock2 356
copy_file_range 357
preadv2 358
pwritev2 359
+pkey_mprotect 362
+pkey_alloc 363
+pkey_free 364
diff --git a/include/lapi/syscalls/x86_64.in b/include/lapi/syscalls/x86_64.in
index 87849e5c0..9c77f1c67 100644
--- a/include/lapi/syscalls/x86_64.in
+++ b/include/lapi/syscalls/x86_64.in
@@ -315,3 +315,6 @@ copy_file_range 326
preadv2 327
pwritev2 328
statx 332
+pkey_mprotect 329
+pkey_alloc 330
+pkey_free 331
diff --git a/runtest/syscalls b/runtest/syscalls
index a1106fb84..a236fce09 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -723,6 +723,8 @@ mprotect02 mprotect02
mprotect03 mprotect03
mprotect04 mprotect04
+pkey01 pkey01
+
mq_notify01 mq_notify01
mq_notify02 mq_notify02
mq_open01 mq_open01
diff --git a/testcases/kernel/syscalls/pkeys/.gitignore b/testcases/kernel/syscalls/pkeys/.gitignore
new file mode 100644
index 000000000..6fd5addb8
--- /dev/null
+++ b/testcases/kernel/syscalls/pkeys/.gitignore
@@ -0,0 +1 @@
+/pkey01
diff --git a/testcases/kernel/syscalls/pkeys/Makefile b/testcases/kernel/syscalls/pkeys/Makefile
new file mode 100644
index 000000000..9ee2c2ea5
--- /dev/null
+++ b/testcases/kernel/syscalls/pkeys/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) 2019 Red Hat, Inc.
+
+top_srcdir ?= ../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/pkeys/pkey.h b/testcases/kernel/syscalls/pkeys/pkey.h
new file mode 100644
index 000000000..bd86bebcc
--- /dev/null
+++ b/testcases/kernel/syscalls/pkeys/pkey.h
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2019 Red Hat, Inc.
+ */
+
+#ifndef PKEYS_H
+#define PKEYS_H
+
+#include "tst_test.h"
+#include "lapi/syscalls.h"
+
+#ifndef PKEY_DISABLE_ACCESS
+# define PKEY_DISABLE_ACCESS 0x1
+# define PKEY_DISABLE_WRITE 0x2
+#endif
+
+#ifndef HAVE_PKEY_MPROTECT
+static inline int pkey_mprotect(void *addr, size_t len, int prot, int pkey)
+{
+ return tst_syscall(SYS_pkey_mprotect, addr, len, prot, pkey);
+}
+
+static inline int pkey_alloc(unsigned int flags, unsigned int access_rights)
+{
+ return tst_syscall(SYS_pkey_alloc, flags, access_rights);
+}
+
+static inline int pkey_free(int pkey)
+{
+ return tst_syscall(SYS_pkey_free, pkey);
+}
+#endif /* HAVE_PKEY_MPROTECT */
+
+static inline void check_pkey_support(void)
+{
+ int pkey = pkey_alloc(0, 0);
+
+ if ((pkey == -1) && (errno == EINVAL))
+ tst_brk(TCONF, "pkey_alloc is not supported");
+ else
+ pkey_free(pkey);
+}
+
+#endif /* PKEYS_H */
diff --git a/testcases/kernel/syscalls/pkeys/pkey01.c b/testcases/kernel/syscalls/pkeys/pkey01.c
new file mode 100644
index 000000000..8faa4be4c
--- /dev/null
+++ b/testcases/kernel/syscalls/pkeys/pkey01.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2019 Red Hat, Inc.
+ *
+ * Test for Memory Protection Keys
+ * Reference: https://lwn.net/Articles/689395/
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/syscall.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+#include "pkey.h"
+
+static int psize;
+static char *buffer;
+
+static struct tcase {
+ unsigned long flags;
+ unsigned long access_rights;
+ char *name;
+} tcases[] = {
+ {0, PKEY_DISABLE_ACCESS, "PKEY_DISABLE_ACCESS"},
+ {0, PKEY_DISABLE_WRITE, "PKEY_DISABLE_WRITE"},
+};
+
+static void setup(void)
+{
+ check_pkey_support();
+
+ psize = getpagesize();
+ buffer = SAFE_MMAP(NULL, psize, PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_SHARED, -1, 0);
+ memset(buffer, 'a', psize);
+}
+
+static void verify_pkey(unsigned int i)
+{
+ int pkey, status;
+ pid_t pid;
+
+ struct tcase *tc = &tcases[i];
+
+ pkey = pkey_alloc(tc->flags, tc->access_rights);
+ if (pkey == -1)
+ tst_brk(TBROK, "pkey_alloc failed");
+
+ tst_res(TINFO, "Set %s on buffer", tc->name);
+ if (pkey_mprotect(buffer, psize, PROT_READ | PROT_WRITE, pkey) == -1)
+ tst_brk(TBROK, "pkey_mprotect failed");
+
+ pid = SAFE_FORK();
+ if (pid == 0) {
+ switch (tc->access_rights) {
+ case PKEY_DISABLE_ACCESS:
+ tst_res(TFAIL, "Read buffer success, buffer[0] = %d", *buffer);
+ break;
+ case PKEY_DISABLE_WRITE:
+ *buffer = 'b';
+ break;
+ }
+ exit(0);
+ }
+
+ SAFE_WAITPID(pid, &status, 0);
+ if (WIFSIGNALED(status)) {
+ if (WTERMSIG(status) == SIGSEGV) {
+ tst_res(TPASS, "Child ended by %s as expected",
+ tst_strsig(SIGSEGV));
+ } else {
+ tst_res(TFAIL, "Child ended by %s unexpected" ,
+ tst_strsig(WTERMSIG(status)));
+ }
+ } else {
+ tst_res(TFAIL, "Child unexpectedly ended");
+ }
+
+ tst_res(TINFO, "Remove %s from buffer", tc->name);
+ if (pkey_mprotect(buffer, psize, PROT_READ | PROT_WRITE, 0x0) == -1)
+ tst_brk(TBROK, "pkey_mprotect failed");
+ *buffer = i;
+ tst_res(TPASS, "Write buffer success, buffer[0] = %d", *buffer);
+
+ if (pkey_free(pkey) == -1)
+ tst_brk(TBROK, "pkey_free failed");
+}
+
+static void cleanup(void)
+{
+ if (buffer)
+ SAFE_MUNMAP(buffer, psize);
+}
+
+static struct tst_test test = {
+ .tcnt = ARRAY_SIZE(tcases),
+ .forks_child = 1,
+ .test = verify_pkey,
+ .setup = setup,
+ .cleanup = cleanup,
+};
--
2.20.1
^ permalink raw reply related [flat|nested] 3+ messages in thread* [LTP] [PATCH] pkey: Add test for memory protection keys
2019-06-20 9:55 [LTP] [PATCH] pkey: Add test for memory protection keys Li Wang
@ 2019-06-20 13:05 ` Jan Stancek
2019-06-21 6:08 ` Li Wang
0 siblings, 1 reply; 3+ messages in thread
From: Jan Stancek @ 2019-06-20 13:05 UTC (permalink / raw)
To: ltp
----- Original Message -----
> Signed-off-by: Li Wang <liwang@redhat.com>
> ---
> configure.ac | 1 +
> include/lapi/syscalls/aarch64.in | 3 +
> include/lapi/syscalls/arm.in | 3 +
> include/lapi/syscalls/i386.in | 3 +
> include/lapi/syscalls/ia64.in | 3 +
> include/lapi/syscalls/powerpc.in | 3 +
> include/lapi/syscalls/powerpc64.in | 3 +
> include/lapi/syscalls/s390.in | 3 +
> include/lapi/syscalls/s390x.in | 3 +
> include/lapi/syscalls/sh.in | 3 +
> include/lapi/syscalls/sparc.in | 3 +
> include/lapi/syscalls/sparc64.in | 3 +
> include/lapi/syscalls/x86_64.in | 3 +
> runtest/syscalls | 2 +
> testcases/kernel/syscalls/pkeys/.gitignore | 1 +
> testcases/kernel/syscalls/pkeys/Makefile | 8 ++
> testcases/kernel/syscalls/pkeys/pkey.h | 44 +++++++++
> testcases/kernel/syscalls/pkeys/pkey01.c | 105 +++++++++++++++++++++
> 18 files changed, 197 insertions(+)
> create mode 100644 testcases/kernel/syscalls/pkeys/.gitignore
> create mode 100644 testcases/kernel/syscalls/pkeys/Makefile
> create mode 100644 testcases/kernel/syscalls/pkeys/pkey.h
> create mode 100644 testcases/kernel/syscalls/pkeys/pkey01.c
>
> diff --git a/configure.ac b/configure.ac
> index 5ecc92781..35997699f 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -76,6 +76,7 @@ AC_CHECK_FUNCS([ \
> profil \
> pwritev \
> pwritev2 \
> + pkey_mprotect \
> readlinkat \
> renameat \
> renameat2 \
> diff --git a/include/lapi/syscalls/aarch64.in
> b/include/lapi/syscalls/aarch64.in
> index 177dd0115..4232defbe 100644
> --- a/include/lapi/syscalls/aarch64.in
> +++ b/include/lapi/syscalls/aarch64.in
> @@ -266,3 +266,6 @@ copy_file_range 285
> preadv2 286
> pwritev2 287
> _sysctl 1078
> +pkey_mprotect 394
> +pkey_alloc 395
> +pkey_free 396
288, 289, 290
> diff --git a/include/lapi/syscalls/arm.in b/include/lapi/syscalls/arm.in
> index f4adedb2c..48b55b5ff 100644
> --- a/include/lapi/syscalls/arm.in
> +++ b/include/lapi/syscalls/arm.in
> @@ -350,3 +350,6 @@ copy_file_range (__NR_SYSCALL_BASE+391)
> preadv2 (__NR_SYSCALL_BASE+392)
> pwritev2 (__NR_SYSCALL_BASE+393)
> statx (__NR_SYSCALL_BASE+397)
> +pkey_mprotect (__NR_SYSCALL_BASE+394)
> +pkey_alloc (__NR_SYSCALL_BASE+395)
> +pkey_free (__NR_SYSCALL_BASE+396)
> diff --git a/include/lapi/syscalls/i386.in b/include/lapi/syscalls/i386.in
> index af5254f77..c54573547 100644
> --- a/include/lapi/syscalls/i386.in
> +++ b/include/lapi/syscalls/i386.in
> @@ -348,3 +348,6 @@ copy_file_range 377
> preadv2 378
> pwritev2 379
> statx 383
> +pkey_mprotect 380
> +pkey_alloc 381
> +pkey_free 382
> diff --git a/include/lapi/syscalls/ia64.in b/include/lapi/syscalls/ia64.in
> index c0aeed08b..56bfd7928 100644
> --- a/include/lapi/syscalls/ia64.in
> +++ b/include/lapi/syscalls/ia64.in
> @@ -305,3 +305,6 @@ mlock2 1346
> copy_file_range 1347
> preadv2 1348
> pwritev2 1349
> +pkey_mprotect 330
> +pkey_alloc 331
> +pkey_free 332
> diff --git a/include/lapi/syscalls/powerpc.in
> b/include/lapi/syscalls/powerpc.in
> index 6b6be58a7..eaf8d45ed 100644
> --- a/include/lapi/syscalls/powerpc.in
> +++ b/include/lapi/syscalls/powerpc.in
> @@ -355,3 +355,6 @@ copy_file_range 379
> preadv2 380
> pwritev2 381
> statx 383
> +pkey_mprotect 386
> +pkey_alloc 384
> +pkey_free 385
> diff --git a/include/lapi/syscalls/powerpc64.in
> b/include/lapi/syscalls/powerpc64.in
> index 6b6be58a7..eaf8d45ed 100644
> --- a/include/lapi/syscalls/powerpc64.in
> +++ b/include/lapi/syscalls/powerpc64.in
> @@ -355,3 +355,6 @@ copy_file_range 379
> preadv2 380
> pwritev2 381
> statx 383
> +pkey_mprotect 386
> +pkey_alloc 384
> +pkey_free 385
> diff --git a/include/lapi/syscalls/s390.in b/include/lapi/syscalls/s390.in
> index 2a2ffe223..3ee5547f1 100644
> --- a/include/lapi/syscalls/s390.in
> +++ b/include/lapi/syscalls/s390.in
> @@ -338,3 +338,6 @@ mlock2 374
> copy_file_range 375
> preadv2 376
> pwritev2 377
> +pkey_mprotect 384
> +pkey_alloc 385
> +pkey_free 386
> diff --git a/include/lapi/syscalls/s390x.in b/include/lapi/syscalls/s390x.in
> index 4c36ce17c..92e882aae 100644
> --- a/include/lapi/syscalls/s390x.in
> +++ b/include/lapi/syscalls/s390x.in
> @@ -337,3 +337,6 @@ mlock2 374
> copy_file_range 375
> preadv2 376
> pwritev2 377
> +pkey_mprotect 384
> +pkey_alloc 385
> +pkey_free 386
> diff --git a/include/lapi/syscalls/sh.in b/include/lapi/syscalls/sh.in
> index a942fb506..00726c1cc 100644
> --- a/include/lapi/syscalls/sh.in
> +++ b/include/lapi/syscalls/sh.in
> @@ -369,3 +369,6 @@ mlock2 390
> copy_file_range 391
> preadv2 392
> pwritev2 393
> +pkey_mprotect 384
> +pkey_alloc 385
> +pkey_free 386
> diff --git a/include/lapi/syscalls/sparc.in b/include/lapi/syscalls/sparc.in
> index 20dc37b01..1b34ab489 100644
> --- a/include/lapi/syscalls/sparc.in
> +++ b/include/lapi/syscalls/sparc.in
> @@ -343,3 +343,6 @@ mlock2 356
> copy_file_range 357
> preadv2 358
> pwritev2 359
> +pkey_mprotect 362
> +pkey_alloc 363
> +pkey_free 364
> diff --git a/include/lapi/syscalls/sparc64.in
> b/include/lapi/syscalls/sparc64.in
> index c100b8e3e..f3142fbdd 100644
> --- a/include/lapi/syscalls/sparc64.in
> +++ b/include/lapi/syscalls/sparc64.in
> @@ -319,3 +319,6 @@ mlock2 356
> copy_file_range 357
> preadv2 358
> pwritev2 359
> +pkey_mprotect 362
> +pkey_alloc 363
> +pkey_free 364
> diff --git a/include/lapi/syscalls/x86_64.in
> b/include/lapi/syscalls/x86_64.in
> index 87849e5c0..9c77f1c67 100644
> --- a/include/lapi/syscalls/x86_64.in
> +++ b/include/lapi/syscalls/x86_64.in
> @@ -315,3 +315,6 @@ copy_file_range 326
> preadv2 327
> pwritev2 328
> statx 332
> +pkey_mprotect 329
> +pkey_alloc 330
> +pkey_free 331
> diff --git a/runtest/syscalls b/runtest/syscalls
> index a1106fb84..a236fce09 100644
> --- a/runtest/syscalls
> +++ b/runtest/syscalls
> @@ -723,6 +723,8 @@ mprotect02 mprotect02
> mprotect03 mprotect03
> mprotect04 mprotect04
>
> +pkey01 pkey01
> +
> mq_notify01 mq_notify01
> mq_notify02 mq_notify02
> mq_open01 mq_open01
> diff --git a/testcases/kernel/syscalls/pkeys/.gitignore
> b/testcases/kernel/syscalls/pkeys/.gitignore
> new file mode 100644
> index 000000000..6fd5addb8
> --- /dev/null
> +++ b/testcases/kernel/syscalls/pkeys/.gitignore
> @@ -0,0 +1 @@
> +/pkey01
> diff --git a/testcases/kernel/syscalls/pkeys/Makefile
> b/testcases/kernel/syscalls/pkeys/Makefile
> new file mode 100644
> index 000000000..9ee2c2ea5
> --- /dev/null
> +++ b/testcases/kernel/syscalls/pkeys/Makefile
> @@ -0,0 +1,8 @@
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# Copyright (c) 2019 Red Hat, Inc.
> +
> +top_srcdir ?= ../../../..
> +
> +include $(top_srcdir)/include/mk/testcases.mk
> +
> +include $(top_srcdir)/include/mk/generic_leaf_target.mk
> diff --git a/testcases/kernel/syscalls/pkeys/pkey.h
> b/testcases/kernel/syscalls/pkeys/pkey.h
> new file mode 100644
> index 000000000..bd86bebcc
> --- /dev/null
> +++ b/testcases/kernel/syscalls/pkeys/pkey.h
> @@ -0,0 +1,44 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2019 Red Hat, Inc.
> + */
> +
> +#ifndef PKEYS_H
> +#define PKEYS_H
> +
> +#include "tst_test.h"
> +#include "lapi/syscalls.h"
> +
> +#ifndef PKEY_DISABLE_ACCESS
> +# define PKEY_DISABLE_ACCESS 0x1
> +# define PKEY_DISABLE_WRITE 0x2
> +#endif
> +
> +#ifndef HAVE_PKEY_MPROTECT
> +static inline int pkey_mprotect(void *addr, size_t len, int prot, int pkey)
> +{
> + return tst_syscall(SYS_pkey_mprotect, addr, len, prot, pkey);
> +}
> +
> +static inline int pkey_alloc(unsigned int flags, unsigned int access_rights)
> +{
> + return tst_syscall(SYS_pkey_alloc, flags, access_rights);
> +}
> +
> +static inline int pkey_free(int pkey)
> +{
> + return tst_syscall(SYS_pkey_free, pkey);
> +}
> +#endif /* HAVE_PKEY_MPROTECT */
> +
> +static inline void check_pkey_support(void)
> +{
> + int pkey = pkey_alloc(0, 0);
> +
> + if ((pkey == -1) && (errno == EINVAL))
Shouldn't this handle also ENOSPC?
ENOSPC (pkey_alloc()) All protection keys available for the current process have been allocated. The number of keys available is
architecture-specific and implementation-specific and may be reduced by kernel-internal use of certain keys. There are
currently 15 keys available to user programs on x86.
This error will also be returned if the processor or operating system does not support protection keys. Applications
should always be prepared to handle this error, since factors outside of the application's control can reduce the number
of available pkeys.
> + tst_brk(TCONF, "pkey_alloc is not supported");
> + else
> + pkey_free(pkey);
> +}
> +
> +#endif /* PKEYS_H */
> diff --git a/testcases/kernel/syscalls/pkeys/pkey01.c
> b/testcases/kernel/syscalls/pkeys/pkey01.c
> new file mode 100644
> index 000000000..8faa4be4c
> --- /dev/null
> +++ b/testcases/kernel/syscalls/pkeys/pkey01.c
> @@ -0,0 +1,105 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2019 Red Hat, Inc.
> + *
> + * Test for Memory Protection Keys
> + * Reference: https://lwn.net/Articles/689395/
> + */
> +
> +#define _GNU_SOURCE
> +#include <stdio.h>
> +#include <unistd.h>
> +#include <errno.h>
> +#include <stdlib.h>
> +#include <sys/syscall.h>
> +#include <sys/mman.h>
> +#include <sys/wait.h>
> +
> +#include "pkey.h"
> +
> +static int psize;
> +static char *buffer;
> +
> +static struct tcase {
> + unsigned long flags;
> + unsigned long access_rights;
> + char *name;
> +} tcases[] = {
> + {0, PKEY_DISABLE_ACCESS, "PKEY_DISABLE_ACCESS"},
> + {0, PKEY_DISABLE_WRITE, "PKEY_DISABLE_WRITE"},
> +};
> +
> +static void setup(void)
> +{
> + check_pkey_support();
> +
> + psize = getpagesize();
> + buffer = SAFE_MMAP(NULL, psize, PROT_READ | PROT_WRITE,
> + MAP_ANONYMOUS | MAP_SHARED, -1, 0);
> + memset(buffer, 'a', psize);
> +}
> +
> +static void verify_pkey(unsigned int i)
> +{
> + int pkey, status;
> + pid_t pid;
> +
> + struct tcase *tc = &tcases[i];
> +
> + pkey = pkey_alloc(tc->flags, tc->access_rights);
> + if (pkey == -1)
> + tst_brk(TBROK, "pkey_alloc failed");
> +
> + tst_res(TINFO, "Set %s on buffer", tc->name);
> + if (pkey_mprotect(buffer, psize, PROT_READ | PROT_WRITE, pkey) == -1)
> + tst_brk(TBROK, "pkey_mprotect failed");
> +
> + pid = SAFE_FORK();
> + if (pid == 0) {
I'd suggest something like:
struct rlimit r;
r.rlim_cur = 1;
r.rlim_max = 1;
SAFE_SETRLIMIT(RLIMIT_CORE, &r);
to avoid getting cores from this child - since it is expected to segfault.
> + switch (tc->access_rights) {
> + case PKEY_DISABLE_ACCESS:
> + tst_res(TFAIL, "Read buffer success, buffer[0] = %d", *buffer);
> + break;
> + case PKEY_DISABLE_WRITE:
> + *buffer = 'b';
> + break;
> + }
> + exit(0);
> + }
> +
> + SAFE_WAITPID(pid, &status, 0);
> + if (WIFSIGNALED(status)) {
> + if (WTERMSIG(status) == SIGSEGV) {
> + tst_res(TPASS, "Child ended by %s as expected",
> + tst_strsig(SIGSEGV));
> + } else {
> + tst_res(TFAIL, "Child ended by %s unexpected" ,
> + tst_strsig(WTERMSIG(status)));
> + }
> + } else {
> + tst_res(TFAIL, "Child unexpectedly ended");
> + }
> +
> + tst_res(TINFO, "Remove %s from buffer", tc->name);
> + if (pkey_mprotect(buffer, psize, PROT_READ | PROT_WRITE, 0x0) == -1)
> + tst_brk(TBROK, "pkey_mprotect failed");
> + *buffer = i;
> + tst_res(TPASS, "Write buffer success, buffer[0] = %d", *buffer);
> +
> + if (pkey_free(pkey) == -1)
> + tst_brk(TBROK, "pkey_free failed");
> +}
> +
> +static void cleanup(void)
> +{
> + if (buffer)
> + SAFE_MUNMAP(buffer, psize);
> +}
> +
> +static struct tst_test test = {
> + .tcnt = ARRAY_SIZE(tcases),
> + .forks_child = 1,
> + .test = verify_pkey,
> + .setup = setup,
> + .cleanup = cleanup,
> +};
> --
> 2.20.1
>
>
> --
> Mailing list info: https://lists.linux.it/listinfo/ltp
>
^ permalink raw reply [flat|nested] 3+ messages in thread* [LTP] [PATCH] pkey: Add test for memory protection keys
2019-06-20 13:05 ` Jan Stancek
@ 2019-06-21 6:08 ` Li Wang
0 siblings, 0 replies; 3+ messages in thread
From: Li Wang @ 2019-06-21 6:08 UTC (permalink / raw)
To: ltp
On Thu, Jun 20, 2019 at 9:05 PM Jan Stancek <jstancek@redhat.com> wrote:
>
>
> ----- Original Message -----
> > Signed-off-by: Li Wang <liwang@redhat.com>
> > ---
> > configure.ac | 1 +
> > include/lapi/syscalls/aarch64.in | 3 +
> > include/lapi/syscalls/arm.in | 3 +
> > include/lapi/syscalls/i386.in | 3 +
> > include/lapi/syscalls/ia64.in | 3 +
> > include/lapi/syscalls/powerpc.in | 3 +
> > include/lapi/syscalls/powerpc64.in | 3 +
> > include/lapi/syscalls/s390.in | 3 +
> > include/lapi/syscalls/s390x.in | 3 +
> > include/lapi/syscalls/sh.in | 3 +
> > include/lapi/syscalls/sparc.in | 3 +
> > include/lapi/syscalls/sparc64.in | 3 +
> > include/lapi/syscalls/x86_64.in | 3 +
> > runtest/syscalls | 2 +
> > testcases/kernel/syscalls/pkeys/.gitignore | 1 +
> > testcases/kernel/syscalls/pkeys/Makefile | 8 ++
> > testcases/kernel/syscalls/pkeys/pkey.h | 44 +++++++++
> > testcases/kernel/syscalls/pkeys/pkey01.c | 105 +++++++++++++++++++++
> > 18 files changed, 197 insertions(+)
> > create mode 100644 testcases/kernel/syscalls/pkeys/.gitignore
> > create mode 100644 testcases/kernel/syscalls/pkeys/Makefile
> > create mode 100644 testcases/kernel/syscalls/pkeys/pkey.h
> > create mode 100644 testcases/kernel/syscalls/pkeys/pkey01.c
> >
> > diff --git a/configure.ac b/configure.ac
> > index 5ecc92781..35997699f 100644
> > --- a/configure.ac
> > +++ b/configure.ac
> > @@ -76,6 +76,7 @@ AC_CHECK_FUNCS([ \
> > profil \
> > pwritev \
> > pwritev2 \
> > + pkey_mprotect \
> > readlinkat \
> > renameat \
> > renameat2 \
> > diff --git a/include/lapi/syscalls/aarch64.in
> > b/include/lapi/syscalls/aarch64.in
> > index 177dd0115..4232defbe 100644
> > --- a/include/lapi/syscalls/aarch64.in
> > +++ b/include/lapi/syscalls/aarch64.in
> > @@ -266,3 +266,6 @@ copy_file_range 285
> > preadv2 286
> > pwritev2 287
> > _sysctl 1078
> > +pkey_mprotect 394
> > +pkey_alloc 395
> > +pkey_free 396
>
> 288, 289, 290
>
Good eyes.
>
> > diff --git a/include/lapi/syscalls/arm.in b/include/lapi/syscalls/arm.in
> > index f4adedb2c..48b55b5ff 100644
> > --- a/include/lapi/syscalls/arm.in
> > +++ b/include/lapi/syscalls/arm.in
> > @@ -350,3 +350,6 @@ copy_file_range (__NR_SYSCALL_BASE+391)
> > preadv2 (__NR_SYSCALL_BASE+392)
> > pwritev2 (__NR_SYSCALL_BASE+393)
> > statx (__NR_SYSCALL_BASE+397)
> > +pkey_mprotect (__NR_SYSCALL_BASE+394)
> > +pkey_alloc (__NR_SYSCALL_BASE+395)
> > +pkey_free (__NR_SYSCALL_BASE+396)
> > diff --git a/include/lapi/syscalls/i386.in b/include/lapi/syscalls/
> i386.in
> > index af5254f77..c54573547 100644
> > --- a/include/lapi/syscalls/i386.in
> > +++ b/include/lapi/syscalls/i386.in
> > @@ -348,3 +348,6 @@ copy_file_range 377
> > preadv2 378
> > pwritev2 379
> > statx 383
> > +pkey_mprotect 380
> > +pkey_alloc 381
> > +pkey_free 382
> > diff --git a/include/lapi/syscalls/ia64.in b/include/lapi/syscalls/
> ia64.in
> > index c0aeed08b..56bfd7928 100644
> > --- a/include/lapi/syscalls/ia64.in
> > +++ b/include/lapi/syscalls/ia64.in
> > @@ -305,3 +305,6 @@ mlock2 1346
> > copy_file_range 1347
> > preadv2 1348
> > pwritev2 1349
> > +pkey_mprotect 330
> > +pkey_alloc 331
> > +pkey_free 332
>
And here should be:
pkey_mprotect 1354
pkey_alloc 1355
pkey_free 1356
> > diff --git a/include/lapi/syscalls/powerpc.in
> > b/include/lapi/syscalls/powerpc.in
> > index 6b6be58a7..eaf8d45ed 100644
> > --- a/include/lapi/syscalls/powerpc.in
> > +++ b/include/lapi/syscalls/powerpc.in
> > @@ -355,3 +355,6 @@ copy_file_range 379
> > preadv2 380
> > pwritev2 381
> > statx 383
> > +pkey_mprotect 386
> > +pkey_alloc 384
> > +pkey_free 385
> > diff --git a/include/lapi/syscalls/powerpc64.in
> > b/include/lapi/syscalls/powerpc64.in
> > index 6b6be58a7..eaf8d45ed 100644
> > --- a/include/lapi/syscalls/powerpc64.in
> > +++ b/include/lapi/syscalls/powerpc64.in
> > @@ -355,3 +355,6 @@ copy_file_range 379
> > preadv2 380
> > pwritev2 381
> > statx 383
> > +pkey_mprotect 386
> > +pkey_alloc 384
> > +pkey_free 385
> > diff --git a/include/lapi/syscalls/s390.in b/include/lapi/syscalls/
> s390.in
> > index 2a2ffe223..3ee5547f1 100644
> > --- a/include/lapi/syscalls/s390.in
> > +++ b/include/lapi/syscalls/s390.in
> > @@ -338,3 +338,6 @@ mlock2 374
> > copy_file_range 375
> > preadv2 376
> > pwritev2 377
> > +pkey_mprotect 384
> > +pkey_alloc 385
> > +pkey_free 386
> > diff --git a/include/lapi/syscalls/s390x.in b/include/lapi/syscalls/
> s390x.in
> > index 4c36ce17c..92e882aae 100644
> > --- a/include/lapi/syscalls/s390x.in
> > +++ b/include/lapi/syscalls/s390x.in
> > @@ -337,3 +337,6 @@ mlock2 374
> > copy_file_range 375
> > preadv2 376
> > pwritev2 377
> > +pkey_mprotect 384
> > +pkey_alloc 385
> > +pkey_free 386
> > diff --git a/include/lapi/syscalls/sh.in b/include/lapi/syscalls/sh.in
> > index a942fb506..00726c1cc 100644
> > --- a/include/lapi/syscalls/sh.in
> > +++ b/include/lapi/syscalls/sh.in
> > @@ -369,3 +369,6 @@ mlock2 390
> > copy_file_range 391
> > preadv2 392
> > pwritev2 393
> > +pkey_mprotect 384
> > +pkey_alloc 385
> > +pkey_free 386
> > diff --git a/include/lapi/syscalls/sparc.in b/include/lapi/syscalls/
> sparc.in
> > index 20dc37b01..1b34ab489 100644
> > --- a/include/lapi/syscalls/sparc.in
> > +++ b/include/lapi/syscalls/sparc.in
> > @@ -343,3 +343,6 @@ mlock2 356
> > copy_file_range 357
> > preadv2 358
> > pwritev2 359
> > +pkey_mprotect 362
> > +pkey_alloc 363
> > +pkey_free 364
> > diff --git a/include/lapi/syscalls/sparc64.in
> > b/include/lapi/syscalls/sparc64.in
> > index c100b8e3e..f3142fbdd 100644
> > --- a/include/lapi/syscalls/sparc64.in
> > +++ b/include/lapi/syscalls/sparc64.in
> > @@ -319,3 +319,6 @@ mlock2 356
> > copy_file_range 357
> > preadv2 358
> > pwritev2 359
> > +pkey_mprotect 362
> > +pkey_alloc 363
> > +pkey_free 364
> > diff --git a/include/lapi/syscalls/x86_64.in
> > b/include/lapi/syscalls/x86_64.in
> > index 87849e5c0..9c77f1c67 100644
> > --- a/include/lapi/syscalls/x86_64.in
> > +++ b/include/lapi/syscalls/x86_64.in
> > @@ -315,3 +315,6 @@ copy_file_range 326
> > preadv2 327
> > pwritev2 328
> > statx 332
> > +pkey_mprotect 329
> > +pkey_alloc 330
> > +pkey_free 331
> > diff --git a/runtest/syscalls b/runtest/syscalls
> > index a1106fb84..a236fce09 100644
> > --- a/runtest/syscalls
> > +++ b/runtest/syscalls
> > @@ -723,6 +723,8 @@ mprotect02 mprotect02
> > mprotect03 mprotect03
> > mprotect04 mprotect04
> >
> > +pkey01 pkey01
> > +
> > mq_notify01 mq_notify01
> > mq_notify02 mq_notify02
> > mq_open01 mq_open01
> > diff --git a/testcases/kernel/syscalls/pkeys/.gitignore
> > b/testcases/kernel/syscalls/pkeys/.gitignore
> > new file mode 100644
> > index 000000000..6fd5addb8
> > --- /dev/null
> > +++ b/testcases/kernel/syscalls/pkeys/.gitignore
> > @@ -0,0 +1 @@
> > +/pkey01
> > diff --git a/testcases/kernel/syscalls/pkeys/Makefile
> > b/testcases/kernel/syscalls/pkeys/Makefile
> > new file mode 100644
> > index 000000000..9ee2c2ea5
> > --- /dev/null
> > +++ b/testcases/kernel/syscalls/pkeys/Makefile
> > @@ -0,0 +1,8 @@
> > +# SPDX-License-Identifier: GPL-2.0-or-later
> > +# Copyright (c) 2019 Red Hat, Inc.
> > +
> > +top_srcdir ?= ../../../..
> > +
> > +include $(top_srcdir)/include/mk/testcases.mk
> > +
> > +include $(top_srcdir)/include/mk/generic_leaf_target.mk
> > diff --git a/testcases/kernel/syscalls/pkeys/pkey.h
> > b/testcases/kernel/syscalls/pkeys/pkey.h
> > new file mode 100644
> > index 000000000..bd86bebcc
> > --- /dev/null
> > +++ b/testcases/kernel/syscalls/pkeys/pkey.h
> > @@ -0,0 +1,44 @@
> > +// SPDX-License-Identifier: GPL-2.0-or-later
> > +/*
> > + * Copyright (c) 2019 Red Hat, Inc.
> > + */
> > +
> > +#ifndef PKEYS_H
> > +#define PKEYS_H
> > +
> > +#include "tst_test.h"
> > +#include "lapi/syscalls.h"
> > +
> > +#ifndef PKEY_DISABLE_ACCESS
> > +# define PKEY_DISABLE_ACCESS 0x1
> > +# define PKEY_DISABLE_WRITE 0x2
> > +#endif
> > +
> > +#ifndef HAVE_PKEY_MPROTECT
> > +static inline int pkey_mprotect(void *addr, size_t len, int prot, int
> pkey)
> > +{
> > + return tst_syscall(SYS_pkey_mprotect, addr, len, prot, pkey);
> > +}
> > +
> > +static inline int pkey_alloc(unsigned int flags, unsigned int
> access_rights)
> > +{
> > + return tst_syscall(SYS_pkey_alloc, flags, access_rights);
> > +}
> > +
> > +static inline int pkey_free(int pkey)
> > +{
> > + return tst_syscall(SYS_pkey_free, pkey);
> > +}
> > +#endif /* HAVE_PKEY_MPROTECT */
> > +
> > +static inline void check_pkey_support(void)
> > +{
> > + int pkey = pkey_alloc(0, 0);
> > +
> > + if ((pkey == -1) && (errno == EINVAL))
>
> Shouldn't this handle also ENOSPC?
>
Yes, if all pkeys have been allocated on a system, then we will get this
error in allocating a new pkey.
I will handle this in v2.
> ENOSPC (pkey_alloc()) All protection keys available for the current
> process have been allocated. The number of keys available is
> architecture-specific and implementation-specific and may
> be reduced by kernel-internal use of certain keys. There are
> currently 15 keys available to user programs on x86.
>
> This error will also be returned if the processor or
> operating system does not support protection keys. Applications
> should always be prepared to handle this error, since
> factors outside of the application's control can reduce the number
> of available pkeys.
>
> > + tst_brk(TCONF, "pkey_alloc is not supported");
> > + else
> > + pkey_free(pkey);
> > +}
> > +
> > +#endif /* PKEYS_H */
> > diff --git a/testcases/kernel/syscalls/pkeys/pkey01.c
> > b/testcases/kernel/syscalls/pkeys/pkey01.c
> > new file mode 100644
> > index 000000000..8faa4be4c
> > --- /dev/null
> > +++ b/testcases/kernel/syscalls/pkeys/pkey01.c
> > @@ -0,0 +1,105 @@
> > +// SPDX-License-Identifier: GPL-2.0-or-later
> > +/*
> > + * Copyright (c) 2019 Red Hat, Inc.
> > + *
> > + * Test for Memory Protection Keys
> > + * Reference: https://lwn.net/Articles/689395/
> > + */
> > +
> > +#define _GNU_SOURCE
> > +#include <stdio.h>
> > +#include <unistd.h>
> > +#include <errno.h>
> > +#include <stdlib.h>
> > +#include <sys/syscall.h>
> > +#include <sys/mman.h>
> > +#include <sys/wait.h>
> > +
> > +#include "pkey.h"
> > +
> > +static int psize;
> > +static char *buffer;
> > +
> > +static struct tcase {
> > + unsigned long flags;
> > + unsigned long access_rights;
> > + char *name;
> > +} tcases[] = {
> > + {0, PKEY_DISABLE_ACCESS, "PKEY_DISABLE_ACCESS"},
> > + {0, PKEY_DISABLE_WRITE, "PKEY_DISABLE_WRITE"},
> > +};
> > +
> > +static void setup(void)
> > +{
> > + check_pkey_support();
> > +
> > + psize = getpagesize();
> > + buffer = SAFE_MMAP(NULL, psize, PROT_READ | PROT_WRITE,
> > + MAP_ANONYMOUS | MAP_SHARED, -1, 0);
> > + memset(buffer, 'a', psize);
> > +}
> > +
> > +static void verify_pkey(unsigned int i)
> > +{
> > + int pkey, status;
> > + pid_t pid;
> > +
> > + struct tcase *tc = &tcases[i];
> > +
> > + pkey = pkey_alloc(tc->flags, tc->access_rights);
> > + if (pkey == -1)
> > + tst_brk(TBROK, "pkey_alloc failed");
> > +
> > + tst_res(TINFO, "Set %s on buffer", tc->name);
> > + if (pkey_mprotect(buffer, psize, PROT_READ | PROT_WRITE, pkey) ==
> -1)
> > + tst_brk(TBROK, "pkey_mprotect failed");
> > +
> > + pid = SAFE_FORK();
> > + if (pid == 0) {
>
> I'd suggest something like:
> struct rlimit r;
>
>
> r.rlim_cur = 1;
>
> r.rlim_max = 1;
>
> SAFE_SETRLIMIT(RLIMIT_CORE, &r);
>
> to avoid getting cores from this child - since it is expected to segfault.
>
Good advice.
>
> > + switch (tc->access_rights) {
> > + case PKEY_DISABLE_ACCESS:
> > + tst_res(TFAIL, "Read buffer success, buffer[0] =
> %d", *buffer);
> > + break;
> > + case PKEY_DISABLE_WRITE:
> > + *buffer = 'b';
> > + break;
> > + }
> > + exit(0);
> > + }
> > +
> > + SAFE_WAITPID(pid, &status, 0);
> > + if (WIFSIGNALED(status)) {
> > + if (WTERMSIG(status) == SIGSEGV) {
> > + tst_res(TPASS, "Child ended by %s as expected",
> > + tst_strsig(SIGSEGV));
> > + } else {
> > + tst_res(TFAIL, "Child ended by %s unexpected" ,
> > + tst_strsig(WTERMSIG(status)));
> > + }
> > + } else {
> > + tst_res(TFAIL, "Child unexpectedly ended");
> > + }
> > +
> > + tst_res(TINFO, "Remove %s from buffer", tc->name);
> > + if (pkey_mprotect(buffer, psize, PROT_READ | PROT_WRITE, 0x0) ==
> -1)
> > + tst_brk(TBROK, "pkey_mprotect failed");
> > + *buffer = i;
> > + tst_res(TPASS, "Write buffer success, buffer[0] = %d", *buffer);
> > +
> > + if (pkey_free(pkey) == -1)
> > + tst_brk(TBROK, "pkey_free failed");
> > +}
> > +
> > +static void cleanup(void)
> > +{
> > + if (buffer)
> > + SAFE_MUNMAP(buffer, psize);
> > +}
> > +
> > +static struct tst_test test = {
> > + .tcnt = ARRAY_SIZE(tcases),
> > + .forks_child = 1,
> > + .test = verify_pkey,
> > + .setup = setup,
> > + .cleanup = cleanup,
> > +};
> > --
> > 2.20.1
> >
> >
> > --
> > Mailing list info: https://lists.linux.it/listinfo/ltp
> >
>
--
Regards,
Li Wang
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.linux.it/pipermail/ltp/attachments/20190621/2dcd470b/attachment-0001.html>
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2019-06-21 6:08 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-06-20 9:55 [LTP] [PATCH] pkey: Add test for memory protection keys Li Wang
2019-06-20 13:05 ` Jan Stancek
2019-06-21 6:08 ` Li Wang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox