[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