From mboxrd@z Thu Jan 1 00:00:00 1970
Return-Path:
Received: from mail-pl1-x62a.google.com (mail-pl1-x62a.google.com [IPv6:2607:f8b0:4864:20::62a])
by sourceware.org (Postfix) with ESMTPS id 0D9273858D35
for ; Wed, 29 Nov 2023 08:53:25 +0000 (GMT)
DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 0D9273858D35
Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=adacore.com
Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=adacore.com
ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 0D9273858D35
Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::62a
ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701248007; cv=none;
b=bbeK4ym3DSeeqp/LvESWP/jlsA37Z7N7RBsmT2jwOebGKdlRBrrJ2P1fCnxyQ/AS+GmB7WPWTFQzHR0gg5NkIOGCPn67L0Fl91DpptQBi4s+WEc5tXoZGC+CaxS3YAWxv9IVruLtsb1YJhadV27KDPHlhCaJE2l2L4E0cH0V3zQ=
ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key;
t=1701248007; c=relaxed/simple;
bh=AYpDGJRDzWGtZfLrel21Gvf0NMeeUvA52l+5cQWnG/4=;
h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=COhoaWgbMuuaRllchnufJLxGmN8xL1dGmYZzGuWnsF7/iMJ3P961obVejNxj5C28Ux216OSqj/q+nckERVYKDJLKGeL9CZ08NxNslWl7Znz3tZZiXBPC8+pK1OhFeaFmI6wgOQTCMhVAJUheYgJnEBkxQ06O6AHm2hAtZhcnyw4=
ARC-Authentication-Results: i=1; server2.sourceware.org
Received: by mail-pl1-x62a.google.com with SMTP id d9443c01a7336-1cfb4d28c43so34073515ad.1
for ; Wed, 29 Nov 2023 00:53:25 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=adacore.com; s=google; t=1701248003; x=1701852803; darn=gcc.gnu.org;
h=mime-version:user-agent:message-id:in-reply-to:date:references
:organization:subject:cc:to:from:from:to:cc:subject:date:message-id
:reply-to;
bh=CXna2T6SDu8Z8Y/VeTkRU+kDJlT0a26afBRoCVlwHB8=;
b=Xyh4CslbcrtyskEO0OUn8tkJQX/ZMqOq99h+KUdxuvedHjhisXq9CBm1EUxD9dWTtb
1kH+seFyZoUcz8EVeCx6xP2sRdqN2WLZAdGjOePSZaZ/UPmfzs1crwhhkfvsRtSQM7wP
Ny22cT6+t92GnCRQ/oCL/VfqA90iLfXZ2G+/GWA8+DVGs/1STybUr2vIatWyATe+dgo9
TqaxRP8iaNvIXGDj6KF/bUqXuavcNfa6MI+lvSUEmQ+/GPuobiWqTGrMcGqn4sSG7+1r
WXVhMuUEfSBktS5xgV+Cteototyr6wYq5RNttXJLyayiunbetCvUs95ginY8U2Xar/c/
6Tkg==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=1e100.net; s=20230601; t=1701248003; x=1701852803;
h=mime-version:user-agent:message-id:in-reply-to:date:references
:organization:subject:cc:to:from:x-gm-message-state:from:to:cc
:subject:date:message-id:reply-to;
bh=CXna2T6SDu8Z8Y/VeTkRU+kDJlT0a26afBRoCVlwHB8=;
b=CHEMLXoA2qaHktwRTudI2zCjJAwAijXnJYxebm7Mh8/fTLHI9pOtGsJasCJ37ZITzz
HNzfHEF64HS0wmKvuTjXWYoW4Qh7ShRK3E0936TVqXnSd1w4o/T1UwXOHVwjVzsuBCoP
EQqIsMXDbmWjPstiJcpuVzOKEAu/vDyqfqOdSouUutmQ7qqQV+MBsIxaz3ORTIMOqG7F
gCdxl9mbZIQK7mS68QRVm0CmuX+ub9avA29l7z4ZKlVZwvWFEpy83IvYsV1QgRKp2ooy
54JWQKFPItZLHJ0fNs1ob3UyPWJfdJYK0Z44CrKSea4qp2bycFi91W6atzur7Y3qIWAW
KHqQ==
X-Gm-Message-State: AOJu0YyzfUIvcvAmvRH6BsGZqxCU9yaBIVe51hM/OmyEMhb4ik+bJx8R
ueXfeqwZzKBww1dyNR34xVYMqA==
X-Google-Smtp-Source: AGHT+IFrMGrZENRy3xLYR7HMMKLweT/4NqE3SXFjPaGCD8Wf2HClY+yvF5knTP7k9xX4EXNyHp6vMw==
X-Received: by 2002:a17:902:ecc5:b0:1cf:c2c8:7f96 with SMTP id a5-20020a170902ecc500b001cfc2c87f96mr13013374plh.48.1701248002515;
Wed, 29 Nov 2023 00:53:22 -0800 (PST)
Received: from free.home ([2804:7f1:2080:8316:5de:a3fa:396c:13d9])
by smtp.gmail.com with ESMTPSA id h1-20020a170902f7c100b001cfad601a4bsm8819488plw.10.2023.11.29.00.53.21
(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
Wed, 29 Nov 2023 00:53:22 -0800 (PST)
Received: from livre (livre.home [172.31.160.2])
by free.home (8.15.2/8.15.2) with ESMTPS id 3AT8r7mr023570
(version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT);
Wed, 29 Nov 2023 05:53:07 -0300
From: Alexandre Oliva
To: Richard Biener
Cc: gcc-patches@gcc.gnu.org, Jeremy Bennett ,
Craig Blackmore ,
Graham Markall
,
Martin Jambor , Jan
Hubicka ,
Jim Wilson , Jeff Law
,
Jakub Jelinek
Subject: Re: [PATCH v4] Introduce strub: machine-independent stack scrubbing
Organization: Free thinker, does not speak for AdaCore
References:
Date: Wed, 29 Nov 2023 05:53:07 -0300
In-Reply-To:
(Richard Biener's message of "Thu, 23 Nov 2023 13:05:27 +0100")
Message-ID:
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.1 (gnu/linux)
MIME-Version: 1.0
Content-Type: text/plain
X-Scanned-By: MIMEDefang 2.84
X-Spam-Status: No, score=-12.3 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,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 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 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.
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, );
...
}
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);
}
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. */
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 the
--help=hardened
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
--
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