From 33af79d12e0fa25545d49e86afc67ea8ad5f2f40 Mon Sep 17 00:00:00 2001
From: Chandra Seetharaman <sekharan@us.ibm.com>
Date: Wed, 16 Jul 2008 17:35:08 -0700
Subject: [PATCH] scsi_dh: Verify "dev" is a sdev before accessing it.

Before accessing the device data structure in hardware handlers,
make sure it is a indeed a sdev device.

Yinghai Lu <yhlu.kernel@gmail.com> found the bug on Jul 16, 2008,
and later tested/verified the following fix.

Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
 drivers/scsi/device_handler/scsi_dh_emc.c   | 7 ++++++-
 drivers/scsi/device_handler/scsi_dh_hp_sw.c | 7 ++++++-
 drivers/scsi/device_handler/scsi_dh_rdac.c  | 7 ++++++-
 3 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c
index ed53f14007a21..f2467e936e554 100644
--- a/drivers/scsi/device_handler/scsi_dh_emc.c
+++ b/drivers/scsi/device_handler/scsi_dh_emc.c
@@ -416,12 +416,17 @@ static int clariion_bus_notify(struct notifier_block *nb,
 				unsigned long action, void *data)
 {
 	struct device *dev = data;
-	struct scsi_device *sdev = to_scsi_device(dev);
+	struct scsi_device *sdev;
 	struct scsi_dh_data *scsi_dh_data;
 	struct clariion_dh_data *h;
 	int i, found = 0;
 	unsigned long flags;
 
+	if (!scsi_is_sdev_device(dev))
+		return 0;
+
+	sdev = to_scsi_device(dev);
+
 	if (action == BUS_NOTIFY_ADD_DEVICE) {
 		for (i = 0; clariion_dev_list[i].vendor; i++) {
 			if (!strncmp(sdev->vendor, clariion_dev_list[i].vendor,
diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
index 12ceab7b36629..ae6be87d6a832 100644
--- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c
+++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
@@ -131,11 +131,16 @@ static int hp_sw_bus_notify(struct notifier_block *nb,
 			    unsigned long action, void *data)
 {
 	struct device *dev = data;
-	struct scsi_device *sdev = to_scsi_device(dev);
+	struct scsi_device *sdev;
 	struct scsi_dh_data *scsi_dh_data;
 	int i, found = 0;
 	unsigned long flags;
 
+	if (!scsi_is_sdev_device(dev))
+		return 0;
+
+	sdev = to_scsi_device(dev);
+
 	if (action == BUS_NOTIFY_ADD_DEVICE) {
 		for (i = 0; hp_sw_dh_data_list[i].vendor; i++) {
 			if (!strncmp(sdev->vendor, hp_sw_dh_data_list[i].vendor,
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c
index 6fff077a888d8..fdf34b0ec6e17 100644
--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
+++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
@@ -608,12 +608,17 @@ static int rdac_bus_notify(struct notifier_block *nb,
 			    unsigned long action, void *data)
 {
 	struct device *dev = data;
-	struct scsi_device *sdev = to_scsi_device(dev);
+	struct scsi_device *sdev;
 	struct scsi_dh_data *scsi_dh_data;
 	struct rdac_dh_data *h;
 	int i, found = 0;
 	unsigned long flags;
 
+	if (!scsi_is_sdev_device(dev))
+		return 0;
+
+	sdev = to_scsi_device(dev);
+
 	if (action == BUS_NOTIFY_ADD_DEVICE) {
 		for (i = 0; rdac_dev_list[i].vendor; i++) {
 			if (!strncmp(sdev->vendor, rdac_dev_list[i].vendor,
-- 
2.30.2