The old call model was small enough to fit in two instructions:
call target
retA call transferred control. A return transferred it back. If the arguments, stack, and return address were plausible enough, execution continued.
That model is now incomplete.
The claim of the essay is that calls and returns are no longer just conventions. On hardened platforms, parts of the call protocol may be checked by hardware, the kernel, the loader, compiler instrumentation, or the runtime. The call boundary can carry security state as well as value state.
The concrete artifact is a shadow stack. In an Intel CET shadow-stack model, a CALL records the return address on both the normal stack and a protected shadow stack. On RET, the processor compares the two. A mismatch is not just a bad return. It is a control-protection failure.
That changes what it means to preserve call state. A hand-written stub or trampoline may satisfy the old visible rule - put a plausible return address on the normal stack - and still violate the hardened rule: the normal return address and the shadow-stack return address must agree.
Other mechanisms check different edges. Branch Target Identification can require indirect branch targets to land on approved landing instructions. Pointer authentication can make a code pointer or return address more than an integer-shaped address. Windows Control Flow Guard can turn indirect-call validity into runtime metadata and checks. These mechanisms are not interchangeable, but they all pressure the same old assumption: a control transfer is not just an address.
The boundary is important. This is not a bypass guide, and it is not a claim that every modern CPU enforces every call. Feature availability, operating-system support, binary opt-in, compiler settings, and platform ABI choices all matter. The safer claim is narrower: modern platforms increasingly enforce pieces of the call and return protocol.
That matters for JITs, hooks, plugins, instrumentation, trampolines, and hand-written assembly. The old checklist asked whether the code preserved arguments, nonvolatile registers, stack alignment, and return behavior. The newer checklist also asks whether unwinders can explain the frame and whether the security machinery accepts the transfer.
A call is still a call. It just has more witnesses.
Read the full essay on lospino.so: Calls Are Now a Security Surface
Original essay published on lospino.so on 2026-06-10.