linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jiri Slaby <jslaby@suse.cz>
To: live-patching@vger.kernel.org
Cc: jpoimboe@redhat.com, sjenning@redhat.com, jkosina@suse.cz,
	vojtech@suse.cz, mingo@redhat.com, linux-kernel@vger.kernel.org,
	Miroslav Benes <mbenes@suse.cz>, Oleg Nesterov <oleg@redhat.com>,
	Peter Zijlstra <peterz@infradead.org>,
	Jiri Slaby <jslaby@suse.cz>
Subject: [RFC kgr on klp 9/9] livepatch: send a fake signal to all tasks
Date: Mon,  4 May 2015 13:40:25 +0200	[thread overview]
Message-ID: <1430739625-4658-9-git-send-email-jslaby@suse.cz> (raw)
In-Reply-To: <1430739625-4658-1-git-send-email-jslaby@suse.cz>

From: Miroslav Benes <mbenes@suse.cz>

kGraft consistency model is of LEAVE_KERNEL and SWITCH_THREAD. This
means that all tasks in the system have to be marked one by one as safe
to call a new patched function. Safe place is on the boundary between
kernel and userspace. The patching waits for all tasks to cross this
boundary and finishes the process afterwards.

The problem is that a task can block the finalization of patching
process for quite a long time, if not forever. The task could sleep
somewhere in the kernel or could be running in the userspace with no
prospect of entering the kernel and thus going through the safe place.

Luckily we can force the task to do that by sending it a fake signal,
that is a signal with no data in signal pending structures (no handler,
no sign of proper signal delivered). Suspend/freezer use this to
freeze the tasks as well. The task gets TIF_SIGPENDING set and is
woken up (if it has been sleeping in the kernel before) or kicked by
rescheduling IPI (if it was running on other CPU). This causes the task
to go to kernel/userspace boundary where the signal would be handled and
the task would be marked as safe in terms of live patching.

There are tasks which are not affected by this technique though. The
fake signal is not sent to kthreads. They should be handled in a
different way. Also if the task is in TASK_RUNNING state but not
currently running on some CPU it doesn't get the IPI, but it would
eventually handle the signal anyway. Last, if the task runs in the kernel
(in TASK_RUNNING state) it gets the IPI, but the signal is not handled
on return from the interrupt. It would be handled on return to the
userspace in the future.

If the task was sleeping in a syscall it would be woken by our fake
signal, it would check if TIF_SIGPENDING is set (by calling
signal_pending() predicate) and return ERESTART* or EINTR. Syscalls with
ERESTART* return values are restarted in case of the fake signal (see
do_signal()). EINTR is propagated back to the userspace program. This
could disturb the program, but...

  * each process dealing with signals should react accordingly to EINTR
    return values.
  * syscalls returning EINTR happen to be quite common situation in the
    system even if no fake signal is sent.
  * freezer sends the fake signal and does not deal with EINTR anyhow.
    Thus EINTR values are returned when the system is resumed.

The very safe marking is done in entry_64.S on syscall and
interrupt/exception exit paths.

Signed-off-by: Miroslav Benes <mbenes@suse.cz>
Reviewed-by: Jiri Kosina <jkosina@suse.cz>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 kernel/livepatch/cmodel-kgraft.c | 23 +++++++++++++++++++++++
 kernel/signal.c                  |  3 ++-
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/kernel/livepatch/cmodel-kgraft.c b/kernel/livepatch/cmodel-kgraft.c
index 196b08823f73..fd041ca30161 100644
--- a/kernel/livepatch/cmodel-kgraft.c
+++ b/kernel/livepatch/cmodel-kgraft.c
@@ -107,6 +107,27 @@ static bool klp_kgraft_still_patching(void)
 	return failed;
 }
 
