Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client

Pull Ceph fixes from Sage Weil:
"Two fixes.

One is a stopgap to prevent a stack blowout when users have a deep
chain of image clones. (We'll rewrite this code to be non-recursive
for the next window, but in the meantime this is a simple fix that
avoids a crash.)

The second fixes a refcount underflow"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client:
rbd: prevent kernel stack blow up on rbd map
rbd: don't leak parent_spec in rbd_dev_probe_parent()

+45 -36
+45 -36
drivers/block/rbd.c
··· 96 96 #define RBD_MINORS_PER_MAJOR 256 97 97 #define RBD_SINGLE_MAJOR_PART_SHIFT 4 98 98 99 + #define RBD_MAX_PARENT_CHAIN_LEN 16 100 + 99 101 #define RBD_SNAP_DEV_NAME_PREFIX "snap_" 100 102 #define RBD_MAX_SNAP_NAME_LEN \ 101 103 (NAME_MAX - (sizeof (RBD_SNAP_DEV_NAME_PREFIX) - 1)) ··· 428 426 size_t count); 429 427 static ssize_t rbd_remove_single_major(struct bus_type *bus, const char *buf, 430 428 size_t count); 431 - static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping); 429 + static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth); 432 430 static void rbd_spec_put(struct rbd_spec *spec); 433 431 434 432 static int rbd_dev_id_to_minor(int dev_id) ··· 5133 5131 return ret; 5134 5132 } 5135 5133 5136 - static int rbd_dev_probe_parent(struct rbd_device *rbd_dev) 5134 + /* 5135 + * @depth is rbd_dev_image_probe() -> rbd_dev_probe_parent() -> 5136 + * rbd_dev_image_probe() recursion depth, which means it's also the 5137 + * length of the already discovered part of the parent chain. 5138 + */ 5139 + static int rbd_dev_probe_parent(struct rbd_device *rbd_dev, int depth) 5137 5140 { 5138 5141 struct rbd_device *parent = NULL; 5139 - struct rbd_spec *parent_spec; 5140 - struct rbd_client *rbdc; 5141 5142 int ret; 5142 5143 5143 5144 if (!rbd_dev->parent_spec) 5144 5145 return 0; 5145 - /* 5146 - * We need to pass a reference to the client and the parent 5147 - * spec when creating the parent rbd_dev. Images related by 5148 - * parent/child relationships always share both. 5149 - */ 5150 - parent_spec = rbd_spec_get(rbd_dev->parent_spec); 5151 - rbdc = __rbd_get_client(rbd_dev->rbd_client); 5152 5146 5153 - ret = -ENOMEM; 5154 - parent = rbd_dev_create(rbdc, parent_spec, NULL); 5155 - if (!parent) 5147 + if (++depth > RBD_MAX_PARENT_CHAIN_LEN) { 5148 + pr_info("parent chain is too long (%d)\n", depth); 5149 + ret = -EINVAL; 5156 5150 goto out_err; 5157 - 5158 - ret = rbd_dev_image_probe(parent, false); 5159 - if (ret < 0) 5160 - goto out_err; 5161 - rbd_dev->parent = parent; 5162 - atomic_set(&rbd_dev->parent_ref, 1); 5163 - 5164 - return 0; 5165 - out_err: 5166 - if (parent) { 5167 - rbd_dev_unparent(rbd_dev); 5168 - rbd_dev_destroy(parent); 5169 - } else { 5170 - rbd_put_client(rbdc); 5171 - rbd_spec_put(parent_spec); 5172 5151 } 5173 5152 5153 + parent = rbd_dev_create(rbd_dev->rbd_client, rbd_dev->parent_spec, 5154 + NULL); 5155 + if (!parent) { 5156 + ret = -ENOMEM; 5157 + goto out_err; 5158 + } 5159 + 5160 + /* 5161 + * Images related by parent/child relationships always share 5162 + * rbd_client and spec/parent_spec, so bump their refcounts. 5163 + */ 5164 + __rbd_get_client(rbd_dev->rbd_client); 5165 + rbd_spec_get(rbd_dev->parent_spec); 5166 + 5167 + ret = rbd_dev_image_probe(parent, depth); 5168 + if (ret < 0) 5169 + goto out_err; 5170 + 5171 + rbd_dev->parent = parent; 5172 + atomic_set(&rbd_dev->parent_ref, 1); 5173 + return 0; 5174 + 5175 + out_err: 5176 + rbd_dev_unparent(rbd_dev); 5177 + if (parent) 5178 + rbd_dev_destroy(parent); 5174 5179 return ret; 5175 5180 } 5176 5181 ··· 5295 5286 * parent), initiate a watch on its header object before using that 5296 5287 * object to get detailed information about the rbd image. 5297 5288 */ 5298 - static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping) 5289 + static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth) 5299 5290 { 5300 5291 int ret; 5301 5292 ··· 5313 5304 if (ret) 5314 5305 goto err_out_format; 5315 5306 5316 - if (mapping) { 5307 + if (!depth) { 5317 5308 ret = rbd_dev_header_watch_sync(rbd_dev); 5318 5309 if (ret) { 5319 5310 if (ret == -ENOENT) ··· 5334 5325 * Otherwise this is a parent image, identified by pool, image 5335 5326 * and snap ids - need to fill in names for those ids. 5336 5327 */ 5337 - if (mapping) 5328 + if (!depth) 5338 5329 ret = rbd_spec_fill_snap_id(rbd_dev); 5339 5330 else 5340 5331 ret = rbd_spec_fill_names(rbd_dev); ··· 5356 5347 * Need to warn users if this image is the one being 5357 5348 * mapped and has a parent. 5358 5349 */ 5359 - if (mapping && rbd_dev->parent_spec) 5350 + if (!depth && rbd_dev->parent_spec) 5360 5351 rbd_warn(rbd_dev, 5361 5352 "WARNING: kernel layering is EXPERIMENTAL!"); 5362 5353 } 5363 5354 5364 - ret = rbd_dev_probe_parent(rbd_dev); 5355 + ret = rbd_dev_probe_parent(rbd_dev, depth); 5365 5356 if (ret) 5366 5357 goto err_out_probe; 5367 5358 ··· 5372 5363 err_out_probe: 5373 5364 rbd_dev_unprobe(rbd_dev); 5374 5365 err_out_watch: 5375 - if (mapping) 5366 + if (!depth) 5376 5367 rbd_dev_header_unwatch_sync(rbd_dev); 5377 5368 out_header_name: 5378 5369 kfree(rbd_dev->header_name); ··· 5435 5426 spec = NULL; /* rbd_dev now owns this */ 5436 5427 rbd_opts = NULL; /* rbd_dev now owns this */ 5437 5428 5438 - rc = rbd_dev_image_probe(rbd_dev, true); 5429 + rc = rbd_dev_image_probe(rbd_dev, 0); 5439 5430 if (rc < 0) 5440 5431 goto err_out_rbd_dev; 5441 5432