From 3b83f60da6dd1becd865c1e2745123a8ae378c25 Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Thu, 11 Oct 2018 17:04:33 +0200 Subject: libceph: enable fallback to ceph_msg_new() in ceph_msgpool_get() ceph_msgpool_get() can fall back to ceph_msg_new() when it is asked for a message whose front portion is larger than pool->front_len. However the caller always passes 0, effectively disabling that code path. The allocation goes to the message pool and returns a message with a front that is smaller than requested, setting us up for a crash. One example of this is a directory with a large number of snapshots. If its snap context doesn't fit, we oops in encode_request_partial(). Signed-off-by: Ilya Dryomov --- net/ceph/msgpool.c | 2 +- net/ceph/osd_client.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'net/ceph') diff --git a/net/ceph/msgpool.c b/net/ceph/msgpool.c index 72571535883f..3dddc074f0d7 100644 --- a/net/ceph/msgpool.c +++ b/net/ceph/msgpool.c @@ -61,7 +61,7 @@ struct ceph_msg *ceph_msgpool_get(struct ceph_msgpool *pool, if (front_len > pool->front_len) { dout("msgpool_get %s need front %d, pool size is %d\n", pool->name, front_len, pool->front_len); - WARN_ON(1); + WARN_ON_ONCE(1); /* try to alloc a fresh message */ return ceph_msg_new(pool->type, front_len, GFP_NOFS, false); diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index f403a483d51d..35bc77c8c230 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -641,7 +641,7 @@ int ceph_osdc_alloc_messages(struct ceph_osd_request *req, gfp_t gfp) msg_size += 4 + 8; /* retry_attempt, features */ if (req->r_mempool) - msg = ceph_msgpool_get(&osdc->msgpool_op, 0); + msg = ceph_msgpool_get(&osdc->msgpool_op, msg_size); else msg = ceph_msg_new(CEPH_MSG_OSD_OP, msg_size, gfp, true); if (!msg) @@ -656,7 +656,7 @@ int ceph_osdc_alloc_messages(struct ceph_osd_request *req, gfp_t gfp) msg_size += req->r_num_ops * sizeof(struct ceph_osd_op); if (req->r_mempool) - msg = ceph_msgpool_get(&osdc->msgpool_op_reply, 0); + msg = ceph_msgpool_get(&osdc->msgpool_op_reply, msg_size); else msg = ceph_msg_new(CEPH_MSG_OSD_OPREPLY, msg_size, gfp, true); if (!msg) -- cgit v1.2.3