aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley2008-07-07 15:50:01 -0500
committerJames Bottomley2008-07-12 10:14:56 -0500
commit8df5fc042c8e7c08dc438c8198b62407ee1e91a0 (patch)
tree87a068716da8f04421e7cb6e9652ced863a9381d /block/bsg.c
parent27898988174bb211fd962ea73b9c6dc09f888705 (diff)
downloadkernel-common-8df5fc042c8e7c08dc438c8198b62407ee1e91a0.tar.gz
kernel-common-8df5fc042c8e7c08dc438c8198b62407ee1e91a0.tar.xz
kernel-common-8df5fc042c8e7c08dc438c8198b62407ee1e91a0.zip
[SCSI] bsg: fix oops on remove
If you do a modremove of any sas driver, you run into an oops on shutdown when the host is removed (coming from the host bsg device). The root cause seems to be that there's a use after free of the bsg_class_device: In bsg_kref_release_function, this is used (to do a put_device(bcg->parent) after bcg->release has been called. In sas (and possibly many other things) bcd->release frees the queue which contains the bsg_class_device, so we get a put_device on unreferenced memory. Fix this by taking a copy of the pointer to the parent before releasing bsg. Acked-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'block/bsg.c')
-rw-r--r--block/bsg.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/block/bsg.c b/block/bsg.c
index f0b7cd34321..54d617f7df3 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -709,11 +709,12 @@ static void bsg_kref_release_function(struct kref *kref)
709{ 709{
710 struct bsg_class_device *bcd = 710 struct bsg_class_device *bcd =
711 container_of(kref, struct bsg_class_device, ref); 711 container_of(kref, struct bsg_class_device, ref);
712 struct device *parent = bcd->parent;
712 713
713 if (bcd->release) 714 if (bcd->release)
714 bcd->release(bcd->parent); 715 bcd->release(bcd->parent);
715 716
716 put_device(bcd->parent); 717 put_device(parent);
717} 718}
718 719
719static int bsg_put_device(struct bsg_device *bd) 720static int bsg_put_device(struct bsg_device *bd)