summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Haberland <sth@linux.ibm.com>2022-09-19 17:49:31 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-09-28 10:55:46 +0200
commitd86b4267834e6d4af62e3073e48166e349ab1b70 (patch)
tree30920a57ce17e1d3916adedeb4a90fce61cfb516
parent40e94056a7452adb522a25a8d3558f896c9f8aa9 (diff)
s390/dasd: fix Oops in dasd_alias_get_start_dev due to missing pavgroup
commit db7ba07108a48c0f95b74fabbfd5d63e924f992d upstream. Fix Oops in dasd_alias_get_start_dev() function caused by the pavgroup pointer being NULL. The pavgroup pointer is checked on the entrance of the function but without the lcu->lock being held. Therefore there is a race window between dasd_alias_get_start_dev() and _lcu_update() which sets pavgroup to NULL with the lcu->lock held. Fix by checking the pavgroup pointer with lcu->lock held. Cc: <stable@vger.kernel.org> # 2.6.25+ Fixes: 8e09f21574ea ("[S390] dasd: add hyper PAV support to DASD device driver, part 1") Signed-off-by: Stefan Haberland <sth@linux.ibm.com> Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com> Link: https://lore.kernel.org/r/20220919154931.4123002-2-sth@linux.ibm.com Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/s390/block/dasd_alias.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c
index 2002684a68b3..53eb32c65abb 100644
--- a/drivers/s390/block/dasd_alias.c
+++ b/drivers/s390/block/dasd_alias.c
@@ -674,12 +674,12 @@ int dasd_alias_remove_device(struct dasd_device *device)
struct dasd_device *dasd_alias_get_start_dev(struct dasd_device *base_device)
{
struct dasd_eckd_private *alias_priv, *private = base_device->private;
- struct alias_pav_group *group = private->pavgroup;
struct alias_lcu *lcu = private->lcu;
struct dasd_device *alias_device;
+ struct alias_pav_group *group;
unsigned long flags;
- if (!group || !lcu)
+ if (!lcu)
return NULL;
if (lcu->pav == NO_PAV ||
lcu->flags & (NEED_UAC_UPDATE | UPDATE_PENDING))
@@ -696,6 +696,11 @@ struct dasd_device *dasd_alias_get_start_dev(struct dasd_device *base_device)
}
spin_lock_irqsave(&lcu->lock, flags);
+ group = private->pavgroup;
+ if (!group) {
+ spin_unlock_irqrestore(&lcu->lock, flags);
+ return NULL;
+ }
alias_device = group->next;
if (!alias_device) {
if (list_empty(&group->aliaslist)) {