Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0ed7285e authored by Sage Weil's avatar Sage Weil Committed by Alex Elder
Browse files

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: default avatarSage Weil <sage@inktank.com>
Reviewed-by: default avatarAlex Elder <elder@inktank.com>
parent 069a4b56
Loading
Loading
Loading
Loading
+20 −11
Original line number Diff line number Diff line
@@ -645,10 +645,12 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end)
	ceph_decode_32_safe(p, end, max, bad);
	while (max--) {
		ceph_decode_need(p, end, 4 + 1 + sizeof(pi->v), bad);
		err = -ENOMEM;
		pi = kzalloc(sizeof(*pi), GFP_NOFS);
		if (!pi)
			goto bad;
		pi->id = ceph_decode_32(p);
		err = -EINVAL;
		ev = ceph_decode_8(p); /* encoding version */
		if (ev > CEPH_PG_POOL_VERSION) {
			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)
		__insert_pg_pool(&map->pg_pools, pi);
	}

	if (version >= 5 && __decode_pool_names(p, end, map) < 0)
	if (version >= 5) {
		err = __decode_pool_names(p, end, map);
		if (err < 0) {
			dout("fail to decode pool names");
			goto bad;
		}
	}

	ceph_decode_32_safe(p, end, map->pool_max, bad);

@@ -745,7 +752,7 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end)
	return map;

bad:
	dout("osdmap_decode fail\n");
	dout("osdmap_decode fail err %d\n", err);
	ceph_osdmap_destroy(map);
	return ERR_PTR(err);
}
@@ -839,6 +846,7 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end,
		if (ev > CEPH_PG_POOL_VERSION) {
			pr_warning("got unknown v %d > %d of ceph_pg_pool\n",
				   ev, CEPH_PG_POOL_VERSION);
			err = -EINVAL;
			goto bad;
		}
		pi = __lookup_pg_pool(&map->pg_pools, pool);
@@ -855,8 +863,11 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end,
		if (err < 0)
			goto bad;
	}
	if (version >= 5 && __decode_pool_names(p, end, map) < 0)
	if (version >= 5) {
		err = __decode_pool_names(p, end, map);
		if (err < 0)
			goto bad;
	}

	/* old_pool */
	ceph_decode_32_safe(p, end, len, bad);
@@ -932,15 +943,13 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end,
			(void) __remove_pg_mapping(&map->pg_temp, pgid);

			/* insert */
			if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) {
			err = -EINVAL;
			if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32))
				goto bad;
			}
			pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS);
			if (!pg) {
			err = -ENOMEM;
			pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS);
			if (!pg)
				goto bad;
			}
			pg->pgid = pgid;
			pg->len = pglen;
			for (j = 0; j < pglen; j++)