mirror of
https://git.proxmox.com/git/mirror_ubuntu-kernels.git
synced 2025-11-30 08:17:48 +00:00
The Enclave Page Cache Map (EPCM) is a secure structure used by the
processor to track the contents of the enclave page cache. The EPCM
contains permissions with which enclave pages can be accessed. SGX
support allows EPCM and PTE page permissions to differ - as long as
the PTE permissions do not exceed the EPCM permissions.
Add a test that:
(1) Creates an SGX enclave page with writable EPCM permission.
(2) Changes the PTE permission on the page to read-only. This should
be permitted because the permission does not exceed the EPCM
permission.
(3) Attempts a write to the page. This should generate a page fault
(#PF) because of the read-only PTE even though the EPCM
permissions allow the page to be written to.
This introduces the first test of SGX exception handling. In this test
the issue that caused the exception (PTE page permissions) can be fixed
from outside the enclave and after doing so it is possible to re-enter
enclave at original entrypoint with ERESUME.
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
Link: https://lkml.kernel.org/r/3bcc73a4b9fe8780bdb40571805e7ced59e01df7.1636997631.git.reinette.chatre@intel.com
66 lines
1.3 KiB
C
66 lines
1.3 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/* Copyright(c) 2016-20 Intel Corporation. */
|
|
|
|
#include <stddef.h>
|
|
#include "defines.h"
|
|
|
|
/*
|
|
* Data buffer spanning two pages that will be placed first in .data
|
|
* segment. Even if not used internally the second page is needed by
|
|
* external test manipulating page permissions.
|
|
*/
|
|
static uint8_t encl_buffer[8192] = { 1 };
|
|
|
|
static void *memcpy(void *dest, const void *src, size_t n)
|
|
{
|
|
size_t i;
|
|
|
|
for (i = 0; i < n; i++)
|
|
((char *)dest)[i] = ((char *)src)[i];
|
|
|
|
return dest;
|
|
}
|
|
|
|
static void do_encl_op_put_to_buf(void *op)
|
|
{
|
|
struct encl_op_put_to_buf *op2 = op;
|
|
|
|
memcpy(&encl_buffer[0], &op2->value, 8);
|
|
}
|
|
|
|
static void do_encl_op_get_from_buf(void *op)
|
|
{
|
|
struct encl_op_get_from_buf *op2 = op;
|
|
|
|
memcpy(&op2->value, &encl_buffer[0], 8);
|
|
}
|
|
|
|
static void do_encl_op_put_to_addr(void *_op)
|
|
{
|
|
struct encl_op_put_to_addr *op = _op;
|
|
|
|
memcpy((void *)op->addr, &op->value, 8);
|
|
}
|
|
|
|
static void do_encl_op_get_from_addr(void *_op)
|
|
{
|
|
struct encl_op_get_from_addr *op = _op;
|
|
|
|
memcpy(&op->value, (void *)op->addr, 8);
|
|
}
|
|
|
|
void encl_body(void *rdi, void *rsi)
|
|
{
|
|
const void (*encl_op_array[ENCL_OP_MAX])(void *) = {
|
|
do_encl_op_put_to_buf,
|
|
do_encl_op_get_from_buf,
|
|
do_encl_op_put_to_addr,
|
|
do_encl_op_get_from_addr,
|
|
};
|
|
|
|
struct encl_op_header *op = (struct encl_op_header *)rdi;
|
|
|
|
if (op->type < ENCL_OP_MAX)
|
|
(*encl_op_array[op->type])(op);
|
|
}
|