public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Richard Biener <richard.guenther@gmail.com>
To: Alexandre Oliva <oliva@adacore.com>
Cc: gcc-patches@gcc.gnu.org,
	Jeremy Bennett <jeremy.bennett@embecosm.com>,
	 Craig Blackmore <craig.blackmore@embecosm.com>,
	Graham Markall <graham.markall@embecosm.com>,
	 Martin Jambor <mjambor@suse.cz>, Jan Hubicka <hubicka@ucw.cz>,
	Jim Wilson <wilson@tuliptree.org>,
	 Jeff Law <jeffreyalaw@gmail.com>,
	Jakub Jelinek <jakub@redhat.com>
Subject: Re: [PATCH v4] Introduce strub: machine-independent stack scrubbing
Date: Wed, 29 Nov 2023 13:48:41 +0100	[thread overview]
Message-ID: <CAFiYyc0t-5TKoRFgs6x1huWX80QZGjin2oW5eyMi2TnN_YZudA@mail.gmail.com> (raw)
In-Reply-To: <or1qc9lz4c.fsf@lxoliva.fsfla.org>

On Wed, Nov 29, 2023 at 9:53 AM Alexandre Oliva <oliva@adacore.com> wrote:
>
> On Nov 23, 2023, Richard Biener <richard.guenther@gmail.com> wrote:
>
> > Conceptually it shouldn't be much different from what IPA-SRA does
> > which is cloning a function but with different arguments, the function
> > signature transform described in terms of ipa-param-manipulation bits.
> > I've talked with Martin and at least there's currently no
> > by-value-to-by-reference
> > "transform", but IPA-SRA can pass two registers instead of one aggregate
> > for example.  There's IPA_PARAM_OP_NEW already to add a new param.
> > In principle the whole function rewriting (apart of recovering
> > from inlining) should be doable within this framework.
>
> I agree, but my attempts to do so have been unfruitful, and hit various
> very obscure issues that made it unworkable.  Maybe someone smarter than
> I am, or with more time than I had, can make the conversion.  The uses
> of IPA_PARAM_OP_NEW for the cloning are there, and the more conservative
> choices I made got it to work reliably, unlike the more adventurous
> alternatives I tried.  One of the obscure issues I recall hitting was
> this one.  I can probably still locate the early strub patch that hit
> the described issue back then, if there's interest.
> https://gcc.gnu.org/pipermail/gcc-patches/2021-July/575044.html
>
> >> The
> >> wrapper already needs a custom ABI, because of the added watermark
> >> pointer, and va_list and whatnot when needed, so a little further
> >> customization to avoid a quite significant overhead seemed desirable.
>
> > I understood the purpose of this, but I also saw it's only ever needed for
> > non-strict operation
>
> Erhm...  I suppose you're not talking about -fstrub=strict, because I
> can't see how this relates with the by-reference argument passing from
> wrapper to wrapped in internal strubbing.
>
> > and I think that if you care about security you'd never
> > want to operate in a way that you don't absolutely know the function
> > you call isn't going to scrub your secrets ...
>
> The ABI between wrapper and wrapped function splitting in internal strub
> doesn't change this.
>
> > But yes, I also wondered why you even run into re-gimplification issues.
>
> Because &arg_#(D)[n_#] is good gimple, but &(*byref_arg_#(D))[n_#] isn't.

