Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/jikos/livepatching

Pull livepatching updates from Jiri Kosina:

 - handle 'infinitely'-long sleeping tasks, from Miroslav Benes

 - remove 'immediate' feature, as it turns out it doesn't provide the
   originally expected semantics, and brings more issues than value

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/livepatching:
  livepatch: add locking to force and signal functions
  livepatch: Remove immediate feature
  livepatch: force transition to finish
  livepatch: send a fake signal to all blocking tasks
  • Loading branch information
torvalds committed Jan 31, 2018
2 parents 183b636 + d05b695 commit e1c70f3
Show file tree
Hide file tree
Showing 13 changed files with 227 additions and 187 deletions.
26 changes: 26 additions & 0 deletions Documentation/ABI/testing/sysfs-kernel-livepatch
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,32 @@ Description:
An attribute which indicates whether the patch is currently in
transition.

What: /sys/kernel/livepatch/<patch>/signal
Date: Nov 2017
KernelVersion: 4.15.0
Contact: [email protected]
Description:
A writable attribute that allows administrator to affect the
course of an existing transition. Writing 1 sends a fake
signal to all remaining blocking tasks. The fake signal
means that no proper signal is delivered (there is no data in
signal pending structures). Tasks are interrupted or woken up,
and forced to change their patched state.

What: /sys/kernel/livepatch/<patch>/force
Date: Nov 2017
KernelVersion: 4.15.0
Contact: [email protected]
Description:
A writable attribute that allows administrator to affect the
course of an existing transition. Writing 1 clears
TIF_PATCH_PENDING flag of all tasks and thus forces the tasks to
the patched or unpatched state. Administrator should not
use this feature without a clearance from a patch
distributor. Removal (rmmod) of patch modules is permanently
disabled when the feature is used. See
Documentation/livepatch/livepatch.txt for more information.

What: /sys/kernel/livepatch/<patch>/<object>
Date: Nov 2014
KernelVersion: 3.19.0
Expand Down
114 changes: 50 additions & 64 deletions Documentation/livepatch/livepatch.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,7 @@ example, they add a NULL pointer or a boundary check, fix a race by adding
a missing memory barrier, or add some locking around a critical section.
Most of these changes are self contained and the function presents itself
the same way to the rest of the system. In this case, the functions might
be updated independently one by one. (This can be done by setting the
'immediate' flag in the klp_patch struct.)
be updated independently one by one.

But there are more complex fixes. For example, a patch might change
ordering of locking in multiple functions at the same time. Or a patch
Expand Down Expand Up @@ -125,40 +124,23 @@ safe to patch tasks:
b) Patching CPU-bound user tasks. If the task is highly CPU-bound
then it will get patched the next time it gets interrupted by an
IRQ.
c) In the future it could be useful for applying patches for
architectures which don't yet have HAVE_RELIABLE_STACKTRACE. In
this case you would have to signal most of the tasks on the
system. However this isn't supported yet because there's
currently no way to patch kthreads without
HAVE_RELIABLE_STACKTRACE.

3. For idle "swapper" tasks, since they don't ever exit the kernel, they
instead have a klp_update_patch_state() call in the idle loop which
allows them to be patched before the CPU enters the idle state.

