linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Josh Poimboeuf <jpoimboe@redhat.com>
To: Petr Mladek <pmladek@suse.cz>
Cc: Seth Jennings <sjenning@redhat.com>,
	Jiri Kosina <jkosina@suse.cz>, Vojtech Pavlik <vojtech@suse.cz>,
	Steven Rostedt <rostedt@goodmis.org>,
	live-patching@vger.kernel.org, kpatch@redhat.com,
	linux-kernel@vger.kernel.org
Subject: Re: more patches for the same func: was Re: [PATCH 2/2] kernel: add support for live patching
Date: Fri, 7 Nov 2014 15:54:26 -0600	[thread overview]
Message-ID: <20141107215426.GH4071@treble.redhat.com> (raw)
In-Reply-To: <20141107173903.GD1136@dhcp128.suse.cz>

On Fri, Nov 07, 2014 at 06:39:03PM +0100, Petr Mladek wrote:
> On Thu 2014-11-06 08:39:08, Seth Jennings wrote:
> > This commit introduces code for the live patching core.  It implements
> > an ftrace-based mechanism and kernel interface for doing live patching
> > of kernel and kernel module functions.
> > 
> > It represents the greatest common functionality set between kpatch and
> > kgraft and can accept patches built using either method.
> > 
> > This first version does not implement any consistency mechanism that
> > ensures that old and new code do not run together.  In practice, ~90% of
> > CVEs are safe to apply in this way, since they simply add a conditional
> > check.  However, any function change that can not execute safely with
> > the old version of the function can _not_ be safely applied in this
> > version.
> 
> [...] 
> 
> > +static int lpc_enable_func(struct lpc_func *func)
> > +{
> > +	int ret;
> > +
> > +	BUG_ON(!func->old_addr);
> > +	BUG_ON(func->state != DISABLED);
> > +	ret = ftrace_set_filter_ip(&func->fops, func->old_addr, 0, 0);
> > +	if (ret) {
> > +		pr_err("failed to set ftrace filter for function '%s' (%d)\n",
> > +		       func->old_name, ret);
> > +		return ret;
> > +	}
> > +	ret = register_ftrace_function(&func->fops);
> > +	if (ret) {
> > +		pr_err("failed to register ftrace handler for function '%s' (%d)\n",
> > +		       func->old_name, ret);
> > +		ftrace_set_filter_ip(&func->fops, func->old_addr, 1, 0);
> > +	} else
> > +		func->state = ENABLED;
> > +
> > +	return ret;
> > +}
> > +
> 
> [...]
> 
> > +/* caller must ensure that obj->mod is set if object is a module */
> > +static int lpc_enable_object(struct module *pmod, struct lpc_object *obj)
> > +{
> > +	struct lpc_func *func;
> > +	int ret;
> > +
> > +	if (obj->mod && !try_module_get(obj->mod))
> > +		return -ENODEV;
> > +
> > +	if (obj->dynrelas) {
> > +		ret = lpc_write_object_relocations(pmod, obj);
> > +		if (ret)
> > +			goto unregister;
> > +	}
> > +	list_for_each_entry(func, &obj->funcs, list) {
> > +		ret = lpc_find_verify_func_addr(func, obj->name);
> > +		if (ret)
> > +			goto unregister;
> > +
> > +		ret = lpc_enable_func(func);
> > +		if (ret)
> > +			goto unregister;
> > +	}
> > +	obj->state = ENABLED;
> > +
> > +	return 0;
> > +unregister:
> > +	WARN_ON(lpc_unregister_object(obj));
> > +	return ret;
> > +}
> > +
> > +/******************************
> > + * enable/disable
> > + ******************************/
> > +
> > +/* must be called with lpc_mutex held */
> > +static struct lpc_patch *lpc_find_patch(struct lp_patch *userpatch)
> > +{
> > +	struct lpc_patch *patch;
> > +
> > +	list_for_each_entry(patch, &lpc_patches, list)
> > +		if (patch->userpatch == userpatch)
> > +			return patch;
> > +
> > +	return NULL;
> > +}
> 
> [...]
> 
> > +
> > +/* must be called with lpc_mutex held */
> > +static int lpc_enable_patch(struct lpc_patch *patch)
> > +{
> > +	struct lpc_object *obj;
> > +	int ret;
> > +
> > +	BUG_ON(patch->state != DISABLED);
> > +
> > +	pr_notice_once("tainting kernel with TAINT_LIVEPATCH\n");
> > +	add_taint(TAINT_LIVEPATCH, LOCKDEP_STILL_OK);
> > +
> > +	pr_notice("enabling patch '%s'\n", patch->mod->name);
> > +
> > +	list_for_each_entry(obj, &patch->objs, list) {
> > +		if (!is_object_loaded(obj))
> > +			continue;
> > +		ret = lpc_enable_object(patch->mod, obj);
> > +		if (ret)
> > +			goto unregister;
> > +	}
> > +	patch->state = ENABLED;
> > +	return 0;
> > +
> > +unregister:
> > +	WARN_ON(lpc_disable_patch(patch));
> > +	return ret;
> > +}
> > +
> > +int lp_enable_patch(struct lp_patch *userpatch)
> > +{
> > +	struct lpc_patch *patch;
> > +	int ret;
> > +
> > +	down(&lpc_mutex);
> > +	patch = lpc_find_patch(userpatch);
> > +	if (!patch) {
> > +		ret = -ENODEV;
> > +		goto out;
> > +	}
> > +	ret = lpc_enable_patch(patch);
> > +out:
> > +	up(&lpc_mutex);
> > +	return ret;
> > +}
> > +EXPORT_SYMBOL_GPL(lp_enable_patch);
> 
> AFAIK, this does not handle correctly the situation when there
> are more patches for the same symbol. IMHO, the first registered
> ftrace function wins. It means that later patches are ignored.

