From patchwork Wed Jul 25 15:01:54 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 28609 Received: (qmail 40434 invoked by alias); 25 Jul 2018 15:02:04 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 40411 invoked by uid 89); 25 Jul 2018 15:02:04 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.4 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=H*r:sk:i12-v6s X-HELO: mail-oi0-f65.google.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to:cc; bh=DK2oaIcmLxUSZBTuqyIz+KPFlshc9kSCgSUTO8Zjyhk=; b=rOXJGh0EVAKapHX7bbucKSppaZihWAVKWVAal0HrQAJBCFjbNiJISRP0Y1x7PRAmvP G1lk7c6LPkzDdTHBBtoSCRHi+4vK2uEYqxgvrdyKO3i+0zcqFp7bMriupQXyYsyWy4PN x/jIYPRDd7elcrNry0KmKB9wOzbAolMxCa8yHQOL27AaUPYTX2Xf5b1/5TzgZocZMbvI o5fbf/eQMF1CHwcvlVxEYCbI1Q4gw5IxcPBLi+el67SslPkIdPn6T01U/Y3xiCrcTY7g rnU7ABH/o/orS8EmV+vxLyPZ3dRw0io+MHpRrcQrAbrVxApdF9TQACq0pRepXho6wSzM HsOA== MIME-Version: 1.0 From: "H.J. Lu" Date: Wed, 25 Jul 2018 08:01:54 -0700 Message-ID: Subject: V2 [PATCH] x86/CET: Add a setcontext test for CET To: "Carlos O'Donell" Cc: GNU C Library On Wed, Jul 25, 2018 at 6:29 AM, Carlos O'Donell wrote: > On 07/25/2018 08:22 AM, H.J. Lu wrote: >> Verify that setcontext works with gaps above and below the newly >> allocated shadow stack. >> >> OK for master? >> >> H.J. >> --- >> * sysdeps/x86/Makefile (tests): Add tst-cet-setcontext-1 if >> CET is enabled. >> (CFLAGS-tst-cet-setcontext-1.c): Add -mshstk. >> * sysdeps/x86/tst-cet-setcontext-1.c: New file. > > OK for 2.28 only if you add a paragraph about exactly how the shadow > stacks are being laid out by the calls and why unmapping ctx3 and ctx4 works > to leave ctx1 with gap above and below. > Here is the updated patch with a comment: /* NB: When shadow stack is enabled, makecontext calls arch_prctl with ARCH_CET_ALLOC_SHSTK to allocate a new shadow stack which can be unmapped. The base address and size of the new shadow stack are returned in __ssp[1] and __ssp[2]. makecontext is called for CTX1, CTX3 and CTX4. But only CTX1 is used. New shadow stacks are allocated in the order of CTX3, CTX1, CTX4. It is very likely that CTX1's shadow stack is placed between CTX3 and CTX4. We munmap CTX3's and CTX4's shadow stacks to create gaps above and below CTX1's shadow stack. We check that setcontext CTX1 works correctly in this case. */ It is also moved to sysdeps/unix/sysv/linux/x86/tst-cet-setcontext-1.c since it is Linux/x86 specific. OK for master? Thanks. From 7b1a739cec11ac76e712769ecdd8585e0e74ad9c Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Tue, 24 Jul 2018 14:58:25 -0700 Subject: [PATCH] x86/CET: Add a setcontext test for CET Verify that setcontext works with gaps above and below the newly allocated shadow stack. * sysdeps/unix/sysv/linux/x86/Makefile (tests): Add tst-cet-setcontext-1 if CET is enabled. (CFLAGS-tst-cet-setcontext-1.c): Add -mshstk. * sysdeps/unix/sysv/linux/x86/tst-cet-setcontext-1.c: New file. --- sysdeps/unix/sysv/linux/x86/Makefile | 7 + .../sysv/linux/x86/tst-cet-setcontext-1.c | 127 ++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 sysdeps/unix/sysv/linux/x86/tst-cet-setcontext-1.c diff --git a/sysdeps/unix/sysv/linux/x86/Makefile b/sysdeps/unix/sysv/linux/x86/Makefile index 111ff9ff58..a30fdb1dc1 100644 --- a/sysdeps/unix/sysv/linux/x86/Makefile +++ b/sysdeps/unix/sysv/linux/x86/Makefile @@ -23,3 +23,10 @@ endif ifeq ($(subdir),setjmp) tests += tst-saved_mask-1 endif + +ifeq ($(enable-cet),yes) +ifeq ($(subdir),stdlib) +tests += tst-cet-setcontext-1 +CFLAGS-tst-cet-setcontext-1.c += -mshstk +endif +endif diff --git a/sysdeps/unix/sysv/linux/x86/tst-cet-setcontext-1.c b/sysdeps/unix/sysv/linux/x86/tst-cet-setcontext-1.c new file mode 100644 index 0000000000..ecf86a9e16 --- /dev/null +++ b/sysdeps/unix/sysv/linux/x86/tst-cet-setcontext-1.c @@ -0,0 +1,127 @@ +/* Check getcontext and setcontext on the context from makecontext + with shadow stack. + Copyright (C) 2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static ucontext_t ctx[5]; +static atomic_int done; + +static void +__attribute__((noinline, noclone)) +f2 (void) +{ + printf ("start f2\n"); + done++; + if (setcontext (&ctx[2]) != 0) + { + printf ("%s: setcontext: %m\n", __FUNCTION__); + exit (EXIT_FAILURE); + } +} + +static void +f1 (void) +{ + printf ("start f1\n"); + if (getcontext (&ctx[2]) != 0) + { + printf ("%s: getcontext: %m\n", __FUNCTION__); + exit (EXIT_FAILURE); + } + if (done) + exit (EXIT_SUCCESS); + f2 (); +} + +static int +do_test (void) +{ + char st1[32768]; + puts ("making contexts"); + if (getcontext (&ctx[0]) != 0) + { + printf ("%s: getcontext: %m\n", __FUNCTION__); + exit (EXIT_FAILURE); + } + if (getcontext (&ctx[1]) != 0) + { + printf ("%s: getcontext: %m\n", __FUNCTION__); + exit (EXIT_FAILURE); + } + + ctx[3].uc_stack.ss_sp = st1; + ctx[3].uc_stack.ss_size = sizeof st1; + ctx[3].uc_link = &ctx[0]; + makecontext (&ctx[3], (void (*) (void)) f1, 0); + + ctx[1].uc_stack.ss_sp = st1; + ctx[1].uc_stack.ss_size = sizeof st1; + ctx[1].uc_link = &ctx[0]; + makecontext (&ctx[1], (void (*) (void)) f1, 0); + + ctx[4].uc_stack.ss_sp = st1; + ctx[4].uc_stack.ss_size = sizeof st1; + ctx[4].uc_link = &ctx[0]; + makecontext (&ctx[4], (void (*) (void)) f1, 0); + + /* NB: When shadow stack is enabled, makecontext calls arch_prctl + with ARCH_CET_ALLOC_SHSTK to allocate a new shadow stack which + can be unmapped. The base address and size of the new shadow + stack are returned in __ssp[1] and __ssp[2]. makecontext is + called for CTX1, CTX3 and CTX4. But only CTX1 is used. New + shadow stacks are allocated in the order of CTX3, CTX1, CTX4. + It is very likely that CTX1's shadow stack is placed between + CTX3 and CTX4. We munmap CTX3's and CTX4's shadow stacks to + create gaps above and below CTX1's shadow stack. We check + that setcontext CTX1 works correctly in this case. */ + if (_get_ssp () != 0) + { + if (ctx[3].__ssp[1] != 0 + && munmap ((void *) (uintptr_t) ctx[3].__ssp[1], + (size_t) ctx[3].__ssp[2]) != 0) + { + printf ("%s: munmap: %m\n", __FUNCTION__); + exit (EXIT_FAILURE); + } + + if (ctx[4].__ssp[1] != 0 + && munmap ((void *) (uintptr_t) ctx[4].__ssp[1], + (size_t) ctx[4].__ssp[2]) != 0) + { + printf ("%s: munmap: %m\n", __FUNCTION__); + exit (EXIT_FAILURE); + } + } + + if (setcontext (&ctx[1]) != 0) + { + printf ("%s: setcontext: %m\n", __FUNCTION__); + exit (EXIT_FAILURE); + } + exit (EXIT_FAILURE); +} + +#include -- 2.17.1