Skip to contentSkip to conversation

Test for Memory Protection Key

PATCH Superseded Li Wang 2 participants 5 messages Jun 25, 2019

v3 of 5 Superseded Latest is v5 →

lore
Share & tools
lore

Li Wang

author
#0 lore raw

v3 cover Test for Memory Protection Key

Change log:
v2 --> v3
* Merge pkey02 into pkey01
* Add huge page in the pkey test
* tst_* functions reprot fail with TERRNO
* tst_res(TFAIL, ...) could print exit code

Li Wang (2):
pkey: add syscall numbers for pkey
pkey: add test for memory protection keys

Signature · 1 line
2.20.1
author
#1 lore raw

PATCH v3 1/2 pkey: add syscall numbers for pkey

---
 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/sparc.in     | 3 +++
 include/lapi/syscalls/sparc64.in   | 3 +++
 include/lapi/syscalls/x86_64.in    | 3 +++
 11 files changed, 33 insertions(+)
include/lapi/syscalls/aarch64.in +3 -0
index ce6080894..7db6e281c 100644
@@ -265,5 +265,8 @@ mlock2 284
 copy_file_range 285
 preadv2 286
 pwritev2 287
+pkey_mprotect 288
+pkey_alloc 289
+pkey_free 290
 pidfd_send_signal 424
 _sysctl 1078
include/lapi/syscalls/arm.in +3 -0
index 33168889f..00e99f2b9 100644
@@ -349,5 +349,8 @@ mlock2 (__NR_SYSCALL_BASE+390)
 copy_file_range (__NR_SYSCALL_BASE+391)
 preadv2 (__NR_SYSCALL_BASE+392)
 pwritev2 (__NR_SYSCALL_BASE+393)
+pkey_mprotect (__NR_SYSCALL_BASE+394)
+pkey_alloc (__NR_SYSCALL_BASE+395)
+pkey_free (__NR_SYSCALL_BASE+396)
 statx (__NR_SYSCALL_BASE+397)
 pidfd_send_signal (__NR_SYSCALL_BASE+424)
include/lapi/syscalls/i386.in +3 -0
index 3355b9127..02f3955ba 100644
@@ -347,5 +347,8 @@ mlock2 376
 copy_file_range 377
 preadv2 378
 pwritev2 379
+pkey_mprotect 380
+pkey_alloc 381
+pkey_free 382
 statx 383
 pidfd_send_signal 424
include/lapi/syscalls/ia64.in +3 -0
index 9ac81e91e..cf9f73e85 100644
@@ -305,4 +305,7 @@ mlock2 1346
 copy_file_range 1347
 preadv2 1348
 pwritev2 1349
+pkey_mprotect 1354
+pkey_alloc 1355
+pkey_free 1356
 pidfd_send_signal 1448
include/lapi/syscalls/powerpc.in +3 -0
index 488d6dfa9..660165d7a 100644
@@ -356,3 +356,6 @@ preadv2 380
 pwritev2 381
 statx 383
 pidfd_send_signal 424
+pkey_mprotect 386
+pkey_alloc 384
+pkey_free 385
include/lapi/syscalls/powerpc64.in +3 -0
index 488d6dfa9..660165d7a 100644
@@ -356,3 +356,6 @@ preadv2 380
 pwritev2 381
 statx 383
 pidfd_send_signal 424
+pkey_mprotect 386
+pkey_alloc 384
+pkey_free 385
include/lapi/syscalls/s390.in +3 -0
index 69b49eac0..c304ef4b7 100644
@@ -338,4 +338,7 @@ mlock2 374
 copy_file_range 375
 preadv2 376
 pwritev2 377
+pkey_mprotect 384
+pkey_alloc 385
+pkey_free 386
 pidfd_send_signal 424
include/lapi/syscalls/s390x.in +3 -0
index 685c16f68..7d632d1dc 100644
@@ -337,4 +337,7 @@ mlock2 374
 copy_file_range 375
 preadv2 376
 pwritev2 377
+pkey_mprotect 384
+pkey_alloc 385
+pkey_free 386
 pidfd_send_signal 424
include/lapi/syscalls/sparc.in +3 -0
index e74b48170..ab7204663 100644
@@ -343,4 +343,7 @@ mlock2 356
 copy_file_range 357
 preadv2 358
 pwritev2 359
+pkey_mprotect 362
+pkey_alloc 363
+pkey_free 364
 pidfd_send_signal 424
include/lapi/syscalls/sparc64.in +3 -0
index 577aa9b35..d17dce5cd 100644
@@ -319,4 +319,7 @@ mlock2 356
 copy_file_range 357
 preadv2 358
 pwritev2 359
+pkey_mprotect 362
+pkey_alloc 363
+pkey_free 364
 pidfd_send_signal 424
