From patchwork Sun Jun 11 00:45:36 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 20911 Received: (qmail 129532 invoked by alias); 11 Jun 2017 00:45:45 -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 129435 invoked by uid 89); 11 Jun 2017 00:45:37 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-24.6 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mail-qk0-f177.google.com X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=edvtJbVfu8wgpS67Vg2I8BLNgFhszx6YD/XzyPpMxtg=; b=qd7q2DhdwIV3CEk54oh1Tw9RI252Vm1vPwc9HMK7iFNzkDIyEidZvgXBfVN40hFtce hJTIiyp0Z2HqfEzCVYmQtKzMFWY8YvsaoVIsqgrYOngWRQvmBlL/NLOVcDE9vspziK7+ kl562VAJgk4eo48kWndTPKfPlPtwUbtRFQK47Xfq35vu4eTHfzLE3cCRqX7rZ3bdyJDA 3jhsZxsphcVupQITNL3oSnb/hyY5IjP4mYBDpKdQC8stjXGcuFJ5SKeZFFIuwi2/IJ8t MZ13iMTdrAdJ688bRT/aqb5gPN0N0yy9t+GaLTgxZ+2uFskwOMlkY0MZC2MDELEf4V9M kTgQ== X-Gm-Message-State: AKS2vOyQERhZyRwlb3+DCAPBhfuNdUPvf/3LoER+0pvVOcXPrE1eNBZN KUMUvFanMbn06tuzgEQ9JaOOMAsYrA== X-Received: by 10.233.223.199 with SMTP id t190mr12600297qkf.247.1497141937980; Sat, 10 Jun 2017 17:45:37 -0700 (PDT) MIME-Version: 1.0 In-Reply-To: <593AC592.7060804@arm.com> References: <451a71c6-7eb7-983d-f808-86cf50fc0dca@redhat.com> <1496876422.12598.31.camel@test-lenovo> <59390EEB.4020409@arm.com> <1496951188.15627.51.camel@test-lenovo> <593A64CC.60100@arm.com> <593A834A.7050301@arm.com> <593A84D6.40007@arm.com> <9f339124-dd5d-d677-0272-b8bba161e382@redhat.com> <593A8A26.3090800@arm.com> <593A9B29.2060103@arm.com> <593AA581.9080804@arm.com> <874lvpi4p0.fsf@oldenburg.str.redhat.com> <593AC592.7060804@arm.com> From: "H.J. Lu" Date: Sat, 10 Jun 2017 17:45:36 -0700 Message-ID: Subject: Re: RFC: Shadow Stack support in glibc To: Szabolcs Nagy Cc: Florian Weimer , nd , Yu-cheng Yu , GNU C Library , Igor Tsimbalist , "Shanbhogue, Vedvyas" On Fri, Jun 9, 2017 at 8:58 AM, Szabolcs Nagy wrote: > On 09/06/17 16:39, H.J. Lu wrote: >> Since the __saved_mask field in jmp_buf is unused for x86, replace >> __saved_mask with a union to save save shadow stack pointer while >> keeping the size of jmp_buf unchanged. >> >> * sysdeps/x86/setjmp.h: New file. > > sigsetjmp/siglongjmp has to save/restore the signal mask > but the signal mask size on linux is at most 16bytes (?) > and glibc uses 128 byte sigset_t. > > so instead of the union below, i'd expect a solution where > if !HURD then the first 16bytes of __saved_mask and the rest > can be accessed separately and the tail bytes are usable > for target specific data. > How about this? I allocated32 bytes for signal mask: /* The biggest signal number + 1 */ #define _JUMP_BUF_SIGSET_NSIG 257 /* Number of longs to hold all signals. */ #define _JUMP_BUF_SIGSET_NWORDS \ ((_JUMP_BUF_SIGSET_NSIG - 1 + 7) / (8 * sizeof (unsigned long int))) typedef struct { unsigned long int __val[_JUMP_BUF_SIGSET_NWORDS]; } __jmp_buf_sigset_t; typedef union { __sigset_t __saved_mask_compat; struct { __jmp_buf_sigset_t __saved_mask; void *__padding[12]; } __saved; } __jmpbuf_target_t; /* Saved signal mask. */ #define __saved_mask __target.__saved.__saved_mask and used #if _JUMP_BUF_SIGSET_NSIG < _NSIG # error _JUMP_BUF_SIGSET_NSIG < _NSIG #endif _Static_assert (sizeof (env[0].__target) == sizeof (__sigset_t), "__jmpbuf_target_t == __sigset_t"); to catch any future issues. From 10fdcdb92c73bcbf170d764ee86196e8999d3357 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Sat, 10 Jun 2017 17:23:06 -0700 Subject: [PATCH] Add bits/setjmp3.h --- include/bits/setjmp3.h | 1 + setjmp/Makefile | 2 +- setjmp/bits/setjmp3.h | 47 +++++++++++++++++++++++++++++++++++++++++++++++ setjmp/longjmp.c | 13 ++++++++++--- setjmp/setjmp.h | 3 ++- setjmp/sigjmp.c | 9 ++++++++- 6 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 include/bits/setjmp3.h create mode 100644 setjmp/bits/setjmp3.h diff --git a/include/bits/setjmp3.h b/include/bits/setjmp3.h new file mode 100644 index 0000000..ea343af --- /dev/null +++ b/include/bits/setjmp3.h @@ -0,0 +1 @@ +#include diff --git a/setjmp/Makefile b/setjmp/Makefile index ca80b8e..b52685f 100644 --- a/setjmp/Makefile +++ b/setjmp/Makefile @@ -22,7 +22,7 @@ subdir := setjmp include ../Makeconfig -headers := setjmp.h bits/setjmp.h bits/setjmp2.h +headers := setjmp.h bits/setjmp.h bits/setjmp2.h bits/setjmp3.h routines := setjmp sigjmp bsd-setjmp bsd-_setjmp \ longjmp __longjmp jmp-unwind diff --git a/setjmp/bits/setjmp3.h b/setjmp/bits/setjmp3.h new file mode 100644 index 0000000..a21b037 --- /dev/null +++ b/setjmp/bits/setjmp3.h @@ -0,0 +1,47 @@ +/* __jmpbuf_target_t defition. + Copyright (C) 2017 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 + . */ + +#ifndef _SETJMP_H +# error "Never include directly; use instead." +#endif + +#include + +/* The biggest signal number + 1 */ +#define _JUMP_BUF_SIGSET_NSIG 257 +/* Number of longs to hold all signals. */ +#define _JUMP_BUF_SIGSET_NWORDS \ + ((_JUMP_BUF_SIGSET_NSIG - 1 + 7) / (8 * sizeof (unsigned long int))) + +typedef struct + { + unsigned long int __val[_JUMP_BUF_SIGSET_NWORDS]; + } __jmp_buf_sigset_t; + +typedef union + { + __sigset_t __saved_mask_compat; + struct + { + __jmp_buf_sigset_t __saved_mask; + void *__padding[12]; + } __saved; + } __jmpbuf_target_t; + +/* Saved signal mask. */ +#define __saved_mask __target.__saved.__saved_mask diff --git a/setjmp/longjmp.c b/setjmp/longjmp.c index 2453c2c..8418894 100644 --- a/setjmp/longjmp.c +++ b/setjmp/longjmp.c @@ -19,6 +19,9 @@ #include #include +#if _JUMP_BUF_SIGSET_NSIG < _NSIG +# error _JUMP_BUF_SIGSET_NSIG < _NSIG +#endif /* Set the signal mask to the one specified in ENV, and jump to the position specified in ENV, causing the setjmp @@ -30,9 +33,13 @@ __libc_siglongjmp (sigjmp_buf env, int val) _longjmp_unwind (env, val); if (env[0].__mask_was_saved) - /* Restore the saved signal mask. */ - (void) __sigprocmask (SIG_SETMASK, &env[0].__saved_mask, - (sigset_t *) NULL); + { + _Static_assert (sizeof (env[0].__target) == sizeof (__sigset_t), + "__jmpbuf_target_t == __sigset_t"); + __sigset_t *saved_mask = (__sigset_t *) &env[0].__saved_mask; + /* Restore the saved signal mask. */ + (void) __sigprocmask (SIG_SETMASK, saved_mask, (sigset_t *) NULL); + } /* Call the machine-dependent function to restore machine state. */ __longjmp (env[0].__jmpbuf, val ?: 1); diff --git a/setjmp/setjmp.h b/setjmp/setjmp.h index 86fb2ed..4763ca1 100644 --- a/setjmp/setjmp.h +++ b/setjmp/setjmp.h @@ -27,6 +27,7 @@ __BEGIN_DECLS #include /* Get `__jmp_buf'. */ +#include #include /* Calling environment, plus possibly a saved signal mask. */ @@ -38,7 +39,7 @@ struct __jmp_buf_tag or add others before it. */ __jmp_buf __jmpbuf; /* Calling environment. */ int __mask_was_saved; /* Saved the signal mask? */ - __sigset_t __saved_mask; /* Saved signal mask. */ + __jmpbuf_target_t __target; /* Target specific data. */ }; diff --git a/setjmp/sigjmp.c b/setjmp/sigjmp.c index 30839ae..91c6f56 100644 --- a/setjmp/sigjmp.c +++ b/setjmp/sigjmp.c @@ -19,6 +19,10 @@ #include #include +#if _JUMP_BUF_SIGSET_NSIG < _NSIG +# error _JUMP_BUF_SIGSET_NSIG < _NSIG +#endif + /* This function is called by the `sigsetjmp' macro before doing a `__setjmp' on ENV[0].__jmpbuf. Always return zero. */ @@ -26,9 +30,12 @@ int __sigjmp_save (sigjmp_buf env, int savemask) { + _Static_assert (sizeof (env[0].__target) == sizeof (__sigset_t), + "__jmpbuf_target_t == __sigset_t"); + __sigset_t *saved_mask = (__sigset_t *) &env[0].__saved_mask; env[0].__mask_was_saved = (savemask && __sigprocmask (SIG_BLOCK, (sigset_t *) NULL, - &env[0].__saved_mask) == 0); + saved_mask) == 0); return 0; } -- 2.9.4