lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
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

Powered by Openwall GNU/*/Linux Powered by OpenVZ