Skip to content

Commit 7185a96

Browse files
author
Jiri Kosina
committed
Merge branch 'for-5.1/fake-signal' into for-linus
Ability to send fake signal to blocking tasks automatically, instead of requiring manual intervention, from Miroslav Benes
2 parents 67bae14 + 0b3d527 commit 7185a96

File tree

5 files changed

+58
-94
lines changed

5 files changed

+58
-94
lines changed

Documentation/ABI/testing/sysfs-kernel-livepatch

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,6 @@ Description:
3333
An attribute which indicates whether the patch is currently in
3434
transition.
3535

36-
What: /sys/kernel/livepatch/<patch>/signal
37-
Date: Nov 2017
38-
KernelVersion: 4.15.0
39-
40-
Description:
41-
A writable attribute that allows administrator to affect the
42-
course of an existing transition. Writing 1 sends a fake
43-
signal to all remaining blocking tasks. The fake signal
44-
means that no proper signal is delivered (there is no data in
45-
signal pending structures). Tasks are interrupted or woken up,
46-
and forced to change their patched state.
47-
4836
What: /sys/kernel/livepatch/<patch>/force
4937
Date: Nov 2017
5038
KernelVersion: 4.15.0

Documentation/livepatch/livepatch.txt

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -158,12 +158,11 @@ If a patch is in transition, this file shows 0 to indicate the task is
158158
unpatched and 1 to indicate it's patched. Otherwise, if no patch is in
159159
transition, it shows -1. Any tasks which are blocking the transition
160160
can be signaled with SIGSTOP and SIGCONT to force them to change their
161-
patched state. This may be harmful to the system though.
162-
/sys/kernel/livepatch/<patch>/signal attribute provides a better alternative.
163-
Writing 1 to the attribute sends a fake signal to all remaining blocking
164-
tasks. No proper signal is actually delivered (there is no data in signal
165-
pending structures). Tasks are interrupted or woken up, and forced to change
166-
their patched state.
161+
patched state. This may be harmful to the system though. Sending a fake signal
162+
to all remaining blocking tasks is a better alternative. No proper signal is
163+
actually delivered (there is no data in signal pending structures). Tasks are
164+
interrupted or woken up, and forced to change their patched state. The fake
165+
signal is automatically sent every 15 seconds.
167166

168167
Administrator can also affect a transition through
169168
/sys/kernel/livepatch/<patch>/force attribute. Writing 1 there clears
@@ -411,8 +410,8 @@ Information about the registered patches can be found under
411410
/sys/kernel/livepatch. The patches could be enabled and disabled
412411
by writing there.
413412

414-
/sys/kernel/livepatch/<patch>/signal and /sys/kernel/livepatch/<patch>/force
415-
attributes allow administrator to affect a patching operation.
413+
/sys/kernel/livepatch/<patch>/force attributes allow administrator to affect a
414+
patching operation.
416415

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

kernel/livepatch/core.c

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,6 @@ static int klp_write_object_relocations(struct module *pmod,
313313
* /sys/kernel/livepatch/<patch>
314314
* /sys/kernel/livepatch/<patch>/enabled
315315
* /sys/kernel/livepatch/<patch>/transition
316-
* /sys/kernel/livepatch/<patch>/signal
317316
* /sys/kernel/livepatch/<patch>/force
318317
* /sys/kernel/livepatch/<patch>/<object>
319318
* /sys/kernel/livepatch/<patch>/<object>/<function,sympos>
@@ -382,35 +381,6 @@ static ssize_t transition_show(struct kobject *kobj,
382381
patch == klp_transition_patch);
383382
}
384383

385-
static ssize_t signal_store(struct kobject *kobj, struct kobj_attribute *attr,
386-
const char *buf, size_t count)
387-
{
388-
struct klp_patch *patch;
389-
int ret;
390-
bool val;
391-
392-
ret = kstrtobool(buf, &val);
393-
if (ret)
394-
return ret;
395-
396-
if (!val)
397-
return count;
398-
399-
mutex_lock(&klp_mutex);
400-
401-
patch = container_of(kobj, struct klp_patch, kobj);
402-
if (patch != klp_transition_patch) {
403-
mutex_unlock(&klp_mutex);
404-
return -EINVAL;
405-
}
406-
407-
klp_send_signals();
408-
409-
mutex_unlock(&klp_mutex);
410-
411-
return count;
412-
}
413-
414384
static ssize_t force_store(struct kobject *kobj, struct kobj_attribute *attr,
415385
const char *buf, size_t count)
416386
{
@@ -442,12 +412,10 @@ static ssize_t force_store(struct kobject *kobj, struct kobj_attribute *attr,
442412

443413
static struct kobj_attribute enabled_kobj_attr = __ATTR_RW(enabled);
444414
static struct kobj_attribute transition_kobj_attr = __ATTR_RO(transition);
445-
static struct kobj_attribute signal_kobj_attr = __ATTR_WO(signal);
446415
static struct kobj_attribute force_kobj_attr = __ATTR_WO(force);
447416
static struct attribute *klp_patch_attrs[] = {
448417
&enabled_kobj_attr.attr,
449418
&transition_kobj_attr.attr,
450-
&signal_kobj_attr.attr,
451419
&force_kobj_attr.attr,
452420
NULL
453421
};

kernel/livepatch/transition.c

Lines changed: 51 additions & 41 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.
@@ -343,6 +347,47 @@ static bool klp_try_switch_task(struct task_struct *task)
343347

344348
}
345349

350+
/*
351+
* Sends a fake signal to all non-kthread tasks with TIF_PATCH_PENDING set.
352+
* Kthreads with TIF_PATCH_PENDING set are woken up.
353+
*/
354+
static void klp_send_signals(void)
355+
{
356+
struct task_struct *g, *task;
357+
358+
if (klp_signals_cnt == SIGNALS_TIMEOUT)
359+
pr_notice("signaling remaining tasks\n");
360+
361+
read_lock(&tasklist_lock);
362+
for_each_process_thread(g, task) {
363+
if (!klp_patch_pending(task))
364+
continue;
365+
366+
/*
367+
* There is a small race here. We could see TIF_PATCH_PENDING
368+
* set and decide to wake up a kthread or send a fake signal.
369+
* Meanwhile the task could migrate itself and the action
370+
* would be meaningless. It is not serious though.
371+
*/
372+
if (task->flags & PF_KTHREAD) {
373+
/*
374+
* Wake up a kthread which sleeps interruptedly and
375+
* still has not been migrated.
376+
*/
377+
wake_up_state(task, TASK_INTERRUPTIBLE);
378+
} else {
379+
/*
380+
* Send fake signal to all non-kthread tasks which are
381+
* still not migrated.
382+
*/
383+
spin_lock_irq(&task->sighand->siglock);
384+
signal_wake_up(task, 0);
385+
spin_unlock_irq(&task->sighand->siglock);
386+
}
387+
}
388+
read_unlock(&tasklist_lock);
389+
}
390+
346391
/*
347392
* Try to switch all remaining tasks to the target patch state by walking the
348393
* stacks of sleeping tasks and looking for any to-be-patched or
@@ -393,6 +438,10 @@ void klp_try_complete_transition(void)
393438
put_online_cpus();
394439

395440
if (!complete) {
441+
if (klp_signals_cnt && !(klp_signals_cnt % SIGNALS_TIMEOUT))
442+
klp_send_signals();
443+
klp_signals_cnt++;
444+
396445
/*
397446
* Some tasks weren't able to be switched over. Try again
398447
* later and/or wait for other methods like kernel exit
@@ -454,6 +503,8 @@ void klp_start_transition(void)
454503
if (task->patch_state != klp_target_state)
455504
set_tsk_thread_flag(task, TIF_PATCH_PENDING);
456505
}
506+
507+
klp_signals_cnt = 0;
457508
}
458509

459510
/*
@@ -576,47 +627,6 @@ void klp_copy_process(struct task_struct *child)
576627
/* TIF_PATCH_PENDING gets copied in setup_thread_stack() */
577628
}
578629

579-
/*
580-
* 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.
583-
*/
584-
void klp_send_signals(void)
585-
{
586-
struct task_struct *g, *task;
587-
588-
pr_notice("signaling remaining tasks\n");
589-
590-
read_lock(&tasklist_lock);
591-
for_each_process_thread(g, task) {
592-
if (!klp_patch_pending(task))
593-
continue;
594-
595-
/*
596-
* There is a small race here. We could see TIF_PATCH_PENDING
597-
* set and decide to wake up a kthread or send a fake signal.
598-
* Meanwhile the task could migrate itself and the action
599-
* would be meaningless. It is not serious though.
600-
*/
601-
if (task->flags & PF_KTHREAD) {
602-
/*
603-
* Wake up a kthread which sleeps interruptedly and
604-
* still has not been migrated.
605-
*/
606-
wake_up_state(task, TASK_INTERRUPTIBLE);
607-
} else {
608-
/*
609-
* Send fake signal to all non-kthread tasks which are
610-
* still not migrated.
611-
*/
612-
spin_lock_irq(&task->sighand->siglock);
613-
signal_wake_up(task, 0);
614-
spin_unlock_irq(&task->sighand->siglock);
615-
}
616-
}
617-
read_unlock(&tasklist_lock);
618-
}
619-
620630
/*
621631
* Drop TIF_PATCH_PENDING of all tasks on admin's request. This forces an
622632
* existing transition to finish.

kernel/livepatch/transition.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ void klp_cancel_transition(void);
1111
void klp_start_transition(void);
1212
void klp_try_complete_transition(void);
1313
void klp_reverse_transition(void);
14-
void klp_send_signals(void);
1514
void klp_force_transition(void);
1615

1716
#endif /* _LIVEPATCH_TRANSITION_H */

0 commit comments

Comments
 (0)