(Note there's not yet such an approach for kthreads.)

All the above approaches may be skipped by setting the 'immediate' flag
in the 'klp_patch' struct, which will disable per-task consistency and
patch all tasks immediately. This can be useful if the patch doesn't
change any function or data semantics. Note that, even with this flag
set, it's possible that some tasks may still be running with an old
version of the function, until that function returns.
Architectures which don't have HAVE_RELIABLE_STACKTRACE solely rely on
the second approach. It's highly likely that some tasks may still be
running with an old version of the function, until that function
returns. In this case you would have to signal the tasks. This
especially applies to kthreads. They may not be woken up and would need
to be forced. See below for more information.

There's also an 'immediate' flag in the 'klp_func' struct which allows
you to specify that certain functions in the patch can be applied
without per-task consistency. This might be useful if you want to patch
a common function like schedule(), and the function change doesn't need
consistency but the rest of the patch does.

For architectures which don't have HAVE_RELIABLE_STACKTRACE, the user
must set patch->immediate which causes all tasks to be patched
immediately. This option should be used with care, only when the patch
doesn't change any function or data semantics.

In the future, architectures which don't have HAVE_RELIABLE_STACKTRACE
may be allowed to use per-task consistency if we can come up with
another way to patch kthreads.
Unless we can come up with another way to patch kthreads, architectures
without HAVE_RELIABLE_STACKTRACE are not considered fully supported by
the kernel livepatching.

The /sys/kernel/livepatch/<patch>/transition file shows whether a patch
is in transition. Only a single patch (the topmost patch on the stack)
Expand All @@ -176,8 +158,31 @@ If a patch is in transition, this file shows 0 to indicate the task is
unpatched and 1 to indicate it's patched. Otherwise, if no patch is in
transition, it shows -1. Any tasks which are blocking the transition
can be signaled with SIGSTOP and SIGCONT to force them to change their
patched state.

patched state. This may be harmful to the system though.
/sys/kernel/livepatch/<patch>/signal attribute provides a better alternative.
Writing 1 to the attribute sends a fake signal to all remaining blocking
tasks. No proper signal is actually delivered (there is no data in signal
pending structures). Tasks are interrupted or woken up, and forced to change
their patched state.

Administrator can also affect a transition through
/sys/kernel/livepatch/<patch>/force attribute. Writing 1 there clears
TIF_PATCH_PENDING flag of all tasks and thus forces the tasks to the patched
state. Important note! The force attribute is intended for cases when the
transition gets stuck for a long time because of a blocking task. Administrator
is expected to collect all necessary data (namely stack traces of such blocking
tasks) and request a clearance from a patch distributor to force the transition.
Unauthorized usage may cause harm to the system. It depends on the nature of the
patch, which functions are (un)patched, and which functions the blocking tasks
are sleeping in (/proc/<pid>/stack may help here). Removal (rmmod) of patch
modules is permanently disabled when the force feature is used. It cannot be
guaranteed there is no task sleeping in such module. It implies unbounded
reference count if a patch module is disabled and enabled in a loop.

Moreover, the usage of force may also affect future applications of live
patches and cause even more harm to the system. Administrator should first
consider to simply cancel a transition (see above). If force is used, reboot
should be planned and no more live patches applied.

3.1 Adding consistency model support to new architectures
---------------------------------------------------------
Expand Down Expand Up @@ -216,13 +221,6 @@ few options:
a good backup option for those architectures which don't have
reliable stack traces yet.

In the meantime, patches for such architectures can bypass the
consistency model by setting klp_patch.immediate to true. This option
is perfectly fine for patches which don't change the semantics of the
patched functions. In practice, this is usable for ~90% of security
fixes. Use of this option also means the patch can't be unloaded after
it has been disabled.


4. Livepatch module
===================
Expand Down Expand Up @@ -278,9 +276,6 @@ into three levels:
only for a particular object ( vmlinux or a kernel module ). Note that
kallsyms allows for searching symbols according to the object name.

There's also an 'immediate' flag which, when set, patches the
function immediately, bypassing the consistency model safety checks.

+ struct klp_object defines an array of patched functions (struct
klp_func) in the same object. Where the object is either vmlinux
(NULL) or a module name.
Expand All @@ -299,9 +294,6 @@ into three levels:
symbols are found. The only exception are symbols from objects
(kernel modules) that have not been loaded yet.

Setting the 'immediate' flag applies the patch to all tasks
immediately, bypassing the consistency model safety checks.

For more details on how the patch is applied on a per-task basis,
see the "Consistency model" section.

Expand All @@ -316,14 +308,12 @@ section "Livepatch life-cycle" below for more details about these
two operations.

Module removal is only safe when there are no users of the underlying
functions. The immediate consistency model is not able to detect this. The
code just redirects the functions at the very beginning and it does not
check if the functions are in use. In other words, it knows when the
functions get called but it does not know when the functions return.
Therefore it cannot be decided when the livepatch module can be safely
removed. This is solved by a hybrid consistency model. When the system is
transitioned to a new patch state (patched/unpatched) it is guaranteed that
no task sleeps or runs in the old code.
functions. This is the reason why the force feature permanently disables
the removal. The forced tasks entered the functions but we cannot say
that they returned back. Therefore it cannot be decided when the
livepatch module can be safely removed. When the system is successfully
transitioned to a new patch state (patched/unpatched) without being
forced it is guaranteed that no task sleeps or runs in the old code.


5. Livepatch life-cycle
Expand All @@ -337,19 +327,12 @@ First, the patch is applied only when all patched symbols for already
loaded objects are found. The error handling is much easier if this
check is done before particular functions get redirected.

Second, the immediate consistency model does not guarantee that anyone is not
sleeping in the new code after the patch is reverted. This means that the new
code needs to stay around "forever". If the code is there, one could apply it
again. Therefore it makes sense to separate the operations that might be done
once and those that need to be repeated when the patch is enabled (applied)
again.

Third, it might take some time until the entire system is migrated
when a more complex consistency model is used. The patch revert might
block the livepatch module removal for too long. Therefore it is useful
to revert the patch using a separate operation that might be called
explicitly. But it does not make sense to remove all information
until the livepatch module is really removed.
Second, it might take some time until the entire system is migrated with
the hybrid consistency model being used. The patch revert might block
the livepatch module removal for too long. Therefore it is useful to
revert the patch using a separate operation that might be called
explicitly. But it does not make sense to remove all information until
the livepatch module is really removed.


5.1. Registration
Expand Down Expand Up @@ -435,6 +418,9 @@ Information about the registered patches can be found under
/sys/kernel/livepatch. The patches could be enabled and disabled
by writing there.

/sys/kernel/livepatch/<patch>/signal and /sys/kernel/livepatch/<patch>/force
attributes allow administrator to affect a patching operation.

See Documentation/ABI/testing/sysfs-kernel-livepatch for more details.


Expand Down
6 changes: 3 additions & 3 deletions arch/powerpc/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
if (thread_info_flags & _TIF_UPROBE)
uprobe_notify_resume(regs);

if (thread_info_flags & _TIF_PATCH_PENDING)
klp_update_patch_state(current);

if (thread_info_flags & _TIF_SIGPENDING) {
BUG_ON(regs != current->thread.regs);
do_signal(current);
Expand All @@ -163,9 +166,6 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
tracehook_notify_resume(regs);
}

if (thread_info_flags & _TIF_PATCH_PENDING)
klp_update_patch_state(current);

user_enter();
}