+static void klp_kgraft_send_fake_signal(void)
+{
+	struct task_struct *p;
+	unsigned long flags;
+
+	read_lock(&tasklist_lock);
+	for_each_process(p) {
+		/*
+		 * send fake signal to all non-kthread processes which are still
+		 * not migrated
+		 */
+		if (!(p->flags & PF_KTHREAD) &&
+		    klp_kgraft_task_in_progress(p) &&
+		    lock_task_sighand(p, &flags)) {
+			signal_wake_up(p, 0);
+			unlock_task_sighand(p, &flags);
+		}
+	}
+	read_unlock(&tasklist_lock);
+}
+
 static void klp_kgraft_work_fn(struct work_struct *work)
 {
 	static bool printed = false;
@@ -117,6 +138,8 @@ static void klp_kgraft_work_fn(struct work_struct *work)
 				KGRAFT_TIMEOUT);
 			printed = true;
 		}
+		/* send fake signal */
+		klp_kgraft_send_fake_signal();
 		/* recheck again later */
 		queue_delayed_work(klp_kgraft_wq, &klp_kgraft_work,
 				KGRAFT_TIMEOUT * HZ);
diff --git a/kernel/signal.c b/kernel/signal.c
index d51c5ddd855c..5a3f56a69122 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -157,7 +157,8 @@ void recalc_sigpending_and_wake(struct task_struct *t)
 
 void recalc_sigpending(void)
 {
-	if (!recalc_sigpending_tsk(current) && !freezing(current))
+	if (!recalc_sigpending_tsk(current) && !freezing(current) &&
+	    !klp_kgraft_task_in_progress(current))
 		clear_thread_flag(TIF_SIGPENDING);
 
 }
-- 
2.3.5


  parent reply	other threads:[~2015-05-04 11:40 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-04 11:40 [RFC kgr on klp 1/9] livepatch: make kobject in klp_object statically allocated Jiri Slaby
2015-05-04 11:40 ` [RFC kgr on klp 2/9] livepatch: introduce patch/func-walking helpers Jiri Slaby
2015-05-04 11:40 ` [RFC kgr on klp 3/9] livepatch: add klp_*_to_patch helpers Jiri Slaby
2015-05-04 11:40 ` [RFC kgr on klp 4/9] livepatch: add kgr infrastructure Jiri Slaby
2015-05-04 12:23   ` Martin Schwidefsky
2015-05-05 13:27     ` Jiri Slaby
2015-05-05 14:34       ` Martin Schwidefsky
2015-05-04 11:40 ` [RFC kgr on klp 5/9] livepatch: teach klp about consistency models Jiri Slaby
2015-05-04 11:40 ` [RFC kgr on klp 6/9] livepatch: do not allow failure while really patching Jiri Slaby
2015-05-04 11:40 ` [RFC kgr on klp 7/9] livepatch: propagate the patch status to functions Jiri Slaby
2015-05-04 11:40 ` [RFC kgr on klp 8/9] livepatch: add kgraft-like patching Jiri Slaby
2015-05-04 11:40 ` Jiri Slaby [this message]
2015-05-04 14:34   ` [RFC kgr on klp 9/9] livepatch: send a fake signal to all tasks Oleg Nesterov
2015-05-06 12:58     ` Miroslav Benes
2015-05-04 12:20 ` [RFC kgr on klp 0/9] kGraft on the top of KLP Jiri Slaby
2015-05-04 15:44   ` Josh Poimboeuf
2015-05-04 22:48     ` Jiri Kosina
2015-05-05  3:43       ` Josh Poimboeuf
2015-05-05  6:14         ` Jiri Kosina
2015-05-05 16:24           ` Josh Poimboeuf
2015-05-12  9:45             ` Jiri Kosina
2015-05-12 15:20               ` Josh Poimboeuf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1430739625-4658-9-git-send-email-jslaby@suse.cz \
    --to=jslaby@suse.cz \
    --cc=jkosina@suse.cz \
    --cc=jpoimboe@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=live-patching@vger.kernel.org \
    --cc=mbenes@suse.cz \
    --cc=mingo@redhat.com \
    --cc=oleg@redhat.com \
    --cc=peterz@infradead.org \
    --cc=sjenning@redhat.com \
    --cc=vojtech@suse.cz \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).