[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20110727163427.GH23793@redhat.com>
Date: Wed, 27 Jul 2011 18:34:27 +0200
From: Oleg Nesterov <oleg@...hat.com>
To: Linus Torvalds <torvalds@...ux-foundation.org>,
Roland McGrath <roland@...k.frob.com>,
Tejun Heo <tj@...nel.org>
Cc: Denys Vlasenko <dvlasenk@...hat.com>,
KOSAKI Motohiro <kosaki.motohiro@...fujitsu.com>,
Matt Fleming <matt.fleming@...ux.intel.com>,
linux-kernel@...r.kernel.org
Subject: [PATCH 8/8] vfork: do not block SIG_DFL/SIG_IGN signals is
single-threaded
vfork() blocks all signals except SIGKILL and SIGSTOP. This means
it doesn't react to ^Z or other fatal signals.
We can unblock all signals which doesn't have a handler and solve
this. Unfortunately, without the really ugly hacks we can not do
this in the multithreaded case, we can not trust sighand->action[]
otherwise.
Let's do this in the single-threaded case at least. Anyway, I do
not think that vfork() from the multithreaded application is sane.
And even in this case other threads can handle the blocked signals
unless they exit after clone_vfork_prepare().
Note: "sighand->count == 1" doesn't handle the dead-leader case,
this is easy to fix.
Signed-off-by: Oleg Nesterov <oleg@...hat.com>
---
kernel/fork.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
--- 3.1/kernel/fork.c~8_more_signals 2011-07-27 17:48:53.000000000 +0200
+++ 3.1/kernel/fork.c 2011-07-27 17:51:54.000000000 +0200
@@ -1506,10 +1506,26 @@ static long clone_vfork_restart(struct r
static void clone_vfork_prepare(void)
{
+ struct sighand_struct *sigh = current->sighand;
sigset_t vfork_mask;
- current->saved_sigmask = current->blocked;
siginitsetinv(&vfork_mask, sigmask(SIGKILL) | sigmask(SIGSTOP));
+ if (atomic_read(&sigh->count) == 1) {
+ __sighandler_t h;
+ int signr;
+ /*
+ * Nobody can play with ->action[], we can unblock all
+ * signals which do not have a handler, they can not
+ * trigger return-to-user-mode.
+ */
+ for (signr = 1; signr <= _NSIG; ++signr) {
+ h = sigh->action[signr-1].sa.sa_handler;
+ if (h == SIG_DFL || h == SIG_IGN)
+ sigdelset(&vfork_mask, signr);
+ }
+ }
+
+ current->saved_sigmask = current->blocked;
set_current_blocked(&vfork_mask);
}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists