[RFC] Objtool toolchain proposal: -fannotate-{jump-table,noreturn}

Indu Bhagat indu.bhagat at oracle.com
Tue Sep 13 15:51:44 PDT 2022


Hi Josh,

On 9/9/22 11:07, Josh Poimboeuf wrote:
> Hi,
> 
> Here's a preview of what I'm planning to discuss at the LPC toolchains
> microconference.  Feel free to start the discussion early :-)
> 
> This is a proposal for some new minor GCC/Clang features which would
> help objtool greatly.
> 
> 
> Background
> ----------
> 
> Objtool is a kernel-specific tool which reverse engineers the control
> flow graph (CFG) of compiled objects.  It then performs various
> validations, annotations, and modifications, mostly with the goal of
> improving robustness and security of the kernel.
> 
> Objtool features which use the CFG include include:
> validation/generation of unwinding metadata; validation of Intel SMAP
> rules; and validation of kernel "noinstr" rules (preventing compiler
> instrumentation in certain critical sections).
> 
> In general it's not feasible for the traditional toolchain to do any of
> this work, because the kernel has a lot of "blind spots" which the
> toolchain doesn't have visibility to, notably asm and inline asm.
> Manual .cfi annotations are very difficult to maintain and even more
> difficult to ensure correctness.  Also, due to kernel live patching, the
> kernel relies on 100% correctness of unwinding metadata, whereas the
> toolchain treats it as a best effort.
> 
> 
> Challenges
> ----------
> 
> Reverse engineering the control flow graph is mostly quite
> straightforward, with two notable exceptions:
> 
> 1) Jump tables (e.g., switch statements):
> 
>     Depending on the architecture, it's somewhere between difficult and
>     impossible to reliabily identify which indirect jumps correspond to
>     jump tables, and what are their corresponding intra-function jump
>     destinations.
> 
> 2) Noreturn functions:
>     
>     There's no reliable way to determine which functions are designated
>     by the compiler to be noreturn (either explictly via function
>     attribute, or implicitly via a static function which is a wrapper
>     around a noreturn function.)  This information is needed because the
>     code after the call to such a function is optimized out as
>     unreachable and objtool has no way of knowing that.
> 
> 

Curious to know what all features of objtool rely on the need to reverse 
engineer the control flow graph. Is it a larger set or it is only for 
ORC generation ?

> Proposal
> --------
> 
> Add the following new compiler flags which create non-allocatable ELF
> sections which "annotate" control flow:
> 
> (Note this is purely hypothetical, intended for starting a discussion.
> I'm not a compiler person and I haven't written any compiler code.)
> 
> 
> 1) -fannotate-jump-table
> 
> Create an .annotate.jump_table section which is an array of the
> following variable-length structure:
> 
>    struct annotate_jump_table {
> 	void *indirect_jmp;
> 	long num_targets;
> 	void *targets[];
>    };
> 
> 
> For example, given the following switch statement code:
> 
>    .Lswitch_jmp:
> 	// %rax is .Lcase_1 or .Lcase_2
> 	jmp %rax
> 
>    .Lcase_1:
> 	...
>    .Lcase_2:
> 	...
> 
> 
> Add the following code:
> 
>    .pushsection .annotate.jump_table
> 	// indirect JMP address
> 	.quad .Lswitch_jmp
> 
> 	// num jump targets
> 	.quad 2
> 
> 	// indirect JMP target addresses
> 	.quad .Lcase_1
> 	.quad .Lcase_2
>    .popsection
> 
> 
> 2) -fannotate-noreturn
> 
> Create an .annotate.noreturn section which is an array of pointers to
> noreturn functions (both explicit/implicit and defined/undefined).
> 
> 
> For example, given the following three noreturn functions:
> 
>    // explicit noreturn:
>    __attribute__((__noreturn__)) void func1(void)
>    {
> 	exit(1);
>    }
> 
>    // explicit noreturn (extern):
>    extern __attribute__((__noreturn__)) void func2(void);
> 
>    // implicit noreturn:
>    static void func3(void)
>    {
>    	// call noreturn function
> 	func2();
>    }
> 
> 
> Add the following code:
> 
>    .pushsection .annotate.noreturn
> 	.quad func1
> 	.quad func2
> 	.quad func3
>    .popsection
> 
> 
> Alternatives
> ------------
> 
> Another idea which has been floated in the past is for objtool to read
> DWARF (or .eh_frame) to help it figure out the control flow.  That
> hasn't been tried yet, but would be considerably more difficult and
> fragile IMO.
> 





More information about the linux-arm-kernel mailing list