diff options
author | Sage Weil <sage@inktank.com> | 2012-10-29 14:01:42 -0400 |
---|---|---|
committer | Alex Elder <elder@inktank.com> | 2012-10-30 09:21:05 -0400 |
commit | 0ed7285e0001b960c888e5455ae982025210ed3d (patch) | |
tree | 4ca3c1faa4d7bc8064d6f0fb609dd3cd568c2554 /net | |
parent | 069a4b5690a952e74157fd489833c71c73f012b3 (diff) |
libceph: fix osdmap decode error paths
Ensure that we set the err value correctly so that we do not pass a 0
value to ERR_PTR and confuse the calling code. (In particular,
osd_client.c handle_map() will BUG(!newmap)).
Signed-off-by: Sage Weil <sage@inktank.com>
Reviewed-by: Alex Elder <elder@inktank.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/ceph/osdmap.c | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index 5433fb0eb3c6..f552aa48fd9e 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c | |||
@@ -645,10 +645,12 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end) | |||
645 | ceph_decode_32_safe(p, end, max, bad); | 645 | ceph_decode_32_safe(p, end, max, bad); |
646 | while (max--) { | 646 | while (max--) { |
647 | ceph_decode_need(p, end, 4 + 1 + sizeof(pi->v), bad); | 647 | ceph_decode_need(p, end, 4 + 1 + sizeof(pi->v), bad); |
648 | err = -ENOMEM; | ||
648 | pi = kzalloc(sizeof(*pi), GFP_NOFS); | 649 | pi = kzalloc(sizeof(*pi), GFP_NOFS); |
649 | if (!pi) | 650 | if (!pi) |
650 | goto bad; | 651 | goto bad; |
651 | pi->id = ceph_decode_32(p); | 652 | pi->id = ceph_decode_32(p); |
653 | err = -EINVAL; | ||
652 | ev = ceph_decode_8(p); /* encoding version */ | 654 | ev = ceph_decode_8(p); /* encoding version */ |
653 | if (ev > CEPH_PG_POOL_VERSION) { | 655 | if (ev > CEPH_PG_POOL_VERSION) { |
654 | pr_warning("got unknown v %d > %d of ceph_pg_pool\n", | 656 | pr_warning("got unknown v %d > %d of ceph_pg_pool\n", |
@@ -664,8 +666,13 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end) | |||
664 | __insert_pg_pool(&map->pg_pools, pi); | 666 | __insert_pg_pool(&map->pg_pools, pi); |
665 | } | 667 | } |
666 | 668 | ||
667 | if (version >= 5 && __decode_pool_names(p, end, map) < 0) | 669 | if (version >= 5) { |
668 | goto bad; | 670 | err = __decode_pool_names(p, end, map); |
671 | if (err < 0) { | ||
672 | dout("fail to decode pool names"); | ||
673 | goto bad; | ||
674 | } | ||
675 | } | ||
669 | 676 | ||
670 | ceph_decode_32_safe(p, end, map->pool_max, bad); | 677 | ceph_decode_32_safe(p, end, map->pool_max, bad); |
671 | 678 | ||
@@ -745,7 +752,7 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end) | |||
745 | return map; | 752 | return map; |
746 | 753 | ||
747 | bad: | 754 | bad: |
748 | dout("osdmap_decode fail\n"); | 755 | dout("osdmap_decode fail err %d\n", err); |
749 | ceph_osdmap_destroy(map); | 756 | ceph_osdmap_destroy(map); |
750 | return ERR_PTR(err); | 757 | return ERR_PTR(err); |
751 | } | 758 | } |
@@ -839,6 +846,7 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
839 | if (ev > CEPH_PG_POOL_VERSION) { | 846 | if (ev > CEPH_PG_POOL_VERSION) { |
840 | pr_warning("got unknown v %d > %d of ceph_pg_pool\n", | 847 | pr_warning("got unknown v %d > %d of ceph_pg_pool\n", |
841 | ev, CEPH_PG_POOL_VERSION); | 848 | ev, CEPH_PG_POOL_VERSION); |
849 | err = -EINVAL; | ||
842 | goto bad; | 850 | goto bad; |
843 | } | 851 | } |
844 | pi = __lookup_pg_pool(&map->pg_pools, pool); | 852 | pi = __lookup_pg_pool(&map->pg_pools, pool); |
@@ -855,8 +863,11 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
855 | if (err < 0) | 863 | if (err < 0) |
856 | goto bad; | 864 | goto bad; |
857 | } | 865 | } |
858 | if (version >= 5 && __decode_pool_names(p, end, map) < 0) | 866 | if (version >= 5) { |
859 | goto bad; | 867 | err = __decode_pool_names(p, end, map); |
868 | if (err < 0) | ||
869 | goto bad; | ||
870 | } | ||
860 | 871 | ||
861 | /* old_pool */ | 872 | /* old_pool */ |
862 | ceph_decode_32_safe(p, end, len, bad); | 873 | ceph_decode_32_safe(p, end, len, bad); |
@@ -932,15 +943,13 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
932 | (void) __remove_pg_mapping(&map->pg_temp, pgid); | 943 | (void) __remove_pg_mapping(&map->pg_temp, pgid); |
933 | 944 | ||
934 | /* insert */ | 945 | /* insert */ |
935 | if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) { | 946 | err = -EINVAL; |
936 | err = -EINVAL; | 947 | if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) |
937 | goto bad; | 948 | goto bad; |
938 | } | 949 | err = -ENOMEM; |
939 | pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS); | 950 | pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS); |
940 | if (!pg) { | 951 | if (!pg) |
941 | err = -ENOMEM; | ||
942 | goto bad; | 952 | goto bad; |
943 | } | ||
944 | pg->pgid = pgid; | 953 | pg->pgid = pgid; |
945 | pg->len = pglen; | 954 | pg->len = pglen; |
946 | for (j = 0; j < pglen; j++) | 955 | for (j = 0; j < pglen; j++) |