[llvm-bugs] [Bug 46994] New: Consider adding a hardened version of -fstack-protector that clears registers on function exit.

via llvm-bugs llvm-bugs at lists.llvm.org
Tue Aug 4 12:35:24 PDT 2020


https://bugs.llvm.org/show_bug.cgi?id=46994

            Bug ID: 46994
           Summary: Consider adding a hardened version of
                    -fstack-protector that clears registers on function
                    exit.
           Product: libraries
           Version: trunk
          Hardware: PC
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: Common Code Generator Code
          Assignee: unassignedbugs at nondot.org
          Reporter: smithp352 at googlemail.com
                CC: llvm-bugs at lists.llvm.org

The LLVM implementation of -fstack-protector does not clear registers
that contain the value or address of __stack_chk_guard. There is an opportunity
for an additional hardened implementation of -fstack-protector that clears the
registers, giving a small amount of extra protection at the cost of additional
instructions in every protected function.

The LLVM stack protection feature -fstack-protector uses a global variable
__stack_chk_guard as the canary value. In most implementations it is
initialized to a random value at program startup. If an attacker can obtain
the value of __stack_chk_guard they can overwrite a protected functions return
address without being detected by writing the __stack_chk_guard value to the
canary location.

The value of __stack_chk_guard is present in the global variable
__stack_chk_guard for the runtime of the program. It is present on the stack
for every protected function currently on the call-stack. Finally the value or
address of __stack_chk_guard is present in one or more registers when the
comparison of the canary to the __stack_chk_guard value is made.

A GCC PR https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96191 notes that on
function exit, the GCC AArch64 backend is not clearing the all registers that
contain the canary value. Comment
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96191#c3 implies that GCC
implementations of -fstack-protector must clear registers that contain the
value or address of __stack_chk_guard.

The LLVM implementation of -fstack-protector for all targets does not clear
registers that contain the value or address of __stack_chk_guard. The LLVM
Security Group do not consider this a security vulnerability in the LLVM
implementation but a different design decision made by GCC that eliminates the
risk of the value of __stack_chk_guard leaking via registers at the expense of
the extra instructions needed to clear the registers. LLVM considers the
additional protection is not worth the additional instructions given that
__stack_chk_guard is already likely to be on the stack via a protected
function in the call-stack. There is an opportunity for an additional hardened
stack protection option that does clear the registers.

Assumptions:

The attacker does not have control of the return address and cannot execute
arbitrary ROP gadgets. If they could then there would be little reason to read
__stack_chk_guard as control flow has already been compromised. Any gadget that
leaks the register values must be encountered before the registers are used for
some other purpose.

The compiler does not consider the values left in registers as live. Reading
these values requires assembly, or some kind of undefined behaviour such as a
mismatched function declaration and definition. Encountering code sequences
like this before the registers are reused is unlikely.

Even if registers are cleared. An attacker may still be able to read the value
of the __stack_chk_guard from the stack.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20200804/ee5d5aa3/attachment.html>


More information about the llvm-bugs mailing list