[kernel] r18462 - in dists/squeeze-security/linux-2.6/debian: . patches/bugfix/all patches/series

Dann Frazier dannf at alioth.debian.org
Sun Jan 8 10:33:52 UTC 2012


Author: dannf
Date: Sun Jan  8 10:33:51 2012
New Revision: 18462

Log:
Restrict ioctl forwarding on partitions and logical volumes (CVE-2011-4127)

Added:
   dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/add-scsi_cmd_blk_ioctl-wrapper.patch
   dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/limit-ioctls-forwarded-to-non-scsi-devices.patch
   dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/treat-lvs-on-one-pv-like-a-partition.patch
   dists/squeeze-security/linux-2.6/debian/patches/series/35squeeze3
Modified:
   dists/squeeze-security/linux-2.6/debian/changelog

Modified: dists/squeeze-security/linux-2.6/debian/changelog
==============================================================================
--- dists/squeeze-security/linux-2.6/debian/changelog	Sun Jan  8 03:28:07 2012	(r18461)
+++ dists/squeeze-security/linux-2.6/debian/changelog	Sun Jan  8 10:33:51 2012	(r18462)
@@ -1,3 +1,9 @@
+linux-2.6 (2.6.32-35squeeze3) UNRELEASED; urgency=low
+
+  * Restrict ioctl forwarding on partitions and logical volumes (CVE-2011-4127)
+
+ -- dann frazier <dannf at debian.org>  Fri, 06 Jan 2012 18:46:21 -0700
+
 linux-2.6 (2.6.32-35squeeze2) stable-security; urgency=high
 
   * Fix regression in /proc/<pid>/maps fixes for CVE-2011-1020

