diff options
Diffstat (limited to 'net/ceph/osdmap.c')
-rw-r--r-- | net/ceph/osdmap.c | 59 |
1 files changed, 53 insertions, 6 deletions
diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index 81e3b84a77ef..3124b71a8883 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c | |||
@@ -135,6 +135,21 @@ bad: | |||
135 | return -EINVAL; | 135 | return -EINVAL; |
136 | } | 136 | } |
137 | 137 | ||
138 | static int skip_name_map(void **p, void *end) | ||
139 | { | ||
140 | int len; | ||
141 | ceph_decode_32_safe(p, end, len ,bad); | ||
142 | while (len--) { | ||
143 | int strlen; | ||
144 | *p += sizeof(u32); | ||
145 | ceph_decode_32_safe(p, end, strlen, bad); | ||
146 | *p += strlen; | ||
147 | } | ||
148 | return 0; | ||
149 | bad: | ||
150 | return -EINVAL; | ||
151 | } | ||
152 | |||
138 | static struct crush_map *crush_decode(void *pbyval, void *end) | 153 | static struct crush_map *crush_decode(void *pbyval, void *end) |
139 | { | 154 | { |
140 | struct crush_map *c; | 155 | struct crush_map *c; |
@@ -143,6 +158,7 @@ static struct crush_map *crush_decode(void *pbyval, void *end) | |||
143 | void **p = &pbyval; | 158 | void **p = &pbyval; |
144 | void *start = pbyval; | 159 | void *start = pbyval; |
145 | u32 magic; | 160 | u32 magic; |
161 | u32 num_name_maps; | ||
146 | 162 | ||
147 | dout("crush_decode %p to %p len %d\n", *p, end, (int)(end - *p)); | 163 | dout("crush_decode %p to %p len %d\n", *p, end, (int)(end - *p)); |
148 | 164 | ||
@@ -150,6 +166,11 @@ static struct crush_map *crush_decode(void *pbyval, void *end) | |||
150 | if (c == NULL) | 166 | if (c == NULL) |
151 | return ERR_PTR(-ENOMEM); | 167 | return ERR_PTR(-ENOMEM); |
152 | 168 | ||
169 | /* set tunables to default values */ | ||
170 | c->choose_local_tries = 2; | ||
171 | c->choose_local_fallback_tries = 5; | ||
172 | c->choose_total_tries = 19; | ||
173 | |||
153 | ceph_decode_need(p, end, 4*sizeof(u32), bad); | 174 | ceph_decode_need(p, end, 4*sizeof(u32), bad); |
154 | magic = ceph_decode_32(p); | 175 | magic = ceph_decode_32(p); |
155 | if (magic != CRUSH_MAGIC) { | 176 | if (magic != CRUSH_MAGIC) { |
@@ -297,7 +318,25 @@ static struct crush_map *crush_decode(void *pbyval, void *end) | |||
297 | } | 318 | } |
298 | 319 | ||
299 | /* ignore trailing name maps. */ | 320 | /* ignore trailing name maps. */ |
321 | for (num_name_maps = 0; num_name_maps < 3; num_name_maps++) { | ||
322 | err = skip_name_map(p, end); | ||
323 | if (err < 0) | ||
324 | goto done; | ||
325 | } | ||
326 | |||
327 | /* tunables */ | ||
328 | ceph_decode_need(p, end, 3*sizeof(u32), done); | ||
329 | c->choose_local_tries = ceph_decode_32(p); | ||
330 | c->choose_local_fallback_tries = ceph_decode_32(p); | ||
331 | c->choose_total_tries = ceph_decode_32(p); | ||
332 | dout("crush decode tunable choose_local_tries = %d", | ||
333 | c->choose_local_tries); | ||
334 | dout("crush decode tunable choose_local_fallback_tries = %d", | ||
335 | c->choose_local_fallback_tries); | ||
336 | dout("crush decode tunable choose_total_tries = %d", | ||
337 | c->choose_total_tries); | ||
300 | 338 | ||
339 | done: | ||
301 | dout("crush_decode success\n"); | 340 | dout("crush_decode success\n"); |
302 | return c; | 341 | return c; |
303 | 342 | ||
@@ -488,15 +527,16 @@ static int __decode_pool_names(void **p, void *end, struct ceph_osdmap *map) | |||
488 | ceph_decode_32_safe(p, end, pool, bad); | 527 | ceph_decode_32_safe(p, end, pool, bad); |
489 | ceph_decode_32_safe(p, end, len, bad); | 528 | ceph_decode_32_safe(p, end, len, bad); |
490 | dout(" pool %d len %d\n", pool, len); | 529 | dout(" pool %d len %d\n", pool, len); |
530 | ceph_decode_need(p, end, len, bad); | ||
491 | pi = __lookup_pg_pool(&map->pg_pools, pool); | 531 | pi = __lookup_pg_pool(&map->pg_pools, pool); |
492 | if (pi) { | 532 | if (pi) { |
533 | char *name = kstrndup(*p, len, GFP_NOFS); | ||
534 | |||
535 | if (!name) | ||
536 | return -ENOMEM; | ||
493 | kfree(pi->name); | 537 | kfree(pi->name); |
494 | pi->name = kmalloc(len + 1, GFP_NOFS); | 538 | pi->name = name; |
495 | if (pi->name) { | 539 | dout(" name is %s\n", pi->name); |
496 | memcpy(pi->name, *p, len); | ||
497 | pi->name[len] = '\0'; | ||
498 | dout(" name is %s\n", pi->name); | ||
499 | } | ||
500 | } | 540 | } |
501 | *p += len; | 541 | *p += len; |
502 | } | 542 | } |
@@ -666,6 +706,9 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end) | |||
666 | ceph_decode_need(p, end, sizeof(u32) + sizeof(u64), bad); | 706 | ceph_decode_need(p, end, sizeof(u32) + sizeof(u64), bad); |
667 | ceph_decode_copy(p, &pgid, sizeof(pgid)); | 707 | ceph_decode_copy(p, &pgid, sizeof(pgid)); |
668 | n = ceph_decode_32(p); | 708 | n = ceph_decode_32(p); |
709 | err = -EINVAL; | ||
710 | if (n > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) | ||
711 | goto bad; | ||
669 | ceph_decode_need(p, end, n * sizeof(u32), bad); | 712 | ceph_decode_need(p, end, n * sizeof(u32), bad); |
670 | err = -ENOMEM; | 713 | err = -ENOMEM; |
671 | pg = kmalloc(sizeof(*pg) + n*sizeof(u32), GFP_NOFS); | 714 | pg = kmalloc(sizeof(*pg) + n*sizeof(u32), GFP_NOFS); |
@@ -889,6 +932,10 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
889 | (void) __remove_pg_mapping(&map->pg_temp, pgid); | 932 | (void) __remove_pg_mapping(&map->pg_temp, pgid); |
890 | 933 | ||
891 | /* insert */ | 934 | /* insert */ |
935 | if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) { | ||
936 | err = -EINVAL; | ||
937 | goto bad; | ||
938 | } | ||
892 | pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS); | 939 | pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS); |
893 | if (!pg) { | 940 | if (!pg) { |
894 | err = -ENOMEM; | 941 | err = -ENOMEM; |