PING [Patch][Middle-end]Add -fzero-call-used-regs=[skip|used-gpr|all-gpr|used|all]

Rodriguez Bahena, Victor victor.rodriguez.bahena@intel.com
Mon Aug 24 14:36:27 GMT 2020



-----Original Message-----
From: Segher Boessenkool <segher@kernel.crashing.org>
Date: Wednesday, August 19, 2020 at 5:58 PM
To: Qing Zhao <QING.ZHAO@ORACLE.COM>
Cc: Richard Biener <richard.guenther@gmail.com>, Jeff Law <law@redhat.com>, Uros Bizjak <ubizjak@gmail.com>, "H. J. Lu" <hjl.tools@gmail.com>, Jakub Jelinek <jakub@redhat.com>, GCC Patches <gcc-patches@gcc.gnu.org>, Kees Cook <keescook@chromium.org>, "Rodriguez Bahena, Victor" <victor.rodriguez.bahena@intel.com>
Subject: Re: PING [Patch][Middle-end]Add -fzero-call-used-regs=[skip|used-gpr|all-gpr|used|all]

    Hi!

    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 

https://github.com/clearlinux-pkgs/gettext/blob/master/gettext.spec#L138

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
    > overhead. 

    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

Regards

Victor Rodriguez



    Segher



More information about the Gcc-patches mailing list