From patchwork Mon Mar 26 06:48:08 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Li Wang X-Patchwork-Id: 890783 X-Patchwork-Delegate: jan.stancek@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=lists.linux.it (client-ip=2001:1418:10:5::2; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from picard.linux.it (picard.linux.it [IPv6:2001:1418:10:5::2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408l8k6p9dz9s1l for ; Mon, 26 Mar 2018 17:48:22 +1100 (AEDT) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id 921D13E6429 for ; Mon, 26 Mar 2018 08:48:18 +0200 (CEST) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-3.smtp.seeweb.it (in-3.smtp.seeweb.it [IPv6:2001:4b78:1:20::3]) by picard.linux.it (Postfix) with ESMTP id D20343E6413 for ; Mon, 26 Mar 2018 08:48:16 +0200 (CEST) Received: from mx1.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by in-3.smtp.seeweb.it (Postfix) with ESMTPS id AE65E1A00E14 for ; Mon, 26 Mar 2018 08:48:15 +0200 (CEST) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5A95A80AD211; Mon, 26 Mar 2018 06:48:13 +0000 (UTC) Received: from dhcp-12-102.nay.redhat.com (unknown [10.66.12.102]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2D6D8215CDAA; Mon, 26 Mar 2018 06:48:10 +0000 (UTC) From: Li Wang To: ltp@lists.linux.it Date: Mon, 26 Mar 2018 14:48:08 +0800 Message-Id: <20180326064808.5503-1-liwang@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 26 Mar 2018 06:48:13 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 26 Mar 2018 06:48:13 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'liwang@redhat.com' RCPT:'' X-Virus-Scanned: clamav-milter 0.99.2 at in-3.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=-0.0 required=7.0 tests=SPF_PASS, T_RP_MATCHES_RCVD autolearn=disabled version=3.4.0 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on in-3.smtp.seeweb.it Cc: Ram Pai Subject: [LTP] [PATCH v2] mprotect04: get right function entry if system using function descriptors X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.18 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" On some big endian powerpc64 ABI, function ptrs are basically pointers to function descriptors. The testcase copies functions which results in function descriptors getting copied. So easily the access was denied by memory protection key in that address when performing it. 10000000-10020000 r-xp 00000000 fd:00 167223 mprotect04 10020000-10030000 r--p 00010000 fd:00 167223 mprotect04 10030000-10040000 rw-p 00020000 fd:00 167223 mprotect04 1001a380000-1001a3b0000 rw-p 00000000 00:00 0 [heap] 7fffa6c60000-7fffa6c80000 --xp 00000000 00:00 0 &exec_func = 0x10030170 &func = 0x7fffa6c60170 While perform the (*func)(); we get segmentation fault. strace log: ----------- mprotect(0x7fffaed00000, 131072, PROT_EXEC) = 0 rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0 --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_PKUERR, si_addr=0x7fffaed00170} --- Reported-and-tested-by: Li Wang Signed-off-by: Ram Pai Suggested-by: Michael Ellerman Signed-off-by: Li Wang --- testcases/kernel/syscalls/mprotect/mprotect04.c | 41 ++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/testcases/kernel/syscalls/mprotect/mprotect04.c b/testcases/kernel/syscalls/mprotect/mprotect04.c index 1173afd..60941a4 100644 --- a/testcases/kernel/syscalls/mprotect/mprotect04.c +++ b/testcases/kernel/syscalls/mprotect/mprotect04.c @@ -56,6 +56,7 @@ int TST_TOTAL = ARRAY_SIZE(testfunc); static volatile int sig_caught; static sigjmp_buf env; static unsigned int copy_sz; +typedef void (*func_ptr_t)(void); int main(int ac, char **av) { @@ -190,6 +191,22 @@ static void clear_cache(void *start, int len) } /* + * To check for the ABI version, because ppc64le can technically use + * function descriptors. + */ +#if defined(__powerpc64__) && (!defined(_CALL_ELF) || _CALL_ELF < 2) +#define USE_FUNCTION_DESCRIPTORS +#endif + +#ifdef USE_FUNCTION_DESCRIPTORS +typedef struct { + uintptr_t entry; + uintptr_t toc; + uintptr_t env; +} func_descr_t; +#endif + +/* * Copy page where &exec_func resides. Also try to copy subsequent page * in case exec_func is close to page boundary. */ @@ -197,11 +214,21 @@ static void *get_func(void *mem) { uintptr_t page_sz = getpagesize(); uintptr_t page_mask = ~(page_sz - 1); - uintptr_t func_page_offset = (uintptr_t)&exec_func & (page_sz - 1); - void *func_copy_start = mem + func_page_offset; - void *page_to_copy = (void *)((uintptr_t)&exec_func & page_mask); + uintptr_t func_page_offset; + void *func_copy_start, *page_to_copy; void *mem_start = mem; +#ifdef USE_FUNCTION_DESCRIPTORS + func_descr_t *opd = (func_descr_t *)&exec_func; + func_page_offset = (uintptr_t)opd->entry & (page_sz - 1); + func_copy_start = mem + func_page_offset; + page_to_copy = (void *)((uintptr_t)opd->entry & page_mask); +#else + func_page_offset = (uintptr_t)&exec_func & (page_sz - 1); + func_copy_start = mem + func_page_offset; + page_to_copy = (void *)((uintptr_t)&exec_func & page_mask); +#endif + /* copy 1st page, if it's not present something is wrong */ if (!page_present(page_to_copy)) { tst_resm(TINFO, "exec_func: %p, page_to_copy: %p\n", @@ -228,7 +255,7 @@ static void *get_func(void *mem) static void testfunc_protexec(void) { - void (*func)(void); + func_ptr_t func; void *p; sig_caught = 0; @@ -236,7 +263,13 @@ static void testfunc_protexec(void) p = SAFE_MMAP(cleanup, 0, copy_sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); +#ifdef USE_FUNCTION_DESCRIPTORS + func_descr_t opd; + opd.entry = (uintptr_t)get_func(p); + func = (func_ptr_t)&opd; +#else func = get_func(p); +#endif /* Change the protection to PROT_EXEC. */ TEST(mprotect(p, copy_sz, PROT_EXEC));