Live-Patching Archive mirror
 help / color / mirror / Atom feed
From: Josh Poimboeuf <jpoimboe@kernel.org>
To: linux-toolchains@vger.kernel.org
Cc: Peter Zijlstra <peterz@infradead.org>,
	Indu Bhagat <indu.bhagat@oracle.com>,
	Nick Desaulniers <ndesaulniers@google.com>,
	linux-kernel@vger.kernel.org,
	"Jose E. Marchesi" <jemarch@gnu.org>,
	Miroslav Benes <mbenes@suse.cz>,
	Mark Rutland <mark.rutland@arm.com>,
	Will Deacon <will@kernel.org>,
	x86@kernel.org, linux-arm-kernel@lists.infradead.org,
	live-patching@vger.kernel.org, linuxppc-dev@lists.ozlabs.org,
	Ard Biesheuvel <ardb@kernel.org>,
	Chen Zhongjin <chenzhongjin@huawei.com>,
	Sathvika Vasireddy <sv@linux.ibm.com>,
	Christophe Leroy <christophe.leroy@csgroup.eu>,
	Mark Brown <broonie@kernel.org>
Subject: [RFC] Objtool toolchain proposal: -fannotate-{jump-table,noreturn}
Date: Fri, 9 Sep 2022 11:07:04 -0700	[thread overview]
Message-ID: <20220909180704.jwwed4zhwvin7uyi@treble> (raw)

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.


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.


-- 
Josh

             reply	other threads:[~2022-09-09 18:07 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-09-09 18:07 Josh Poimboeuf [this message]
2022-09-11 15:26 ` [RFC] Objtool toolchain proposal: -fannotate-{jump-table,noreturn} Peter Zijlstra
2022-09-11 15:31   ` Ard Biesheuvel
2022-09-12 10:52 ` Borislav Petkov
2022-09-12 14:17   ` Michael Matz
2022-09-14  0:04     ` Josh Poimboeuf
2022-09-14 14:00       ` Peter Zijlstra
2022-09-14 14:28         ` Michael Matz
2022-09-14 14:55           ` Peter Zijlstra
2022-09-14 17:34             ` Segher Boessenkool
2022-09-15  2:56     ` Chen Zhongjin
2022-09-15  8:47       ` Peter Zijlstra
2022-09-20 16:49         ` Ard Biesheuvel
2022-09-21  3:16           ` Chen Zhongjin
2022-09-12 11:31 ` Segher Boessenkool
2022-09-14 10:21   ` Josh Poimboeuf
2022-09-14 12:08     ` Michael Matz
2022-09-14 12:16     ` Segher Boessenkool
2022-09-13 22:51 ` Indu Bhagat
2022-09-14  0:12   ` Josh Poimboeuf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220909180704.jwwed4zhwvin7uyi@treble \
    --to=jpoimboe@kernel.org \
    --cc=ardb@kernel.org \
    --cc=broonie@kernel.org \
    --cc=chenzhongjin@huawei.com \
    --cc=christophe.leroy@csgroup.eu \
    --cc=indu.bhagat@oracle.com \
    --cc=jemarch@gnu.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-toolchains@vger.kernel.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=live-patching@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mbenes@suse.cz \
    --cc=ndesaulniers@google.com \
    --cc=peterz@infradead.org \
    --cc=sv@linux.ibm.com \
    --cc=will@kernel.org \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).