From patchwork Thu Jun 20 09:55:48 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Li Wang X-Patchwork-Id: 1119318 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=lists.linux.it (client-ip=213.254.12.146; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from picard.linux.it (picard.linux.it [213.254.12.146]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45TxzD5y2fz9s4V for ; Thu, 20 Jun 2019 19:56:06 +1000 (AEST) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id F38922988EB for ; Thu, 20 Jun 2019 11:56:00 +0200 (CEST) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-4.smtp.seeweb.it (in-4.smtp.seeweb.it [IPv6:2001:4b78:1:20::4]) by picard.linux.it (Postfix) with ESMTP id 247FB2987A9 for ; Thu, 20 Jun 2019 11:55:58 +0200 (CEST) Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by in-4.smtp.seeweb.it (Postfix) with ESMTPS id C561C10009FC for ; Thu, 20 Jun 2019 11:55:49 +0200 (CEST) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 697D3356FE for ; Thu, 20 Jun 2019 09:55:52 +0000 (UTC) Received: from dhcp-3-207.nay.redhat.com (dhcp-3-207.nay.redhat.com [10.66.3.207]) by smtp.corp.redhat.com (Postfix) with ESMTP id 655EF5C1A1 for ; Thu, 20 Jun 2019 09:55:51 +0000 (UTC) From: Li Wang To: ltp@lists.linux.it Date: Thu, 20 Jun 2019 17:55:48 +0800 Message-Id: <20190620095548.28335-1-liwang@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Thu, 20 Jun 2019 09:55:52 +0000 (UTC) X-Virus-Scanned: clamav-milter 0.99.2 at in-4.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=-0.0 required=7.0 tests=SPF_HELO_PASS,SPF_PASS autolearn=disabled version=3.4.0 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on in-4.smtp.seeweb.it Subject: [LTP] [PATCH] pkey: Add test for memory protection keys X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.18 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" Signed-off-by: Li Wang --- 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 +#include +#include +#include +#include +#include +#include + +#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, +};