[LTP] [PATCH] mprotect04: Support execute-only page access permissions
Jan Stancek
jstancek@redhat.com
Thu Feb 7 08:04:25 CET 2019
----- Original Message -----
> Linux version 4.9 introduced support for execute-only page access permissions
> on
> arm64. As a result, user space processes, by default, cannot read from
> their own .text sections. This change adds an extra call to mprotect()
> to explicitly change access protections to allow relevant parts of the
> .text section to be read.
>
> Without this change, mprotect04 generates false TBROK results. We
> previously saw this test output:
>
> mprotect04 1 TPASS : test PROT_NONE for mprotect success
> mprotect04 0 TINFO : exec_func: 0x5ac82d3588, page_to_copy:
> 0x5ac82d3000
> mprotect04 2 TBROK :
> ltp/testcases/kernel/syscalls/mprotect/mprotect04.c:236: page_to_copy not
> present
> mprotect04 3 TBROK :
> ltp/testcases/kernel/syscalls/mprotect/mprotect04.c:236: Remaining cases
> broken
>
> Signed-off-by: Daniel Mentz <danielmentz@google.com>
> ---
> .../kernel/syscalls/mprotect/mprotect04.c | 31 ++++++++++++++++---
> 1 file changed, 27 insertions(+), 4 deletions(-)
>
> diff --git a/testcases/kernel/syscalls/mprotect/mprotect04.c
> b/testcases/kernel/syscalls/mprotect/mprotect04.c
> index 60941a422..811449f6a 100644
> --- a/testcases/kernel/syscalls/mprotect/mprotect04.c
> +++ b/testcases/kernel/syscalls/mprotect/mprotect04.c
> @@ -217,6 +217,7 @@ static void *get_func(void *mem)
> uintptr_t func_page_offset;
> void *func_copy_start, *page_to_copy;
> void *mem_start = mem;
> + int exec_only_platform = 0;
>
> #ifdef USE_FUNCTION_DESCRIPTORS
> func_descr_t *opd = (func_descr_t *)&exec_func;
> @@ -229,17 +230,35 @@ static void *get_func(void *mem)
> page_to_copy = (void *)((uintptr_t)&exec_func & page_mask);
> #endif
>
> - /* copy 1st page, if it's not present something is wrong */
> + /* Copy 1st page. If it's not accessible, we might be running on a
> + * platform that supports execute-only page access permissions, in which
> + * case we have to explicitly change access protections to allow the
> + * memory to be read. */
> if (!page_present(page_to_copy)) {
> - tst_resm(TINFO, "exec_func: %p, page_to_copy: %p\n",
> - &exec_func, page_to_copy);
> - tst_brkm(TBROK, cleanup, "page_to_copy not present\n");
> + TEST(mprotect(page_to_copy, page_sz, PROT_READ | PROT_EXEC));
> + if (TEST_RETURN == -1) {
> + tst_resm(TFAIL | TTERRNO,
> + "mprotect(PROT_READ|PROT_EXEC) failed");
> + return NULL;
> + }
> + /* If the memory is still not accessible, then something must be
> + * wrong. */
> + if (!page_present(page_to_copy)) {
> + tst_resm(TINFO, "exec_func: %p, page_to_copy: %p\n",
> + &exec_func, page_to_copy);
> + tst_brkm(TBROK, cleanup, "page_to_copy not present\n");
> + }
> + exec_only_platform = 1;
> }
> memcpy(mem, page_to_copy, page_sz);
>
> /* copy 2nd page if possible */
> mem += page_sz;
> page_to_copy += page_sz;
> + /* Mark page readable on platforms that support execute-only page access
> + * permissions. */
> + if (exec_only_platform)
> + mprotect(page_to_copy, page_sz, PROT_READ | PROT_EXEC);
Is there a chance 2nd page will be something else than code?
E.g. some section that was previously also writeable.
> if (page_present(page_to_copy))
> memcpy(mem, page_to_copy, page_sz);
> else
> @@ -271,6 +290,9 @@ static void testfunc_protexec(void)
> func = get_func(p);
> #endif
>
> + if (!func)
> + goto out;
> +
> /* Change the protection to PROT_EXEC. */
> TEST(mprotect(p, copy_sz, PROT_EXEC));
>
> @@ -294,6 +316,7 @@ static void testfunc_protexec(void)
> }
> }
>
> +out:
> SAFE_MUNMAP(cleanup, p, copy_sz);
> }
>
> --
> 2.20.1.611.gfbb209baf1-goog
>
>
More information about the ltp
mailing list