|
Miroslav Benes |
c5e518 |
From: Miroslav Benes <mbenes@suse.cz>
|
|
Miroslav Benes |
c5e518 |
Date: Tue, 15 Jan 2019 17:45:07 +0100
|
|
Miroslav Benes |
c5e518 |
Subject: livepatch: Remove signal sysfs attribute
|
|
Miroslav Benes |
c5e518 |
Git-commit: 0b3d52790e1cfd6b80b826a245d24859e89632f7
|
|
Miroslav Benes |
8ba9e1 |
Patch-mainline: v5.1-rc1
|
|
Miroslav Benes |
c5e518 |
References: bsc#1071995 fate#323487
|
|
Miroslav Benes |
c5e518 |
|
|
Miroslav Benes |
c5e518 |
The fake signal is send automatically now. We can rely on it completely
|
|
Miroslav Benes |
c5e518 |
and remove the sysfs attribute.
|
|
Miroslav Benes |
c5e518 |
|
|
Miroslav Benes |
c5e518 |
Signed-off-by: Miroslav Benes <mbenes@suse.cz>
|
|
Miroslav Benes |
c5e518 |
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
|
|
Miroslav Benes |
c5e518 |
---
|
|
Miroslav Benes |
c5e518 |
Documentation/ABI/testing/sysfs-kernel-livepatch | 12 ----
|
|
Miroslav Benes |
c5e518 |
Documentation/livepatch/livepatch.txt | 16 ++---
|
|
Miroslav Benes |
c5e518 |
kernel/livepatch/core.c | 32 ---------
|
|
Miroslav Benes |
c5e518 |
kernel/livepatch/transition.c | 82 ++++++++++++------------
|
|
Miroslav Benes |
c5e518 |
kernel/livepatch/transition.h | 1 -
|
|
Miroslav Benes |
c5e518 |
5 files changed, 48 insertions(+), 95 deletions(-)
|
|
Miroslav Benes |
c5e518 |
|
|
Miroslav Benes |
c5e518 |
diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch
|
|
Miroslav Benes |
c5e518 |
index dac7e1e62a8b..85db352f68f9 100644
|
|
Miroslav Benes |
c5e518 |
--- a/Documentation/ABI/testing/sysfs-kernel-livepatch
|
|
Miroslav Benes |
c5e518 |
+++ b/Documentation/ABI/testing/sysfs-kernel-livepatch
|
|
Miroslav Benes |
c5e518 |
@@ -33,18 +33,6 @@ Contact: live-patching@vger.kernel.org
|
|
Miroslav Benes |
c5e518 |
An attribute which indicates whether the patch is currently in
|
|
Miroslav Benes |
c5e518 |
transition.
|
|
Miroslav Benes |
c5e518 |
|
|
Miroslav Benes |
c5e518 |
-What: /sys/kernel/livepatch/<patch>/signal
|
|
Miroslav Benes |
c5e518 |
-Date: Nov 2017
|
|
Miroslav Benes |
c5e518 |
-KernelVersion: 4.15.0
|
|
Miroslav Benes |
c5e518 |
-Contact: live-patching@vger.kernel.org
|
|
Miroslav Benes |
c5e518 |
-Description:
|
|
Miroslav Benes |
c5e518 |
- A writable attribute that allows administrator to affect the
|
|
Miroslav Benes |
c5e518 |
- course of an existing transition. Writing 1 sends a fake
|
|
Miroslav Benes |
c5e518 |
- signal to all remaining blocking tasks. The fake signal
|
|
Miroslav Benes |
c5e518 |
- means that no proper signal is delivered (there is no data in
|
|
Miroslav Benes |
c5e518 |
- signal pending structures). Tasks are interrupted or woken up,
|
|
Miroslav Benes |
c5e518 |
- and forced to change their patched state.
|
|
Miroslav Benes |
c5e518 |
-
|
|
Miroslav Benes |
c5e518 |
What: /sys/kernel/livepatch/<patch>/force
|
|
Miroslav Benes |
c5e518 |
Date: Nov 2017
|
|
Miroslav Benes |
c5e518 |
KernelVersion: 4.15.0
|
|
Miroslav Benes |
c5e518 |
diff --git a/Documentation/livepatch/livepatch.txt b/Documentation/livepatch/livepatch.txt
|
|
Miroslav Benes |
c5e518 |
index 407e0f03dc99..4627b41ff02e 100644
|
|
Miroslav Benes |
c5e518 |
--- a/Documentation/livepatch/livepatch.txt
|
|
Miroslav Benes |
c5e518 |
+++ b/Documentation/livepatch/livepatch.txt
|
|
Miroslav Benes |
c5e518 |
@@ -158,13 +158,11 @@ If a patch is in transition, this file shows 0 to indicate the task is
|
|
Miroslav Benes |
c5e518 |
unpatched and 1 to indicate it's patched. Otherwise, if no patch is in
|
|
Miroslav Benes |
c5e518 |
transition, it shows -1. Any tasks which are blocking the transition
|
|
Miroslav Benes |
c5e518 |
can be signaled with SIGSTOP and SIGCONT to force them to change their
|
|
Miroslav Benes |
c5e518 |
-patched state. This may be harmful to the system though.
|
|
Miroslav Benes |
c5e518 |
-/sys/kernel/livepatch/<patch>/signal attribute provides a better alternative.
|
|
Miroslav Benes |
c5e518 |
-Writing 1 to the attribute sends a fake signal to all remaining blocking
|
|
Miroslav Benes |
c5e518 |
-tasks. No proper signal is actually delivered (there is no data in signal
|
|
Miroslav Benes |
c5e518 |
-pending structures). Tasks are interrupted or woken up, and forced to change
|
|
Miroslav Benes |
c5e518 |
-their patched state. Despite the sysfs attribute the fake signal is also sent
|
|
Miroslav Benes |
c5e518 |
-every 15 seconds automatically.
|
|
Miroslav Benes |
c5e518 |
+patched state. This may be harmful to the system though. Sending a fake signal
|
|
Miroslav Benes |
c5e518 |
+to all remaining blocking tasks is a better alternative. No proper signal is
|
|
Miroslav Benes |
c5e518 |
+actually delivered (there is no data in signal pending structures). Tasks are
|
|
Miroslav Benes |
c5e518 |
+interrupted or woken up, and forced to change their patched state. The fake
|
|
Miroslav Benes |
c5e518 |
+signal is automatically sent every 15 seconds.
|
|
Miroslav Benes |
c5e518 |
|
|
Miroslav Benes |
c5e518 |
Administrator can also affect a transition through
|
|
Miroslav Benes |
c5e518 |
/sys/kernel/livepatch/<patch>/force attribute. Writing 1 there clears
|
|
Miroslav Benes |
c5e518 |
@@ -412,8 +410,8 @@ Information about the registered patches can be found under
|
|
Miroslav Benes |
c5e518 |
/sys/kernel/livepatch. The patches could be enabled and disabled
|
|
Miroslav Benes |
c5e518 |
by writing there.
|
|
Miroslav Benes |
c5e518 |
|
|
Miroslav Benes |
c5e518 |
-/sys/kernel/livepatch/<patch>/signal and /sys/kernel/livepatch/<patch>/force
|
|
Miroslav Benes |
c5e518 |
-attributes allow administrator to affect a patching operation.
|
|
Miroslav Benes |
c5e518 |
+/sys/kernel/livepatch/<patch>/force attributes allow administrator to affect a
|
|
Miroslav Benes |
c5e518 |
+patching operation.
|
|
Miroslav Benes |
c5e518 |
|
|
Miroslav Benes |
c5e518 |
See Documentation/ABI/testing/sysfs-kernel-livepatch for more details.
|
|
Miroslav Benes |
c5e518 |
|
|
Miroslav Benes |
c5e518 |
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
|
|
Miroslav Benes |
c5e518 |
index adca5cf07f7e..fe1993399823 100644
|
|
Miroslav Benes |
c5e518 |
--- a/kernel/livepatch/core.c
|
|
Miroslav Benes |
c5e518 |
+++ b/kernel/livepatch/core.c
|
|
Miroslav Benes |
c5e518 |
@@ -313,7 +313,6 @@ static int klp_write_object_relocations(struct module *pmod,
|
|
Miroslav Benes |
c5e518 |
* /sys/kernel/livepatch/<patch>
|
|
Miroslav Benes |
c5e518 |
* /sys/kernel/livepatch/<patch>/enabled
|
|
Miroslav Benes |
c5e518 |
* /sys/kernel/livepatch/<patch>/transition
|
|
Miroslav Benes |
c5e518 |
- * /sys/kernel/livepatch/<patch>/signal
|
|
Miroslav Benes |
c5e518 |
* /sys/kernel/livepatch/<patch>/force
|
|
Miroslav Benes |
c5e518 |
* /sys/kernel/livepatch/<patch>/<object>
|
|
Miroslav Benes |
c5e518 |
* /sys/kernel/livepatch/<patch>/<object>/<function,sympos>
|
|
Miroslav Benes |
c5e518 |
@@ -382,35 +381,6 @@ static ssize_t transition_show(struct kobject *kobj,
|
|
Miroslav Benes |
c5e518 |
patch == klp_transition_patch);
|
|
Miroslav Benes |
c5e518 |
}
|
|
Miroslav Benes |
c5e518 |
|
|
Miroslav Benes |
c5e518 |
-static ssize_t signal_store(struct kobject *kobj, struct kobj_attribute *attr,
|
|
Miroslav Benes |
c5e518 |
- const char *buf, size_t count)
|
|
Miroslav Benes |
c5e518 |
-{
|
|
Miroslav Benes |
c5e518 |
- struct klp_patch *patch;
|
|
Miroslav Benes |
c5e518 |
- int ret;
|
|
Miroslav Benes |
c5e518 |
- bool val;
|
|
Miroslav Benes |
c5e518 |
-
|
|
Miroslav Benes |
c5e518 |
- ret = kstrtobool(buf, &val;;
|
|
Miroslav Benes |
c5e518 |
- if (ret)
|
|
Miroslav Benes |
c5e518 |
- return ret;
|
|
Miroslav Benes |
c5e518 |
-
|
|
Miroslav Benes |
c5e518 |
- if (!val)
|
|
Miroslav Benes |
c5e518 |
- return count;
|
|
Miroslav Benes |
c5e518 |
-
|
|
Miroslav Benes |
c5e518 |
- mutex_lock(&klp_mutex);
|
|
Miroslav Benes |
c5e518 |
-
|
|
Miroslav Benes |
c5e518 |
- patch = container_of(kobj, struct klp_patch, kobj);
|
|
Miroslav Benes |
c5e518 |
- if (patch != klp_transition_patch) {
|
|
Miroslav Benes |
c5e518 |
- mutex_unlock(&klp_mutex);
|
|
Miroslav Benes |
c5e518 |
- return -EINVAL;
|
|
Miroslav Benes |
c5e518 |
- }
|
|
Miroslav Benes |
c5e518 |
-
|
|
Miroslav Benes |
c5e518 |
- klp_send_signals();
|
|
Miroslav Benes |
c5e518 |
-
|
|
Miroslav Benes |
c5e518 |
- mutex_unlock(&klp_mutex);
|
|
Miroslav Benes |
c5e518 |
-
|
|
Miroslav Benes |
c5e518 |
- return count;
|
|
Miroslav Benes |
c5e518 |
-}
|
|
Miroslav Benes |
c5e518 |
-
|
|
Miroslav Benes |
c5e518 |
static ssize_t force_store(struct kobject *kobj, struct kobj_attribute *attr,
|
|
Miroslav Benes |
c5e518 |
const char *buf, size_t count)
|
|
Miroslav Benes |
c5e518 |
{
|
|
Miroslav Benes |
c5e518 |
@@ -442,12 +412,10 @@ static ssize_t force_store(struct kobject *kobj, struct kobj_attribute *attr,
|
|
Miroslav Benes |
c5e518 |
|
|
Miroslav Benes |
c5e518 |
static struct kobj_attribute enabled_kobj_attr = __ATTR_RW(enabled);
|
|
Miroslav Benes |
c5e518 |
static struct kobj_attribute transition_kobj_attr = __ATTR_RO(transition);
|
|
Miroslav Benes |
c5e518 |
-static struct kobj_attribute signal_kobj_attr = __ATTR_WO(signal);
|
|
Miroslav Benes |
c5e518 |
static struct kobj_attribute force_kobj_attr = __ATTR_WO(force);
|
|
Miroslav Benes |
c5e518 |
static struct attribute *klp_patch_attrs[] = {
|
|
Miroslav Benes |
c5e518 |
&enabled_kobj_attr.attr,
|
|
Miroslav Benes |
c5e518 |
&transition_kobj_attr.attr,
|
|
Miroslav Benes |
c5e518 |
- &signal_kobj_attr.attr,
|
|
Miroslav Benes |
c5e518 |
&force_kobj_attr.attr,
|
|
Miroslav Benes |
c5e518 |
NULL
|
|
Miroslav Benes |
c5e518 |
};
|
|
Miroslav Benes |
c5e518 |
diff --git a/kernel/livepatch/transition.c b/kernel/livepatch/transition.c
|
|
Miroslav Benes |
c5e518 |
index ea7697bb753e..183b2086ba03 100644
|
|
Miroslav Benes |
c5e518 |
--- a/kernel/livepatch/transition.c
|
|
Miroslav Benes |
c5e518 |
+++ b/kernel/livepatch/transition.c
|
|
Miroslav Benes |
c5e518 |
@@ -347,6 +347,47 @@ static bool klp_try_switch_task(struct task_struct *task)
|
|
Miroslav Benes |
c5e518 |
|
|
Miroslav Benes |
c5e518 |
}
|
|
Miroslav Benes |
c5e518 |
|
|
Miroslav Benes |
c5e518 |
+/*
|
|
Miroslav Benes |
c5e518 |
+ * Sends a fake signal to all non-kthread tasks with TIF_PATCH_PENDING set.
|
|
Miroslav Benes |
c5e518 |
+ * Kthreads with TIF_PATCH_PENDING set are woken up.
|
|
Miroslav Benes |
c5e518 |
+ */
|
|
Miroslav Benes |
c5e518 |
+static void klp_send_signals(void)
|
|
Miroslav Benes |
c5e518 |
+{
|
|
Miroslav Benes |
c5e518 |
+ struct task_struct *g, *task;
|
|
Miroslav Benes |
c5e518 |
+
|
|
Miroslav Benes |
c5e518 |
+ if (klp_signals_cnt == SIGNALS_TIMEOUT)
|
|
Miroslav Benes |
c5e518 |
+ pr_notice("signaling remaining tasks\n");
|
|
Miroslav Benes |
c5e518 |
+
|
|
Miroslav Benes |
c5e518 |
+ read_lock(&tasklist_lock);
|
|
Miroslav Benes |
c5e518 |
+ for_each_process_thread(g, task) {
|
|
Miroslav Benes |
c5e518 |
+ if (!klp_patch_pending(task))
|
|
Miroslav Benes |
c5e518 |
+ continue;
|
|
Miroslav Benes |
c5e518 |
+
|
|
Miroslav Benes |
c5e518 |
+ /*
|
|
Miroslav Benes |
c5e518 |
+ * There is a small race here. We could see TIF_PATCH_PENDING
|
|
Miroslav Benes |
c5e518 |
+ * set and decide to wake up a kthread or send a fake signal.
|
|
Miroslav Benes |
c5e518 |
+ * Meanwhile the task could migrate itself and the action
|
|
Miroslav Benes |
c5e518 |
+ * would be meaningless. It is not serious though.
|
|
Miroslav Benes |
c5e518 |
+ */
|
|
Miroslav Benes |
c5e518 |
+ if (task->flags & PF_KTHREAD) {
|
|
Miroslav Benes |
c5e518 |
+ /*
|
|
Miroslav Benes |
c5e518 |
+ * Wake up a kthread which sleeps interruptedly and
|
|
Miroslav Benes |
c5e518 |
+ * still has not been migrated.
|
|
Miroslav Benes |
c5e518 |
+ */
|
|
Miroslav Benes |
c5e518 |
+ wake_up_state(task, TASK_INTERRUPTIBLE);
|
|
Miroslav Benes |
c5e518 |
+ } else {
|
|
Miroslav Benes |
c5e518 |
+ /*
|
|
Miroslav Benes |
c5e518 |
+ * Send fake signal to all non-kthread tasks which are
|
|
Miroslav Benes |
c5e518 |
+ * still not migrated.
|
|
Miroslav Benes |
c5e518 |
+ */
|
|
Miroslav Benes |
c5e518 |
+ spin_lock_irq(&task->sighand->siglock);
|
|
Miroslav Benes |
c5e518 |
+ signal_wake_up(task, 0);
|
|
Miroslav Benes |
c5e518 |
+ spin_unlock_irq(&task->sighand->siglock);
|
|
Miroslav Benes |
c5e518 |
+ }
|
|
Miroslav Benes |
c5e518 |
+ }
|
|
Miroslav Benes |
c5e518 |
+ read_unlock(&tasklist_lock);
|
|
Miroslav Benes |
c5e518 |
+}
|
|
Miroslav Benes |
c5e518 |
+
|
|
Miroslav Benes |
c5e518 |
/*
|
|
Miroslav Benes |
c5e518 |
* Try to switch all remaining tasks to the target patch state by walking the
|
|
Miroslav Benes |
c5e518 |
* stacks of sleeping tasks and looking for any to-be-patched or
|
|
Miroslav Benes |
c5e518 |
@@ -586,47 +627,6 @@ void klp_copy_process(struct task_struct *child)
|
|
Miroslav Benes |
c5e518 |
/* TIF_PATCH_PENDING gets copied in setup_thread_stack() */
|
|
Miroslav Benes |
c5e518 |
}
|
|
Miroslav Benes |
c5e518 |
|
|
Miroslav Benes |
c5e518 |
-/*
|
|
Miroslav Benes |
c5e518 |
- * Sends a fake signal to all non-kthread tasks with TIF_PATCH_PENDING set.
|
|
Miroslav Benes |
c5e518 |
- * Kthreads with TIF_PATCH_PENDING set are woken up.
|
|
Miroslav Benes |
c5e518 |
- */
|
|
Miroslav Benes |
c5e518 |
-void klp_send_signals(void)
|
|
Miroslav Benes |
c5e518 |
-{
|
|
Miroslav Benes |
c5e518 |
- struct task_struct *g, *task;
|
|
Miroslav Benes |
c5e518 |
-
|
|
Miroslav Benes |
c5e518 |
- if (klp_signals_cnt == SIGNALS_TIMEOUT)
|
|
Miroslav Benes |
c5e518 |
- pr_notice("signaling remaining tasks\n");
|
|
Miroslav Benes |
c5e518 |
-
|
|
Miroslav Benes |
c5e518 |
- read_lock(&tasklist_lock);
|
|
Miroslav Benes |
c5e518 |
- for_each_process_thread(g, task) {
|
|
Miroslav Benes |
c5e518 |
- if (!klp_patch_pending(task))
|
|
Miroslav Benes |
c5e518 |
- continue;
|
|
Miroslav Benes |
c5e518 |
-
|
|
Miroslav Benes |
c5e518 |
- /*
|
|
Miroslav Benes |
c5e518 |
- * There is a small race here. We could see TIF_PATCH_PENDING
|
|
Miroslav Benes |
c5e518 |
- * set and decide to wake up a kthread or send a fake signal.
|
|
Miroslav Benes |
c5e518 |
- * Meanwhile the task could migrate itself and the action
|
|
Miroslav Benes |
c5e518 |
- * would be meaningless. It is not serious though.
|
|
Miroslav Benes |
c5e518 |
- */
|
|
Miroslav Benes |
c5e518 |
- if (task->flags & PF_KTHREAD) {
|
|
Miroslav Benes |
c5e518 |
- /*
|
|
Miroslav Benes |
c5e518 |
- * Wake up a kthread which sleeps interruptedly and
|
|
Miroslav Benes |
c5e518 |
- * still has not been migrated.
|
|
Miroslav Benes |
c5e518 |
- */
|
|
Miroslav Benes |
c5e518 |
- wake_up_state(task, TASK_INTERRUPTIBLE);
|
|
Miroslav Benes |
c5e518 |
- } else {
|
|
Miroslav Benes |
c5e518 |
- /*
|
|
Miroslav Benes |
c5e518 |
- * Send fake signal to all non-kthread tasks which are
|
|
Miroslav Benes |
c5e518 |
- * still not migrated.
|
|
Miroslav Benes |
c5e518 |
- */
|
|
Miroslav Benes |
c5e518 |
- spin_lock_irq(&task->sighand->siglock);
|
|
Miroslav Benes |
c5e518 |
- signal_wake_up(task, 0);
|
|
Miroslav Benes |
c5e518 |
- spin_unlock_irq(&task->sighand->siglock);
|
|
Miroslav Benes |
c5e518 |
- }
|
|
Miroslav Benes |
c5e518 |
- }
|
|
Miroslav Benes |
c5e518 |
- read_unlock(&tasklist_lock);
|
|
Miroslav Benes |
c5e518 |
-}
|
|
Miroslav Benes |
c5e518 |
-
|
|
Miroslav Benes |
c5e518 |
/*
|
|
Miroslav Benes |
c5e518 |
* Drop TIF_PATCH_PENDING of all tasks on admin's request. This forces an
|
|
Miroslav Benes |
c5e518 |
* existing transition to finish.
|
|
Miroslav Benes |
c5e518 |
diff --git a/kernel/livepatch/transition.h b/kernel/livepatch/transition.h
|
|
Miroslav Benes |
c5e518 |
index f9d0bc016067..322db16233de 100644
|
|
Miroslav Benes |
c5e518 |
--- a/kernel/livepatch/transition.h
|
|
Miroslav Benes |
c5e518 |
+++ b/kernel/livepatch/transition.h
|
|
Miroslav Benes |
c5e518 |
@@ -11,7 +11,6 @@ void klp_cancel_transition(void);
|
|
Miroslav Benes |
c5e518 |
void klp_start_transition(void);
|
|
Miroslav Benes |
c5e518 |
void klp_try_complete_transition(void);
|
|
Miroslav Benes |
c5e518 |
void klp_reverse_transition(void);
|
|
Miroslav Benes |
c5e518 |
-void klp_send_signals(void);
|
|
Miroslav Benes |
c5e518 |
void klp_force_transition(void);
|
|
Miroslav Benes |
c5e518 |
|
|
Miroslav Benes |
c5e518 |
#endif /* _LIVEPATCH_TRANSITION_H */
|
|
Miroslav Benes |
c5e518 |
|