From mboxrd@z Thu Jan 1 00:00:00 1970
Return-Path:
Received: from mail-lf1-x130.google.com (mail-lf1-x130.google.com [IPv6:2a00:1450:4864:20::130])
by sourceware.org (Postfix) with ESMTPS id 9F06E3858C31
for ; Wed, 29 Nov 2023 12:48:56 +0000 (GMT)
DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 9F06E3858C31
Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com
Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com
ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 9F06E3858C31
Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::130
ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701262139; cv=none;
b=jfsLN8SpYJs5qoC/MUAH1G01tlxjmirjGS5IRKFQkRut7wOmDWNWGdjru70ixe3+WSoFTTqmA/x6gzIrq98GvIgjvYCT4f4tesk8A72H6/bF066gJtJgNLSbkAOJ0MCgdujChz1YIKxN1+MXi/fpVUHbyww5wPoDLjPicw4rN8c=
ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key;
t=1701262139; c=relaxed/simple;
bh=MAfn+lBU/cc2Wc1+JtUbGMUKBbo6HmmzqZpyV3Gz6Vs=;
h=DKIM-Signature:MIME-Version:From:Date:Message-ID:Subject:To; b=DNFG4PK447WvHyJb/aYTT6A6rgsZI5+p7/JyyD3R5fwOvXhUBCXCNJTQuw/FG9Pz9EFDU7+wejXqu/MBCvVq8c+IFSsE5JPM6jc7ZSCNTfky95W5/WlqilLNuViXm6Eit45rISzy4PcGlvUIy4Ql5RM3B60aZnVYgWpjRs0pVJY=
ARC-Authentication-Results: i=1; server2.sourceware.org
Received: by mail-lf1-x130.google.com with SMTP id 2adb3069b0e04-50abb83866bso9032448e87.3
for ; Wed, 29 Nov 2023 04:48:56 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=gmail.com; s=20230601; t=1701262135; x=1701866935; darn=gcc.gnu.org;
h=content-transfer-encoding:cc:to:subject:message-id:date:from
:in-reply-to:references:mime-version:from:to:cc:subject:date
:message-id:reply-to;
bh=4VU9tR/kFRErO6Phin8w5eKo5xKUjazkDqu3tivklkE=;
b=Krjv4T/SP2H3CUWaO6SN19+LpSsmjSf78b5TszSzlrXUewSmn7lQEM7vw0LFuWcl8K
dSv5v+C6gHiZ49+f+12GxZjTk2VpTlJZVGz0gFdWsYHnYMszUCfE+mRgFHkFi1+XdZT9
Hr38Q/2BD82vFc8c/OuDwvojLE0KeWfUjhEKXQ5AhpF11c0GPcioUboYHViIstfjsGjM
LtXP+cpHR5NbXU6zn9KSlRWcvXH/tbP/2P968bmAoG5BVUUGG2irSAkd0PCw2iIzt3if
whrZR/e9PFqwPZ3+O3hjje34lpszECKI4J4NS/XJwBfL+dAn+ZKdNP5caWLTZoibNjsR
ahew==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=1e100.net; s=20230601; t=1701262135; x=1701866935;
h=content-transfer-encoding:cc:to:subject:message-id:date:from
:in-reply-to:references:mime-version:x-gm-message-state:from:to:cc
:subject:date:message-id:reply-to;
bh=4VU9tR/kFRErO6Phin8w5eKo5xKUjazkDqu3tivklkE=;
b=ezfzZGXfocA8hkSDzUNEtvBzGa88ZJpQN9mci4KClIjn+hRxHBDT6qVozufYeiz3k4
8qgu+obJEyc8I2nJKdQIVjxuecD9swifvH0Zd56enp34neMOGLAtkBPbvnHbT+JhGUEU
pua1taRmII/dXwANhDAxvqb141yyrmbSI14pl09o3PMWKiKoZk3C/W5H/hfWvJdq4rXh
XL62OcuAB23l5cq1XoaK1xhAYWOikZy6YLzVMkMkIue221T+GILB8W7iuMbRQO3TN//2
7OBy6NAOoSn7XsSDrTsxVeE32vCziUpI5lUiDjtU6hBLxwuS9ZDqtM3uIQArSmIAlChO
dWmQ==
X-Gm-Message-State: AOJu0Yxzk9ywr+YEHGzyyuGF849uJLgHRm/e7vJr6Y/7YaMrMiLxXWJQ
l79gQrhShKHk4I0JmcgJS1NZKaYEBgXoS3/DSrY=
X-Google-Smtp-Source: AGHT+IEfozK+2QKTgTv6/yfFRziA6bf6EN7+orBssdkiKIm7js98rQveCY73OveTSIpxV+jDZq0fyhQvpPV2V8k03mI=
X-Received: by 2002:a05:6512:3b9c:b0:50b:c699:b4f7 with SMTP id
g28-20020a0565123b9c00b0050bc699b4f7mr1158754lfv.38.1701262134637; Wed, 29
Nov 2023 04:48:54 -0800 (PST)
MIME-Version: 1.0
References:
In-Reply-To:
From: Richard Biener
Date: Wed, 29 Nov 2023 13:48:41 +0100
Message-ID:
Subject: Re: [PATCH v4] Introduce strub: machine-independent stack scrubbing
To: Alexandre Oliva
Cc: gcc-patches@gcc.gnu.org, Jeremy Bennett ,
Craig Blackmore , Graham Markall ,
Martin Jambor , Jan Hubicka , Jim Wilson ,
Jeff Law , Jakub Jelinek
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
X-Spam-Status: No, score=-7.5 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,GIT_PATCH_0,KAM_SHORT,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE,WEIRD_QUOTING autolearn=ham autolearn_force=no version=3.4.6
X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org
List-Id:
On Wed, Nov 29, 2023 at 9:53=E2=80=AFAM Alexandre Oliva =
wrote:
>
> On Nov 23, 2023, Richard Biener 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 aggregat=
e
> > 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=3Dstrict, 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 wh=
en
> >> > 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, );
> ...
> }
>
> into
>
> wrapped_foo (va_list &wrap)
> {
> va_list ap;
>
> ...
> va_copy (ap, wrap);
> ...
> }
>
> foo (...)
> {
> va_list wrap;
>
> va_start (wrap, );
> 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=3Drelaxed mode
> is in effect (that's the default). In -fstrub=3Dstrict 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=3Dstrict 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
> Profiling and Test Coverage in Freestanding Environments.
>
> +
> + New options -fharden-compares
> + and -fharden-conditional-branches
to verify compares
> + and conditional branches, to detect some power-deprivation
> + hardware attacks, using reversed conditions.
> +
>
>
>
> 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.
> of hardening flags. The options it enables can be displayed using t=
he
> --help=3Dhardened
option.
>
> +
> + New option -fharden-control-flow-redundancy
, 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.
> +
> +
> + New type attribute hardbool
, for C and Ada. Hardened
> + booleans take user-specified representations for true
> + and false
, presumably with higher hamming distance
> + than standard booleans, and get verified at every use, detecting
> + memory corruption and some malicious attacks.
> +
> +
> + New type attribute strub
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.
> +
> +
> + New option -finline-stringops
, to force inline
> + expansion of memcmp
, memcpy
,
> + memmove
and memset
, even when that is
> + not an optimization, to avoid relying on library
> + implementations.
> +
>
>
> New Languages and Language specific improvements
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