Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date: Thu, 9 Dec 2010 22:15:28 +0300
From: Solar Designer <solar@...nwall.com>
To: oss-security@...ts.openwall.com
Subject: Re: kernel: Dangerous interaction between clear_child_tid, set_fs(), and kernel oopses

On Wed, Dec 08, 2010 at 10:34:38AM -0500, Nelson Elhage wrote:
> ... rearrange things so that the flow
> is "check interrupt -> set_fs() -> everything else".

This is what I did.  Works fine so far.

--- linux-2.6.18-194.26.1.el5.028stab079.1/kernel/exit.c	2010-11-30 12:26:53 +0000
+++ linux-2.6.18-194.26.1.el5.028stab079.1-owl/kernel/exit.c	2010-12-09 09:49:18 +0000
@@ -949,12 +949,28 @@ fastcall NORET_TYPE void do_exit(long co
 	int group_dead;
 	unsigned int mycpu;
 
+	/*
+	 * Check this first since set_fs() below depends on
+	 * current_thread_info(), which we better not access when we're in
+	 * interrupt context.  Other than that, we want to do the set_fs()
+	 * as early as possible.
+	 */
+	if (unlikely(in_interrupt()))
+		panic("Aiee, killing interrupt handler!");
+
+	/*
+	 * If do_exit is called because this process Oops'ed, it's possible
+	 * that get_fs() was left as KERNEL_DS, so reset it to USER_DS before
+	 * continuing. Amongst other possible reasons, this is to prevent
+	 * mm_release()->clear_child_tid() from writing to a user-controlled
+	 * kernel address.
+	 */
+	set_fs(USER_DS);
+
 	profile_task_exit(tsk);
 
 	WARN_ON(atomic_read(&tsk->fs_excl));
 
-	if (unlikely(in_interrupt()))
-		panic("Aiee, killing interrupt handler!");
 	if (unlikely(!tsk->pid))
 		panic("Attempted to kill the idle task!");
 #ifdef CONFIG_VE

Thanks,

Alexander

Powered by blists - more mailing lists

Your e-mail address:

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.