PING [Patch][Middle-end]Add -fzero-call-used-regs=[skip|used-gpr|all-gpr|used|all]
Rodriguez Bahena, Victor
Mon Aug 24 14:36:27 GMT 2020
From: Segher Boessenkool <email@example.com>
Date: Wednesday, August 19, 2020 at 5:58 PM
To: Qing Zhao <QING.ZHAO@ORACLE.COM>
Cc: Richard Biener <firstname.lastname@example.org>, Jeff Law <email@example.com>, Uros Bizjak <firstname.lastname@example.org>, "H. J. Lu" <email@example.com>, Jakub Jelinek <firstname.lastname@example.org>, GCC Patches <email@example.com>, Kees Cook <firstname.lastname@example.org>, "Rodriguez Bahena, Victor" <email@example.com>
Subject: Re: PING [Patch][Middle-end]Add -fzero-call-used-regs=[skip|used-gpr|all-gpr|used|all]
On Wed, Aug 19, 2020 at 03:05:36PM -0500, Qing Zhao wrote:
> So, cleaning the scratch registers that are used to pass parameters at return instructions should
> effectively mitigate ROP attack.
But that is *very* expensive, in general. Instead of doing just a
return instruction (which effectively costs 0 cycles, and is just one
insn), you now have to zero all call-clobbered register at every return
(typically many returns per function, and you are talking 10+ registers
even if only considering the simple integer registers).
Numbers on how expensive this is (for what arch, in code size and in
execution time) would be useful. If it is so expensive that no one will
use it, it helps security at most none at all :-(
It is used in some operating systems and packages such as
export CFLAGS="$CFLAGS -O3 -ffat-lto-objects -flto=4 -fstack-protector-strong -mzero-caller-saved-regs=used "
There is no record that this flag creates a considerable penalty in execution time.
> Q1. Which registers should be set to zeros at the return of the function?
> A. the caller-saved, i.e, call-used, or call-clobbered registers.
> For ROP mitigation purpose, only the call-used registers that pass
> parameters need to be zeroed.
> For register erasure purpose, all the call-used registers might need to
> be zeroed. we can provide multiple levels to user for controling the runtime
The call-clobbered regs are the only ones you *can* touch. That does
not mean you should clear them all (it doesn't help much at all in some
cases). Only the backend knows.
> So, from both run-time performance and code-size aspects, setting the
> registers to zero is a better approach.
From a security perspective, this isn't clear though. But that is a lot
of extra research ;-)
The paper from IEEE provide a clear example on how to use mzero-caller
I think the patch has a solid background and there are multiple projects that highlight the importance of cleaning as technique to prevent security issues in ROP attacks
More information about the Gcc-patches