Added: dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/add-scsi_cmd_blk_ioctl-wrapper.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/add-scsi_cmd_blk_ioctl-wrapper.patch	Sun Jan  8 10:33:51 2012	(r18462)
@@ -0,0 +1,157 @@
+From 3831a172b179a5b74142aca314fe84b79e115410 Mon Sep 17 00:00:00 2001
+From: dann frazier <dannf at debian.org>
+Date: Fri, 6 Jan 2012 14:30:17 -0700
+Subject: [PATCH 1/3] Introduce a wrapper around scsi_cmd_ioctl that takes a
+ block device. The function will then be enhanced to
+ detect partition block devices and, in that case,
+ subject the ioctls to whitelisting.
+
+Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
+[dannf: backported to Debian's 2.6.32]
+---
+ block/scsi_ioctl.c         |    7 +++++++
+ drivers/block/cciss.c      |    6 +++---
+ drivers/block/ub.c         |   14 +-------------
+ drivers/block/virtio_blk.c |    4 ++--
+ drivers/cdrom/cdrom.c      |    3 +--
+ drivers/scsi/sd.c          |    2 +-
+ include/linux/blkdev.h     |    2 ++
+ 7 files changed, 17 insertions(+), 21 deletions(-)
+
+diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
+index 1d5a780..114ee29 100644
+--- a/block/scsi_ioctl.c
++++ b/block/scsi_ioctl.c
+@@ -689,6 +689,13 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod
+ }
+ EXPORT_SYMBOL(scsi_cmd_ioctl);
+ 
++int scsi_cmd_blk_ioctl(struct block_device *bd, fmode_t mode,
++		       unsigned int cmd, void __user *arg)
++{
++	return scsi_cmd_ioctl(bd->bd_disk->queue, bd->bd_disk, mode, cmd, arg);
++}
++EXPORT_SYMBOL(scsi_cmd_blk_ioctl);
++
+ int __init blk_scsi_ioctl_init(void)
+ {
+ 	blk_set_cmd_filter_defaults(&blk_default_cmd_filter);
+diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
+index ca9c548..68b90d9 100644
+--- a/drivers/block/cciss.c
++++ b/drivers/block/cciss.c
+@@ -1583,7 +1583,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
+ 			return status;
+ 		}
+ 
+-	/* scsi_cmd_ioctl handles these, below, though some are not */
++	/* scsi_cmd_blk_ioctl handles these, below, though some are not */
+ 	/* very meaningful for cciss.  SG_IO is the main one people want. */
+ 
+ 	case SG_GET_VERSION_NUM:
+@@ -1594,9 +1594,9 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
+ 	case SG_EMULATED_HOST:
+ 	case SG_IO:
+ 	case SCSI_IOCTL_SEND_COMMAND:
+-		return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp);
++		return scsi_cmd_blk_ioctl(bdev, mode, cmd, argp);
+ 
+-	/* scsi_cmd_ioctl would normally handle these, below, but */
++	/* scsi_cmd_blk_ioctl would normally handle these, below, but */
+ 	/* they aren't a good fit for cciss, as CD-ROMs are */
+ 	/* not supported, and we don't have any bus/target/lun */
+ 	/* which we present to the kernel. */
+diff --git a/drivers/block/ub.c b/drivers/block/ub.c
+index c739b20..5e0ac9a 100644
+--- a/drivers/block/ub.c
++++ b/drivers/block/ub.c
+@@ -1721,18 +1721,6 @@ static int ub_bd_release(struct gendisk *disk, fmode_t mode)
+ }
+ 
+ /*
+- * The ioctl interface.
+- */
+-static int ub_bd_ioctl(struct block_device *bdev, fmode_t mode,
+-    unsigned int cmd, unsigned long arg)
+-{
+-	struct gendisk *disk = bdev->bd_disk;
+-	void __user *usermem = (void __user *) arg;
+-
+-	return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, usermem);
+-}
+-
+-/*
+  * This is called by check_disk_change if we reported a media change.
+  * The main onjective here is to discover the features of the media such as
+  * the capacity, read-only status, etc. USB storage generally does not
+@@ -1793,7 +1781,7 @@ static const struct block_device_operations ub_bd_fops = {
+ 	.owner		= THIS_MODULE,
+ 	.open		= ub_bd_open,
+ 	.release	= ub_bd_release,
+-	.locked_ioctl	= ub_bd_ioctl,
++	.locked_ioctl	= scsi_cmd_blk_ioctl,
+ 	.media_changed	= ub_bd_media_changed,
+ 	.revalidate_disk = ub_bd_revalidate,
+ };
+diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
+index 51042f0..44d019b 100644
+--- a/drivers/block/virtio_blk.c
++++ b/drivers/block/virtio_blk.c
+@@ -200,8 +200,8 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode,
+ 	if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_SCSI))
+ 		return -ENOTTY;
+ 
+-	return scsi_cmd_ioctl(disk->queue, disk, mode, cmd,
+-			      (void __user *)data);
++	return scsi_cmd_blk_ioctl(bdev, mode, cmd,
++				  (void __user *)data);
+ }
+ 
+ /* We provide getgeo only to please some old bootloader/partitioning tools */
+diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
+index 614da5b..59cccc9 100644
+--- a/drivers/cdrom/cdrom.c
++++ b/drivers/cdrom/cdrom.c
+@@ -2684,12 +2684,11 @@ int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev,
+ {
+ 	void __user *argp = (void __user *)arg;
+ 	int ret;
+-	struct gendisk *disk = bdev->bd_disk;
+ 
+ 	/*
+ 	 * Try the generic SCSI command ioctl's first.
+ 	 */
+-	ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp);
++	ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp);
+ 	if (ret != -ENOTTY)
+ 		return ret;
+ 
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index 160b47e..a5f3728 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -840,7 +840,7 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode,
+ 		case SCSI_IOCTL_GET_BUS_NUMBER:
+ 			return scsi_ioctl(sdp, cmd, p);
+ 		default:
+-			error = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, p);
++			error = scsi_cmd_blk_ioctl(bdev, mode, cmd, p);
+ 			if (error != -ENOTTY)
+ 				return error;
+ 	}
+diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
+index 57da328..025b78b 100644
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -779,6 +779,8 @@ extern void blk_plug_device(struct request_queue *);
+ extern void blk_plug_device_unlocked(struct request_queue *);
+ extern int blk_remove_plug(struct request_queue *);
+ extern void blk_recount_segments(struct request_queue *, struct bio *);
++extern int scsi_cmd_blk_ioctl(struct block_device *, fmode_t,
++			      unsigned int, void __user *);
+ extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t,
+ 			  unsigned int, void __user *);
+ extern int sg_scsi_ioctl(struct request_queue *, struct gendisk *, fmode_t,
+-- 
+1.7.8.2
+

Added: dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/limit-ioctls-forwarded-to-non-scsi-devices.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/limit-ioctls-forwarded-to-non-scsi-devices.patch	Sun Jan  8 10:33:51 2012	(r18462)
@@ -0,0 +1,140 @@
+From 264713ad6e27fcd33eb2095a98ffa6d34ce2ea4b Mon Sep 17 00:00:00 2001
+From: dann frazier <dannf at debian.org>
+Date: Fri, 6 Jan 2012 14:31:06 -0700
+Subject: [PATCH 2/3] Linux allows executing the SG_IO ioctl on a partition or
+ even on an LVM volume, and will pass the command to the
+ underlying block device. This is well-known, but it is
+ also a large security problem when (via Unix
+ permissions, ACLs, SELinux or a combination thereof) a
+ program or user needs to be granted access to a
+ particular partition or logical volume but not to the
+ full device.
+
+This patch limits the ioctls that are forwarded to non-SCSI devices to
+a few ones that are harmless.  This restriction includes programs
+running with the CAP_SYS_RAWIO.  If for example I let a program access
+/dev/sda2 and /dev/sdb, it still should not be able to read/write outside
+the boundaries of /dev/sda2 independent of the capabilities.
+
+This patch does not affect the non-libata IDE driver.  That driver however
+alreadys test for bd != bd->bd_contains before issuing some ioctl; so,
+programs that do not require CAP_SYS_RAWIO are safe.  A workaround is
+just to use libata.
+
+Encryption on the host is a mitigating factor, but it does not provide
+a full solution.  In particular it doesn't protect against DoS (write
+random data), replay attacks (reinstate old ciphertext sectors), or
+writes to unencrypted areas including the MBR, the partition table, or
+/boot.
+
+Thanks to Daniel Berrange, Milan Broz, Mike Christie, Alasdair Kergon,
+Petr Matousek, Jeff Moyer, Mike Snitzer and others for help discussing
+this issue.
+
+Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
+[dannf: backported to Debian's 2.6.32]
+---
+ block/scsi_ioctl.c     |   34 ++++++++++++++++++++++++++++++++++
+ drivers/scsi/sd.c      |   11 +++++++++--
+ include/linux/blkdev.h |    1 +
+ 3 files changed, 44 insertions(+), 2 deletions(-)
+
+diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
+index 114ee29..5cd4e02 100644
+--- a/block/scsi_ioctl.c
++++ b/block/scsi_ioctl.c
+@@ -689,9 +689,43 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod
+ }
+ EXPORT_SYMBOL(scsi_cmd_ioctl);
+ 
++int scsi_verify_blk_ioctl(struct block_device *bd, unsigned int cmd)
++{
++	if (bd && bd == bd->bd_contains)
++		return 0;
++
++	/* Actually none of this is particularly useful on a partition
++	 * device, but let's play it safe.
++	 */
++	switch (cmd) {
++	case SCSI_IOCTL_GET_IDLUN:
++	case SCSI_IOCTL_GET_BUS_NUMBER:
++	case SCSI_IOCTL_GET_PCI:
++	case SCSI_IOCTL_PROBE_HOST:
++	case SG_GET_VERSION_NUM:
++	case SG_SET_TIMEOUT:
++	case SG_GET_TIMEOUT:
++	case SG_GET_RESERVED_SIZE:
++	case SG_SET_RESERVED_SIZE:
++	case SG_EMULATED_HOST:
++		return 0;
++	default:
++		break;
++	}
++	/* In particular, rule out all resets and host-specific ioctls.  */
++	return -ENOTTY;
++}
++EXPORT_SYMBOL(scsi_verify_blk_ioctl);
++
+ int scsi_cmd_blk_ioctl(struct block_device *bd, fmode_t mode,
+ 		       unsigned int cmd, void __user *arg)
+ {
++	int ret;
++
++	ret = scsi_verify_blk_ioctl(bd, cmd);
++	if (ret < 0)
++		return ret;
++
+ 	return scsi_cmd_ioctl(bd->bd_disk->queue, bd->bd_disk, mode, cmd, arg);
+ }
+ EXPORT_SYMBOL(scsi_cmd_blk_ioctl);
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index a5f3728..4219572 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -819,6 +819,10 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode,
+ 	SCSI_LOG_IOCTL(1, printk("sd_ioctl: disk=%s, cmd=0x%x\n",
+ 						disk->disk_name, cmd));
+ 
++	error = scsi_verify_blk_ioctl(bdev, cmd);
++	if (error < 0)
++		return error;
++
+ 	/*
+ 	 * If we are in the middle of error recovery, don't let anyone
+ 	 * else try and use this device.  Also, if error recovery fails, it
+@@ -998,6 +1002,11 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode,
+ 			   unsigned int cmd, unsigned long arg)
+ {
+ 	struct scsi_device *sdev = scsi_disk(bdev->bd_disk)->device;
++	int ret;
++
++	ret = scsi_verify_blk_ioctl(bdev, cmd);
++	if (ret < 0)
++		return ret;
+ 
+ 	/*
+ 	 * If we are in the middle of error recovery, don't let anyone
+@@ -1009,8 +1018,6 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode,
+ 		return -ENODEV;
+ 	       
+ 	if (sdev->host->hostt->compat_ioctl) {
+-		int ret;
+-
+ 		ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg);
+ 
+ 		return ret;
+diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
+index 025b78b..09beade 100644
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -779,6 +779,7 @@ extern void blk_plug_device(struct request_queue *);
+ extern void blk_plug_device_unlocked(struct request_queue *);
+ extern int blk_remove_plug(struct request_queue *);
+ extern void blk_recount_segments(struct request_queue *, struct bio *);
++extern int scsi_verify_blk_ioctl(struct block_device *, unsigned int);
+ extern int scsi_cmd_blk_ioctl(struct block_device *, fmode_t,
+ 			      unsigned int, void __user *);
+ extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t,
+-- 
+1.7.8.2
+

Added: dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/treat-lvs-on-one-pv-like-a-partition.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/treat-lvs-on-one-pv-like-a-partition.patch	Sun Jan  8 10:33:51 2012	(r18462)
@@ -0,0 +1,61 @@
+From d4a97721ab45133e6e0d058fb711e0b55fe2e0db Mon Sep 17 00:00:00 2001
+From: dann frazier <dannf at debian.org>
+Date: Fri, 6 Jan 2012 14:35:32 -0700
+Subject: [PATCH 3/3] A logical volume can map to just part of underlying
+ physical volume. In this case, it must be treated like
+ a partition.
+
+Based on a patch from Alasdair G Kergon.
+
+Cc: Alasdair G Kergon <agk at redhat.com>
+Cc: Mike Snitzer <msnitzer at redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
+[dannf: backported to Debian's 2.6.32]
+---
+ drivers/md/dm-linear.c |   12 +++++++++++-
+ drivers/md/dm-mpath.c  |    6 ++++++
+ 2 files changed, 17 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
+index 82f7d6e..7ab302d 100644
+--- a/drivers/md/dm-linear.c
++++ b/drivers/md/dm-linear.c
+@@ -116,7 +116,17 @@ static int linear_ioctl(struct dm_target *ti, unsigned int cmd,
+ 			unsigned long arg)
+ {
+ 	struct linear_c *lc = (struct linear_c *) ti->private;
+-	return __blkdev_driver_ioctl(lc->dev->bdev, lc->dev->mode, cmd, arg);
++	struct dm_dev *dev = lc->dev;
++	int r = 0;
++
++	/*
++	 * Only pass ioctls through if the device sizes match exactly.
++	 */
++	if (lc->start ||
++	    ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
++		r = scsi_verify_blk_ioctl(NULL, cmd);
++
++	return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
+ }
+ 
+ static int linear_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
+diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
+index fcf717c..60d1f93 100644
+--- a/drivers/md/dm-mpath.c
++++ b/drivers/md/dm-mpath.c
+@@ -1459,6 +1459,12 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
+ 
+ 	spin_unlock_irqrestore(&m->lock, flags);
+ 
++	/*
++	 * Only pass ioctls through if the device sizes match exactly.
++	 */
++	if (r == 0 && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT)
++		r = scsi_verify_blk_ioctl(NULL, cmd);
++
+ 	return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg);
+ }
+ 
+-- 
+1.7.8.2
+

Added: dists/squeeze-security/linux-2.6/debian/patches/series/35squeeze3
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze-security/linux-2.6/debian/patches/series/35squeeze3	Sun Jan  8 10:33:51 2012	(r18462)
@@ -0,0 +1,3 @@
++ bugfix/all/add-scsi_cmd_blk_ioctl-wrapper.patch
++ bugfix/all/limit-ioctls-forwarded-to-non-scsi-devices.patch
++ bugfix/all/treat-lvs-on-one-pv-like-a-partition.patch



More information about the Kernel-svn-changes mailing list