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