Overview

The stack protection feature in LLVM's Arm backend can be rendered ineffective when the stack protector slot is re-allocated so that is appears after the local variables that it is meant to protect, leaving the function potentially vulnerable to a stack-based buffer overflow.

Description

The stack protection feature provided in the LLVM Arm backend is an optional mitigating feature used to protect against buffer overflows. It works by adding a cookie value between local variables and the stack frame return address. The compiler stores this value in memory and checks the cookie with the LocalStackSlotAllocation function to ensure that it has not changed or been overwritten. If the value has changed, then the function will terminate. Since it currently pre-allocates the stack protector before the local variables in the stack, it's possible that a new stack protector can be allocated later in the process. If that happens, it leaves the stack protection ineffective as the new stack protector slot appears after the local variables that it is meant to protect. Additionally, it is also possible for the stack cookie pointer to spill to the stack and potentially be overwritten. This could happen in an area on the stack before the stack protector slot, rendering it ineffective.

Impact

When the stack protection feature is rendered ineffective, it leaves the function vulnerable to stack-based buffer overflows. It is possible that the return address could be overwritten due to a local buffer overflow and is not caught when the cookie is checked at the end. It is also possible that the cookie itself could be overwritten since it resides on the stack, causing an unintended value to pass the check.

Solution

Apply an Update

Apply the latest updates from LLVM and Arm. Both of LLVM's commits can be found here and here.

Acknowledgements

Thanks to Jeffrey Crowell and Will Estes of Apple for reporting this vulnerability.

This document was written by Madison Oliver.