Chuck Ebbert 14525ab
From: Roland McGrath <roland@redhat.com>
Chuck Ebbert 14525ab
Date: Wed, 8 Sep 2010 02:37:06 +0000 (-0700)
Chuck Ebbert 14525ab
Subject: execve: make responsive to SIGKILL with large arguments
Chuck Ebbert 14525ab
X-Git-Tag: v2.6.36-rc4~12
Chuck Ebbert 14525ab
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=9aea5a65aa7a1af9a4236dfaeb0088f1624f9919
Chuck Ebbert 14525ab
Chuck Ebbert 14525ab
execve: make responsive to SIGKILL with large arguments
Chuck Ebbert 14525ab
Chuck Ebbert 14525ab
An execve with a very large total of argument/environment strings
Chuck Ebbert 14525ab
can take a really long time in the execve system call.  It runs
Chuck Ebbert 14525ab
uninterruptibly to count and copy all the strings.  This change
Chuck Ebbert 14525ab
makes it abort the exec quickly if sent a SIGKILL.
Chuck Ebbert 14525ab
Chuck Ebbert 14525ab
Note that this is the conservative change, to interrupt only for
Chuck Ebbert 14525ab
SIGKILL, by using fatal_signal_pending().  It would be perfectly
Chuck Ebbert 14525ab
correct semantics to let any signal interrupt the string-copying in
Chuck Ebbert 14525ab
execve, i.e. use signal_pending() instead of fatal_signal_pending().
Chuck Ebbert 14525ab
We'll save that change for later, since it could have user-visible
Chuck Ebbert 14525ab
consequences, such as having a timer set too quickly make it so that
Chuck Ebbert 14525ab
an execve can never complete, though it always happened to work before.
Chuck Ebbert 14525ab
Chuck Ebbert 14525ab
Signed-off-by: Roland McGrath <roland@redhat.com>
Chuck Ebbert 14525ab
Reviewed-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Chuck Ebbert 14525ab
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Chuck Ebbert 14525ab
---
Chuck Ebbert 14525ab
Chuck Ebbert 14525ab
diff --git a/fs/exec.c b/fs/exec.c
Chuck Ebbert 14525ab
index 6f2d777..828dd24 100644
Chuck Ebbert 14525ab
--- a/fs/exec.c
Chuck Ebbert 14525ab
+++ b/fs/exec.c
Chuck Ebbert 14525ab
@@ -376,6 +376,9 @@ static int count(const char __user * const __user * argv, int max)
Chuck Ebbert 14525ab
 			argv++;
Chuck Ebbert 14525ab
 			if (i++ >= max)
Chuck Ebbert 14525ab
 				return -E2BIG;
Chuck Ebbert 14525ab
+
Chuck Ebbert 14525ab
+			if (fatal_signal_pending(current))
Chuck Ebbert 14525ab
+				return -ERESTARTNOHAND;
Chuck Ebbert 14525ab
 			cond_resched();
Chuck Ebbert 14525ab
 		}
Chuck Ebbert 14525ab
 	}
Chuck Ebbert 14525ab
@@ -419,6 +422,10 @@ static int copy_strings(int argc, const char __user *const __user *argv,
Chuck Ebbert 14525ab
 		while (len > 0) {
Chuck Ebbert 14525ab
 			int offset, bytes_to_copy;
Chuck Ebbert 14525ab
 
Chuck Ebbert 14525ab
+			if (fatal_signal_pending(current)) {
Chuck Ebbert 14525ab
+				ret = -ERESTARTNOHAND;
Chuck Ebbert 14525ab
+				goto out;
Chuck Ebbert 14525ab
+			}
Chuck Ebbert 14525ab
 			cond_resched();
Chuck Ebbert 14525ab
 
Chuck Ebbert 14525ab
 			offset = pos % PAGE_SIZE;