diff options
author | Ilya Dryomov <ilya.dryomov@inktank.com> | 2013-12-24 14:19:24 -0500 |
---|---|---|
committer | Ilya Dryomov <ilya.dryomov@inktank.com> | 2013-12-31 13:32:10 -0500 |
commit | b3b33b0e43323af4fb697f4378218d3c268d02cd (patch) | |
tree | a66facb833b060476439c9988b81311e827c35c6 /net | |
parent | 2b3e0c905af43cfe402a2ef3f800be5dc1684005 (diff) |
crush: pass weight vector size to map function
Pass the size of the weight vector into crush_do_rule() to ensure that we
don't access values past the end. This can happen if the caller misbehaves
and passes a weight vector that is smaller than max_devices.
Currently the monitor tries to prevent that from happening, but this will
gracefully tolerate previous bad osdmaps that got into this state. It's
also a bit more defensive.
Reflects ceph.git commit 5922e2c2b8335b5e46c9504349c3a55b7434c01a.
Signed-off-by: Ilya Dryomov <ilya.dryomov@inktank.com>
Reviewed-by: Sage Weil <sage@inktank.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/ceph/crush/mapper.c | 17 | ||||
-rw-r--r-- | net/ceph/osdmap.c | 2 |
2 files changed, 13 insertions, 6 deletions
diff --git a/net/ceph/crush/mapper.c b/net/ceph/crush/mapper.c index cbd06a91941c..18d2cf66f102 100644 --- a/net/ceph/crush/mapper.c +++ b/net/ceph/crush/mapper.c | |||
@@ -264,8 +264,12 @@ static int crush_bucket_choose(struct crush_bucket *in, int x, int r) | |||
264 | * true if device is marked "out" (failed, fully offloaded) | 264 | * true if device is marked "out" (failed, fully offloaded) |
265 | * of the cluster | 265 | * of the cluster |
266 | */ | 266 | */ |
267 | static int is_out(const struct crush_map *map, const __u32 *weight, int item, int x) | 267 | static int is_out(const struct crush_map *map, |
268 | const __u32 *weight, int weight_max, | ||
269 | int item, int x) | ||
268 | { | 270 | { |
271 | if (item >= weight_max) | ||
272 | return 1; | ||
269 | if (weight[item] >= 0x10000) | 273 | if (weight[item] >= 0x10000) |
270 | return 0; | 274 | return 0; |
271 | if (weight[item] == 0) | 275 | if (weight[item] == 0) |
@@ -292,7 +296,7 @@ static int is_out(const struct crush_map *map, const __u32 *weight, int item, in | |||
292 | */ | 296 | */ |
293 | static int crush_choose(const struct crush_map *map, | 297 | static int crush_choose(const struct crush_map *map, |
294 | struct crush_bucket *bucket, | 298 | struct crush_bucket *bucket, |
295 | const __u32 *weight, | 299 | const __u32 *weight, int weight_max, |
296 | int x, int numrep, int type, | 300 | int x, int numrep, int type, |
297 | int *out, int outpos, | 301 | int *out, int outpos, |
298 | int firstn, int recurse_to_leaf, | 302 | int firstn, int recurse_to_leaf, |
@@ -396,7 +400,7 @@ static int crush_choose(const struct crush_map *map, | |||
396 | if (item < 0) { | 400 | if (item < 0) { |
397 | if (crush_choose(map, | 401 | if (crush_choose(map, |
398 | map->buckets[-1-item], | 402 | map->buckets[-1-item], |
399 | weight, | 403 | weight, weight_max, |
400 | x, outpos+1, 0, | 404 | x, outpos+1, 0, |
401 | out2, outpos, | 405 | out2, outpos, |
402 | firstn, 0, | 406 | firstn, 0, |
@@ -414,6 +418,7 @@ static int crush_choose(const struct crush_map *map, | |||
414 | /* out? */ | 418 | /* out? */ |
415 | if (itemtype == 0) | 419 | if (itemtype == 0) |
416 | reject = is_out(map, weight, | 420 | reject = is_out(map, weight, |
421 | weight_max, | ||
417 | item, x); | 422 | item, x); |
418 | else | 423 | else |
419 | reject = 0; | 424 | reject = 0; |
@@ -470,10 +475,12 @@ reject: | |||
470 | * @x: hash input | 475 | * @x: hash input |
471 | * @result: pointer to result vector | 476 | * @result: pointer to result vector |
472 | * @result_max: maximum result size | 477 | * @result_max: maximum result size |
478 | * @weight: weight vector (for map leaves) | ||
479 | * @weight_max: size of weight vector | ||
473 | */ | 480 | */ |
474 | int crush_do_rule(const struct crush_map *map, | 481 | int crush_do_rule(const struct crush_map *map, |
475 | int ruleno, int x, int *result, int result_max, | 482 | int ruleno, int x, int *result, int result_max, |
476 | const __u32 *weight) | 483 | const __u32 *weight, int weight_max) |
477 | { | 484 | { |
478 | int result_len; | 485 | int result_len; |
479 | int a[CRUSH_MAX_SET]; | 486 | int a[CRUSH_MAX_SET]; |
@@ -545,7 +552,7 @@ int crush_do_rule(const struct crush_map *map, | |||
545 | j = 0; | 552 | j = 0; |
546 | osize += crush_choose(map, | 553 | osize += crush_choose(map, |
547 | map->buckets[-1-w[i]], | 554 | map->buckets[-1-w[i]], |
548 | weight, | 555 | weight, weight_max, |
549 | x, numrep, | 556 | x, numrep, |
550 | curstep->arg2, | 557 | curstep->arg2, |
551 | o+osize, j, | 558 | o+osize, j, |
diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index dbd9a4792427..6477a68ddecb 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c | |||
@@ -1165,7 +1165,7 @@ static int *calc_pg_raw(struct ceph_osdmap *osdmap, struct ceph_pg pgid, | |||
1165 | } | 1165 | } |
1166 | r = crush_do_rule(osdmap->crush, ruleno, pps, osds, | 1166 | r = crush_do_rule(osdmap->crush, ruleno, pps, osds, |
1167 | min_t(int, pool->size, *num), | 1167 | min_t(int, pool->size, *num), |
1168 | osdmap->osd_weight); | 1168 | osdmap->osd_weight, osdmap->max_osd); |
1169 | if (r < 0) { | 1169 | if (r < 0) { |
1170 | pr_err("error %d from crush rule: pool %lld ruleset %d type %d" | 1170 | pr_err("error %d from crush rule: pool %lld ruleset %d type %d" |
1171 | " size %d\n", r, pgid.pool, pool->crush_ruleset, | 1171 | " size %d\n", r, pgid.pool, pool->crush_ruleset, |