summaryrefslogtreecommitdiffstats
path: root/kernel/livepatch/transition.c
diff options
context:
space:
mode:
authorMiroslav Benes <mbenes@suse.cz>2017-11-22 05:29:21 -0500
committerJiri Kosina <jkosina@suse.cz>2017-12-07 07:21:35 -0500
commitc99a2be790b07752d8cc694434d3450afd4c5a00 (patch)
tree086f38cd5bae5145e4677c552a8776990f12c2fb /kernel/livepatch/transition.c
parent43347d56c8d9dd732cee2f8efd384ad21dd1f6c4 (diff)
livepatch: force transition to finish
If a task sleeps in a set of patched functions uninterruptedly, it could block the whole transition indefinitely. Thus it may be useful to clear its TIF_PATCH_PENDING to allow the process to finish. Admin can do that now by writing to force sysfs attribute in livepatch sysfs directory. TIF_PATCH_PENDING is then cleared for all tasks and the transition can finish successfully. Important note! Administrator should not use this feature without a clearance from a patch distributor. It must be checked that by doing so the consistency model guarantees are not violated. Removal (rmmod) of patch modules is permanently disabled when the feature is used. It cannot be guaranteed there is no task sleeping in such module. Signed-off-by: Miroslav Benes <mbenes@suse.cz> Acked-by: Josh Poimboeuf <jpoimboe@redhat.com> Reviewed-by: Petr Mladek <pmladek@suse.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'kernel/livepatch/transition.c')
-rw-r--r--kernel/livepatch/transition.c36
1 files changed, 34 insertions, 2 deletions
diff --git a/kernel/livepatch/transition.c b/kernel/livepatch/transition.c
index edcfcb8ebb2d..be5bfa533ee8 100644
--- a/kernel/livepatch/transition.c
+++ b/kernel/livepatch/transition.c
@@ -33,6 +33,8 @@ struct klp_patch *klp_transition_patch;
33 33
34static int klp_target_state = KLP_UNDEFINED; 34static int klp_target_state = KLP_UNDEFINED;
35 35
36static bool klp_forced = false;
37
36/* 38/*
37 * This work can be performed periodically to finish patching or unpatching any 39 * This work can be performed periodically to finish patching or unpatching any
38 * "straggler" tasks which failed to transition in the first attempt. 40 * "straggler" tasks which failed to transition in the first attempt.
@@ -146,9 +148,12 @@ done:
146 /* 148 /*
147 * See complementary comment in __klp_enable_patch() for why we 149 * See complementary comment in __klp_enable_patch() for why we
148 * keep the module reference for immediate patches. 150 * keep the module reference for immediate patches.
151 *
152 * klp_forced or immediate_func set implies unbounded increase of
153 * module's ref count if the module is disabled/enabled in a loop.
149 */ 154 */
150 if (!klp_transition_patch->immediate && !immediate_func && 155 if (!klp_forced && !klp_transition_patch->immediate &&
151 klp_target_state == KLP_UNPATCHED) { 156 !immediate_func && klp_target_state == KLP_UNPATCHED) {
152 module_put(klp_transition_patch->mod); 157 module_put(klp_transition_patch->mod);
153 } 158 }
154 159
@@ -649,3 +654,30 @@ void klp_send_signals(void)
649 } 654 }
650 read_unlock(&tasklist_lock); 655 read_unlock(&tasklist_lock);
651} 656}
657
658/*
659 * Drop TIF_PATCH_PENDING of all tasks on admin's request. This forces an
660 * existing transition to finish.
661 *
662 * NOTE: klp_update_patch_state(task) requires the task to be inactive or
663 * 'current'. This is not the case here and the consistency model could be
664 * broken. Administrator, who is the only one to execute the
665 * klp_force_transitions(), has to be aware of this.
666 */
667void klp_force_transition(void)
668{
669 struct task_struct *g, *task;
670 unsigned int cpu;
671
672 pr_warn("forcing remaining tasks to the patched state\n");
673
674 read_lock(&tasklist_lock);
675 for_each_process_thread(g, task)
676 klp_update_patch_state(task);
677 read_unlock(&tasklist_lock);
678
679 for_each_possible_cpu(cpu)
680 klp_update_patch_state(idle_task(cpu));
681
682 klp_forced = true;
683}