Expand Down
6 changes: 3 additions & 3 deletions arch/x86/entry/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ static void exit_to_usermode_loop(struct pt_regs *regs, u32 cached_flags)
if (cached_flags & _TIF_UPROBE)
uprobe_notify_resume(regs);

if (cached_flags & _TIF_PATCH_PENDING)
klp_update_patch_state(current);

/* deal with pending signal delivery */
if (cached_flags & _TIF_SIGPENDING)
do_signal(regs);
Expand All @@ -165,9 +168,6 @@ static void exit_to_usermode_loop(struct pt_regs *regs, u32 cached_flags)
if (cached_flags & _TIF_USER_RETURN_NOTIFY)
fire_user_return_notifiers();

if (cached_flags & _TIF_PATCH_PENDING)
klp_update_patch_state(current);

/* Disable IRQs and retry */
local_irq_disable();

Expand Down
4 changes: 0 additions & 4 deletions include/linux/livepatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
* @new_func: pointer to the patched function code
* @old_sympos: a hint indicating which symbol position the old function
* can be found (optional)
* @immediate: patch the func immediately, bypassing safety mechanisms
* @old_addr: the address of the function being patched
* @kobj: kobject for sysfs resources
* @stack_node: list node for klp_ops func_stack list
Expand Down Expand Up @@ -76,7 +75,6 @@ struct klp_func {
* in kallsyms for the given object is used.
*/
unsigned long old_sympos;
bool immediate;

/* internal */
unsigned long old_addr;
Expand Down Expand Up @@ -137,7 +135,6 @@ struct klp_object {
* struct klp_patch - patch structure for live patching
* @mod: reference to the live patch module
* @objs: object entries for kernel objects to be patched
* @immediate: patch all funcs immediately, bypassing safety mechanisms
* @list: list node for global list of registered patches
* @kobj: kobject for sysfs resources
* @enabled: the patch is enabled (but operation may be incomplete)
Expand All @@ -147,7 +144,6 @@ struct klp_patch {
/* external */
struct module *mod;
struct klp_object *objs;
bool immediate;

/* internal */
struct list_head list;
Expand Down
76 changes: 65 additions & 11 deletions kernel/livepatch/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -366,11 +366,6 @@ static int __klp_enable_patch(struct klp_patch *patch)
/*
* A reference is taken on the patch module to prevent it from being
* unloaded.
*
* Note: For immediate (no consistency model) patches we don't allow
* patch modules to unload since there is no safe/sane method to
* determine if a thread is still running in the patched code contained
* in the patch module once the ftrace registration is successful.
*/
if (!try_module_get(patch->mod))
return -ENODEV;
Expand Down Expand Up @@ -454,6 +449,8 @@ EXPORT_SYMBOL_GPL(klp_enable_patch);
* /sys/kernel/livepatch/<patch>
* /sys/kernel/livepatch/<patch>/enabled
* /sys/kernel/livepatch/<patch>/transition
* /sys/kernel/livepatch/<patch>/signal
* /sys/kernel/livepatch/<patch>/force
* /sys/kernel/livepatch/<patch>/<object>
* /sys/kernel/livepatch/<patch>/<object>/<function,sympos>
*/
Expand Down Expand Up @@ -528,11 +525,73 @@ static ssize_t transition_show(struct kobject *kobj,
patch == klp_transition_patch);
}

static ssize_t signal_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count)
{
struct klp_patch *patch;
int ret;
bool val;

ret = kstrtobool(buf, &val);
if (ret)
return ret;

if (!val)
return count;

mutex_lock(&klp_mutex);

patch = container_of(kobj, struct klp_patch, kobj);
if (patch != klp_transition_patch) {
mutex_unlock(&klp_mutex);
return -EINVAL;
}

klp_send_signals();

mutex_unlock(&klp_mutex);

return count;
}

static ssize_t force_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count)
{
struct klp_patch *patch;
int ret;
bool val;

ret = kstrtobool(buf, &val);
if (ret)
return ret;

if (!val)
return count;

mutex_lock(&klp_mutex);

patch = container_of(kobj, struct klp_patch, kobj);
if (patch != klp_transition_patch) {
mutex_unlock(&klp_mutex);
return -EINVAL;
}

klp_force_transition();

mutex_unlock(&klp_mutex);

return count;
}

static struct kobj_attribute enabled_kobj_attr = __ATTR_RW(enabled);
static struct kobj_attribute transition_kobj_attr = __ATTR_RO(transition);
static struct kobj_attribute signal_kobj_attr = __ATTR_WO(signal);
static struct kobj_attribute force_kobj_attr = __ATTR_WO(force);
static struct attribute *klp_patch_attrs[] = {
&enabled_kobj_attr.attr,
&transition_kobj_attr.attr,
&signal_kobj_attr.attr,
&force_kobj_attr.attr,
NULL
};

Expand Down Expand Up @@ -830,12 +889,7 @@ int klp_register_patch(struct klp_patch *patch)
if (!klp_initialized())
return -ENODEV;

/*
* Architectures without reliable stack traces have to set
* patch->immediate because there's currently no way to patch kthreads
* with the consistency model.
*/
if (!klp_have_reliable_stack() && !patch->immediate) {
if (!klp_have_reliable_stack()) {
pr_err("This architecture doesn't have support for the livepatch consistency model.\n");
return -ENOSYS;
}
Expand Down
Loading

0 comments on commit e1c70f3

Please sign in to comment.