pub enum Control {
None,
Branch,
Return,
Full,
Check,
}Expand description
Which control flow transfers are checked, which is what -fcf-protection= asks.
Two mechanisms and one flag, because the hardware turns them on together and a program built for one and not the other is a program with a hole in whichever half was left out. The forward edge is an indirect call or jump, and it is checked by a landing pad at every address one is allowed to arrive at, so a corrupted function pointer reaches somewhere somebody meant rather than any byte of the program. The backward edge is a return, and it is checked against a second copy of the return address the program cannot write to, which needs no instructions at all: the machine keeps the copy and the loader turns it on.
Which is why the marker matters as much as the code. An object says in a note which halves it was built for, the linker takes the intersection over every input, and the loader turns on what survives. One object built without the note is enough to turn the whole program’s protection off, so the note goes in even for a mode that changes no instruction.
Variants§
None
-fcf-protection=none and -fno-cf-protection, and what a command line that says nothing
gets. gcc’s own default is the same on the targets this compiler has a back end for.
Branch
-fcf-protection=branch. The forward edge alone: a landing pad at every function, and a
note that asks for the check on indirect transfers and not on returns.
Return
-fcf-protection=return. The backward edge alone, which is the note and nothing else,
since the copy of the return address is the machine’s own and no instruction maintains it.
Full
-fcf-protection=full, and what the bare -fcf-protection means. Both halves.
Check
-fcf-protection=check. Asks that the compilation be checked for compatibility with the
mode rather than built in it, so nothing is instrumented and no note is written, which is
exactly what gcc emits for it.
Implementations§
Source§impl Control
impl Control
Sourcepub const fn ret(self) -> bool
pub const fn ret(self) -> bool
Whether returns are asked to be checked against the machine’s own copy.
Sourcepub const fn any(self) -> bool
pub const fn any(self) -> bool
Whether anything at all is asked for, which is what decides whether the file says what it was built for.
False for the two modes that build nothing. Control::None asks for nothing and
Control::Check asks that the compilation be looked at rather than changed, and gcc
writes no note for either.