aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Elder <elder@inktank.com>2013-05-13 21:35:37 -0400
committerAlex Elder <elder@inktank.com>2013-05-17 13:50:10 -0400
commit3abef3b3585bbc67d56fdc9c67761a900fb4b69d (patch)
treed94c9555797c77e4c92f2fea22049a962af48de9
parent7262cfca430a1a0e0707149af29ae86bc0ded230 (diff)
rbd: fix cleanup in rbd_add()
Bjorn Helgaas pointed out that a recent commit introduced a use-after-free condition in an error path for rbd_add(). He correctly stated: I think b536f69a3a5 "rbd: set up devices only for mapped images" introduced a use-after-free error in rbd_add(): ... If rbd_dev_device_setup() returns an error, we call rbd_dev_image_release(), which ultimately kfrees rbd_dev. Then we call rbd_dev_destroy(), which references fields in the already-freed rbd_dev struct before kfreeing it again. The simple fix is to return the error code after the call to rbd_dev_image_release(). Closer examination revealed that there's no need to clean up rbd_opts in that function, so fix that too. Update some other comments that have also become out of date. Reported-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Alex Elder <elder@inktank.com> Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
-rw-r--r--drivers/block/rbd.c23
1 files changed, 14 insertions, 9 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 5f64ba77bc7f..3a897a531e9c 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -4700,8 +4700,10 @@ out:
4700 return ret; 4700 return ret;
4701} 4701}
4702 4702
4703/* Undo whatever state changes are made by v1 or v2 image probe */ 4703/*
4704 4704 * Undo whatever state changes are made by v1 or v2 header info
4705 * call.
4706 */
4705static void rbd_dev_unprobe(struct rbd_device *rbd_dev) 4707static void rbd_dev_unprobe(struct rbd_device *rbd_dev)
4706{ 4708{
4707 struct rbd_image_header *header; 4709 struct rbd_image_header *header;
@@ -4905,9 +4907,10 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
4905 int tmp; 4907 int tmp;
4906 4908
4907 /* 4909 /*
4908 * Get the id from the image id object. If it's not a 4910 * Get the id from the image id object. Unless there's an
4909 * format 2 image, we'll get ENOENT back, and we'll assume 4911 * error, rbd_dev->spec->image_id will be filled in with
4910 * it's a format 1 image. 4912 * a dynamically-allocated string, and rbd_dev->image_format
4913 * will be set to either 1 or 2.
4911 */ 4914 */
4912 ret = rbd_dev_image_id(rbd_dev); 4915 ret = rbd_dev_image_id(rbd_dev);
4913 if (ret) 4916 if (ret)
@@ -5029,16 +5032,18 @@ static ssize_t rbd_add(struct bus_type *bus,
5029 rbd_dev->mapping.read_only = read_only; 5032 rbd_dev->mapping.read_only = read_only;
5030 5033
5031 rc = rbd_dev_device_setup(rbd_dev); 5034 rc = rbd_dev_device_setup(rbd_dev);
5032 if (!rc) 5035 if (rc) {
5033 return count; 5036 rbd_dev_image_release(rbd_dev);
5037 goto err_out_module;
5038 }
5039
5040 return count;
5034 5041
5035 rbd_dev_image_release(rbd_dev);
5036err_out_rbd_dev: 5042err_out_rbd_dev:
5037 rbd_dev_destroy(rbd_dev); 5043 rbd_dev_destroy(rbd_dev);
5038err_out_client: 5044err_out_client:
5039 rbd_put_client(rbdc); 5045 rbd_put_client(rbdc);
5040err_out_args: 5046err_out_args:
5041 kfree(rbd_opts);
5042 rbd_spec_put(spec); 5047 rbd_spec_put(spec);
5043err_out_module: 5048err_out_module:
5044 module_put(THIS_MODULE); 5049 module_put(THIS_MODULE);