[kernel] r10559 - in dists/sarge-security/kernel-2.4/source/kernel-source-2.4.27-2.4.27/debian: . patches patches/series

Dann Frazier dannf at alioth.debian.org
Sun Feb 17 18:28:19 UTC 2008


Author: dannf
Date: Sun Feb 17 18:28:18 2008
New Revision: 10559

Log:
* 261_listxattr-mem-corruption.diff
  [SECURITY] Fix userspace corruption vulnerability caused by
  incorrectly promoted return values in bad_inode_ops
  This patches changes the kernel ABI.
  See CVE-2006-5753

Added:
   dists/sarge-security/kernel-2.4/source/kernel-source-2.4.27-2.4.27/debian/patches/261_listxattr-mem-corruption.diff
Modified:
   dists/sarge-security/kernel-2.4/source/kernel-source-2.4.27-2.4.27/debian/changelog
   dists/sarge-security/kernel-2.4/source/kernel-source-2.4.27-2.4.27/debian/patches/series/2.4.27-10sarge6

Modified: dists/sarge-security/kernel-2.4/source/kernel-source-2.4.27-2.4.27/debian/changelog
==============================================================================
--- dists/sarge-security/kernel-2.4/source/kernel-source-2.4.27-2.4.27/debian/changelog	(original)
+++ dists/sarge-security/kernel-2.4/source/kernel-source-2.4.27-2.4.27/debian/changelog	Sun Feb 17 18:28:18 2008
@@ -65,8 +65,13 @@
     [SECURITY] Add some sanity checking for a corrupted i_size in
     ext2_find_entry()
     See CVE-2006-6054
+  * 261_listxattr-mem-corruption.diff
+    [SECURITY] Fix userspace corruption vulnerability caused by
+    incorrectly promoted return values in bad_inode_ops
+    This patches changes the kernel ABI.
+    See CVE-2006-5753
 
- -- dann frazier <dannf at debian.org>  Wed, 13 Feb 2008 23:32:09 -0700
+ -- dann frazier <dannf at debian.org>  Thu, 14 Feb 2008 14:48:39 -0700
 
 kernel-source-2.4.27 (2.4.27-10sarge5) stable-security; urgency=high
 

Added: dists/sarge-security/kernel-2.4/source/kernel-source-2.4.27-2.4.27/debian/patches/261_listxattr-mem-corruption.diff
==============================================================================
--- (empty file)
+++ dists/sarge-security/kernel-2.4/source/kernel-source-2.4.27-2.4.27/debian/patches/261_listxattr-mem-corruption.diff	Sun Feb 17 18:28:18 2008
@@ -0,0 +1,279 @@
+commit f654703d45148071037e8b904e7a674c6d78466a
+Author: dann frazier <dannf at dannf.org>
+Date:   Wed Jan 23 23:12:12 2008 -0700
+
+    2.4: fix memory corruption from misinterpreted bad_inode_ops return values
+    
+    This is a 2.4 backport of a linux-2.6 change by Eric Sandeen
+    (commit be6aab0e9fa6d3c6d75aa1e38ac972d8b4ee82b8)
+    
+    CVE-2006-5753 was assigned for this issue.
+    
+    I've built and boot-tested this, but I'm not sure how to exercise
+    these codepaths.
+    
+    Commit log from 2.6 follows.
+    
+      CVE-2006-5753 is for a case where an inode can be marked bad, switching
+      the ops to bad_inode_ops, which are all connected as:
+    
+      static int return_EIO(void)
+      {
+              return -EIO;
+      }
+    
+      #define EIO_ERROR ((void *) (return_EIO))
+    
+      static struct inode_operations bad_inode_ops =
+      {
+              .create         = bad_inode_create
+      ...etc...
+    
+      The problem here is that the void cast causes return types to not be
+      promoted, and for ops such as listxattr which expect more than 32 bits of
+      return value, the 32-bit -EIO is interpreted as a large positive 64-bit
+      number, i.e. 0x00000000fffffffa instead of 0xfffffffa.
+    
+      This goes particularly badly when the return value is taken as a number of
+      bytes to copy into, say, a user's buffer for example...
+    
+      I originally had coded up the fix by creating a return_EIO_<TYPE> macro
+      for each return type, like this:
+    
+      static int return_EIO_int(void)
+      {
+      	return -EIO;
+      }
+      #define EIO_ERROR_INT ((void *) (return_EIO_int))
+    
+      static struct inode_operations bad_inode_ops =
+      {
+      	.create		= EIO_ERROR_INT,
+      ...etc...
+    
+      but Al felt that it was probably better to create an EIO-returner for each
+      actual op signature.  Since so few ops share a signature, I just went ahead
+      & created an EIO function for each individual file & inode op that returns
+      a value.
+    
+    Signed-off-by: dann frazier <dannf at hp.com>
+
+diff --git a/fs/bad_inode.c b/fs/bad_inode.c
+index 850ba5e..b6b1d7d 100644
+--- a/fs/bad_inode.c
++++ b/fs/bad_inode.c
+@@ -9,6 +9,76 @@
+ #include <linux/fs.h>
+ #include <linux/stat.h>
+ #include <linux/sched.h>
++#include <linux/poll.h>
++
++static loff_t bad_file_llseek(struct file *file, loff_t offset, int origin)
++{
++	return -EIO;
++}
++
++static ssize_t bad_file_read(struct file *filp, char __user *buf,
++			size_t size, loff_t *ppos)
++{
++        return -EIO;
++}
++
++static ssize_t bad_file_write(struct file *filp, const char __user *buf,
++			size_t siz, loff_t *ppos)
++{
++        return -EIO;
++}
++
++static int bad_file_readdir(struct file *filp, void *dirent, filldir_t filldir)
++{
++	return -EIO;
++}
++
++static unsigned int bad_file_poll(struct file *filp, poll_table *wait)
++{
++	return POLLERR;
++}
++
++static int bad_file_ioctl (struct inode *inode, struct file *filp,
++			unsigned int cmd, unsigned long arg)
++{
++	return -EIO;
++}
++
++static int bad_file_mmap(struct file *file, struct vm_area_struct *vma)
++{
++	return -EIO;
++}
++
++static int bad_file_open(struct inode *inode, struct file *filp)
++{
++	return -EIO;
++}
++
++static int bad_file_flush(struct file *file)
++{
++	return -EIO;
++}
++
++static int bad_file_release(struct inode *inode, struct file *filp)
++{
++	return -EIO;
++}
++
++static int bad_file_fsync(struct file *file, struct dentry *dentry,
++			int datasync)
++{
++	return -EIO;
++}
++
++static int bad_file_fasync(int fd, struct file *filp, int on)
++{
++	return -EIO;
++}
++
++static int bad_file_lock(struct file *file, int cmd, struct file_lock *fl)
++{
++	return -EIO;
++}
+ 
+ /*
+  * The follow_link operation is special: it must behave as a no-op
+@@ -20,46 +90,107 @@ static int bad_follow_link(struct dentry *dent, struct nameidata *nd)
+ 	return vfs_follow_link(nd, ERR_PTR(-EIO));
+ }
+ 
+-static int return_EIO(void)
++static struct file_operations bad_file_ops =
++{
++	llseek:		bad_file_llseek,
++	read:		bad_file_read,
++	write:		bad_file_write,
++	readdir:	bad_file_readdir,
++	poll:		bad_file_poll,
++	ioctl:		bad_file_ioctl,
++	mmap:		bad_file_mmap,
++	open:		bad_file_open,
++	flush:		bad_file_flush,
++	release:	bad_file_release,
++	fsync:		bad_file_fsync,
++	fasync:		bad_file_fasync,
++	lock:		bad_file_lock,
++};
++
++static int bad_inode_create (struct inode *dir, struct dentry *dentry,
++		int mode)
+ {
+ 	return -EIO;
+ }
++  
++static struct dentry *bad_inode_lookup(struct inode *dir,
++			struct dentry *dentry)
++{
++	return ERR_PTR(-EIO);
++}
+ 
+-#define EIO_ERROR ((void *) (return_EIO))
++static int bad_inode_link (struct dentry *old_dentry, struct inode *dir,
++		struct dentry *dentry)
++{
++	return -EIO;
++}
+ 
+-static struct file_operations bad_file_ops =
++static int bad_inode_unlink(struct inode *dir, struct dentry *dentry)
+ {
+-	llseek:		EIO_ERROR,
+-	read:		EIO_ERROR,
+-	write:		EIO_ERROR,
+-	readdir:	EIO_ERROR,
+-	poll:		EIO_ERROR,
+-	ioctl:		EIO_ERROR,
+-	mmap:		EIO_ERROR,
+-	open:		EIO_ERROR,
+-	flush:		EIO_ERROR,
+-	release:	EIO_ERROR,
+-	fsync:		EIO_ERROR,
+-	fasync:		EIO_ERROR,
+-	lock:		EIO_ERROR,
+-};
++	return -EIO;
++}
++
++static int bad_inode_symlink (struct inode *dir, struct dentry *dentry,
++		const char *symname)
++{
++	return -EIO;
++}
++
++static int bad_inode_mkdir(struct inode *dir, struct dentry *dentry,
++			int mode)
++{
++	return -EIO;
++}
++
++static int bad_inode_rmdir (struct inode *dir, struct dentry *dentry)
++{
++	return -EIO;
++}
++
++static int bad_inode_mknod (struct inode *dir, struct dentry *dentry,
++			int mode, int rdev)
++{
++	return -EIO;
++}
++
++static int bad_inode_rename (struct inode *old_dir, struct dentry *old_dentry,
++		struct inode *new_dir, struct dentry *new_dentry)
++{
++	return -EIO;
++}
++
++static int bad_inode_readlink(struct dentry *dentry, char __user *buffer,
++		int buflen)
++{
++	return -EIO;
++}
++
++static int bad_inode_permission(struct inode *inode, int mask)
++{
++	return -EIO;
++}
++
++static int bad_inode_revalidate(struct dentry *dentry)
++{
++	return -EIO;
++}
+ 
+ struct inode_operations bad_inode_ops =
+ {
+-	create:		EIO_ERROR,
+-	lookup:		EIO_ERROR,
+-	link:		EIO_ERROR,
+-	unlink:		EIO_ERROR,
+-	symlink:	EIO_ERROR,
+-	mkdir:		EIO_ERROR,
+-	rmdir:		EIO_ERROR,
+-	mknod:		EIO_ERROR,
+-	rename:		EIO_ERROR,
+-	readlink:	EIO_ERROR,
++	create:		bad_inode_create,
++	lookup:		bad_inode_lookup,
++	link:		bad_inode_link,
++	unlink:		bad_inode_unlink,
++	symlink:	bad_inode_symlink,
++	mkdir:		bad_inode_mkdir,
++	rmdir:		bad_inode_rmdir,
++	mknod:		bad_inode_mknod,
++	rename:		bad_inode_rename,
++	readlink:	bad_inode_readlink,
+ 	follow_link:	bad_follow_link,
+-	truncate:	EIO_ERROR,
+-	permission:	EIO_ERROR,
+-	revalidate:	EIO_ERROR,
++	/* truncate returns void */
++	permission:	bad_inode_permission,
++	revalidate:	bad_inode_revalidate,
+ };
+ 
+ 

Modified: dists/sarge-security/kernel-2.4/source/kernel-source-2.4.27-2.4.27/debian/patches/series/2.4.27-10sarge6
==============================================================================
--- dists/sarge-security/kernel-2.4/source/kernel-source-2.4.27-2.4.27/debian/patches/series/2.4.27-10sarge6	(original)
+++ dists/sarge-security/kernel-2.4/source/kernel-source-2.4.27-2.4.27/debian/patches/series/2.4.27-10sarge6	Sun Feb 17 18:28:18 2008
@@ -20,3 +20,4 @@
 + 258_ext2_readdir-f_pos-fix.diff
 + 259_ext2_readdir-infinite-loop.diff
 + 260_ext2-skip-pages-past-num-blocks.diff
++ 261_listxattr-mem-corruption.diff



More information about the Kernel-svn-changes mailing list