Commit 03634bbf authored by Sandipan Das's avatar Sandipan Das Committed by Michael Ellerman

selftests/powerpc: Harden test for execute-disabled pkeys

Commit 192b6a78 ("powerpc/book3s64/pkeys: Fix
pkey_access_permitted() for execute disable pkey") fixed a
bug that caused repetitive faults for pkeys with no execute
rights alongside some combination of read and write rights.

This removes the last two cases of the test, which check
the behaviour of pkeys with read, write but no execute
rights and all the rights, in favour of checking all the
possible combinations of read, write and execute rights
to be able to detect bugs like the one mentioned above.
Signed-off-by: default avatarSandipan Das <sandipan@linux.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/db467500f8af47727bba6b35796e8974a78b71e5.1595821792.git.sandipan@linux.ibm.com
parent 264d7fcc
...@@ -237,55 +237,53 @@ static int test(void) ...@@ -237,55 +237,53 @@ static int test(void)
*fault_addr = PPC_INST_NOP; *fault_addr = PPC_INST_NOP;
FAIL_IF(remaining_faults != 0 || fault_code != SEGV_ACCERR); FAIL_IF(remaining_faults != 0 || fault_code != SEGV_ACCERR);
/* /* Free the current pkey */
* Jump to the executable region when AMR bits are set i.e. sys_pkey_free(pkey);
* the pkey permits neither read nor write access.
*
* This should generate a pkey fault based on IAMR bits which
* are set to not permit execution. AMR bits should not affect
* execution.
*
* This also checks if the overwrite of the first instruction
* word from a trap to a no-op succeeded.
*/
fault_addr = insns;
fault_type = PKEY_DISABLE_EXECUTE;
fault_pkey = pkey;
remaining_faults = 1;
FAIL_IF(sys_pkey_mprotect(insns, pgsize, PROT_EXEC, pkey) != 0);
pkey_set_rights(pkey, PKEY_DISABLE_ACCESS);
printf("execute at %p, pkey permissions are %s\n", fault_addr,
pkey_rights(rights));
asm volatile("mtctr %0; bctrl" : : "r"(insns));
FAIL_IF(remaining_faults != 0 || fault_code != SEGV_PKUERR);
rights = 0;
do {
/* /*
* Free the current pkey and allocate a new one that is * Allocate pkeys with all valid combinations of read,
* fully permissive. * write and execute restrictions.
*/ */
sys_pkey_free(pkey);
rights = 0;
pkey = sys_pkey_alloc(0, rights); pkey = sys_pkey_alloc(0, rights);
FAIL_IF(pkey < 0);
/* /*
* Jump to the executable region when AMR bits are not set * Jump to the executable region. AMR bits may or may not
* i.e. the pkey permits read and write access. * be set but they should not affect execution.
* *
* This should not generate any faults as the IAMR bits are * This should generate pkey faults based on IAMR bits which
* also not set and hence will the pkey will not restrict * may be set to restrict execution.
* execution. *
* The first iteration also checks if the overwrite of the
* first instruction word from a trap to a no-op succeeded.
*/ */
fault_pkey = pkey; fault_pkey = pkey;
fault_type = -1;
remaining_faults = 0; remaining_faults = 0;
if (rights & PKEY_DISABLE_EXECUTE) {
fault_type = PKEY_DISABLE_EXECUTE;
remaining_faults = 1;
}
FAIL_IF(sys_pkey_mprotect(insns, pgsize, PROT_EXEC, pkey) != 0); FAIL_IF(sys_pkey_mprotect(insns, pgsize, PROT_EXEC, pkey) != 0);
printf("execute at %p, pkey permissions are %s\n", fault_addr, printf("execute at %p, pkey permissions are %s\n", fault_addr,
pkey_rights(rights)); pkey_rights(rights));
asm volatile("mtctr %0; bctrl" : : "r"(insns)); asm volatile("mtctr %0; bctrl" : : "r"(insns));
FAIL_IF(remaining_faults != 0); FAIL_IF(remaining_faults != 0);
if (rights & PKEY_DISABLE_EXECUTE)
FAIL_IF(fault_code != SEGV_PKUERR);
/* Free the current pkey */
sys_pkey_free(pkey);
/* Find next valid combination of pkey rights */
rights = next_pkey_rights(rights);
} while (rights);
/* Cleanup */ /* Cleanup */
munmap((void *) insns, pgsize); munmap((void *) insns, pgsize);
sys_pkey_free(pkey);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment