History

rbd: prevent kernel stack blow up on rbd map

Mapping an image with a long parent chain (e.g. image foo, whose parent is bar, whose parent is baz, etc) currently leads to a kernel stack overflow, due to the following recursion in the reply path: rbd_osd_req_callback() rbd_obj_request_complete() rbd_img_obj_callback() rbd_img_parent_read_callback() rbd_obj_request_complete() ... Limit the parent chain to 16 images, which is ~5K worth of stack. When the above recursion is eliminated, this limit can be lifted. Fixes: http://tracker.ceph.com/issues/12538

Ilya Dryomov committed 11 years ago

Commit 6d69bb51 parent 1f2c6651 file · +23 −10Browse files

Unified · Split

drivers/block/rbd.c+23−10
@@ -96,6 +96,8 @@ static int atomic_dec_return_safe(atomic_t *v) · 95 unmodified lines
96#define RBD_MINORS_PER_MAJOR 25696#define RBD_MINORS_PER_MAJOR 256
97#define RBD_SINGLE_MAJOR_PART_SHIFT 497#define RBD_SINGLE_MAJOR_PART_SHIFT 4
98 98
99#define RBD_MAX_PARENT_CHAIN_LEN 16
100
99#define RBD_SNAP_DEV_NAME_PREFIX "snap_"101#define RBD_SNAP_DEV_NAME_PREFIX "snap_"
100#define RBD_MAX_SNAP_NAME_LEN \102#define RBD_MAX_SNAP_NAME_LEN \
101 (NAME_MAX - (sizeof (RBD_SNAP_DEV_NAME_PREFIX) - 1))103 (NAME_MAX - (sizeof (RBD_SNAP_DEV_NAME_PREFIX) - 1))
@@ -426,7 +428,7 @@ static ssize_t rbd_add_single_major(struct bus_type *bus, const char *buf, · 324 unmodified lines
426 size_t count);428 size_t count);
427static ssize_t rbd_remove_single_major(struct bus_type *bus, const char *buf,429static ssize_t rbd_remove_single_major(struct bus_type *bus, const char *buf,
428 size_t count);430 size_t count);
429static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping);431static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth);
430static void rbd_spec_put(struct rbd_spec *spec);432static void rbd_spec_put(struct rbd_spec *spec);
431 433
432static int rbd_dev_id_to_minor(int dev_id)434static int rbd_dev_id_to_minor(int dev_id)
@@ -5131,7 +5133,12 @@ out_err: · 4698 unmodified lines
5131 return ret;5133 return ret;
5132}5134}
5133 5135
5134static int rbd_dev_probe_parent(struct rbd_device *rbd_dev)5136/*
5137 * @depth is rbd_dev_image_probe() -> rbd_dev_probe_parent() ->
5138 * rbd_dev_image_probe() recursion depth, which means it's also the
5139 * length of the already discovered part of the parent chain.
5140 */
5141static int rbd_dev_probe_parent(struct rbd_device *rbd_dev, int depth)
5135{5142{
5136 struct rbd_device *parent = NULL;5143 struct rbd_device *parent = NULL;
5137 int ret;5144 int ret;
@@ -5139,6 +5146,12 @@ static int rbd_dev_probe_parent(struct rbd_device *rbd_dev) · 1 unmodified line
5139 if (!rbd_dev->parent_spec)5146 if (!rbd_dev->parent_spec)
5140 return 0;5147 return 0;
5141 5148
5149 if (++depth > RBD_MAX_PARENT_CHAIN_LEN) {
5150 pr_info("parent chain is too long (%d)\n", depth);
5151 ret = -EINVAL;
5152 goto out_err;
5153 }
5154
5142 parent = rbd_dev_create(rbd_dev->rbd_client, rbd_dev->parent_spec,5155 parent = rbd_dev_create(rbd_dev->rbd_client, rbd_dev->parent_spec,
5143 NULL);5156 NULL);
5144 if (!parent) {5157 if (!parent) {
@@ -5153,7 +5166,7 @@ static int rbd_dev_probe_parent(struct rbd_device *rbd_dev) · 8 unmodified lines
5153 __rbd_get_client(rbd_dev->rbd_client);5166 __rbd_get_client(rbd_dev->rbd_client);
5154 rbd_spec_get(rbd_dev->parent_spec);5167 rbd_spec_get(rbd_dev->parent_spec);
5155 5168
5156 ret = rbd_dev_image_probe(parent, false);5169 ret = rbd_dev_image_probe(parent, depth);
5157 if (ret < 0)5170 if (ret < 0)
5158 goto out_err;5171 goto out_err;
5159 5172
@@ -5282,7 +5295,7 @@ static void rbd_dev_image_release(struct rbd_device *rbd_dev) · 122 unmodified lines
5282 * parent), initiate a watch on its header object before using that5295 * parent), initiate a watch on its header object before using that
5283 * object to get detailed information about the rbd image.5296 * object to get detailed information about the rbd image.
5284 */5297 */
5285static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)5298static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
5286{5299{
5287 int ret;5300 int ret;
5288 5301
@@ -5300,7 +5313,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping) · 11 unmodified lines
5300 if (ret)5313 if (ret)
5301 goto err_out_format;5314 goto err_out_format;
5302 5315
5303 if (mapping) {5316 if (!depth) {
5304 ret = rbd_dev_header_watch_sync(rbd_dev);5317 ret = rbd_dev_header_watch_sync(rbd_dev);
5305 if (ret) {5318 if (ret) {
5306 if (ret == -ENOENT)5319 if (ret == -ENOENT)
@@ -5321,7 +5334,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping) · 14 unmodified lines
5321 * Otherwise this is a parent image, identified by pool, image5334 * Otherwise this is a parent image, identified by pool, image
5322 * and snap ids - need to fill in names for those ids.5335 * and snap ids - need to fill in names for those ids.
5323 */5336 */
5324 if (mapping)5337 if (!depth)
5325 ret = rbd_spec_fill_snap_id(rbd_dev);5338 ret = rbd_spec_fill_snap_id(rbd_dev);
5326 else5339 else
5327 ret = rbd_spec_fill_names(rbd_dev);5340 ret = rbd_spec_fill_names(rbd_dev);
@@ -5343,12 +5356,12 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping) · 15 unmodified lines
5343 * Need to warn users if this image is the one being5356 * Need to warn users if this image is the one being
5344 * mapped and has a parent.5357 * mapped and has a parent.
5345 */5358 */
5346 if (mapping && rbd_dev->parent_spec)5359 if (!depth && rbd_dev->parent_spec)
5347 rbd_warn(rbd_dev,5360 rbd_warn(rbd_dev,
5348 "WARNING: kernel layering is EXPERIMENTAL!");5361 "WARNING: kernel layering is EXPERIMENTAL!");
5349 }5362 }
5350 5363
5351 ret = rbd_dev_probe_parent(rbd_dev);5364 ret = rbd_dev_probe_parent(rbd_dev, depth);
5352 if (ret)5365 if (ret)
5353 goto err_out_probe;5366 goto err_out_probe;
5354 5367
@@ -5359,7 +5372,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping) · 4 unmodified lines
5359err_out_probe:5372err_out_probe:
5360 rbd_dev_unprobe(rbd_dev);5373 rbd_dev_unprobe(rbd_dev);
5361err_out_watch:5374err_out_watch:
5362 if (mapping)5375 if (!depth)
5363 rbd_dev_header_unwatch_sync(rbd_dev);5376 rbd_dev_header_unwatch_sync(rbd_dev);
5364out_header_name:5377out_header_name:
5365 kfree(rbd_dev->header_name);5378 kfree(rbd_dev->header_name);
@@ -5422,7 +5435,7 @@ static ssize_t do_rbd_add(struct bus_type *bus, · 56 unmodified lines
5422 spec = NULL; /* rbd_dev now owns this */5435 spec = NULL; /* rbd_dev now owns this */
5423 rbd_opts = NULL; /* rbd_dev now owns this */5436 rbd_opts = NULL; /* rbd_dev now owns this */
5424 5437
5425 rc = rbd_dev_image_probe(rbd_dev, true);5438 rc = rbd_dev_image_probe(rbd_dev, 0);
5426 if (rc < 0)5439 if (rc < 0)
5427 goto err_out_rbd_dev;5440 goto err_out_rbd_dev;
5428 5441