include/lapi/syscalls/x86_64.in +3 -0
index 99d387277..fdb414c10 100644
@@ -314,5 +314,8 @@ mlock2 325
 copy_file_range 326
 preadv2 327
 pwritev2 328
+pkey_mprotect 329
+pkey_alloc 330
+pkey_free 331
 statx 332
 pidfd_send_signal 424
Signature · 1 line
2.20.1
author
#2 lore raw

PATCH v3 2/2 pkey: add test for memory protection keys

Memory Protection Keys for Userspace (PKU aka PKEYs) is a Skylake-SP server feature that provides a mechanism for enforcing page-based protections, but without requiring modification of the page tables when an application changes protection domains. It works by dedicating 4 previously ignored bits in each page table entry to a "protection key", giving 16 possible keys.

Basic method for PKEYs test:
1. test allocates a pkey(e.g. PKEY_DISABLE_ACCESS) via pkey_alloc()
2. pkey_mprotect() apply this pkey to a piece of memory buffer
3. check if the access right of buffer has been changed and take effect
4. remove the access right(pkey) from this buffer via pkey_mprotect()
5. check if buffer area can be read or write after removing pkey
6. pkey_free() releases the pkey after using it

Looping around this basic test on diffenrent types of memory.

---
 configure.ac                               |   1 +
 runtest/syscalls                           |   2 +
 testcases/kernel/syscalls/pkeys/.gitignore |   1 +
 testcases/kernel/syscalls/pkeys/Makefile   |   8 +
 testcases/kernel/syscalls/pkeys/pkey.h     |  50 +++++
 testcases/kernel/syscalls/pkeys/pkey01.c   | 235 +++++++++++++++++++++
 6 files changed, 297 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
configure.ac +1 -0
index 65fc2a232..5a9b74b0a 100644
@@ -74,6 +74,7 @@ AC_CHECK_FUNCS([ \
     pidfd_send_signal \
     preadv \
     preadv2 \
+    pkey_mprotect \
     profil \
     pwritev \
     pwritev2 \
runtest/syscalls +2 -0
index c6a064481..6ea991f12 100644
@@ -721,6 +721,8 @@ mprotect02 mprotect02
 mprotect03 mprotect03
 mprotect04 mprotect04
 
+pkey01 pkey01
+
 mq_notify01 mq_notify01
 mq_notify02 mq_notify02
 mq_open01 mq_open01
testcases/kernel/syscalls/pkeys/.gitignore new file +1 -0
new file mode 100644
index 000000000..6fd5addb8
@@ -0,0 +1 @@
+/pkey01
testcases/kernel/syscalls/pkeys/Makefile new file +8 -0
new file mode 100644
index 000000000..9ee2c2ea5
@@ -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
testcases/kernel/syscalls/pkeys/pkey.h new file +50 -0

50 lines not on this page · raw message

testcases/kernel/syscalls/pkeys/pkey01.c new file +235 -0

235 lines not on this page · raw message

Signature · 1 line
2.20.1
#3 lore raw

PATCH v3 2/2 pkey: add test for memory protection keys

----- Original Message -----

Quoted 6 lines
testcases/kernel/syscalls/pkeys/pkey.h new file +6 -0
+
+#ifndef PKEYS_H
+#define PKEYS_H
+
+#include "tst_test.h"
+#include "lapi/syscalls.h"

testcases/kernel/syscalls/pkeys/pkey.h line 20

Quoted 10 lines
testcases/kernel/syscalls/pkeys/pkey.h new file +10 -0
+
+#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);

Hi,

This should be __NR_*:

In file included from pkey01.c:32:
pkey.h: In function ?pkey_mprotect?:
pkey.h:20: error: ?SYS_pkey_mprotect? undeclared (first use in this function) pkey.h:20: error: (Each undeclared identifier is reported only once pkey.h:20: error: for each function it appears in.)
pkey.h: In function ?pkey_alloc?:
pkey.h:25: error: ?SYS_pkey_alloc? undeclared (first use in this function) pkey.h: In function ?pkey_free?:
pkey.h:30: error: ?SYS_pkey_free? undeclared (first use in this function)

testcases/kernel/syscalls/pkeys/pkey01.c line 64

Quoted 10 lines
testcases/kernel/syscalls/pkeys/pkey01.c new file +10 -0
+static void setup(void)
+{
+	int i, fd;
+
+	if (access("/proc/sys/vm/nr_hugepages", F_OK)) {
+		tst_res(TINFO, "Huge page is not supported");
+		size = getpagesize();
+		no_hugepage = 1;
+	} else {
+		SAFE_FILE_PRINTF("/proc/sys/vm/nr_hugepages", "%d", 1);

There are 2 problems here, both related to fact that this file exists, but may return EOPNOTSUPP on read/write.

1. save_restore should ignore also read/open errors if path is prefixed with '?' I'll send this separately.

2. SAFE_FILE_PRINTF in pkey01.c shouldn't be safe, because we need to somehow detect that write worked

# ls -la /proc/sys/vm/nr_hugepages
-rw-r--r--. 1 root root 0 Jun 25 04:12 /proc/sys/vm/nr_hugepages
# cat /proc/sys/vm/nr_hugepages
cat: /proc/sys/vm/nr_hugepages: Operation not supported

testcases/kernel/syscalls/pkeys/pkey01.c line 234

Quoted 7 lines
testcases/kernel/syscalls/pkeys/pkey01.c new file +7 -0
+static struct tst_test test = {
+	.tcnt = ARRAY_SIZE(tcases),
+	.forks_child = 1,
+	.test = verify_pkey,
+	.setup = setup,
+	.cleanup = cleanup,
+	.save_restore = save_restore,

.needs_root = 1 as well, since we write to /proc and mount tmpfs

Rest looks good to me, but I haven't found yet system that could run the test.

Regards,
Jan

author
#4 lore raw

PATCH v3 2/2 pkey: add test for memory protection keys

Quoted 17 lines · Jan Stancek

----- Original Message -----

Quoted 4 lines
testcases/kernel/syscalls/pkeys/pkey.h new file +4 -0
+
+#ifndef PKEYS_H
+#define PKEYS_H
+

testcases/kernel/syscalls/pkeys/pkey.h

Quoted 10 lines
testcases/kernel/syscalls/pkeys/pkey.h new file +10 -0
+#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)

Quoted 7 lines

testcases/kernel/syscalls/pkeys/pkey.h line 20

Quoted 2 lines
testcases/kernel/syscalls/pkeys/pkey.h new file +2 -0
+{
+     return tst_syscall(SYS_pkey_mprotect, addr, len, prot, pkey);

Hi,

This should be __NR_*:

Exactly. Sorry about that mistake.

Quoted 26 lines

In file included from pkey01.c:32:
pkey.h: In function ?pkey_mprotect?:
pkey.h:20: error: ?SYS_pkey_mprotect? undeclared (first use in this function)
pkey.h:20: error: (Each undeclared identifier is reported only once pkey.h:20: error: for each function it appears in.)
pkey.h: In function ?pkey_alloc?:
pkey.h:25: error: ?SYS_pkey_alloc? undeclared (first use in this function) pkey.h: In function ?pkey_free?:
pkey.h:30: error: ?SYS_pkey_free? undeclared (first use in this function)

testcases/kernel/syscalls/pkeys/pkey01.c line 64

Quoted 10 lines
testcases/kernel/syscalls/pkeys/pkey01.c new file +10 -0
+static void setup(void)
+{
+     int i, fd;
+
+     if (access("/proc/sys/vm/nr_hugepages", F_OK)) {
+             tst_res(TINFO, "Huge page is not supported");
+             size = getpagesize();
+             no_hugepage = 1;
+     } else {
+             SAFE_FILE_PRINTF("/proc/sys/vm/nr_hugepages", "%d", 1);

There are 2 problems here, both related to fact that this file exists, but may return EOPNOTSUPP on read/write.

Quoted 4 lines

1. save_restore should ignore also read/open errors if path is prefixed with '?'
I'll send this separately.

Thank you for that patch.

Quoted 5 lines

2. SAFE_FILE_PRINTF in pkey01.c shouldn't be safe, because we need to somehow
detect that write worked

Yes, we should verify if that value has been wrote.

Quoted 15 lines
# ls -la /proc/sys/vm/nr_hugepages
-rw-r--r--. 1 root root 0 Jun 25 04:12 /proc/sys/vm/nr_hugepages
# cat /proc/sys/vm/nr_hugepages
cat: /proc/sys/vm/nr_hugepages: Operation not supported

testcases/kernel/syscalls/pkeys/pkey01.c line 234

Quoted 7 lines
testcases/kernel/syscalls/pkeys/pkey01.c new file +7 -0
+static struct tst_test test = {
+     .tcnt = ARRAY_SIZE(tcases),
+     .forks_child = 1,
+     .test = verify_pkey,
+     .setup = setup,
+     .cleanup = cleanup,
+     .save_restore = save_restore,
Quoted 2 lines

.needs_root = 1 as well, since we write to /proc and mount tmpfs

Agree.

Quoted 7 lines

Rest looks good to me, but I haven't found yet system that could run the test.

Regards,
Jan

Signature · 5 lines
Regards,
Li Wang
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.linux.it/pipermail/ltp/attachments/20190625/cc81287a/attachment.html>