[LTP] [PATCH] pkey: Add test for memory protection keys

Li Wang liwang@redhat.com
Fri Jun 21 08:08:57 CEST 2019


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>


More information about the ltp mailing list