Skip to content

Commit cba82de

Browse files
mirabJiri Kosina
authored andcommitted
livepatch: Send a fake signal periodically
An administrator may send a fake signal to all remaining blocking tasks of a running transition by writing to /sys/kernel/livepatch/<patch>/signal attribute. Let's do it automatically after 15 seconds. The timeout is chosen deliberately. It gives the tasks enough time to transition themselves. Theoretically, sending it once should be more than enough. However, every task must get outside of a patched function to be successfully transitioned. It could prove not to be simple and resending could be helpful in that case. A new workqueue job could be a cleaner solution to achieve it, but it could also introduce deadlocks and cause more headaches with synchronization and cancelling. [[email protected]: removed added newline] Signed-off-by: Miroslav Benes <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent a2818ee commit cba82de

File tree

2 files changed

+15
-4
lines changed

2 files changed

+15
-4
lines changed

Documentation/livepatch/livepatch.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,8 @@ patched state. This may be harmful to the system though.
163163
Writing 1 to the attribute sends a fake signal to all remaining blocking
164164
tasks. No proper signal is actually delivered (there is no data in signal
165165
pending structures). Tasks are interrupted or woken up, and forced to change
166-
their patched state.
166+
their patched state. Despite the sysfs attribute the fake signal is also sent
167+
every 15 seconds automatically.
167168

168169
Administrator can also affect a transition through
169170
/sys/kernel/livepatch/<patch>/force attribute. Writing 1 there clears

kernel/livepatch/transition.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,14 @@
2929
#define MAX_STACK_ENTRIES 100
3030
#define STACK_ERR_BUF_SIZE 128
3131

32+
#define SIGNALS_TIMEOUT 15
33+
3234
struct klp_patch *klp_transition_patch;
3335

3436
static int klp_target_state = KLP_UNDEFINED;
3537

38+
static unsigned int klp_signals_cnt;
39+
3640
/*
3741
* This work can be performed periodically to finish patching or unpatching any
3842
* "straggler" tasks which failed to transition in the first attempt.
@@ -393,6 +397,10 @@ void klp_try_complete_transition(void)
393397
put_online_cpus();
394398

395399
if (!complete) {
400+
if (klp_signals_cnt && !(klp_signals_cnt % SIGNALS_TIMEOUT))
401+
klp_send_signals();
402+
klp_signals_cnt++;
403+
396404
/*
397405
* Some tasks weren't able to be switched over. Try again
398406
* later and/or wait for other methods like kernel exit
@@ -454,6 +462,8 @@ void klp_start_transition(void)
454462
if (task->patch_state != klp_target_state)
455463
set_tsk_thread_flag(task, TIF_PATCH_PENDING);
456464
}
465+
466+
klp_signals_cnt = 0;
457467
}
458468

459469
/*
@@ -578,14 +588,14 @@ void klp_copy_process(struct task_struct *child)
578588

579589
/*
580590
* Sends a fake signal to all non-kthread tasks with TIF_PATCH_PENDING set.
581-
* Kthreads with TIF_PATCH_PENDING set are woken up. Only admin can request this
582-
* action currently.
591+
* Kthreads with TIF_PATCH_PENDING set are woken up.
583592
*/
584593
void klp_send_signals(void)
585594
{
586595
struct task_struct *g, *task;
587596

588-
pr_notice("signaling remaining tasks\n");
597+
if (klp_signals_cnt == SIGNALS_TIMEOUT)
598+
pr_notice("signaling remaining tasks\n");
589599

590600
read_lock(&tasklist_lock);
591601
for_each_process_thread(g, task) {

0 commit comments

Comments
 (0)