mm: backing-dev: Take a reference to the bdi in use to prevent UAF

KASAN reports a reproducible issue in the BDI handling code due to a
dereference of a previously freed pointer to 'struct backing_dev_info'
in bdi_unregister().

Because of a distinct lack of locking and/or reference taking,
blk_cleanup_queue() puts the final taken reference to the bdi, which
is then promptly freed by release_bdi().  However, del_gendisk() calls
bdi_unregister() after the fact, which then attempts to dereference
it causing the kernel to panic.

Bug: 182815710
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Change-Id: Iaf3dadf3b983a4b7d74d4e273fc676350cfc387f
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index cd607fb..fdae423 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -877,9 +877,13 @@
 	if (bdi->dev)	/* The driver needs to use separate queues per device */
 		return 0;
 
+	bdi_get(bdi);
+
 	dev = device_create_vargs(bdi_class, NULL, MKDEV(0, 0), bdi, fmt, args);
-	if (IS_ERR(dev))
+	if (IS_ERR(dev)) {
+		bdi_put(bdi);
 		return PTR_ERR(dev);
+	}
 
 	cgwb_bdi_register(bdi);
 	bdi->dev = dev;
@@ -959,6 +963,8 @@
 		put_device(bdi->owner);
 		bdi->owner = NULL;
 	}
+
+	bdi_put(bdi);
 }
 
 static void release_bdi(struct kref *ref)