diff options
author | Ilya Dryomov <idryomov@gmail.com> | 2016-01-31 08:35:59 -0500 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2016-02-04 12:25:23 -0500 |
commit | f224a6915f266921507bb6e50a82f87a3de5b4b5 (patch) | |
tree | 01ec95389acdeba3651745a1a9457d976c011152 | |
parent | db6aed70235b35a113e1b0e81cb293fd2e92de0f (diff) |
crush: ensure bucket id is valid before indexing buckets array
We were indexing the buckets array without verifying the index was
within the [0,max_buckets) range. This could happen because
a multistep rule does not have enough buckets and has CRUSH_ITEM_NONE
for an intermediate result, which would feed in CRUSH_ITEM_NONE and
make us crash.
Reflects ceph.git commit 976a24a326da8931e689ee22fce35feab5b67b76.
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Reviewed-by: Sage Weil <sage@redhat.com>
-rw-r--r-- | net/ceph/crush/mapper.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/net/ceph/crush/mapper.c b/net/ceph/crush/mapper.c index 393bfb22d5bb..97ecf6f262aa 100644 --- a/net/ceph/crush/mapper.c +++ b/net/ceph/crush/mapper.c | |||
@@ -888,6 +888,7 @@ int crush_do_rule(const struct crush_map *map, | |||
888 | osize = 0; | 888 | osize = 0; |
889 | 889 | ||
890 | for (i = 0; i < wsize; i++) { | 890 | for (i = 0; i < wsize; i++) { |
891 | int bno; | ||
891 | /* | 892 | /* |
892 | * see CRUSH_N, CRUSH_N_MINUS macros. | 893 | * see CRUSH_N, CRUSH_N_MINUS macros. |
893 | * basically, numrep <= 0 means relative to | 894 | * basically, numrep <= 0 means relative to |
@@ -900,6 +901,13 @@ int crush_do_rule(const struct crush_map *map, | |||
900 | continue; | 901 | continue; |
901 | } | 902 | } |
902 | j = 0; | 903 | j = 0; |
904 | /* make sure bucket id is valid */ | ||
905 | bno = -1 - w[i]; | ||
906 | if (bno < 0 || bno >= map->max_buckets) { | ||
907 | /* w[i] is probably CRUSH_ITEM_NONE */ | ||
908 | dprintk(" bad w[i] %d\n", w[i]); | ||
909 | continue; | ||
910 | } | ||
903 | if (firstn) { | 911 | if (firstn) { |
904 | int recurse_tries; | 912 | int recurse_tries; |
905 | if (choose_leaf_tries) | 913 | if (choose_leaf_tries) |
@@ -911,7 +919,7 @@ int crush_do_rule(const struct crush_map *map, | |||
911 | recurse_tries = choose_tries; | 919 | recurse_tries = choose_tries; |
912 | osize += crush_choose_firstn( | 920 | osize += crush_choose_firstn( |
913 | map, | 921 | map, |
914 | map->buckets[-1-w[i]], | 922 | map->buckets[bno], |
915 | weight, weight_max, | 923 | weight, weight_max, |
916 | x, numrep, | 924 | x, numrep, |
917 | curstep->arg2, | 925 | curstep->arg2, |
@@ -930,7 +938,7 @@ int crush_do_rule(const struct crush_map *map, | |||
930 | numrep : (result_max-osize)); | 938 | numrep : (result_max-osize)); |
931 | crush_choose_indep( | 939 | crush_choose_indep( |
932 | map, | 940 | map, |
933 | map->buckets[-1-w[i]], | 941 | map->buckets[bno], |
934 | weight, weight_max, | 942 | weight, weight_max, |
935 | x, out_size, numrep, | 943 | x, out_size, numrep, |
936 | curstep->arg2, | 944 | curstep->arg2, |