<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/93048>93048</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            Combining -fsanitize=safe-stack with __builtin_longjmp and __builtin_setjmp can result 
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            llvm:codegen,
            llvm
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          smithp35
      </td>
    </tr>
</table>

<pre>
    This issue has been created from security group issue https://bugs.chromium.org/p/llvm/issues/detail?id=60 raised by nmosier@stanford.edu 
[in.txt](https://github.com/llvm/llvm-project/files/15405388/in.txt)
as the security group think that this would be better resolved in the public domain.

The issue description and examples are taken directly from the issue:

LLVM's SafeStack sanitizer (enabled with clang option -fsanitizer=safe-stack) incorrectly and unsafely instruments the llvm.stacksave intrinsic (which returns the current value of the stack pointer, rsp on x86-64) by replacing all calls to that intrinsic with a load of SafeStack's unsafe stack pointer (llvm/lib/CodeGen/SafeStack.cpp:711). This works most of the time, since (1) all dynamic allocations are moved to the unsafe stack and (2) the value returned by llvm.stacksave is generally only ever passed to llvm.stackrestore to implement scoped VLAs. However, one less common use case of llvm.stacksave is to save the current value of the stack pointer in a setjmp buffer. Subsequent longjmp's expect the native stack pointer in the setjmp buffer; however, SafeStack's instrumentation causes the unsafe stack pointer to be stored in the setjmp buffer instead. When a longjmp is executed, this results in the _unsafe_ stack pointer to be loaded into the _native_ stack pointer rsp, effectively switching callstacks from the native safe stack to SafeStack's unsafe stack, which likely contains attacker-controlled data. Thus, an attacker can launch a ROP attack following such a vulnerable longjmp.

Attached is a proof of concept (poc.c) and a malicious input file passed to the miscompiled program. Compile it as follows:
```
clang -fsanitize=safe-stack poc.c
```
This produces an executable `a.out`. Run it under valgrind, redirecting input from in.txt (attached), to observe a return to 0xdeadbeef:
```
valgrind ./a.out < in.txt
``` 

The poc.c file contents as it cannot be attached.
```
#include <stdio.h>

__attribute__((noinline)) void foo(int x) {
  char buf[x];
  fgets(buf, x, stdin);
  void *env[5];
  if (!__builtin_setjmp(env))
    __builtin_longjmp(env, 1);
}

int main() {
  foo(256);
}
```

The security group thought that while there was a problem with using -fsanitize=safe-stack and `__builtin_setjmp` and `__builtin_longjmp` these builtins were not intended to be used as replacements for the libc setjmp and longjmp, they were expected to be used internally for exception handling: https://groups.google.com/g/llvm-dev/c/9QgfdW23K8M . Hence it was better to have this issue in the public domain.

[in.txt](https://github.com/llvm/llvm-project/files/15405549/in.txt)

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJysV1tv47oR_jXMy2AFmbId-8EPudQ9QPeg7dnFOY8GRY4kbihS5cWx--uLIX2Jk3TbAgWCRBE5t2--uUiEoHuLuGGLR7Z4vhMpDs5vwqjjMDWLu9ap4-b7oAPoEBLCIAK0iBakRxFRQefdCAFl8joeofcuTeerMU6BNQ-MbxnftqkPlRy8G3UaK-d7xrcT41tj9iPj2ywSGN8qjEIb1my1Ys3zsgYvdEAF7RHs6IJGz-Z1iMJ2zqsKVQJWP7P6gS0eta3iIbLFM-OrW-O9jkNqK-nGq0X682Xy7gfKyPi20ybbny3m9aJZrcinoo-viwURIA74PtY4aPsCcRCRHgO8umQUtAgtxogePAZn9qhA2yw-pdZoCcqNQtvq5Hv-_X3AE3IKg_R6itpZEFYBHsQ4GQwgPEIUL2hBaY8ymmPBP55FKeI3Kr9-_f1Xxu8DfBMdfotCvkAQVkf9T_TA-AqtaA0qeNVxAGmE7cEVs1-6y0XWPAfR4ZdA8oyvQVvp_Mk8uZcsnZsjaBuiTyPaWKAiiKssFsQeQdvotQ1akunXQcsBPMbkbbktk_doI-yFSQiuK2hnpyenbUTP-BP4MIGzcFgtvyzn5E17BI-TEVLbHoQxIIUxAaIrSbkazUEKME4o0n6BJANUYrg1R26eyaJbxrdPTuGf0TK-vQhXcppY83A_mzG-ruB7oYB_CTC6EM9RRD0iOR-0lUhq6XZ2Vh2tGLWkZycFQV-yPDriTA4Cb50jxBlfcdJAhwWuAmSpk_ewB-jRohfGHMFZcwTco4dJhFBMXO97DNERxxxoYhylEoJ0Eyr4_etDqOAX90rSFIyzCAZDAOnG0VlIAUGKkFP30YXoID_-d5mmahEQMP4YJ2hT16Gv4FtqA_4jkaRxtv8xTjl1eJhQxqzDiqj3n6gqdftGGWseYbiGcsuFK41zQkCKFDB8zMTZQHRU7xk59am1rBGFquCPAW3mYHafcMEDyhRRkRu5gXgMycRwVrQrJnef2iQuZ5snouwKAO8v-zCReuw6lHRujhBedZQDlUwul5ypay8543iNNbqfFAwpL_Vs9Atpl85GoYnKkc7Rf6E33hlqNkpEQZWSAskJe7kEUlgwIllJdfrbX_92OoHOGeNeydmQ8tk-GSJ0a_AM5U0nfSCxgYAJIGDyznXEMumsxClS9UxOVjLXoFUgYBRGS-0SoT6lCDQM3hQIQTLqIN04aYpg8q73YqzgqbwBHUGEk5vh2oOX9ekn_1v667Wx3vRVKB59Jpd7yuSdSpJGgD1RJkfPlrWoXIpsWVfwW7LkSbIKPdVW77XNvPJYxgUheAqQMl3mG8EhToDRrCMeOnBtQL9HEKfOQu_qg0KhWsTu34V4NgoV49vsGLDm6WTonQS8n30ZgQI9sSVPEREoIimsdZEIf3a0-tQ844220iSFZDZEpV01sOZPby3tdiJGr9sUcbdjfMX4yjptjbaYo1_D3mkFnXOMr7SNcKB37P6xiAPIQXiqa7Z4PNCu0VxOuh5jYHxFh_yJBJ-AnLCk-Hot62f8Ae2eLR4Xtzp0B9mp2W7XJm2itrvSSvK03hcXz5cBrrcuHbFce4LZW6vs_vktCBQX7R_Z1E10JW6-WH4u_Q7vS-4-LEUu9UMsE_h1oJTGAT3CqzhVZGtwLBM5Bf2TssjTbll_QGNZfzw6Q7CsyVpAOB0EeCXbRCHqh1aVqm6RRpYijpUFAsvm0jlfthfdynMfJ1sXhKlR47EoLcPnVmFuujaPW9KFB-o6NEgGYZXRtmfNw7vtOMMWqt653uBpT-3PS6rCPeNbyfh2_fe-U3_w5i-rX6GCX5C2CR0zqqd1MzoYypi9rOz_cfH8v67Oi_n64-p8pzaNWjdrcYeb2f1s2axny3p2N2yWvOlWslY1rvj9GrsZrjqueIerer6UOLvTG17zeb3gfLbgy_msmuGirZu1aJHPajmfs3mNo9CmyiuH8_1djnqzbur56s6IFk3IHzecZ--bB-kU9rTFccafzq85p68fv8mh0bcKm9dGhxiueqOOBjdPbmy1_RllM6s_sDJT6D2N88QrAx_ukjeb_xn7y3dTiXe_4f8KAAD__xFcovs">