Some of the Gcc compiled clone tests in restricted mode face stack corruption. This occurs as the run-time permission settings (executive or restricted mode) in the PCC may be lost if function pointers are materialised from the GOT entries. This further leads to selecting an incorrect stack pointer(CSP instead of RCSP) and hence the crash.
As a workaround, materialise the function pointer clone_base_fn explicitly by building branch address from the PCC. Here it is assumed that the bounds and permissions of clone_base_fn are same as the PCC , which is not an issue in practice (being in the same translation unit).
Signed-off-by: Amit Daniel Kachhap amit.kachhap@arm.com --- tools/testing/selftests/arm64/morello/clone.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/arm64/morello/clone.c b/tools/testing/selftests/arm64/morello/clone.c index 69189287144a..730811f9b7c2 100644 --- a/tools/testing/selftests/arm64/morello/clone.c +++ b/tools/testing/selftests/arm64/morello/clone.c @@ -98,6 +98,7 @@ void clone_single(struct test_fixture *data) { int ppid = 0, cpid = 0; int result = -EINVAL; + void *ptr = clone_base_fn;
void *new_stack = mmap_verified(NULL, STACK_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0, STACK_REQ_PERMS); @@ -119,7 +120,18 @@ void clone_single(struct test_fixture *data)
EXPECT_TRUE(!(data->flags & CLONE_TH_RESTRICTED) || in_restricted());
- result = __clone(clone_base_fn, (uintcap_t)new_stack + STACK_SIZE, + /* + * Function pointers are materialised by the compiler by either + * computing from the PCC (ADRP + ADD + SEAL) or loading from GOT. The + * run-time permission settings (executive or restrictive) in PCC may + * not match with the GOT entries. Hence, materialise the function + * pointers explicitly to avoid this mismatch issue. + */ + if (in_restricted()) { + ptr = cheri_address_set(cheri_pcc_get(), (ptraddr_t)ptr); + ptr = cheri_sentry_create(ptr); + } + result = __clone(ptr, (uintcap_t)new_stack + STACK_SIZE, clone_flags, data, &ppid, tls, &cpid);
EXPECT_GT(result, 0) {