All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kees Cook <keescook@chromium.org>
To: Peter Zijlstra <peterz@infradead.org>
Cc: Ard Biesheuvel <ardb@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Sami Tolvanen <samitolvanen@google.com>, X86 ML <x86@kernel.org>,
	Josh Poimboeuf <jpoimboe@redhat.com>,
	Nathan Chancellor <nathan@kernel.org>,
	Nick Desaulniers <ndesaulniers@google.com>,
	Sedat Dilek <sedat.dilek@gmail.com>,
	Steven Rostedt <rostedt@goodmis.org>,
	linux-hardening@vger.kernel.org,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	llvm@lists.linux.dev
Subject: Re: [PATCH v5 00/15] x86: Add support for Clang CFI
Date: Wed, 27 Oct 2021 15:27:59 -0700	[thread overview]
Message-ID: <202110271430.2A3980217@keescook> (raw)
In-Reply-To: <YXnC1jqwR2ZKfMdk@hirez.programming.kicks-ass.net>

On Wed, Oct 27, 2021 at 11:21:26PM +0200, Peter Zijlstra wrote:
> On Wed, Oct 27, 2021 at 10:11:28AM -0700, Kees Cook wrote:
> > On Wed, Oct 27, 2021 at 03:04:55PM +0200, Peter Zijlstra wrote:
> > > [...]
> > > cold_function()
> > > {
> > > 	...
> > > 	global_foo->func1(args1);
> > > 	...
> > > }
> > 
> > If global_foo is non-const, then the static call stuff is just an
> > obfuscated indirect call.
> 
> It is not. The target is determined once, at boot time, depending on the
> hardware, it then never changes. The static_call() results in a direct
> call to that function.

Right, I mean it is _effectively_ an indirect call in the sense that the
call destination is under the control of a writable memory location.
Yes, static_call_update() must be called to make the change, hence why I
didn't wave my arms around when static_call was originally added. It's a
net benefit for the kernel: actual indirect calls now become updatable
direct calls. This means reachability becomes much harder for attackers;
I'm totally a fan. :)

> > If static_call_update() accepts an arbitrary function argument, then it
> > needs to perform the same validation that is currently being injected
> > at indirect call sites to avoid having static calls weaken CFI.
> 
> static_call_update() is a macro and has compile time signature checks,
> the actual function is __static_call_update() and someone can go add
> extra validation in there if they so desire.
> 
> I did have this patch:
> 
>   https://lkml.kernel.org/r/20210904105529.GA5106@worktop.programming.kicks-ass.net
> 
> but I never did get around to finishing it. Although looking at it now,
> I suppose static_call_seal() might be a better name.

Right -- though wouldn't just adding __ro_after_init do the same?

DEFINE_STATIC_CALL(static_call_name, func_a) __ro_after_init;

If you wanted the clean WARN_ON, __static_call_update() could check if
the struct static_call_key is in a non-writable region.

> And you're worried about __static_call_update() over text_poke_bp()
> because?

Both have a meaningful lack of exposure to common attacker-reachable
code paths (e.g., it's likely rare that there are ways attackers can
control the target/content of a text_poke_bp(): alternatives and ftrace,
both of which tend to use read-only content).

static_call_update() is limited per-site with a fixed set of hardcoded
targets (i.e. any place static_call() is used), but the content
is effectively arbitrary (coming from writable memory). AIUI, it's
intended to be used more widely than text_poke_bp(), and it seems like
call sites using static_call_update() will become less rare in future
kernels. (Currently it seems mostly focused on sched and pmu, which
don't traditionally have much userspace control).

So, they're kind of opposite, but for me the question is for examining
the changes to reachability and what kind of primitives their existence
provides an attacker. IMO, static_calls are a net gain over indirect
calls (from some usually writable function pointer) because it becomes
a direct call. It's risk doesn't match a "real" direct call, though,
since they do still have the (much more narrow) risk of having something
call static_call_update() from a writable function pointer as in your
example, but that's still a defensively better position than an regular
indirect call.

What I'm hoping to see from static_calls is maybe defaulting to being
ro_after_init, and explicitly marking those that can't be, which makes
auditing easier and put things into a default-safe state (i.e. both
fixed targets and fixed content).

> > Getting a "jump table to actual function" primitive only avoids the added
> > jump -- all the CFI checking remains bypassed.
> 
> Exactly, so the extra jump serves no purpose and needs to go. Doubly so
> because people are looking at static_call() to undo some of the
> performance damage introduced by CFI :-)

Well, sure, it's inefficient, not _broken_. :) And can you point to the
"use static_calls because CFI is slow" discussion? I'd be curious to read
through that; the past performance testing had shown that CFI performance
overhead tends to be less than the gains of LTO. So compared to a "stock"
kernel, things should be about the same if not faster.

That said, I understand I'm talking to you, and you're paying very close
attention to the scheduler, etc. :) I'm sure there are specific
workloads that look terrible under CFI!

> > If static call function
> > address storage isn't const, for CFI to work as expected the update()
> > routine will need to do the same checking that is done at indirect call
> > sites when extracting the "real" function for writing into a direct call.
> 
> I've mentioned static_call like a hundred times in these CFI threads..
> if you want to do CFI on them, go ahead. I'm just not sure the C type
> system is up for that, you'll have to somehow frob the signature symbol
> into __static_call_update(), something like __builtin_type_symbol().
> 
> > To avoid all of this, though, it'd be better if static calls only
> > switched between one of a per-site const list of possible functions,
> > which would make it a much tighter hand-rolled CFI system itself. :)
> > (i.e. it would operate from a specific and short list of expected
> > functions rather than the "best effort" approach of matching function
> > prototypes as done by Clang CFI.)
> 
> That sounds like a ton of painful ugly.

Right, I know. That's why I'm saying that I see these features as
certainly related, but not at odds with each other. CFI doesn't protect
static_call sites, but static_call sites are already more well protected
than their earlier indirect calls.

The only note I had was that if static_call wants to dig into the jump
table, it likely needs to static_call-specific: we don't want a general
way to do that without knowing we have some reasonable bounds on the
behavior of the code using it. I think it's fine to have static_calls
do this, though it'd be nice if they could be a little more defensive
(generally) at the same time.

-- 
Kees Cook

  reply	other threads:[~2021-10-27 22:28 UTC|newest]

