From: Ilya Dryomov <idryomov@gmail.com>
Date: Thu, 11 Oct 2018 17:04:33 +0200
Subject: libceph: enable fallback to ceph_msg_new() in ceph_msgpool_get()
Git-commit: 3b83f60da6dd1becd865c1e2745123a8ae378c25
Patch-mainline: v4.20-rc1
References: bsc#1135897
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 <idryomov@gmail.com>
Acked-by: Luis Henriques <lhenriques@suse.com>
---
net/ceph/msgpool.c | 2 +-
net/ceph/osd_client.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
--- a/net/ceph/msgpool.c
+++ b/net/ceph/msgpool.c
@@ -60,7 +60,7 @@ struct ceph_msg *ceph_msgpool_get(struct
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);
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -640,7 +640,7 @@ int ceph_osdc_alloc_messages(struct ceph
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)
@@ -655,7 +655,7 @@ int ceph_osdc_alloc_messages(struct ceph
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)