Commit message: aacraid: missing capable() check in compat ioctl

In commit d496f94d22d1 ('[SCSI] aacraid: fix security weakness') we
added a check on CAP_SYS_RAWIO to the ioctl.  The compat ioctls need the
check as well.

Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Cc: stable@kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
CVE: CVE-2013-6383
CWE: CWE-264
Vulnerability description: The aac_compat_ioctl function in drivers/scsi/aacraid/linit.c in the Linux kernel before 3.11.8 does not require the CAP_SYS_RAWIO capability, which allows local users to bypass intended access restrictions via a crafted ioctl call.

Project: linux
File: linit.c

static int aac_change_queue_depth(struct scsi_device *sdev, int depth,
				  int reason)
{
	if (reason != SCSI_QDEPTH_DEFAULT)
		return -EOPNOTSUPP;

	if (sdev->tagged_supported && (sdev->type == TYPE_DISK) &&
	    (sdev_channel(sdev) == CONTAINER_CHANNEL)) {
		struct scsi_device * dev;
		struct Scsi_Host *host = sdev->host;
		unsigned num = 0;

		__shost_for_each_device(dev, host) {
			if (dev->tagged_supported && (dev->type == TYPE_DISK) &&
			    (sdev_channel(dev) == CONTAINER_CHANNEL))
				++num;
			++num;
		}
		if (num >= host->can_queue)
			num = host->can_queue - 1;
		if (depth > (host->can_queue - num))
			depth = host->can_queue - num;
		if (depth > 256)
			depth = 256;
		else if (depth < 2)
			depth = 2;
		scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, depth);
	} else
		scsi_adjust_queue_depth(sdev, 0, 1);
	return sdev->queue_depth;
}

Project: linux
File: linit.c

static ssize_t aac_show_flags(struct device *cdev,
			      struct device_attribute *attr, char *buf)
{
	int len = 0;
	struct aac_dev *dev = (struct aac_dev*)class_to_shost(cdev)->hostdata;

	if (nblank(dprintk(x)))
		len = snprintf(buf, PAGE_SIZE, "dprintk\n");
#ifdef AAC_DETAILED_STATUS_INFO
	len += snprintf(buf + len, PAGE_SIZE - len,
			"AAC_DETAILED_STATUS_INFO\n");
#endif
	if (dev->raw_io_interface && dev->raw_io_64)
		len += snprintf(buf + len, PAGE_SIZE - len,
				"SAI_READ_CAPACITY_16\n");
	if (dev->jbod)
		len += snprintf(buf + len, PAGE_SIZE - len, "SUPPORTED_JBOD\n");
	if (dev->supplement_adapter_info.SupportedOptions2 &
		AAC_OPTION_POWER_MANAGEMENT)
		len += snprintf(buf + len, PAGE_SIZE - len,
				"SUPPORTED_POWER_MANAGEMENT\n");
	if (dev->msi)
		len += snprintf(buf + len, PAGE_SIZE - len, "PCI_HAS_MSI\n");
	return len;
}

Project: linux
File: linit.c

static ssize_t aac_show_model(struct device *device,
			      struct device_attribute *attr, char *buf)
{
	struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
	int len;

	if (dev->supplement_adapter_info.AdapterTypeText[0]) {
		char * cp = dev->supplement_adapter_info.AdapterTypeText;
		while (*cp && *cp != ' ')
			++cp;
		while (*cp == ' ')
			++cp;
		len = snprintf(buf, PAGE_SIZE, "%s\n", cp);
	} else
		len = snprintf(buf, PAGE_SIZE, "%s\n",
		  aac_drivers[dev->cardtype].model);
	return len;
}

Project: linux
File: linit.c

static ssize_t aac_show_monitor_version(struct device *device,
					struct device_attribute *attr,
					char *buf)
{
	struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
	int len, tmp;

	tmp = le32_to_cpu(dev->adapter_info.monitorrev);
	len = snprintf(buf, PAGE_SIZE, "%d.%d-%d[%d]\n",
	  tmp >> 24, (tmp >> 16) & 0xff, tmp & 0xff,
	  le32_to_cpu(dev->adapter_info.monitorbuild));
	return len;
}

Project: linux
File: linit.c

static ssize_t aac_show_reset_adapter(struct device *device,
				      struct device_attribute *attr,
				      char *buf)
{
	struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
	int len, tmp;

	tmp = aac_adapter_check_health(dev);
	if ((tmp == 0) && dev->in_reset)
		tmp = -EBUSY;
	len = snprintf(buf, PAGE_SIZE, "0x%x\n", tmp);
	return len;
}

Project: linux
File: linit.c

static ssize_t aac_show_serial_number(struct device *device,
			       struct device_attribute *attr, char *buf)
{
	struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
	int len = 0;

	if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0)
		len = snprintf(buf, 16, "%06X\n",
		  le32_to_cpu(dev->adapter_info.serial[0]));
	if (len &&
	  !memcmp(&dev->supplement_adapter_info.MfgPcbaSerialNo[
	    sizeof(dev->supplement_adapter_info.MfgPcbaSerialNo)-len],
	  buf, len-1))
		len = snprintf(buf, 16, "%.*s\n",
		  (int)sizeof(dev->supplement_adapter_info.MfgPcbaSerialNo),
		  dev->supplement_adapter_info.MfgPcbaSerialNo);

	return min(len, 16);
}