'arg_#(D)' looks like a SSA name, and no, taking the address doesn't work,
so I assume it was &MEM[arg_(D)][n_#] which is indeed OK.  But you
shouldn't need to change a pointer argument to be passed by reference,
do you?  As said, you want to restrict by-reference passing to arguments
that are !is_gimple_reg_type ().  Everywhere where a plain PARM_DECL
was valid a *ptr indirection is as well.

> Maybe instead of going through regimplify, we could explicitly create an
> SSA name for the indirection load, so that the purpose is made more
> explicit.
>
> > replacing the PARM_DECL there with a MEM_REF (new-PARM_DECL) should
> > work without re-gimplification.
>
> FWIW, I thought so as well ;-)
>
> > I didn't remember seeing that you do sth like wrapping
> > each "strubbed call" inside a try { call(); } finally { do-strub } to
> > ensure this.
> > Guess it was well hidden in the large patch ;)
>
> Indeed, gsi_insert_finally_seq_after_call is where this is taken care of.
>
> >> > As it's only for optimization, how much of the code would go away when
> >> > you avoid changing the parameters of the wrapped function?
> >>
> >> We can't avoid changing them entirely, and IIRC some of the
> >> infrastructure for regimplification was also used for va_list and
> >> apply_args handling, so it wouldn't save all that much.
>
> > Ah, var-args ... indeed for simple forwarding it shouldn't be too bad.
> > I wonder if this were a way to remove the restriction on function
> > splitting of var-args functions - there's a recent bugreport about that
> > (before any va_arg () has been called, of course).
>
> If running va_start unconditionally in varargs functions is generally
> acceptable, then the method I've used for wrapping varargs functions
> should work generally, yeah.  The trick was to turn:
>
> foo (...)
> {
>   va_list ap;
>
>   ...
>   va_start (&ap, <ignored>);
>   ...
> }
>
> into
>
> wrapped_foo (va_list &wrap)
> {
>   va_list ap;
>
>   ...
>   va_copy (ap, wrap);
>   ...
> }
>
> foo (...)
> {
>   va_list wrap;
>
>   va_start (wrap, <also ignored>);
>   wrapped_foo (wrap);
>   va_end (wrap);
> }

