Bill Wendling via llvm-dev
2020-Aug-06 23:12 UTC
[llvm-dev] [RFC] Zeroing Caller Saved Regs
[This feature addresses https://bugs.llvm.org/show_bug.cgi?id=37880 and https://github.com/KSPP/linux/issues/84.] Clang has been ramping up its support of the Linux kernel. We recently added "asm goto with outputs", a long requested feature. We want to continue building our relationship with the Linux community. KSPP is a project to improve security in the Linux kernel, through both kernel changes and compiler features. One compiler feature they want is the ability to zero out caller-saved registers on function return as a defense against stale register contents being used as a side-channel or speculation path. The option will be "opt-in" for each target. Targets that don't support the flag should probably emit a warning or error. Our proposal for the feature is modeled off of H. J. Lu's description[1] (copied with some modifications): ``` Add -mzero-caller-saved-regs=[skip|used-gpr|all-gpr|used|all] command-line option and zero_caller_saved_regs function attributes: * Don't zero caller-saved registers upon function return (default): -mzero-caller-saved-regs=skip zero_caller_saved_regs("skip") * Zero used caller-saved integer registers upon function return: -mzero-caller-saved-regs=used-gpr zero_caller_saved_regs("used-gpr") * Zero all integer registers upon function return: -mzero-caller-saved-regs=all-gpr zero_caller_saved_regs("all-gpr") * Zero used caller-saved integer and vector registers upon function return: -mzero-caller-saved-regs=used zero_caller_saved_regs("used") * Zero all caller-saved integer and vector registers upon function return: -mzero-caller-saved-regs=all zero_caller_saved_regs("all") ``` -bw [1] https://github.com/clearlinux-pkgs/gcc/blob/master/0001-x86-Add-mzero-caller.patch
David Chisnall via llvm-dev
2020-Aug-07 08:18 UTC
[llvm-dev] [RFC] Zeroing Caller Saved Regs
Hi Bill, The thing missing from the RFC, though tangentially referenced in a couple of the links, is the threat model for this. We’ve looked in the past (and had a paper at EuroS&P a few years ago) at the ways in which the compiler can leak secrets that the C abstract machine believes are erased but can be found via a stack memory safety gadget. Fully addressing this requires zeroing spill slots and may also require spilling temporary registers across calls rather than placing values in callee-save registers (though if *all* code is compiled defensively, then the callee can be trusted to zero spill slots for these). It appears as if this proposal is to address a weaker security model: leaking secrets via transient execution vulnerabilities. As such, it is not concerned with secrets spilled to the stack or leaked from the caller to callee in callee-save registers. The latter almost makes sense. These registers are normally spilled unconditionally on entry to a function if they are used. The presence of shrink wrapping invalidates this assumption though, and there are transient execution paths through a function that uses shrink wrapping that will leak secrets from the caller. I would therefore expect that this option would disable shrink wrapping. The former makes less sense to me. Anything that loads from the stack and does something with the result is a potential gadget for leaking secrets spilled to the stack by a prior call via transient execution side channels and, even in the presence of this defence, it seems likely that there are a large number of useful gadgets remaining. I think it would be useful for the discussion to have a clear threat model that this intends to defend against and a rough analysis of the security benefits that this is believed to bring. David> On 7 Aug 2020, at 00:12, Bill Wendling via llvm-dev <llvm-dev at lists.llvm.org> wrote: > > [This feature addresses https://bugs.llvm.org/show_bug.cgi?id=37880 > and https://github.com/KSPP/linux/issues/84.] > > Clang has been ramping up its support of the Linux kernel. We recently > added "asm goto with outputs", a long requested feature. We want to > continue building our relationship with the Linux community. > > KSPP is a project to improve security in the Linux kernel, through > both kernel changes and compiler features. One compiler feature they > want is the ability to zero out caller-saved registers on function > return as a defense against stale register contents being used as a > side-channel or speculation path. > > The option will be "opt-in" for each target. Targets that don't > support the flag should probably emit a warning or error. > > Our proposal for the feature is modeled off of H. J. Lu's > description[1] (copied with some modifications): > > ``` > Add -mzero-caller-saved-regs=[skip|used-gpr|all-gpr|used|all] > command-line option and zero_caller_saved_regs function attributes: > > * Don't zero caller-saved registers upon function return (default): > > -mzero-caller-saved-regs=skip > zero_caller_saved_regs("skip") > > * Zero used caller-saved integer registers upon function return: > > -mzero-caller-saved-regs=used-gpr > zero_caller_saved_regs("used-gpr") > > * Zero all integer registers upon function return: > > -mzero-caller-saved-regs=all-gpr > zero_caller_saved_regs("all-gpr") > > * Zero used caller-saved integer and vector registers upon function return: > > -mzero-caller-saved-regs=used > zero_caller_saved_regs("used") > > * Zero all caller-saved integer and vector registers upon function return: > > -mzero-caller-saved-regs=all > zero_caller_saved_regs("all") > ``` > > -bw > > [1] https://github.com/clearlinux-pkgs/gcc/blob/master/0001-x86-Add-mzero-caller.patch > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >
On Fri, Aug 7, 2020 at 1:18 AM David Chisnall <David.Chisnall at cl.cam.ac.uk> wrote:> I think it would be useful for the discussion to have a clear threat model that this intends to defend against and a rough analysis of the security benefits that this is believed to bring.I view this as being even more about a ROP defense. Dealing with spill slots is, IMO, a separate issue, more related to the auto-var-init work (though that would be stack erasure on function exit, rather than entry, which addresses a different set of issues). I think this thread from the GCC list has some good details on the ROP defense: https://gcc.gnu.org/pipermail/gcc-patches/2020-August/551607.html -- Kees Cook
James Courtier-Dutton via llvm-dev
2020-Aug-10 12:07 UTC
[llvm-dev] [cfe-dev] [RFC] Zeroing Caller Saved Regs
On Fri, 7 Aug 2020 at 00:12, Bill Wendling via cfe-dev <cfe-dev at lists.llvm.org> wrote:> > [This feature addresses https://bugs.llvm.org/show_bug.cgi?id=37880 > and https://github.com/KSPP/linux/issues/84.] > > Clang has been ramping up its support of the Linux kernel. We recently > added "asm goto with outputs", a long requested feature. We want to > continue building our relationship with the Linux community. > > KSPP is a project to improve security in the Linux kernel, through > both kernel changes and compiler features. One compiler feature they > want is the ability to zero out caller-saved registers on function > return as a defense against stale register contents being used as a > side-channel or speculation path. > > The option will be "opt-in" for each target. Targets that don't > support the flag should probably emit a warning or error. > > Our proposal for the feature is modeled off of H. J. Lu's > description[1] (copied with some modifications): > > ``` > Add -mzero-caller-saved-regs=[skip|used-gpr|all-gpr|used|all] > command-line option and zero_caller_saved_regs function attributes: > > * Don't zero caller-saved registers upon function return (default): > > -mzero-caller-saved-regs=skip > zero_caller_saved_regs("skip") > > * Zero used caller-saved integer registers upon function return: > > -mzero-caller-saved-regs=used-gpr > zero_caller_saved_regs("used-gpr") > > * Zero all integer registers upon function return: > > -mzero-caller-saved-regs=all-gpr > zero_caller_saved_regs("all-gpr") > > * Zero used caller-saved integer and vector registers upon function return: > > -mzero-caller-saved-regs=used > zero_caller_saved_regs("used") > > * Zero all caller-saved integer and vector registers upon function return: > > -mzero-caller-saved-regs=all > zero_caller_saved_regs("all") > ``` > > -bw > > [1] https://github.com/clearlinux-pkgs/gcc/blob/master/0001-x86-Add-mzero-caller.patchWhile the above might have a significant impact on performance, adding this sort of security controls at the C and C++ level would be very helpful. e.g. int function_containing_secret() { int secret = 12345; /* do some work with the secret */ secret = 0; return 0; } Now, with compiler optimisations, the last "secret = 0;" will get optimised out, as there are no uses of it. Having some way to enforce that the "secret = 0" remains, and at assembler level, which every registers and temporary stack values it was stored in are wiped could be a useful addition. I don't quite understand how the zero-all-values helps in the ROP case, because the zero-all-value part can be bypassed by the malicious user. Kind Regards James
James Y Knight via llvm-dev
2020-Aug-10 12:14 UTC
[llvm-dev] [cfe-dev] [RFC] Zeroing Caller Saved Regs
The presence of those 4 different zeroing modes feels to me like this gcc feature was added speculatively -- with the intent of gathering some data on the various tradeoffs and impacts of the different options, rather than with the expectation that it's necessarily going to be actually useful. Has that investigation already been done? If so, which of the modes is useful, and for what? On Fri, Aug 7, 2020 at 4:18 AM David Chisnall via cfe-dev < cfe-dev at lists.llvm.org> wrote:> Hi Bill, > > The thing missing from the RFC, though tangentially referenced in a couple > of the links, is the threat model for this. > > We’ve looked in the past (and had a paper at EuroS&P a few years ago) at > the ways in which the compiler can leak secrets that the C abstract machine > believes are erased but can be found via a stack memory safety gadget. > Fully addressing this requires zeroing spill slots and may also require > spilling temporary registers across calls rather than placing values in > callee-save registers (though if *all* code is compiled defensively, then > the callee can be trusted to zero spill slots for these). > > It appears as if this proposal is to address a weaker security model: > leaking secrets via transient execution vulnerabilities. As such, it is > not concerned with secrets spilled to the stack or leaked from the caller > to callee in callee-save registers. > > The latter almost makes sense. These registers are normally spilled > unconditionally on entry to a function if they are used. The presence of > shrink wrapping invalidates this assumption though, and there are transient > execution paths through a function that uses shrink wrapping that will leak > secrets from the caller. I would therefore expect that this option would > disable shrink wrapping. > > The former makes less sense to me. Anything that loads from the stack and > does something with the result is a potential gadget for leaking secrets > spilled to the stack by a prior call via transient execution side channels > and, even in the presence of this defence, it seems likely that there are a > large number of useful gadgets remaining. > > I think it would be useful for the discussion to have a clear threat model > that this intends to defend against and a rough analysis of the security > benefits that this is believed to bring. > > David > > > On 7 Aug 2020, at 00:12, Bill Wendling via llvm-dev < > llvm-dev at lists.llvm.org> wrote: > > > > [This feature addresses https://bugs.llvm.org/show_bug.cgi?id=37880 > > and https://github.com/KSPP/linux/issues/84.] > > > > Clang has been ramping up its support of the Linux kernel. We recently > > added "asm goto with outputs", a long requested feature. We want to > > continue building our relationship with the Linux community. > > > > KSPP is a project to improve security in the Linux kernel, through > > both kernel changes and compiler features. One compiler feature they > > want is the ability to zero out caller-saved registers on function > > return as a defense against stale register contents being used as a > > side-channel or speculation path. > > > > The option will be "opt-in" for each target. Targets that don't > > support the flag should probably emit a warning or error. > > > > Our proposal for the feature is modeled off of H. J. Lu's > > description[1] (copied with some modifications): > > > > ``` > > Add -mzero-caller-saved-regs=[skip|used-gpr|all-gpr|used|all] > > command-line option and zero_caller_saved_regs function attributes: > > > > * Don't zero caller-saved registers upon function return (default): > > > > -mzero-caller-saved-regs=skip > > zero_caller_saved_regs("skip") > > > > * Zero used caller-saved integer registers upon function return: > > > > -mzero-caller-saved-regs=used-gpr > > zero_caller_saved_regs("used-gpr") > > > > * Zero all integer registers upon function return: > > > > -mzero-caller-saved-regs=all-gpr > > zero_caller_saved_regs("all-gpr") > > > > * Zero used caller-saved integer and vector registers upon function > return: > > > > -mzero-caller-saved-regs=used > > zero_caller_saved_regs("used") > > > > * Zero all caller-saved integer and vector registers upon function > return: > > > > -mzero-caller-saved-regs=all > > zero_caller_saved_regs("all") > > ``` > > > > -bw > > > > [1] > https://github.com/clearlinux-pkgs/gcc/blob/master/0001-x86-Add-mzero-caller.patch > > _______________________________________________ > > LLVM Developers mailing list > > llvm-dev at lists.llvm.org > > https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev > > > > _______________________________________________ > cfe-dev mailing list > cfe-dev at lists.llvm.org > https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200810/e4827e59/attachment.html>