Comment

Comment by messe

For anybody unfamiliar with this, as I was, this appears to refer to Intel's Indirect Branch Tracking feature[1] (and the equivalent on ARM, BTI). The idea is that an indirect branch can only pass control to a location that starts with an "end branch" instruction. An indirect branch is one that jumps to a location whose value is loaded or computed from either a register or memory address: think calling a function pointer in C.

Without IBT, you'd have this equivalence between C and assembly:

    main() {
        void (*f)();
        f = foo;
        f();
    }

    void foo() { }

    ---

    main:
        movl $foo, %edx
        call *%edx
        ret

    foo:
        ret
If IBT is enabled, the above code triggers an exception because foo doesn't begin with an "end branch" instruction. When IBT is enabled by the compiler, the above code gets assembled as:

    main:
        endbr64 
        movl $foo, %edx
        call *%edx
        ret

    foo:
        endbr64
        ret
Now the compiler inserts endbr64 at the start of each function prologue. The reason for this feature, is to use as a defense in depth against JOP, and COP attacks, as it means that the only "widgets" available to you are entire functions, which can be far harder to exploit and chain.

[1]: https://www.intel.com/content/dam/develop/external/us/en/doc...

parent messe 3 years ago

Discussion

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton