RISC-V: Add support for TLS stack protector canary access
gcc/ * config/riscv/riscv-opts.h (stack_protector_guard): New enum. * config/riscv/riscv.c (riscv_option_override): Handle the new options. * config/riscv/riscv.md (stack_protect_set): New pattern to handle flexible stack protector guard settings. (stack_protect_set_<mode>): Ditto. (stack_protect_test): Ditto. (stack_protect_test_<mode>): Ditto. * config/riscv/riscv.opt (mstack-protector-guard=, mstack-protector-guard-reg=, mstack-protector-guard-offset=): New options. * doc/invoke.texi (Option Summary) [RISC-V Options]: Add -mstack-protector-guard=, -mstack-protector-guard-reg=, and -mstack-protector-guard-offset=. (RISC-V Options): Ditto. Signed-off-by: cooper <cooper.qu@linux.alibaba.com> Signed-off-by: Guo Ren <guoren@linux.alibaba.com>
This commit is contained in:
parent
febd7c43bc
commit
c931e8d5a9
|
@ -51,4 +51,10 @@ enum riscv_align_data {
|
||||||
riscv_align_data_type_natural
|
riscv_align_data_type_natural
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Where to get the canary for the stack protector. */
|
||||||
|
enum stack_protector_guard {
|
||||||
|
SSP_TLS, /* per-thread canary in TLS block */
|
||||||
|
SSP_GLOBAL /* global canary */
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* ! GCC_RISCV_OPTS_H */
|
#endif /* ! GCC_RISCV_OPTS_H */
|
||||||
|
|
|
@ -4775,6 +4775,53 @@ riscv_option_override (void)
|
||||||
" [%<-mriscv-attribute%>]");
|
" [%<-mriscv-attribute%>]");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (riscv_stack_protector_guard == SSP_GLOBAL
|
||||||
|
&& global_options_set.x_riscv_stack_protector_guard_offset_str)
|
||||||
|
{
|
||||||
|
error ("incompatible options %<-mstack-protector-guard=global%> and "
|
||||||
|
"%<-mstack-protector-guard-offset=%s%>",
|
||||||
|
riscv_stack_protector_guard_offset_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (riscv_stack_protector_guard == SSP_TLS
|
||||||
|
&& !(global_options_set.x_riscv_stack_protector_guard_offset_str
|
||||||
|
&& global_options_set.x_riscv_stack_protector_guard_reg_str))
|
||||||
|
{
|
||||||
|
error ("both %<-mstack-protector-guard-offset%> and "
|
||||||
|
"%<-mstack-protector-guard-reg%> must be used "
|
||||||
|
"with %<-mstack-protector-guard=sysreg%>");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (global_options_set.x_riscv_stack_protector_guard_reg_str)
|
||||||
|
{
|
||||||
|
const char *str = riscv_stack_protector_guard_reg_str;
|
||||||
|
int reg = decode_reg_name (str);
|
||||||
|
|
||||||
|
if (!IN_RANGE (reg, GP_REG_FIRST + 1, GP_REG_LAST))
|
||||||
|
error ("%qs is not a valid base register in %qs", str,
|
||||||
|
"-mstack-protector-guard-reg=");
|
||||||
|
|
||||||
|
riscv_stack_protector_guard_reg = reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (global_options_set.x_riscv_stack_protector_guard_offset_str)
|
||||||
|
{
|
||||||
|
char *end;
|
||||||
|
const char *str = riscv_stack_protector_guard_offset_str;
|
||||||
|
errno = 0;
|
||||||
|
long offs = strtol (riscv_stack_protector_guard_offset_str, &end, 0);
|
||||||
|
|
||||||
|
if (!*str || *end || errno)
|
||||||
|
error ("%qs is not a valid number in %qs", str,
|
||||||
|
"-mstack-protector-guard-offset=");
|
||||||
|
|
||||||
|
if (!SMALL_OPERAND (offs))
|
||||||
|
error ("%qs is not a valid offset in %qs", str,
|
||||||
|
"-mstack-protector-guard-offset=");
|
||||||
|
|
||||||
|
riscv_stack_protector_guard_offset = offs;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Implement TARGET_CONDITIONAL_REGISTER_USAGE. */
|
/* Implement TARGET_CONDITIONAL_REGISTER_USAGE. */
|
||||||
|
|
|
@ -65,6 +65,10 @@
|
||||||
UNSPECV_BLOCKAGE
|
UNSPECV_BLOCKAGE
|
||||||
UNSPECV_FENCE
|
UNSPECV_FENCE
|
||||||
UNSPECV_FENCE_I
|
UNSPECV_FENCE_I
|
||||||
|
|
||||||
|
;; Stack Smash Protector
|
||||||
|
UNSPEC_SSP_SET
|
||||||
|
UNSPEC_SSP_TEST
|
||||||
])
|
])
|
||||||
|
|
||||||
(define_constants
|
(define_constants
|
||||||
|
@ -2523,6 +2527,82 @@
|
||||||
""
|
""
|
||||||
{})
|
{})
|
||||||
|
|
||||||
|
;; Named patterns for stack smashing protection.
|
||||||
|
|
||||||
|
(define_expand "stack_protect_set"
|
||||||
|
[(match_operand 0 "memory_operand")
|
||||||
|
(match_operand 1 "memory_operand")]
|
||||||
|
""
|
||||||
|
{
|
||||||
|
machine_mode mode = GET_MODE (operands[0]);
|
||||||
|
if (riscv_stack_protector_guard == SSP_TLS)
|
||||||
|
{
|
||||||
|
rtx reg = gen_rtx_REG (Pmode, riscv_stack_protector_guard_reg);
|
||||||
|
rtx offset = GEN_INT (riscv_stack_protector_guard_offset);
|
||||||
|
rtx addr = gen_rtx_PLUS (Pmode, reg, offset);
|
||||||
|
operands[1] = gen_rtx_MEM (Pmode, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit_insn ((mode == DImode
|
||||||
|
? gen_stack_protect_set_di
|
||||||
|
: gen_stack_protect_set_si) (operands[0], operands[1]));
|
||||||
|
DONE;
|
||||||
|
})
|
||||||
|
|
||||||
|
;; DO NOT SPLIT THIS PATTERN. It is important for security reasons that the
|
||||||
|
;; canary value does not live beyond the life of this sequence.
|
||||||
|
(define_insn "stack_protect_set_<mode>"
|
||||||
|
[(set (match_operand:GPR 0 "memory_operand" "=m")
|
||||||
|
(unspec:GPR [(match_operand:GPR 1 "memory_operand" "m")]
|
||||||
|
UNSPEC_SSP_SET))
|
||||||
|
(set (match_scratch:GPR 2 "=&r") (const_int 0))]
|
||||||
|
""
|
||||||
|
"<load>\\t%2, %1\;<store>\\t%2, %0\;li\t%2, 0"
|
||||||
|
[(set_attr "length" "12")])
|
||||||
|
|
||||||
|
(define_expand "stack_protect_test"
|
||||||
|
[(match_operand 0 "memory_operand")
|
||||||
|
(match_operand 1 "memory_operand")
|
||||||
|
(match_operand 2)]
|
||||||
|
""
|
||||||
|
{
|
||||||
|
rtx result;
|
||||||
|
machine_mode mode = GET_MODE (operands[0]);
|
||||||
|
|
||||||
|
result = gen_reg_rtx(mode);
|
||||||
|
if (riscv_stack_protector_guard == SSP_TLS)
|
||||||
|
{
|
||||||
|
rtx reg = gen_rtx_REG (Pmode, riscv_stack_protector_guard_reg);
|
||||||
|
rtx offset = GEN_INT (riscv_stack_protector_guard_offset);
|
||||||
|
rtx addr = gen_rtx_PLUS (Pmode, reg, offset);
|
||||||
|
operands[1] = gen_rtx_MEM (Pmode, addr);
|
||||||
|
}
|
||||||
|
emit_insn ((mode == DImode
|
||||||
|
? gen_stack_protect_test_di
|
||||||
|
: gen_stack_protect_test_si) (result,
|
||||||
|
operands[0],
|
||||||
|
operands[1]));
|
||||||
|
|
||||||
|
if (mode == DImode)
|
||||||
|
emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
|
||||||
|
result, const0_rtx, operands[2]));
|
||||||
|
else
|
||||||
|
emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
|
||||||
|
result, const0_rtx, operands[2]));
|
||||||
|
|
||||||
|
DONE;
|
||||||
|
})
|
||||||
|
|
||||||
|
(define_insn "stack_protect_test_<mode>"
|
||||||
|
[(set (match_operand:GPR 0 "register_operand" "=r")
|
||||||
|
(unspec:GPR [(match_operand:GPR 1 "memory_operand" "m")
|
||||||
|
(match_operand:GPR 2 "memory_operand" "m")]
|
||||||
|
UNSPEC_SSP_TEST))
|
||||||
|
(clobber (match_scratch:GPR 3 "=&r"))]
|
||||||
|
""
|
||||||
|
"<load>\t%3, %1\;<load>\t%0, %2\;xor\t%0, %3, %0\;li\t%3, 0"
|
||||||
|
[(set_attr "length" "12")])
|
||||||
|
|
||||||
(include "sync.md")
|
(include "sync.md")
|
||||||
(include "peephole.md")
|
(include "peephole.md")
|
||||||
(include "pic.md")
|
(include "pic.md")
|
||||||
|
|
|
@ -151,3 +151,31 @@ Enum(riscv_align_data) String(xlen) Value(riscv_align_data_type_xlen)
|
||||||
|
|
||||||
EnumValue
|
EnumValue
|
||||||
Enum(riscv_align_data) String(natural) Value(riscv_align_data_type_natural)
|
Enum(riscv_align_data) String(natural) Value(riscv_align_data_type_natural)
|
||||||
|
|
||||||
|
mstack-protector-guard=
|
||||||
|
Target RejectNegative Joined Enum(stack_protector_guard) Var(riscv_stack_protector_guard) Init(SSP_GLOBAL)
|
||||||
|
Use given stack-protector guard.
|
||||||
|
|
||||||
|
Enum
|
||||||
|
Name(stack_protector_guard) Type(enum stack_protector_guard)
|
||||||
|
Valid arguments to -mstack-protector-guard=:
|
||||||
|
|
||||||
|
EnumValue
|
||||||
|
Enum(stack_protector_guard) String(tls) Value(SSP_TLS)
|
||||||
|
|
||||||
|
EnumValue
|
||||||
|
Enum(stack_protector_guard) String(global) Value(SSP_GLOBAL)
|
||||||
|
|
||||||
|
mstack-protector-guard-reg=
|
||||||
|
Target RejectNegative Joined Var(riscv_stack_protector_guard_reg_str)
|
||||||
|
Use the given base register for addressing the stack-protector guard.
|
||||||
|
|
||||||
|
TargetVariable
|
||||||
|
int riscv_stack_protector_guard_reg = 0
|
||||||
|
|
||||||
|
mstack-protector-guard-offset=
|
||||||
|
Target RejectNegative Joined Integer Var(riscv_stack_protector_guard_offset_str)
|
||||||
|
Use the given offset for addressing the stack-protector guard.
|
||||||
|
|
||||||
|
TargetVariable
|
||||||
|
long riscv_stack_protector_guard_offset = 0
|
||||||
|
|
|
@ -1140,7 +1140,9 @@ See RS/6000 and PowerPC Options.
|
||||||
-mexplicit-relocs -mno-explicit-relocs @gol
|
-mexplicit-relocs -mno-explicit-relocs @gol
|
||||||
-mrelax -mno-relax @gol
|
-mrelax -mno-relax @gol
|
||||||
-mriscv-attribute -mmo-riscv-attribute @gol
|
-mriscv-attribute -mmo-riscv-attribute @gol
|
||||||
-malign-data=@var{type}}
|
-malign-data=@var{type} @gol
|
||||||
|
+-mstack-protector-guard=@var{guard} -mstack-protector-guard-reg=@var{reg} @gol
|
||||||
|
+-mstack-protector-guard-offset=@var{offset}}
|
||||||
|
|
||||||
@emph{RL78 Options}
|
@emph{RL78 Options}
|
||||||
@gccoptlist{-msim -mmul=none -mmul=g13 -mmul=g14 -mallregs @gol
|
@gccoptlist{-msim -mmul=none -mmul=g13 -mmul=g14 -mallregs @gol
|
||||||
|
@ -25795,6 +25797,24 @@ Control how GCC aligns variables and constants of array, structure, or union
|
||||||
types. Supported values for @var{type} are @samp{xlen} which uses x register
|
types. Supported values for @var{type} are @samp{xlen} which uses x register
|
||||||
width as the alignment value, and @samp{natural} which uses natural alignment.
|
width as the alignment value, and @samp{natural} which uses natural alignment.
|
||||||
@samp{xlen} is the default.
|
@samp{xlen} is the default.
|
||||||
|
|
||||||
|
@item -mstack-protector-guard=@var{guard}
|
||||||
|
@itemx -mstack-protector-guard-reg=@var{reg}
|
||||||
|
@itemx -mstack-protector-guard-offset=@var{offset}
|
||||||
|
@opindex mstack-protector-guard
|
||||||
|
@opindex mstack-protector-guard-reg
|
||||||
|
@opindex mstack-protector-guard-offset
|
||||||
|
Generate stack protection code using canary at @var{guard}. Supported
|
||||||
|
locations are @samp{global} for a global canary or @samp{tls} for per-thread
|
||||||
|
canary in the TLS block.
|
||||||
|
|
||||||
|
With the latter choice the options
|
||||||
|
@option{-mstack-protector-guard-reg=@var{reg}} and
|
||||||
|
@option{-mstack-protector-guard-offset=@var{offset}} furthermore specify
|
||||||
|
which register to use as base register for reading the canary,
|
||||||
|
and from what offset from that base register. There is no default
|
||||||
|
register or offset as this is entirely for use within the Linux
|
||||||
|
kernel.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@node RL78 Options
|
@node RL78 Options
|
||||||
|
|
Loading…
Reference in New Issue