From: "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com>
To: linuxppc-dev@lists.ozlabs.org, mpe@ellerman.id.au
Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com>,
linuxram@us.ibm.com, Sandipan Das <sandipan@linux.ibm.com>
Subject: [PATCH] powerpc/book3s64/pkeys: Fix pkey_access_permitted w.r.t execute disable pkey
Date: Sun, 12 Jul 2020 18:50:47 +0530 [thread overview]
Message-ID: <20200712132047.1038594-1-aneesh.kumar@linux.ibm.com> (raw)
Even if the IAMR value deny the execute access, current kernel return true
w.r.t pkey_access_permitted() for execute permission check if the AMR
read pkey bit is cleared.
This results in repeated page fault loop with a test like below.
#define _GNU_SOURCE
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <inttypes.h>
#include <assert.h>
#include <malloc.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/mman.h>
#ifdef SYS_pkey_mprotect
#undef SYS_pkey_mprotect
#endif
#ifdef SYS_pkey_alloc
#undef SYS_pkey_alloc
#endif
#ifdef SYS_pkey_free
#undef SYS_pkey_free
#endif
#undef PKEY_DISABLE_EXECUTE
#define PKEY_DISABLE_EXECUTE 0x4
#define SYS_pkey_mprotect 386
#define SYS_pkey_alloc 384
#define SYS_pkey_free 385
#define PPC_INST_NOP 0x60000000
#define PPC_INST_BLR 0x4e800020
#define PROT_RWX (PROT_READ | PROT_WRITE | PROT_EXEC)
static int sys_pkey_mprotect(void *addr, size_t len, int prot, int pkey)
{
return syscall(SYS_pkey_mprotect, addr, len, prot, pkey);
}
static int sys_pkey_alloc(unsigned long flags, unsigned long access_rights)
{
return syscall(SYS_pkey_alloc, flags, access_rights);
}
static int sys_pkey_free(int pkey)
{
return syscall(SYS_pkey_free, pkey);
}
static void do_execute(void *region)
{
/* jump to region */
asm volatile(
"mtctr %0;"
"bctrl"
: : "r"(region) : "ctr", "lr");
}
static void do_protect(void *region)
{
size_t pgsize;
int i, pkey;
pgsize = getpagesize();
pkey = sys_pkey_alloc(0, PKEY_DISABLE_EXECUTE);
assert (pkey > 0);
/* perform mprotect */
assert(!sys_pkey_mprotect(region, pgsize, PROT_RWX, pkey));
do_execute(region);
/* free pkey */
assert(!sys_pkey_free(pkey));
}
int main(int argc, char **argv)
{
size_t pgsize, numinsns;
unsigned int *region;
int i;
/* allocate memory region to protect */
pgsize = getpagesize();
region = memalign(pgsize, pgsize);
assert(region != NULL);
assert(!mprotect(region, pgsize, PROT_RWX));
/* fill page with NOPs with a BLR at the end */
numinsns = pgsize / sizeof(region[0]);
for (i = 0; i < numinsns - 1; i++)
region[i] = PPC_INST_NOP;
region[i] = PPC_INST_BLR;
do_protect(region);
return EXIT_SUCCESS;
}
Fixes: f2407ef3ba22 ("powerpc: helper to validate key-access permissions of a pte")
Reported-by: Sandipan Das <sandipan@linux.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
---
arch/powerpc/mm/book3s64/pkeys.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/arch/powerpc/mm/book3s64/pkeys.c b/arch/powerpc/mm/book3s64/pkeys.c
index ca5fcb4bff32..d174106bab67 100644
--- a/arch/powerpc/mm/book3s64/pkeys.c
+++ b/arch/powerpc/mm/book3s64/pkeys.c
@@ -354,12 +354,14 @@ static bool pkey_access_permitted(int pkey, bool write, bool execute)
u64 amr;
pkey_shift = pkeyshift(pkey);
- if (execute && !(read_iamr() & (IAMR_EX_BIT << pkey_shift)))
- return true;
+ if (execute)
+ return !(read_iamr() & (IAMR_EX_BIT << pkey_shift));
+
+ amr = read_amr();
+ if (write)
+ return !(amr & (AMR_WR_BIT << pkey_shift));
- amr = read_amr(); /* Delay reading amr until absolutely needed */
- return ((!write && !(amr & (AMR_RD_BIT << pkey_shift))) ||
- (write && !(amr & (AMR_WR_BIT << pkey_shift))));
+ return !(amr & (AMR_RD_BIT << pkey_shift));
}
bool arch_pte_access_permitted(u64 pte, bool write, bool execute)
--
2.26.2
next reply other threads:[~2020-07-12 13:23 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-07-12 13:20 Aneesh Kumar K.V [this message]
2020-07-16 12:47 ` [PATCH] powerpc/book3s64/pkeys: Fix pkey_access_permitted w.r.t execute disable pkey Michael Ellerman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200712132047.1038594-1-aneesh.kumar@linux.ibm.com \
--to=aneesh.kumar@linux.ibm.com \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=linuxram@us.ibm.com \
--cc=mpe@ellerman.id.au \
--cc=sandipan@linux.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.