rpms/kernel/F-11 fs-pipe-null-ptr-deref-fix.patch, NONE, 1.1 kernel.spec, 1.1774, 1.1775

Kyle McMartin kyle at fedoraproject.org
Wed Nov 4 03:54:25 UTC 2009


Author: kyle

Update of /cvs/pkgs/rpms/kernel/F-11
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv23670

Modified Files:
	kernel.spec 
Added Files:
	fs-pipe-null-ptr-deref-fix.patch 
Log Message:
* Tue Nov 03 2009 Kyle McMartin <kyle at redhat.com> 2.6.30.9-96
- fs/pipe.c: fix null pointer dereference (CVE-2009-3547)


fs-pipe-null-ptr-deref-fix.patch:
 pipe.c |   42 ++++++++++++++++++++++++++++++------------
 1 file changed, 30 insertions(+), 12 deletions(-)

--- NEW FILE fs-pipe-null-ptr-deref-fix.patch ---
>From ad3960243e55320d74195fb85c975e0a8cc4466c Mon Sep 17 00:00:00 2001
From: Earl Chew <earl_chew at agilent.com>
Date: Mon, 19 Oct 2009 15:55:41 -0700
Subject: [PATCH] fs: pipe.c null pointer dereference

This patch fixes a null pointer exception in pipe_rdwr_open() which
generates the stack trace:

> Unable to handle kernel NULL pointer dereference at 0000000000000028 RIP:
>  [<ffffffff802899a5>] pipe_rdwr_open+0x35/0x70
>  [<ffffffff8028125c>] __dentry_open+0x13c/0x230
>  [<ffffffff8028143d>] do_filp_open+0x2d/0x40
>  [<ffffffff802814aa>] do_sys_open+0x5a/0x100
>  [<ffffffff8021faf3>] sysenter_do_call+0x1b/0x67

The failure mode is triggered by an attempt to open an anonymous
pipe via /proc/pid/fd/* as exemplified by this script:

=============================================================
while : ; do
   { echo y ; sleep 1 ; } | { while read ; do echo z$REPLY; done ; } &
   PID=$!
   OUT=$(ps -efl | grep 'sleep 1' | grep -v grep |
        { read PID REST ; echo $PID; } )
   OUT="${OUT%% *}"
   DELAY=$((RANDOM * 1000 / 32768))
   usleep $((DELAY * 1000 + RANDOM % 1000 ))
   echo n > /proc/$OUT/fd/1                 # Trigger defect
done
=============================================================

Note that the failure window is quite small and I could only
reliably reproduce the defect by inserting a small delay
in pipe_rdwr_open(). For example:

 static int
 pipe_rdwr_open(struct inode *inode, struct file *filp)
 {
       msleep(100);
       mutex_lock(&inode->i_mutex);

Although the defect was observed in pipe_rdwr_open(), I think it
makes sense to replicate the change through all the pipe_*_open()
functions.

The core of the change is to verify that inode->i_pipe has not
been released before attempting to manipulate it. If inode->i_pipe
is no longer present, return ENOENT to indicate so.

The comment about potentially using atomic_t for i_pipe->readers
and i_pipe->writers has also been removed because it is no longer
relevant in this context. The inode->i_mutex lock must be used so
that inode->i_pipe can be dealt with correctly.

Signed-off-by: Earl Chew <earl_chew at agilent.com>
Cc: stable at kernel.org
Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
---
 fs/pipe.c |   41 ++++++++++++++++++++++++++++++-----------
 1 files changed, 30 insertions(+), 11 deletions(-)

diff --git a/fs/pipe.c b/fs/pipe.c
index 52c4151..ae17d02 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -777,36 +777,55 @@ pipe_rdwr_release(struct inode *inode, struct file *filp)
 static int
 pipe_read_open(struct inode *inode, struct file *filp)
 {
-	/* We could have perhaps used atomic_t, but this and friends
-	   below are the only places.  So it doesn't seem worthwhile.  */
+	int ret = -ENOENT;
+
 	mutex_lock(&inode->i_mutex);
-	inode->i_pipe->readers++;
+
+	if (inode->i_pipe) {
+		ret = 0;
+		inode->i_pipe->readers++;
+	}
+
 	mutex_unlock(&inode->i_mutex);
 
-	return 0;
+	return ret;
 }
 
 static int
 pipe_write_open(struct inode *inode, struct file *filp)
 {
+	int ret = -ENOENT;
+
 	mutex_lock(&inode->i_mutex);
-	inode->i_pipe->writers++;
+
+	if (inode->i_pipe) {
+		ret = 0;
+		inode->i_pipe->writers++;
+	}
+
 	mutex_unlock(&inode->i_mutex);
 
-	return 0;
+	return ret;
 }
 
 static int
 pipe_rdwr_open(struct inode *inode, struct file *filp)
 {
+	int ret = -ENOENT;
+
 	mutex_lock(&inode->i_mutex);
-	if (filp->f_mode & FMODE_READ)
-		inode->i_pipe->readers++;
-	if (filp->f_mode & FMODE_WRITE)
-		inode->i_pipe->writers++;
+
+	if (inode->i_pipe) {
+		ret = 0;
+		if (filp->f_mode & FMODE_READ)
+			inode->i_pipe->readers++;
+		if (filp->f_mode & FMODE_WRITE)
+			inode->i_pipe->writers++;
+	}
+
 	mutex_unlock(&inode->i_mutex);
 
-	return 0;
+	return ret;
 }
 
 /*
-- 
1.6.5.1



Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-11/kernel.spec,v
retrieving revision 1.1774
retrieving revision 1.1775
diff -u -p -r1.1774 -r1.1775
--- kernel.spec	25 Oct 2009 10:45:32 -0000	1.1774
+++ kernel.spec	4 Nov 2009 03:54:25 -0000	1.1775
@@ -829,6 +829,10 @@ Patch16430: kvm-prevent-overflow-in-kvm-
 # disable the stackprotector on fns that don't have onstack arrays
 Patch16440: disable-stackprotector-all.patch
 
+# fs/pipe.c: null ptr dereference fix
+# rhbz#530490 (CVE-2009-3547) [ad3960243e55320d74195fb85c975e0a8cc4466c]
+Patch16450: fs-pipe-null-ptr-deref-fix.patch
+
 %endif
 
 BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root
@@ -1555,6 +1559,10 @@ ApplyPatch kvm-prevent-overflow-in-kvm-g
 # disable the stackprotector on fns that don't have onstack arrays
 ApplyPatch disable-stackprotector-all.patch
 
+# fs/pipe.c: null ptr dereference fix
+# rhbz#530490 (CVE-2009-3547) [ad3960243e55320d74195fb85c975e0a8cc4466c]
+ApplyPatch fs-pipe-null-ptr-deref-fix.patch
+
 # END OF PATCH APPLICATIONS
 
 %endif
@@ -2143,6 +2151,9 @@ fi
 # and build.
 
 %changelog
+* Tue Nov 03 2009 Kyle McMartin <kyle at redhat.com> 2.6.30.9-96
+- fs/pipe.c: fix null pointer dereference (CVE-2009-3547)
+
 * Sun Oct 25 2009 Chuck Ebbert <cebbert at redhat.com>  2.6.30.9-95
 - Disable the stack protector on functions that don't have onstack arrays.
 




More information about the fedora-extras-commits mailing list