Yeah, good point.  With kpatch we had a single ftrace_ops which was
shared for all patched functions, so we didn't have this problem.  From
the ftrace handler, we would just get the most recent version of the
function from our hash table.

With livepatch we decided to change to the model of one ftrace ops per
patched function.  Which I think is probably a good idea, but it's hard
to say for sure without knowing our consistency model yet.

> 
> In kGraft, we detect this situation and do the following:
> 
>    add_new_ftrace_function()
>    /* old one still might be used at this stage */
>    if (old_function)
>       remove_old_ftrace_function();
>    /* the new one is used from now on */
> 
> Similar problem is when a patch is disabled. We need to know
> if it was actually used. If not, we are done. If it is active,
> we need to look if there is an older patch for the the same
> symbol and enable the other ftrace function instead.

Yeah, maybe we should do something similar for livepatch.

> 
> Best Regards,
> Petr
> 
> 
> PS: We should probably decide on the used structures before we start
> coding fixes for this particular problems. I have similar concern about
> the complexity as my colleagues have. But I need to think more about
> it. Let's discuss it in the other thread.

Sounds good :-)

-- 
Josh

  reply	other threads:[~2014-11-07 21:54 UTC|newest]

Thread overview: 73+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-11-06 14:39 [PATCH 0/2] Kernel Live Patching Seth Jennings
2014-11-06 14:39 ` [PATCH 1/2] kernel: add TAINT_LIVEPATCH Seth Jennings
2014-11-09 20:19   ` Greg KH
2014-11-11 14:54     ` Seth Jennings
2014-11-06 14:39 ` [PATCH 2/2] kernel: add support for live patching Seth Jennings
2014-11-06 15:11   ` Jiri Kosina
2014-11-06 16:20     ` Seth Jennings
2014-11-06 16:32       ` Josh Poimboeuf
2014-11-06 18:00       ` Vojtech Pavlik
2014-11-06 22:20       ` Jiri Kosina
2014-11-07 12:50         ` Josh Poimboeuf
2014-11-07 13:13           ` Jiri Kosina
2014-11-07 13:22             ` Josh Poimboeuf
2014-11-07 14:57             ` Seth Jennings
2014-11-06 15:51   ` Jiri Slaby
2014-11-06 16:57     ` Seth Jennings
2014-11-06 17:12       ` Josh Poimboeuf
2014-11-07 18:21       ` Petr Mladek
2014-11-07 20:31         ` Josh Poimboeuf
2014-11-30 12:23     ` Pavel Machek
2014-12-01 16:49       ` Seth Jennings
2014-11-06 20:02   ` Steven Rostedt
2014-11-06 20:19     ` Seth Jennings
2014-11-07 17:13   ` module notifier: was " Petr Mladek
2014-11-07 18:07     ` Seth Jennings
2014-11-07 18:40       ` Petr Mladek
2014-11-07 18:55         ` Seth Jennings
2014-11-11 19:40         ` Seth Jennings
2014-11-11 22:17           ` Jiri Kosina
2014-11-11 22:48             ` Seth Jennings
2014-11-07 17:39   ` more patches for the same func: " Petr Mladek
2014-11-07 21:54     ` Josh Poimboeuf [this message]
2014-11-07 19:40   ` Andy Lutomirski
2014-11-07 19:42     ` Seth Jennings
2014-11-07 19:52     ` Seth Jennings
2014-11-10 10:08   ` Jiri Kosina
2014-11-10 17:31     ` Josh Poimboeuf
2014-11-13 10:16   ` Miroslav Benes
2014-11-13 14:38     ` Josh Poimboeuf
2014-11-13 17:12     ` Seth Jennings
2014-11-14 13:30       ` Miroslav Benes
2014-11-14 14:52         ` Petr Mladek
2014-11-06 18:44 ` [PATCH 0/2] Kernel Live Patching Christoph Hellwig
2014-11-06 18:51   ` Vojtech Pavlik
2014-11-06 18:58     ` Christoph Hellwig
2014-11-06 19:34       ` Josh Poimboeuf
2014-11-06 19:49         ` Steven Rostedt
2014-11-06 20:02           ` Josh Poimboeuf
2014-11-07  7:46           ` Christoph Hellwig
2014-11-07  7:45         ` Christoph Hellwig
2014-11-06 20:24       ` Vojtech Pavlik
2014-11-07  7:47         ` Christoph Hellwig
2014-11-07 13:11           ` Josh Poimboeuf
2014-11-07 14:04             ` Vojtech Pavlik
2014-11-07 15:45               ` Josh Poimboeuf
2014-11-07 21:27                 ` Vojtech Pavlik
2014-11-08  3:45                   ` Josh Poimboeuf
2014-11-08  8:07                     ` Vojtech Pavlik
2014-11-10 17:09                       ` Josh Poimboeuf
2014-11-11  9:05                         ` Vojtech Pavlik
2014-11-11 17:45                           ` Josh Poimboeuf
2014-11-11  1:24                   ` Masami Hiramatsu
2014-11-11 10:26                     ` Vojtech Pavlik
2014-11-12 17:33                       ` Masami Hiramatsu
2014-11-12 21:47                         ` Vojtech Pavlik
2014-11-13 15:56                           ` Masami Hiramatsu
2014-11-13 16:38                             ` Vojtech Pavlik
2014-11-18 12:47                               ` Petr Mladek
2014-11-18 18:58                                 ` Josh Poimboeuf
2014-11-07 12:31         ` Josh Poimboeuf
2014-11-07 12:48           ` Vojtech Pavlik
2014-11-07 13:06             ` Josh Poimboeuf
2014-11-09 20:16 ` Greg KH

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=20141107215426.GH4071@treble.redhat.com \
    --to=jpoimboe@redhat.com \
    --cc=jkosina@suse.cz \
    --cc=kpatch@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=live-patching@vger.kernel.org \
    --cc=pmladek@suse.cz \
    --cc=rostedt@goodmis.org \
    --cc=sjenning@redhat.com \
    --cc=vojtech@suse.cz \
    /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 NNTP newsgroup(s).