Thread overview: 117+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-13 18:16 [PATCH v5 00/15] x86: Add support for Clang CFI Sami Tolvanen
2021-10-13 18:16 ` [PATCH v5 01/15] objtool: Add CONFIG_CFI_CLANG support Sami Tolvanen
2021-10-13 18:59   ` Kees Cook
2021-10-14  0:44   ` Josh Poimboeuf
2021-10-14 10:22   ` Peter Zijlstra
2021-10-14 19:20     ` Sami Tolvanen
2021-10-13 18:16 ` [PATCH v5 02/15] objtool: Add ASM_STACK_FRAME_NON_STANDARD Sami Tolvanen
2021-10-13 18:59   ` Kees Cook
2021-10-13 18:16 ` [PATCH v5 03/15] linkage: Add DECLARE_NOT_CALLED_FROM_C Sami Tolvanen
2021-10-13 19:00   ` Kees Cook
2021-10-15  2:51   ` Andy Lutomirski
2021-10-15 15:35     ` Sami Tolvanen
2021-10-15 15:55     ` Thomas Gleixner
2021-10-15 16:22       ` Andy Lutomirski
2021-10-15 16:47         ` Sami Tolvanen
2021-10-15 17:34           ` Andy Lutomirski
2021-10-15 17:57       ` Thomas Gleixner
2021-10-15 18:42         ` Sami Tolvanen
2021-10-15 19:35           ` Andy Lutomirski
2021-10-15 20:37             ` Sami Tolvanen
2021-10-16 21:12               ` Josh Poimboeuf
2021-10-18 17:08                 ` Sami Tolvanen
2021-10-15 22:17           ` Thomas Gleixner
2021-10-16 21:16             ` Josh Poimboeuf
2021-10-13 18:16 ` [PATCH v5 04/15] cfi: Add DEFINE_CFI_IMMEDIATE_RETURN_STUB Sami Tolvanen
2021-10-13 19:02   ` Kees Cook
2021-10-13 18:16 ` [PATCH v5 05/15] tracepoint: Exclude tp_stub_func from CFI checking Sami Tolvanen
2021-10-13 19:03   ` Kees Cook
2021-10-13 19:20   ` Steven Rostedt
2021-10-13 18:16 ` [PATCH v5 06/15] ftrace: Use an opaque type for functions not callable from C Sami Tolvanen
2021-10-13 19:04   ` Kees Cook
2021-10-13 19:20   ` Steven Rostedt
2021-10-13 18:16 ` [PATCH v5 07/15] lkdtm: Disable UNSET_SMEP with CFI Sami Tolvanen
2021-10-13 18:16 ` [PATCH v5 08/15] lkdtm: Use an opaque type for lkdtm_rodata_do_nothing Sami Tolvanen
2021-10-13 18:16 ` [PATCH v5 09/15] x86: Use an opaque type for functions not callable from C Sami Tolvanen
2021-10-14 11:21   ` Borislav Petkov
2021-10-14 16:07     ` Kees Cook
2021-10-14 17:31       ` Borislav Petkov
2021-10-14 18:24         ` Sami Tolvanen
2021-10-14 19:00           ` Nick Desaulniers
2021-10-14 18:47         ` Kees Cook
2021-10-14 18:52           ` Steven Rostedt
2021-10-14 19:06             ` Josh Poimboeuf
2021-10-13 18:16 ` [PATCH v5 10/15] x86/purgatory: Disable CFI Sami Tolvanen
2021-10-13 19:05   ` Kees Cook
2021-10-13 18:16 ` [PATCH v5 11/15] x86, relocs: Ignore __typeid__ relocations Sami Tolvanen
2021-10-13 18:16 ` [PATCH v5 12/15] x86, module: " Sami Tolvanen
2021-10-13 18:55   ` Kees Cook
2021-10-13 18:16 ` [PATCH v5 13/15] x86, cpu: Use LTO for cpu.c with CFI Sami Tolvanen
2021-10-13 18:16 ` [PATCH v5 14/15] x86, kprobes: Fix optprobe_template_func type mismatch Sami Tolvanen
2021-10-13 18:16 ` [PATCH v5 15/15] x86, build: Allow CONFIG_CFI_CLANG to be selected Sami Tolvanen
2021-10-13 18:56   ` Kees Cook
2021-10-13 19:07 ` [PATCH v5 00/15] x86: Add support for Clang CFI Kees Cook
2021-10-19 10:06 ` Alexander Lobakin
2021-10-19 15:40   ` Sami Tolvanen
2021-10-21 10:27 ` Alexander Lobakin
2021-10-26 20:16 ` Peter Zijlstra
2021-10-27 10:02   ` David Laight
2021-10-27 10:17     ` Peter Zijlstra
2021-10-27 12:05   ` Mark Rutland
2021-10-27 12:22     ` Ard Biesheuvel
2021-10-27 12:48       ` Peter Zijlstra
2021-10-27 13:04         ` Peter Zijlstra
2021-10-27 13:30           ` Ard Biesheuvel
2021-10-27 14:03             ` Peter Zijlstra
2021-10-27 14:18               ` Ard Biesheuvel
2021-10-27 14:36                 ` Peter Zijlstra
2021-10-27 15:50                 ` Sami Tolvanen
2021-10-27 15:55                   ` Ard Biesheuvel
2021-10-29 20:03                   ` Peter Zijlstra
2021-10-30  7:47                     ` [PATCH] static_call,x86: Robustify trampoline patching Peter Zijlstra
2021-10-30  8:16                       ` Peter Zijlstra
2021-11-02 17:35                         ` Kees Cook
2021-11-02 18:15                           ` Peter Zijlstra
2021-11-15 13:09                         ` Rasmus Villemoes
2021-10-30 17:19                       ` Ard Biesheuvel
2021-10-30 18:02                         ` Peter Zijlstra
2021-10-30 18:55                           ` Ard Biesheuvel
2021-10-31 16:24                             ` Ard Biesheuvel
2021-10-31 16:39                               ` Peter Zijlstra
2021-10-31 16:44                                 ` Ard Biesheuvel
2021-10-31 20:09                                   ` Peter Zijlstra
2021-10-31 20:21                                     ` Ard Biesheuvel
2021-10-31 20:44                                       ` Peter Zijlstra
2021-10-31 23:36                                         ` Ard Biesheuvel
2021-11-01  9:01                                           ` Peter Zijlstra
2021-11-01  9:36                                             ` David Laight
2021-11-01 14:14                                             ` Ard Biesheuvel
2021-11-02 12:57                                               ` Peter Zijlstra
2021-11-02 15:15                                                 ` Peter Zijlstra
2021-11-02 17:44                                                   ` Ard Biesheuvel
2021-11-02 18:14                                                     ` Peter Zijlstra
2021-11-02 18:17                                                       ` Peter Zijlstra
2021-11-02 18:18                                                       ` Ard Biesheuvel
2021-11-02 21:48                                                         ` Peter Zijlstra
2021-11-02 18:10                                                 ` Kees Cook
2021-11-02 21:02                                                   ` Andy Lutomirski
2021-11-02 23:13                                                     ` Kees Cook
2021-11-03  0:20                                                       ` Andy Lutomirski
2021-11-03  8:35                                                         ` Peter Zijlstra
2021-11-03 10:01                                                           ` David Laight
2021-11-03 19:32                                                           ` Andy Lutomirski
2021-11-02 21:19                                                   ` Peter Zijlstra
2021-11-11 12:15                       ` [tip: locking/urgent] " tip-bot2 for Peter Zijlstra
2021-10-30 19:07                     ` [PATCH v5 00/15] x86: Add support for Clang CFI Sami Tolvanen
2021-10-27 17:11           ` Kees Cook
2021-10-27 21:21             ` Peter Zijlstra
2021-10-27 22:27               ` Kees Cook [this message]
2021-10-28 11:09                 ` Peter Zijlstra
2021-10-28 17:12                   ` Kees Cook
2021-10-28 20:29                     ` Peter Zijlstra
2021-11-02 17:26                       ` Kees Cook
2021-11-01  4:13                 ` Andy Lutomirski
2021-10-27 12:46     ` Peter Zijlstra
2021-10-27 12:55     ` David Laight
2021-10-27 13:17       ` Mark Rutland
2021-10-27 21:31         ` David Laight

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=202110271430.2A3980217@keescook \
    --to=keescook@chromium.org \
    --cc=ardb@kernel.org \
    --cc=jpoimboe@redhat.com \
    --cc=linux-hardening@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=llvm@lists.linux.dev \
    --cc=mark.rutland@arm.com \
    --cc=nathan@kernel.org \
    --cc=ndesaulniers@google.com \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=samitolvanen@google.com \
    --cc=sedat.dilek@gmail.com \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.