[Ada] introduce stack scrub (strub) feature

gcc/ada/

	* doc/gnat_rm.rst: Add...
	* doc/gnat_rm/security_hardening_features.rst: New.
	* doc/gnat_rm/about_this_guide.rst: Link to new chapter.
	* gnat_rm.texi: Regenerate.
	* gcc-interface/utils.c (handle_strub_attribute): New.
	(gnat_internal_attribute_table): Add strub.
	* libgnat/a-except.adb: Make Rcheck_CE_* strub-callable.
	* libgnat/a-except.ads (Raise_Exception): Likewise.
	(Raise_Exception_Always): Likewise.
	* libgnat/s-arit128.ads (Multiply_With_Ovflo_Check128):
	Likewise.
	* libgnat/s-arit64.ads (Multiply_With_Ovflo_Check64):
	Likewise.
	* libgnat/s-secsta.ads (SS_Allocate, SS_Mark, SS_Release):
	Likewise.
This commit is contained in:
Alexandre Oliva 2021-09-23 09:46:54 -03:00 committed by Pierre-Marie de Rodat
parent b1657ff3a0
commit a23e02091e
10 changed files with 1178 additions and 851 deletions

View File

@ -55,6 +55,7 @@ GNAT Reference Manual
gnat_rm/specialized_needs_annexes
gnat_rm/implementation_of_specific_ada_features
gnat_rm/implementation_of_ada_2012_features
gnat_rm/security_hardening_features
gnat_rm/obsolescent_features
gnat_rm/compatibility_and_porting_guide

View File

@ -96,6 +96,9 @@ This reference manual contains the following chapters:
* :ref:`Implementation_of_Ada_2012_Features`, describes the status of the
GNAT implementation of the Ada 2012 language standard.
* :ref:`Security_Hardening_Features` documents GNAT extensions aimed
at security hardening.
* :ref:`Obsolescent_Features` documents implementation dependent features,
including pragmas and attributes, which are considered obsolescent, since
there are other preferred ways of achieving the same results. These

View File

@ -0,0 +1,89 @@
.. _Security_Hardening_Features:
***************************
Security Hardening Features
***************************
This chapter describes Ada extensions aimed at security hardening that
are provided by GNAT.
.. Register Scrubbing:
Register Scrubbing
==================
GNAT can generate code to zero-out hardware registers before returning
from a subprogram.
It can be enabled with the *-fzero-call-used-regs* command line
option, to affect all subprograms in a compilation, and with a
:samp:`Machine_Attribute` pragma, to affect only specific subprograms.
.. code-block:: ada
procedure Foo;
pragma Machine_Attribute (Foo, "zero_call_used_regs", "used");
-- Before returning, Foo scrubs only call-clobbered registers
-- that it uses itself.
function Bar return Integer;
pragma Machine_Attribute (Bar, "zero_call_used_regs", "all");
-- Before returning, Bar scrubs all call-clobbered registers.
For usage and more details on the command line option, and on the
``zero_call_used_regs`` attribute, see :title:`Using the GNU Compiler
Collection (GCC)`.
.. Stack Scrubbing:
Stack Scrubbing
===============
GNAT can generate code to zero-out stack frames used by subprograms.
It can be activated with the :samp:`Machine_Attribute` pragma, on
specific subprograms and variables.
.. code-block:: ada
function Foo returns Integer;
pragma Machine_Attribute (Foo, "strub");
-- Foo and its callers are modified so as to scrub the stack
-- space used by Foo after it returns.
procedure Bar;
pragma Machine_Attribute (Bar, "strub", "internal");
-- Bar is turned into a wrapper for its original body,
-- and they scrub the stack used by the original body.
Var : Integer;
pragma Machine_Attribute (Var, "strub");
-- Reading from Var in a subprogram enables stack scrubbing
-- of the stack space used by the subprogram.
There are also *-fstrub* command line options to control default
settings. For usage and more details on the command line option, and
on the ``strub`` attribute, see :title:`Using the GNU Compiler
Collection (GCC)`.
Note that Ada secondary stacks are not scrubbed. The restriction
``No_Secondary_Stack`` avoids their use, and thus their accidental
preservation of data that should be scrubbed.
Also note that the machine attribute is not integrated in the Ada type
system. Though it may modify subprogram and variable interfaces, it
is not fully reflected in Ada types, ``Access`` attributes, renaming
and overriding. Every access type, renaming, and overriding and
overridden dispatching operations that may refer to an entity with an
attribute-modified interface must be annotated with the same
interface-modifying attribute, or with an interface-compatible one.
Even then, the pragma is currently only functional when applied to
subprograms and scalar variables; other uses, such as directly on
types and subtypes, may be silently ignored. Specifically, it is not
currently recommended to rely on any effects this pragma might be
expected to have when calling subprograms through access-to-subprogram
variables.

View File

@ -94,6 +94,7 @@ static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
static tree handle_stack_protect_attribute (tree *, tree, tree, int, bool *);
static tree handle_no_stack_protector_attribute (tree *, tree, tree, int, bool *);
static tree handle_strub_attribute (tree *, tree, tree, int, bool *);
static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
static tree handle_noclone_attribute (tree *, tree, tree, int, bool *);
static tree handle_noicf_attribute (tree *, tree, tree, int, bool *);
@ -157,6 +158,8 @@ const struct attribute_spec gnat_internal_attribute_table[] =
{ "no_stack_protector",0, 0, true, false, false, false,
handle_no_stack_protector_attribute,
attr_stack_protect_exclusions },
{ "strub", 0, 1, false, true, false, true,
handle_strub_attribute, NULL },
{ "noinline", 0, 0, true, false, false, false,
handle_noinline_attribute, NULL },
{ "noclone", 0, 0, true, false, false, false,
@ -6602,6 +6605,15 @@ handle_no_stack_protector_attribute (tree *node, tree name, tree, int,
return NULL_TREE;
}
/* Handle a "strub" attribute; arguments as in
struct attribute_spec.handler. */
static tree
handle_strub_attribute (tree *, tree, tree, int, bool *no_add_attrs)
{
*no_add_attrs = true;
return NULL_TREE;
}
/* Handle a "noinline" attribute; arguments as in
struct attribute_spec.handler. */

File diff suppressed because it is too large Load Diff

View File

@ -629,6 +629,96 @@ package body Ada.Exceptions is
pragma No_Return (Rcheck_CE_Invalid_Data_Ext);
pragma No_Return (Rcheck_CE_Range_Check_Ext);
-- Make all of these procedures callable from strub contexts.
-- These attributes are not visible to callers; they are made
-- visible in trans.c:build_raise_check.
pragma Machine_Attribute (Rcheck_CE_Access_Check,
"strub", "callable");
pragma Machine_Attribute (Rcheck_CE_Null_Access_Parameter,
"strub", "callable");
pragma Machine_Attribute (Rcheck_CE_Discriminant_Check,
"strub", "callable");
pragma Machine_Attribute (Rcheck_CE_Divide_By_Zero,
"strub", "callable");
pragma Machine_Attribute (Rcheck_CE_Explicit_Raise,
"strub", "callable");
pragma Machine_Attribute (Rcheck_CE_Index_Check,
"strub", "callable");
pragma Machine_Attribute (Rcheck_CE_Invalid_Data,
"strub", "callable");
pragma Machine_Attribute (Rcheck_CE_Length_Check,
"strub", "callable");
pragma Machine_Attribute (Rcheck_CE_Null_Exception_Id,
"strub", "callable");
pragma Machine_Attribute (Rcheck_CE_Null_Not_Allowed,
"strub", "callable");
pragma Machine_Attribute (Rcheck_CE_Overflow_Check,
"strub", "callable");
pragma Machine_Attribute (Rcheck_CE_Partition_Check,
"strub", "callable");
pragma Machine_Attribute (Rcheck_CE_Range_Check,
"strub", "callable");
pragma Machine_Attribute (Rcheck_CE_Tag_Check,
"strub", "callable");
pragma Machine_Attribute (Rcheck_PE_Access_Before_Elaboration,
"strub", "callable");
pragma Machine_Attribute (Rcheck_PE_Accessibility_Check,
"strub", "callable");
pragma Machine_Attribute (Rcheck_PE_Address_Of_Intrinsic,
"strub", "callable");
pragma Machine_Attribute (Rcheck_PE_Aliased_Parameters,
"strub", "callable");
pragma Machine_Attribute (Rcheck_PE_All_Guards_Closed,
"strub", "callable");
pragma Machine_Attribute (Rcheck_PE_Bad_Predicated_Generic_Type,
"strub", "callable");
pragma Machine_Attribute (Rcheck_PE_Build_In_Place_Mismatch,
"strub", "callable");
pragma Machine_Attribute (Rcheck_PE_Current_Task_In_Entry_Body,
"strub", "callable");
pragma Machine_Attribute (Rcheck_PE_Duplicated_Entry_Address,
"strub", "callable");
pragma Machine_Attribute (Rcheck_PE_Explicit_Raise,
"strub", "callable");
pragma Machine_Attribute (Rcheck_PE_Implicit_Return,
"strub", "callable");
pragma Machine_Attribute (Rcheck_PE_Misaligned_Address_Value,
"strub", "callable");
pragma Machine_Attribute (Rcheck_PE_Missing_Return,
"strub", "callable");
pragma Machine_Attribute (Rcheck_PE_Non_Transportable_Actual,
"strub", "callable");
pragma Machine_Attribute (Rcheck_PE_Overlaid_Controlled_Object,
"strub", "callable");
pragma Machine_Attribute (Rcheck_PE_Potentially_Blocking_Operation,
"strub", "callable");
pragma Machine_Attribute (Rcheck_PE_Stream_Operation_Not_Allowed,
"strub", "callable");
pragma Machine_Attribute (Rcheck_PE_Stubbed_Subprogram_Called,
"strub", "callable");
pragma Machine_Attribute (Rcheck_PE_Unchecked_Union_Restriction,
"strub", "callable");
pragma Machine_Attribute (Rcheck_PE_Finalize_Raised_Exception,
"strub", "callable");
pragma Machine_Attribute (Rcheck_SE_Empty_Storage_Pool,
"strub", "callable");
pragma Machine_Attribute (Rcheck_SE_Explicit_Raise,
"strub", "callable");
pragma Machine_Attribute (Rcheck_SE_Infinite_Recursion,
"strub", "callable");
pragma Machine_Attribute (Rcheck_SE_Object_Too_Large,
"strub", "callable");
pragma Machine_Attribute (Rcheck_CE_Access_Check_Ext,
"strub", "callable");
pragma Machine_Attribute (Rcheck_CE_Index_Check_Ext,
"strub", "callable");
pragma Machine_Attribute (Rcheck_CE_Invalid_Data_Ext,
"strub", "callable");
pragma Machine_Attribute (Rcheck_CE_Range_Check_Ext,
"strub", "callable");
---------------------------------------------
-- Reason Strings for Run-Time Check Calls --
---------------------------------------------

View File

@ -184,6 +184,15 @@ private
-- Raise_Exception_Always if it can determine this is the case. The Export
-- allows this routine to be accessed from Pure units.
-- Make these callable from strub contexts.
pragma Machine_Attribute (Raise_Exception_Always,
"strub", "callable");
pragma Machine_Attribute (Raise_Exception,
"strub", "callable");
-- This property should arguably be visible to callers, but let's
-- keep it private for now. In practice, it doesn't matter, since
-- it's only checked in the back end.
procedure Raise_From_Controlled_Operation (X : Exception_Occurrence);
pragma No_Return (Raise_From_Controlled_Operation);
pragma Export

View File

@ -81,4 +81,11 @@ package System.Arith_128 is
-- then Q is the rounded quotient. The remainder R is not affected by the
-- setting of the Round flag.
private
-- Make it callable from strub contexts.
-- There is a matching setting in trans.c,
-- for calls issued by Gigi.
pragma Machine_Attribute (Multiply_With_Ovflo_Check128,
"strub", "callable");
end System.Arith_128;

View File

@ -93,4 +93,11 @@ package System.Arith_64 is
Round : Boolean) renames Double_Divide64;
-- Renamed procedure to preserve compatibility with earlier versions
private
-- Make it callable from strub contexts.
-- There is a matching setting in trans.c,
-- for calls issued by Gigi.
pragma Machine_Attribute (Multiply_With_Ovflo_Check64,
"strub", "callable");
end System.Arith_64;

View File

@ -440,4 +440,9 @@ private
function Get_Stack_Info (Stack : SS_Stack_Ptr) return Stack_Info;
-- Obtain the information attributes of secondary stack Stack
pragma Machine_Attribute (SS_Allocate, "strub", "callable");
pragma Machine_Attribute (SS_Mark, "strub", "callable");
pragma Machine_Attribute (SS_Release, "strub", "callable");
-- Enable these to be called from within strub contexts.
end System.Secondary_Stack;