<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - [CFI] Codegen performs argument expansion after CFI check - invalidating CFI."
   href="https://bugs.llvm.org/show_bug.cgi?id=35353">35353</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>[CFI] Codegen performs argument expansion after CFI check - invalidating CFI.
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>LLVM Codegen
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>mitchphillips@outlook.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Clang's codegen is generating code in the following order:
 1. CFI check for vcall.
 2. Evaluation of arguments.
 3. Execution of vcall.

This severely undermines the effectiveness of CFI, as non-sequential control
flow instructions should not be present between the CFI check and the execution
of the protected indirect call/jump.

The most common instance of this issue is when we have a vcall which has at
least one argument provided by a function-returned temporary. Even if the
function which is providing the argument is a direct call, we cannot guarantee
that the register(s) used to make the protected indirect call/jump are not
clobbered through the call. Often, the compiler will save the register(s) used
by the protected call/jump to a scratch register.

This issue affects approximately 6,932 instructions in the Chrome browser
binary, representing 41.8% of all "unexpected unprotected" indirect CF
instructions.

This issue is revealed by llvm-cfi-verify. Please see below for an example:

$ clang++ -flto -fsanitize=cfi -fvisibility=hidden -g a3.cc
$ llvm-cfi-verify a.out
----------------- Begin Instruction -----------------
FAIL_KNOWN_ISSUE 0x40067c:      callq   *%r14 
  0x40067c = /tmp/a3.cc:9:6 (main)
-----------------------------------------------------
Total Indirect CF Instructions: 1
Expected Protected: 0 (0.00%)
Unexpected Protected: 0 (0.00%)
Expected Unprotected: 0 (0.00%)
Unexpected Unprotected (BAD): 1 (100.00%)

$ cat a3.cc
struct A {
  virtual void f(int) {}
};

int x() { return 0; }

int main() {
  A* a = new A();
  a->f(x());  // Should be CFI protected - x() is executed between CFI check
and execution.
}

$ objdump -d a.out
<..snip..>
  40064f:       48 b9 60 07 40 00 00    movabs $0x400760,%rcx
  400656:       00 00 00 
  400659:       48 83 c1 10             add    $0x10,%rcx
  40065d:       48 89 5d e8             mov    %rbx,-0x18(%rbp)
  400661:       48 8b 5d e8             mov    -0x18(%rbp),%rbx
  400665:       48 8b 03                mov    (%rbx),%rax
  400668:       48 39 c8                cmp    %rcx,%rax
  40066b:       74 02                   je     40066f <main+0x4f>  # cfi check
branch
  40066d:       0f 0b                   ud2                        #
cfi-failure
  40066f:       4c 8b 30                mov    (%rax),%r14
  400672:       e8 99 ff ff ff          callq  400610 <_Z1xv>      # direct
call, can clobber %r14
  400677:       48 89 df                mov    %rbx,%rdi
  40067a:       31 f6                   xor    %esi,%esi
  40067c:       41 ff d6                callq  *%r14               #
instruction that should be protected
<..snip..></pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>