enum stage {
STAGE_INIT_SIMPLE,
TEST_SIMPLE,
STAGE_INIT_FETCH_PROT_OVERRIDE,
TEST_FETCH_PROT_OVERRIDE,
TEST_STORAGE_PROT_OVERRIDE,
STAGE_END /* must be the last entry (it's the amount of tests) */
};
struct test { enum stage stage; void *addr;
uint8_t key; enum permission expected;
} tests[] = { /* * We perform each test in the array by executing TEST PROTECTION on * the specified addr with the specified key and checking if the returned * permissions match the expected value. * Both guest and host cooperate to set up the required test conditions. * A central condition is that the page targeted by addr has to be DAT * protected in the host mappings, in order for KVM to emulate the * TEST PROTECTION instruction. * Since the page tables are shared, the host uses mprotect to achieve * this. * * Test resulting in RW_PROTECTED/TRANSL_UNAVAIL will be interpreted * by SIE, not KVM, but there is no harm in testing them also. * See Enhanced Suppression-on-Protection Facilities in the * Interpretive-Execution Mode
*/ /* * guest: set storage key of page_store_prot to 1 * storage key of page_fetch_prot to 9 and enable * protection for it * STAGE_INIT_SIMPLE * host: write protect both via mprotect
*/ /* access key 0 matches any storage key -> RW */
{ TEST_SIMPLE, page_store_prot, 0x00, READ_WRITE }, /* access key matches storage key -> RW */
{ TEST_SIMPLE, page_store_prot, 0x10, READ_WRITE }, /* mismatched keys, but no fetch protection -> RO */
{ TEST_SIMPLE, page_store_prot, 0x20, READ }, /* access key 0 matches any storage key -> RW */
{ TEST_SIMPLE, page_fetch_prot, 0x00, READ_WRITE }, /* access key matches storage key -> RW */
{ TEST_SIMPLE, page_fetch_prot, 0x90, READ_WRITE }, /* mismatched keys, fetch protection -> inaccessible */
{ TEST_SIMPLE, page_fetch_prot, 0x10, RW_PROTECTED }, /* page 0 not mapped yet -> translation not available */
{ TEST_SIMPLE, (void *)0x00, 0x10, TRANSL_UNAVAIL }, /* * host: try to map page 0 * guest: set storage key of page 0 to 9 and enable fetch protection * STAGE_INIT_FETCH_PROT_OVERRIDE * host: write protect page 0 * enable fetch protection override
*/ /* mismatched keys, fetch protection, but override applies -> RO */
{ TEST_FETCH_PROT_OVERRIDE, (void *)0x00, 0x10, READ }, /* mismatched keys, fetch protection, override applies to 0-2048 only -> inaccessible */
{ TEST_FETCH_PROT_OVERRIDE, (void *)2049, 0x10, RW_PROTECTED }, /* * host: enable storage protection override
*/ /* mismatched keys, but override applies (storage key 9) -> RW */
{ TEST_STORAGE_PROT_OVERRIDE, page_fetch_prot, 0x10, READ_WRITE }, /* mismatched keys, no fetch protection, override doesn't apply -> RO */
{ TEST_STORAGE_PROT_OVERRIDE, page_store_prot, 0x20, READ }, /* mismatched keys, but override applies (storage key 9) -> RW */
{ TEST_STORAGE_PROT_OVERRIDE, (void *)2049, 0x10, READ_WRITE }, /* end marker */
{ STAGE_END, 0, 0, 0 },
};
for (; tests[*i].stage == stage; (*i)++) { /* * Some fetch protection override tests require that page 0 * be mapped, however, when the hosts tries to map that page via * vm_vaddr_alloc, it may happen that some other page gets mapped * instead. * In order to skip these tests we detect this inside the guest
*/
skip = tests[*i].addr < (void *)PAGE_SIZE &&
tests[*i].expected != TRANSL_UNAVAIL &&
!mapped_0; if (!skip) {
result = test_protection(tests[*i].addr, tests[*i].key);
__GUEST_ASSERT(result == tests[*i].expected, "Wanted %u, got %u, for i = %u",
tests[*i].expected, result, *i);
}
} return stage;
}
staticvoid guest_code(void)
{ bool mapped_0; int i = 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.