mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Josh Poimboeuf <jpoimboe@redhat.com>
To: Petr Mladek <pmladek@suse.com>
Cc: Joe Lawrence <joe.lawrence@redhat.com>,
	live-patching@vger.kernel.org, linux-kernel@vger.kernel.org,
	Jessica Yu <jeyu@kernel.org>, Jiri Kosina <jikos@kernel.org>,
	Miroslav Benes <mbenes@suse.cz>,
	Chris J Arges <chris.j.arges@canonical.com>
Subject: Re: [PATCH] livepatch: add (un)patch hooks
Date: Wed, 19 Jul 2017 23:17:23 -0500	[thread overview]
Message-ID: <20170720041723.35r6qk2fia7xix3t@treble> (raw)
In-Reply-To: <20170719204952.4fyhtig3rbw7z4w4@treble>

On Wed, Jul 19, 2017 at 03:49:52PM -0500, Josh Poimboeuf wrote:
> > I am sorry for the long mail. But I have really troubles to
> > understand and describe what can be done with these hooks
> > a safe way.
> > 
> > It might help if you share some real-life examples.
> 
> Agreed, we should share some real world examples.  For a few cases, load
> hooks were extremely useful.  But most of our experience has been with
> the kpatch consistency model, so we need to revisit our past findings
> and view them through the livepatch lens.
> 
> One crazy -- but potentially very useful -- idea would be if the user
> were allowed to run stop_machine() from the load hook.  If possible,
> that would help prevent a lot of race conditions.

To try to give us all a better idea of what's needed, here are some of
the patches that Joe and I looked at before which seem to need load
hooks.  A few of these are ones we actually delivered to customers with
kpatch.  I've tried to re-analyze them in light of the livepatch CM.


First, a few observations:

- Load hooks are a power feature.  They're live patching in "hard mode".
  But they're also very powerful.  Luckily I think they're only needed
  in a few cases, probably < 5% of patches.

- In general, the hooks seem to be useful for cases like:

  - global data updates

  - "patches" to __init and probe functions

  - patching otherwise unpatchable code (i.e., assembly)

  In many/most cases, it seems like stop_machine() would be very useful
  to avoid concurrency issues.

- The more examples I look at, the more I'm thinking we will need both
  pre-patch and post-patch hooks, as well as pre-unpatch and
  post-unpatch hooks.

- The pre-patch and pre-unpatch hooks can be run before the
  patching/unpatching process begins.

- The post-patch and post-unpatch hooks will need to be run from either
  klp_complete_transition() or klp_module_coming/going(), depending on
  whether the to-be-patched module is already loaded or is being
  loaded/unloaded.


Here's a simple example:

  75ff39ccc1bd ("tcp: make challenge acks less predictable")

It involves changing a global sysctl, as well as a patch to the
tcp_send_challenge_ack() function.  We used load hooks to change the
sysctl.

In this case, if we're being super paranoid, it might make sense to
patch the data *after* patching is complete (i.e., a post-patch hook),
so that tcp_send_challenge_ack() could first be changed to read
sysctl_tcp_challenge_ack_limit with READ_ONCE.  But I think the race is
harmless (and such a race already exists in that function with respect
to sysctl writes anyway).

Another way of dealing with concurrency would be to use stop_machine()
in the load hook.


Another example:

  48900cb6af42 ("virtio-net: drop NETIF_F_FRAGLIST")

That changes the net_device features in a driver probe function.  I
don't know exactly how to patch it, but if it's possible, I'm pretty
sure load hooks is the way to do it :-)


Another one:

  54a20552e1ea ("KVM: x86: work around infinite loop in microcode when #AC is delivered")

Again, I have no idea how to do it, but I'd bet that load hooks are
involved.


This one was interesting:

  6f442be2fb22 ("x86_64, traps: Stop using IST for #SS")

A livepatch patch for it is below.  We had something similar for kpatch.
The below patch is completely untested because we don't have
kpatch-build tooling support for livepatch hooks yet.

Note that the load hook would need to run *after* the patch has been
applied and the transition has completed.  And also, it would need to
run inside stop_machine().  I didn't put that in the patch yet.  But it
should at least give you an idea.


diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 819662746e23..68fe9d5f1c22 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -236,6 +236,7 @@ DO_ERROR(X86_TRAP_NP,     SIGBUS,  "segment not present",	segment_not_present)
 #ifdef CONFIG_X86_32
 DO_ERROR(X86_TRAP_SS,     SIGBUS,  "stack segment",		stack_segment)
 #endif
+DO_ERROR(X86_TRAP_SS,     SIGBUS,  "stack segment",		stack_segment_v2)
 DO_ERROR(X86_TRAP_AC,     SIGBUS,  "alignment check",		alignment_check)
 
 #ifdef CONFIG_X86_64
diff --git a/fs/proc/cmdline.c b/fs/proc/cmdline.c
index cbd82dff7e81..504b01dea937 100644
--- a/fs/proc/cmdline.c
+++ b/fs/proc/cmdline.c
@@ -27,3 +27,42 @@ static int __init proc_cmdline_init(void)
 	return 0;
 }
 fs_initcall(proc_cmdline_init);
+
+
+#include "kpatch-macros.h"
+#include <asm/traps.h>
+#include <asm/desc.h>
+#include <asm/cacheflush.h>
+#define trace_stack_segment_v2 stack_segment_v2
+
+static void swapgs_load_hook(void)
+{
+	/* bug doesn't exist on xen */
+	if (paravirt_enabled() && strcmp(pv_info.name, "KVM"))
+		return;
+
+	write_cr0(read_cr0() & ~X86_CR0_WP);
+	barrier();
+
+	/* disable IST for #SS */
+	set_intr_gate(X86_TRAP_SS, stack_segment_v2);
+
+	barrier();
+	write_cr0(read_cr0() | X86_CR0_WP);
+}
+KLP_LOAD_HOOK(swapgs_load_hook);
+
+static void swapgs_unload_hook(void)
+{
+	if (paravirt_enabled() && strcmp(pv_info.name, "KVM"))
+		return;
+
+	write_cr0(read_cr0() & ~X86_CR0_WP);
+	barrier();
+
+	set_intr_gate_ist(X86_TRAP_SS, stack_segment_v2, STACKFAULT_STACK);
+
+	barrier();
+	write_cr0(read_cr0() | X86_CR0_WP);
+}
+KLP_UNLOAD_HOOK(swapgs_unload_hook);

  reply	other threads:[~2017-07-20  4:17 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-07-12 14:09 [PATCH] livepatch hooks, revisted Joe Lawrence
2017-07-12 14:10 ` [PATCH] livepatch: add (un)patch hooks Joe Lawrence
2017-07-14  1:46   ` Josh Poimboeuf
2017-07-14 13:23     ` Joe Lawrence
2017-07-14 13:46       ` Josh Poimboeuf
2017-07-18 11:10         ` Miroslav Benes
2017-07-18 11:15     ` Miroslav Benes
2017-07-19  2:08       ` Josh Poimboeuf
2017-07-19 15:29         ` Petr Mladek
2017-07-19 19:11         ` Miroslav Benes
2017-07-17 15:51   ` Petr Mladek
2017-07-19 18:59     ` Joe Lawrence
2017-07-20 14:36       ` Petr Mladek
2017-07-19 20:49     ` Josh Poimboeuf
2017-07-20  4:17       ` Josh Poimboeuf [this message]
2017-07-20  4:20         ` Josh Poimboeuf
2017-07-20  4:30         ` Josh Poimboeuf
2017-07-20 15:50         ` Petr Mladek
2017-07-20 17:04           ` Josh Poimboeuf
2017-07-27 20:43         ` Joe Lawrence
2017-07-27 21:36           ` Josh Poimboeuf
2017-07-28 18:08             ` Joe Lawrence
2017-07-28 18:29               ` 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=20170720041723.35r6qk2fia7xix3t@treble \
    --to=jpoimboe@redhat.com \
    --cc=chris.j.arges@canonical.com \
    --cc=jeyu@kernel.org \
    --cc=jikos@kernel.org \
    --cc=joe.lawrence@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=live-patching@vger.kernel.org \
    --cc=mbenes@suse.cz \
    --cc=pmladek@suse.com \
    /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

all inboxes | Powered by JetHome®