Ah, nice trick indeed.  I think that should work, it might not
be optimal (I don't think we will optimize the va_copy).

>
> Here's the opening comment I added to ipa-strub.cc:
>
> /* This file introduces two passes that, together, implement
>    machine-independent stack scrubbing, strub for short.  It arranges
>    for stack frames that have strub enabled to be zeroed-out after
>    relinquishing control to a caller, whether by returning or by
>    propagating an exception.  This admittedly unusual design decision
>    was driven by exception support (one needs a stack frame to be
>    active to propagate exceptions out of it), and it enabled an
>    implementation that is entirely machine-independent (no custom
>    epilogue code is required).
>
>    Strub modes can be selected for stack frames by attaching attribute
>    strub to functions or to variables (to their types, actually).
>    Different strub modes, with different implementation details, are
>    available, and they can be selected by an argument to the strub
>    attribute.  When enabled by strub-enabled variables, whether by
>    accessing (as in reading from) statically-allocated ones, or by
>    introducing (as in declaring) automatically-allocated ones, a
>    suitable mode is selected automatically.
>
>    At-calls mode modifies the interface of a function, adding a stack
>    watermark argument, that callers use to clean up the stack frame of
>    the called function.  Because of the interface change, it can only
>    be used when explicitly selected, or when a function is internal to
>    a translation unit.  Strub-at-calls function types are distinct
>    from their original types (they're not modified in-place), and they
>    are not interchangeable with other function types.
>
>    Internal mode, in turn, does not modify the type or the interface
>    of a function.  It is currently implemented by turning the function
>    into a wrapper, moving the function body to a separate wrapped
>    function, and scrubbing the wrapped body's stack in the wrapper.
>    Internal-strub function types are mostly interface-compatible with
>    other strub modes, namely callable (from strub functions, though
>    not strub-enabled) and disabled (not callable from strub
>    functions).
>
>    Always_inline functions can be strub functions, but they can only
>    be called from other strub functions, because strub functions must
>    never be inlined into non-strub functions.  Internal and at-calls
>    modes are indistinguishable when it comes to always_inline
>    functions: they will necessarily be inlined into another strub
>    function, and will thus be integrated into the caller's stack
>    frame, whatever the mode.  (Contrast with non-always_inline strub
>    functions: an at-calls function can be called from other strub
>    functions, ensuring no discontinuity in stack erasing, whereas an
>    internal-strub function can only be called from other strub
>    functions if it happens to be inlined, or if -fstrub=relaxed mode
>    is in effect (that's the default).  In -fstrub=strict mode,
>    internal-strub functions are not callable from strub functions,
>    because the wrapper itself is not strubbed.
>
>    The implementation involves two simple-IPA passes.  The earliest
>    one, strub-mode, assigns strub modes to functions.  It needs to run
>    before any inlining, so that we can prevent inlining of strub
>    functions into non-strub functions.  It notes explicit strub mode
>    requests, enables strub in response to strub variables and testing
>    options, and flags unsatisfiable requests.
>
>    Three possibilities of unsatisfiable requests come to mind: (a)
>    when a strub mode is explicitly selected, but the function uses
>    features that make it ineligible for that mode (e.g. at-calls rules
>    out calling __builtin_apply_args, because of the interface changes,
>    and internal mode rules out noclone or otherwise non-versionable
>    functions, non-default varargs, non-local or forced labels, and
>    functions with far too many arguments); (b) when some strub mode
>    must be enabled because of a strub variable, but the function is
>    not eligible or not viable for any mode; and (c) when
>    -fstrub=strict is enabled, and calls are found in strub functions
>    to functions that are not callable from strub contexts.
>    compute_strub_mode implements (a) and (b), and verify_strub
>    implements (c).
>
>    The second IPA pass modifies interfaces of at-calls-strub functions
>    and types, introduces strub calls in and around them. and splits
>    internal-strub functions.  It is placed after early inlining, so
>    that even internal-strub functions get a chance of being inlined
>    into other strub functions, but before non-early inlining, so that
>    internal-strub wrapper functions still get a chance of inlining
>    after splitting.
>
>    Wrappers avoid duplicating the copying of large arguments again by
>    passing them by reference to the wrapped bodies.  This involves
>    occasional SSA rewriting of address computations, because of the
>    additional indirection.  Besides these changes, and the
>    introduction of the stack watermark parameter, wrappers and wrapped
>    functions cooperate to handle variable argument lists (performing
>    va_start in the wrapper, passing the list as an argument, and
>    replacing va_start calls in the wrapped body with va_copy), and
>    __builtin_apply_args (also called in the wrapper and passed to the
>    wrapped body as an argument).
>
>    Strub bodies (both internal-mode wrapped bodies, and at-calls
>    functions) always start by adjusting the watermark parameter, by
>    calling __builtin___strub_update.  The compiler inserts them in the
>    main strub pass.  Allocations of additional stack space for the
>    frame (__builtin_alloca) are also followed by watermark updates.
>    Stack space temporarily allocated to pass arguments to other
>    functions, released right after the call, is not regarded as part
>    of the frame.  Around calls to them, i.e., in internal-mode
>    wrappers and at-calls callers (even calls through pointers), calls
>    to __builtin___strub_enter and __builtin___strub_leave are
>    inserted, the latter as a __finally block, so that it runs at
>    regular and exceptional exit paths.  strub_enter only initializes
>    the stack watermark, and strub_leave is where the scrubbing takes
>    place, overwriting with zeros the stack space from the top of the
>    stack to the watermark.
>
>    These calls can be optimized in various cases.  In
>    pass_ipa_strub::adjust_at_calls_call, for example, we enable
>    tail-calling and other optimized calls from one strub body to
>    another by passing on the watermark parameter.  The builtins
>    themselves may undergo inline substitution during expansion,
>    dependign on optimization levels.  This involves dealing with stack
>    red zones (when the builtins are called out-of-line, the red zone
>    cannot be used) and other ugly details related with inlining strub
>    bodies into other strub bodies (see expand_builtin_strub_update).
>    expand_builtin_strub_leave may even perform partial inline
>    substitution.  */

Thanks.

> The type attribute description now starts like this:
>
> @cindex @code{strub} type attribute
> @item strub
> This attribute defines stack-scrubbing properties of functions and
> variables, so that functions that access sensitive data can have their
> stack frames zeroed-out upon returning or propagating exceptions.  This
> may be enabled explicitly, by selecting certain @code{strub} modes for
> specific functions, or implicitly, by means of @code{strub} variables.
>
> And I've fixed the symbol versioning for strub and hardcfr functions.
>
> I've just pushed the base strub patch and the recent incremental changes
> (and some commits used for testing) to refs/users/aoliva/heads/strub.
>
>
> Here are changes.html entries for this and for the other newly-added
> features:
>
> new AdaCore-contributed hardening features in gcc 13 and 14
>
> Mention hardening of conditionals (added in gcc 13), control flow
> redundancy, hardened booleans, and stack scrubbing.
>
> Also cover forced inlining of string operations while at that.
> ---
>  htdocs/gcc-13/changes.html |    6 ++++++
>  htdocs/gcc-14/changes.html |   29 +++++++++++++++++++++++++++++
>  2 files changed, 35 insertions(+)
>
> diff --git a/htdocs/gcc-13/changes.html b/htdocs/gcc-13/changes.html
> index 8ef3d63952daf..c1dea18caf59b 100644
> --- a/htdocs/gcc-13/changes.html
> +++ b/htdocs/gcc-13/changes.html
> @@ -168,6 +168,12 @@ You may also want to check out our
>      been added, see also
>      <a href="https://gcc.gnu.org/onlinedocs/gcc/Freestanding-Environments.html">Profiling and Test Coverage in Freestanding Environments</a>.
>    </li>
> +  <li>
> +    New options <code>-fharden-compares</code>
> +    and <code>-fharden-conditional-branches</code> to verify compares
> +    and conditional branches, to detect some power-deprivation
> +    hardware attacks, using reversed conditions.
> +  </li>
>  </ul>
>
>
> diff --git a/htdocs/gcc-14/changes.html b/htdocs/gcc-14/changes.html
> index 2088ee91a34e1..cb92f8d8095c3 100644
> --- a/htdocs/gcc-14/changes.html
> +++ b/htdocs/gcc-14/changes.html
> @@ -109,6 +109,35 @@ a work-in-progress.</p>
>      of hardening flags.  The options it enables can be displayed using the
>      <code>--help=hardened</code> option.
>    </li>
> +  <li>
> +    New option <code>-fharden-control-flow-redundancy</code>, to
> +    verify, at the end of functions, that the visited basic blocks
> +    correspond to a legitimate execution path, so as to detect and
> +    prevent attacks that transfer control into the middle of
> +    functions.
> +  </li>
> +  <li>
> +    New type attribute <code>hardbool</code>, for C and Ada.  Hardened
> +    booleans take user-specified representations for <code>true</code>
> +    and <code>false</code>, presumably with higher hamming distance
> +    than standard booleans, and get verified at every use, detecting
> +    memory corruption and some malicious attacks.
> +  </li>
> +  <li>
> +    New type attribute <code>strub</code> to control stack scrubbing
> +    properties of functions and variables.  The stack frame used by
> +    functions marked with the attribute gets zeroed-out upon returning
> +    or exception escaping.  Scalar variables marked with the attribute
> +    cause functions contaning or accessing them to get stack scrubbing
> +    enabled implicitly.
> +  </li>
> +  <li>
> +    New option <code>-finline-stringops</code>, to force inline
> +    expansion of <code>memcmp</code>, <code>memcpy</code>,
> +    <code>memmove</code> and <code>memset</code>, even when that is
> +    not an optimization, to avoid relying on library
> +    implementations.
> +  </li>
>  </ul>
>  <!-- .................................................................. -->
>  <h2 id="languages">New Languages and Language specific improvements</h2>

LGTM.

Can you check on the pass-by-reference thing again please?

Let's see if Honza or Martin have any comments on the IPA bits, I just
mentioned what I think should be doable ...

Thanks,
Richard.

>
> --
> Alexandre Oliva, happy hacker            https://FSFLA.org/blogs/lxo/
>    Free Software Activist                   GNU Toolchain Engineer
> More tolerance and less prejudice are key for inclusion and diversity
> Excluding neuro-others for not behaving ""normal"" is *not* inclusive

  reply	other threads:[~2023-11-29 12:48 UTC|newest]

Thread overview: 59+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <ormtqpsbuc.fsf@lxoliva.fsfla.org>
2021-09-09  7:11 ` [PATCH] " Alexandre Oliva
2022-07-29  6:16   ` [PATCH v2 00/10] Introduce " Alexandre Oliva
2022-07-29  6:24     ` [PATCH v2 01/10] Introduce strub: documentation, and new command-line options Alexandre Oliva
2022-07-29  6:25     ` [PATCH v2 02/10] Introduce strub: torture tests for C and C++ Alexandre Oliva
2022-08-09 13:34       ` Alexandre Oliva
2022-07-29  6:25     ` [PATCH v2 03/10] Introduce strub: non-torture " Alexandre Oliva
2022-07-29  6:26     ` [PATCH v2 04/10] Introduce strub: tests for C++ and Ada Alexandre Oliva
2022-07-29  6:26     ` [PATCH v2 05/10] Introduce strub: builtins and runtime Alexandre Oliva
2022-07-29  6:27     ` [PATCH v2 06/10] Introduce strub: attributes Alexandre Oliva
2022-07-29  6:28     ` [PATCH v2 07/10] Introduce strub: infrastructure interfaces and adjustments Alexandre Oliva
2022-07-29  6:28     ` [PATCH v2 08/10] Introduce strub: strub modes Alexandre Oliva
2022-07-29  6:30     ` [PATCH v2 09/10] Introduce strub: strubm (mode assignment) pass Alexandre Oliva
2022-07-29  6:34     ` [PATCH v2 10/10] Introduce strub: strub pass Alexandre Oliva
2022-07-29  6:36     ` [PATCH v2 00/10] Introduce strub: machine-independent stack scrubbing Alexandre Oliva
2022-10-10  8:48       ` Richard Biener
2022-10-11 11:57         ` Alexandre Oliva
2022-10-11 11:59           ` Richard Biener
2022-10-11 13:33             ` Alexandre Oliva
2022-10-13 11:38               ` Richard Biener
2022-10-13 13:15                 ` Alexandre Oliva
2023-06-16  6:09     ` [PATCH v3] " Alexandre Oliva
2023-06-27 21:28       ` Qing Zhao
2023-06-28  8:20         ` Alexandre Oliva
2023-10-20  6:03       ` [PATCH v4] " Alexandre Oliva
2023-10-26  6:15         ` Alexandre Oliva
2023-11-20 12:40           ` Alexandre Oliva
2023-11-22 14:14             ` Richard Biener
2023-11-23 10:56               ` Alexandre Oliva
2023-11-23 12:05                 ` Richard Biener
2023-11-29  8:53                   ` Alexandre Oliva
2023-11-29 12:48                     ` Richard Biener [this message]
2023-11-30  4:13                       ` Alexandre Oliva
2023-11-30 12:00                         ` Richard Biener
2023-12-02 17:56                           ` [PATCH v5] " Alexandre Oliva
2023-12-05  6:25                             ` Alexandre Oliva
2023-12-06  1:04                               ` Alexandre Oliva
2023-12-05  9:01                             ` Richard Biener
2023-12-06  8:36                             ` Causes to nvptx bootstrap fail: " Tobias Burnus
2023-12-06 11:32                               ` Thomas Schwinge
2023-12-06 22:12                                 ` Alexandre Oliva
2023-12-07  3:33                                   ` [PATCH] strub: enable conditional support Alexandre Oliva
2023-12-07  7:24                                     ` Richard Biener
2023-12-07 16:44                                     ` Thomas Schwinge
2023-12-07 17:52                                       ` [PATCH] Alexandre Oliva
2023-12-08  6:46                                         ` [PATCH] Richard Biener
2023-12-08  9:33                                         ` [PATCH] strub: skip emutls after strubm errors Thomas Schwinge
2023-12-10  9:16                                           ` FX Coudert
2023-12-07  7:21                                   ` Causes to nvptx bootstrap fail: [PATCH v5] Introduce strub: machine-independent stack scrubbing Richard Biener
2023-12-06 10:22                             ` Jan Hubicka
2023-12-07 21:19                               ` Alexandre Oliva
2023-12-07 21:39                               ` Alexandre Oliva
2023-12-09  2:08                                 ` [PATCH] strub: add note on attribute access Alexandre Oliva
2023-12-11  7:26                                   ` Richard Biener
2023-12-12 14:21                                   ` Jan Hubicka
2023-12-11  8:40                             ` [PATCH] testsuite: Disable -fstack-protector* for some strub tests Jakub Jelinek
2023-12-11  8:59                               ` Richard Biener
2023-12-20  8:15                           ` [PATCH FYI] www: new AdaCore-contributed hardening features in gcc 13 and 14 Alexandre Oliva
2023-11-30  5:04                       ` [PATCH v4] Introduce strub: machine-independent stack scrubbing Alexandre Oliva
2023-11-30 11:56                         ` Richard Biener

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAFiYyc0t-5TKoRFgs6x1huWX80QZGjin2oW5eyMi2TnN_YZudA@mail.gmail.com \
    --to=richard.guenther@gmail.com \
    --cc=craig.blackmore@embecosm.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=graham.markall@embecosm.com \
    --cc=hubicka@ucw.cz \
    --cc=jakub@redhat.com \
    --cc=jeffreyalaw@gmail.com \
    --cc=jeremy.bennett@embecosm.com \
    --cc=mjambor@suse.cz \
    --cc=oliva@adacore.com \
    --cc=wilson@tuliptree.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).