|
|
3604df |
From eebc1b2076206600e9ed9ac6b3cd061708f96401 Mon Sep 17 00:00:00 2001
|
|
|
3604df |
From: Poornima G <pgurusid@redhat.com>
|
|
|
3604df |
Date: Tue, 14 Feb 2017 12:45:36 +0530
|
|
|
3604df |
Subject: [PATCH 291/294] rpcsvc: Add rpchdr and proghdr to iobref before
|
|
|
3604df |
submitting to transport
|
|
|
3604df |
|
|
|
3604df |
Backport of https://review.gluster.org/16613
|
|
|
3604df |
|
|
|
3604df |
Issue:
|
|
|
3604df |
When fio is run on multiple clients (each client writes to its own files),
|
|
|
3604df |
and meanwhile the clients does a readdirp, thus the client which did
|
|
|
3604df |
a readdirp will now recieve the upcalls. In this scenario the client
|
|
|
3604df |
disconnects with rpc decode failed error.
|
|
|
3604df |
|
|
|
3604df |
RCA:
|
|
|
3604df |
Upcall calls rpcsvc_request_submit to submit the request to socket:
|
|
|
3604df |
rpcsvc_request_submit currently:
|
|
|
3604df |
rpcsvc_request_submit () {
|
|
|
3604df |
iobuf = iobuf_new
|
|
|
3604df |
iov = iobuf->ptr
|
|
|
3604df |
fill iobuf to contain xdrised upcall content - proghdr
|
|
|
3604df |
rpcsvc_callback_submit (..iov..)
|
|
|
3604df |
...
|
|
|
3604df |
if (iobuf)
|
|
|
3604df |
iobuf_unref (iobuf)
|
|
|
3604df |
}
|
|
|
3604df |
|
|
|
3604df |
rpcsvc_callback_submit (... iov...) {
|
|
|
3604df |
...
|
|
|
3604df |
iobuf = iobuf_new
|
|
|
3604df |
iov1 = iobuf->ptr
|
|
|
3604df |
fill iobuf to contain xdrised rpc header - rpchdr
|
|
|
3604df |
msg.rpchdr = iov1
|
|
|
3604df |
msg.proghdr = iov
|
|
|
3604df |
...
|
|
|
3604df |
rpc_transport_submit_request (msg)
|
|
|
3604df |
...
|
|
|
3604df |
if (iobuf)
|
|
|
3604df |
iobuf_unref (iobuf)
|
|
|
3604df |
}
|
|
|
3604df |
|
|
|
3604df |
rpcsvc_callback_submit assumes that once rpc_transport_submit_request()
|
|
|
3604df |
returns the msg is written on to socket and thus the buffers(rpchdr, proghdr)
|
|
|
3604df |
can be freed, which is not the case. In especially high workload,
|
|
|
3604df |
rpc_transport_submit_request() may not be able to write to socket immediately
|
|
|
3604df |
and hence adds it to its own queue and returns as successful. Thus, we have
|
|
|
3604df |
use after free, for rpchdr and proghdr. Hence the clients gets garbage rpchdr
|
|
|
3604df |
and proghdr and thus fails to decode the rpc, resulting in disconnect.
|
|
|
3604df |
|
|
|
3604df |
To prevent this, we need to add the rpchdr and proghdr to a iobref and send
|
|
|
3604df |
it in msg:
|
|
|
3604df |
iobref_add (iobref, iobufs)
|
|
|
3604df |
msg.iobref = iobref;
|
|
|
3604df |
The socket layer takes a ref on msg.iobref, if it cannot write to socket and
|
|
|
3604df |
is adding to the queue. Thus we do not have use after free.
|
|
|
3604df |
|
|
|
3604df |
Thank You for discussing, debugging and fixing along:
|
|
|
3604df |
Prashanth Pai <ppai@redhat.com>
|
|
|
3604df |
Raghavendra G <rgowdapp@redhat.com>
|
|
|
3604df |
Rajesh Joseph <rjoseph@redhat.com>
|
|
|
3604df |
Kotresh HR <khiremat@redhat.com>
|
|
|
3604df |
Mohammed Rafi KC <rkavunga@redhat.com>
|
|
|
3604df |
Soumya Koduri <skoduri@redhat.com>
|
|
|
3604df |
|
|
|
3604df |
> Reviewed-on: https://review.gluster.org/16613
|
|
|
3604df |
> Reviewed-by: Prashanth Pai <ppai@redhat.com>
|
|
|
3604df |
> Smoke: Gluster Build System <jenkins@build.gluster.org>
|
|
|
3604df |
> Reviewed-by: soumya k <skoduri@redhat.com>
|
|
|
3604df |
> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
|
|
|
3604df |
> CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
|
|
|
3604df |
> Reviewed-by: Raghavendra G <rgowdapp@redhat.com>
|
|
|
3604df |
|
|
|
3604df |
Change-Id: Ifa6bf6f4879141f42b46830a37c1574b21b37275
|
|
|
3604df |
BUG: 1409135
|
|
|
3604df |
Signed-off-by: Poornima G <pgurusid@redhat.com>
|
|
|
3604df |
Reviewed-on: https://code.engineering.redhat.com/gerrit/97927
|
|
|
3604df |
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
|
|
|
3604df |
---
|
|
|
3604df |
rpc/rpc-lib/src/rpcsvc.c | 33 +++++++++++++++++++++++++++++++--
|
|
|
3604df |
rpc/rpc-lib/src/rpcsvc.h | 3 ++-
|
|
|
3604df |
xlators/mgmt/glusterd/src/glusterd.c | 6 ++++--
|
|
|
3604df |
xlators/protocol/server/src/server.c | 20 +++++++++++++-------
|
|
|
3604df |
4 files changed, 50 insertions(+), 12 deletions(-)
|
|
|
3604df |
|
|
|
3604df |
diff --git a/rpc/rpc-lib/src/rpcsvc.c b/rpc/rpc-lib/src/rpcsvc.c
|
|
|
3604df |
index 2d2a7ff..641b63c 100644
|
|
|
3604df |
--- a/rpc/rpc-lib/src/rpcsvc.c
|
|
|
3604df |
+++ b/rpc/rpc-lib/src/rpcsvc.c
|
|
|
3604df |
@@ -1000,6 +1000,7 @@ int rpcsvc_request_submit (rpcsvc_t *rpc, rpc_transport_t *trans,
|
|
|
3604df |
struct iovec iov = {0, };
|
|
|
3604df |
struct iobuf *iobuf = NULL;
|
|
|
3604df |
ssize_t xdr_size = 0;
|
|
|
3604df |
+ struct iobref *iobref = NULL;
|
|
|
3604df |
|
|
|
3604df |
if (!req)
|
|
|
3604df |
goto out;
|
|
|
3604df |
@@ -1022,26 +1023,40 @@ int rpcsvc_request_submit (rpcsvc_t *rpc, rpc_transport_t *trans,
|
|
|
3604df |
iov.iov_len = ret;
|
|
|
3604df |
count = 1;
|
|
|
3604df |
|
|
|
3604df |
+ iobref = iobref_new ();
|
|
|
3604df |
+ if (!iobref) {
|
|
|
3604df |
+ ret = -1;
|
|
|
3604df |
+ gf_log ("rpcsvc", GF_LOG_WARNING, "Failed to create iobref");
|
|
|
3604df |
+ goto out;
|
|
|
3604df |
+ }
|
|
|
3604df |
+
|
|
|
3604df |
+ iobref_add (iobref, iobuf);
|
|
|
3604df |
+
|
|
|
3604df |
ret = rpcsvc_callback_submit (rpc, trans, prog, procnum,
|
|
|
3604df |
- &iov, count);
|
|
|
3604df |
+ &iov, count, iobref);
|
|
|
3604df |
|
|
|
3604df |
out:
|
|
|
3604df |
if (iobuf)
|
|
|
3604df |
iobuf_unref (iobuf);
|
|
|
3604df |
|
|
|
3604df |
+ if (iobref)
|
|
|
3604df |
+ iobref_unref (iobref);
|
|
|
3604df |
+
|
|
|
3604df |
return ret;
|
|
|
3604df |
}
|
|
|
3604df |
|
|
|
3604df |
int
|
|
|
3604df |
rpcsvc_callback_submit (rpcsvc_t *rpc, rpc_transport_t *trans,
|
|
|
3604df |
rpcsvc_cbk_program_t *prog, int procnum,
|
|
|
3604df |
- struct iovec *proghdr, int proghdrcount)
|
|
|
3604df |
+ struct iovec *proghdr, int proghdrcount,
|
|
|
3604df |
+ struct iobref *iobref)
|
|
|
3604df |
{
|
|
|
3604df |
struct iobuf *request_iob = NULL;
|
|
|
3604df |
struct iovec rpchdr = {0,};
|
|
|
3604df |
rpc_transport_req_t req;
|
|
|
3604df |
int ret = -1;
|
|
|
3604df |
int proglen = 0;
|
|
|
3604df |
+ gf_boolean_t new_iobref = _gf_false;
|
|
|
3604df |
|
|
|
3604df |
if (!rpc) {
|
|
|
3604df |
goto out;
|
|
|
3604df |
@@ -1063,11 +1078,22 @@ rpcsvc_callback_submit (rpcsvc_t *rpc, rpc_transport_t *trans,
|
|
|
3604df |
"cannot build rpc-record");
|
|
|
3604df |
goto out;
|
|
|
3604df |
}
|
|
|
3604df |
+ if (!iobref) {
|
|
|
3604df |
+ iobref = iobref_new ();
|
|
|
3604df |
+ if (!iobref) {
|
|
|
3604df |
+ gf_log ("rpcsvc", GF_LOG_WARNING, "Failed to create iobref");
|
|
|
3604df |
+ goto out;
|
|
|
3604df |
+ }
|
|
|
3604df |
+ new_iobref = 1;
|
|
|
3604df |
+ }
|
|
|
3604df |
+
|
|
|
3604df |
+ iobref_add (iobref, request_iob);
|
|
|
3604df |
|
|
|
3604df |
req.msg.rpchdr = &rpchdr;
|
|
|
3604df |
req.msg.rpchdrcount = 1;
|
|
|
3604df |
req.msg.proghdr = proghdr;
|
|
|
3604df |
req.msg.proghdrcount = proghdrcount;
|
|
|
3604df |
+ req.msg.iobref = iobref;
|
|
|
3604df |
|
|
|
3604df |
ret = rpc_transport_submit_request (trans, &req;;
|
|
|
3604df |
if (ret == -1) {
|
|
|
3604df |
@@ -1081,6 +1107,9 @@ rpcsvc_callback_submit (rpcsvc_t *rpc, rpc_transport_t *trans,
|
|
|
3604df |
out:
|
|
|
3604df |
iobuf_unref (request_iob);
|
|
|
3604df |
|
|
|
3604df |
+ if (new_iobref)
|
|
|
3604df |
+ iobref_unref (iobref);
|
|
|
3604df |
+
|
|
|
3604df |
return ret;
|
|
|
3604df |
}
|
|
|
3604df |
|
|
|
3604df |
diff --git a/rpc/rpc-lib/src/rpcsvc.h b/rpc/rpc-lib/src/rpcsvc.h
|
|
|
3604df |
index 63a6dad..cf3e590 100644
|
|
|
3604df |
--- a/rpc/rpc-lib/src/rpcsvc.h
|
|
|
3604df |
+++ b/rpc/rpc-lib/src/rpcsvc.h
|
|
|
3604df |
@@ -581,7 +581,8 @@ int rpcsvc_request_submit (rpcsvc_t *rpc, rpc_transport_t *trans,
|
|
|
3604df |
|
|
|
3604df |
int rpcsvc_callback_submit (rpcsvc_t *rpc, rpc_transport_t *trans,
|
|
|
3604df |
rpcsvc_cbk_program_t *prog, int procnum,
|
|
|
3604df |
- struct iovec *proghdr, int proghdrcount);
|
|
|
3604df |
+ struct iovec *proghdr, int proghdrcount,
|
|
|
3604df |
+ struct iobref *iobref);
|
|
|
3604df |
|
|
|
3604df |
rpcsvc_actor_t *
|
|
|
3604df |
rpcsvc_program_actor (rpcsvc_request_t *req);
|
|
|
3604df |
diff --git a/xlators/mgmt/glusterd/src/glusterd.c b/xlators/mgmt/glusterd/src/glusterd.c
|
|
|
3604df |
index 498672b..3bcf2d5 100644
|
|
|
3604df |
--- a/xlators/mgmt/glusterd/src/glusterd.c
|
|
|
3604df |
+++ b/xlators/mgmt/glusterd/src/glusterd.c
|
|
|
3604df |
@@ -245,7 +245,8 @@ glusterd_fetchspec_notify (xlator_t *this)
|
|
|
3604df |
list_for_each_entry (trans, &priv->xprt_list, list) {
|
|
|
3604df |
rpcsvc_callback_submit (priv->rpc, trans,
|
|
|
3604df |
&glusterd_cbk_prog,
|
|
|
3604df |
- GF_CBK_FETCHSPEC, NULL, 0);
|
|
|
3604df |
+ GF_CBK_FETCHSPEC, NULL, 0,
|
|
|
3604df |
+ NULL);
|
|
|
3604df |
}
|
|
|
3604df |
}
|
|
|
3604df |
pthread_mutex_unlock (&priv->xprt_lock);
|
|
|
3604df |
@@ -281,7 +282,8 @@ glusterd_fetchsnap_notify (xlator_t *this)
|
|
|
3604df |
list_for_each_entry (trans, &priv->xprt_list, list) {
|
|
|
3604df |
rpcsvc_callback_submit (priv->rpc, trans,
|
|
|
3604df |
&glusterd_cbk_prog,
|
|
|
3604df |
- GF_CBK_GET_SNAPS, NULL, 0);
|
|
|
3604df |
+ GF_CBK_GET_SNAPS, NULL, 0,
|
|
|
3604df |
+ NULL);
|
|
|
3604df |
}
|
|
|
3604df |
}
|
|
|
3604df |
pthread_mutex_unlock (&priv->xprt_lock);
|
|
|
3604df |
diff --git a/xlators/protocol/server/src/server.c b/xlators/protocol/server/src/server.c
|
|
|
3604df |
index 3c3664d..0bbfd09 100644
|
|
|
3604df |
--- a/xlators/protocol/server/src/server.c
|
|
|
3604df |
+++ b/xlators/protocol/server/src/server.c
|
|
|
3604df |
@@ -1289,12 +1289,18 @@ server_process_event_upcall (xlator_t *this, void *data)
|
|
|
3604df |
if (!client || strcmp(client->client_uid, client_uid))
|
|
|
3604df |
continue;
|
|
|
3604df |
|
|
|
3604df |
- rpcsvc_request_submit(conf->rpc, xprt,
|
|
|
3604df |
- &server_cbk_prog,
|
|
|
3604df |
- cbk_procnum,
|
|
|
3604df |
- up_req,
|
|
|
3604df |
- this->ctx,
|
|
|
3604df |
- xdrproc);
|
|
|
3604df |
+ ret = rpcsvc_request_submit (conf->rpc, xprt,
|
|
|
3604df |
+ &server_cbk_prog,
|
|
|
3604df |
+ cbk_procnum,
|
|
|
3604df |
+ up_req,
|
|
|
3604df |
+ this->ctx,
|
|
|
3604df |
+ xdrproc);
|
|
|
3604df |
+ if (ret < 0) {
|
|
|
3604df |
+ gf_msg_debug (this->name, 0, "Failed to send "
|
|
|
3604df |
+ "upcall to client:%s upcall "
|
|
|
3604df |
+ "event:%d", client_uid,
|
|
|
3604df |
+ upcall_data->event_type);
|
|
|
3604df |
+ }
|
|
|
3604df |
break;
|
|
|
3604df |
}
|
|
|
3604df |
}
|
|
|
3604df |
@@ -1329,7 +1335,7 @@ server_process_child_event (xlator_t *this, int32_t event, void *data,
|
|
|
3604df |
rpcsvc_callback_submit (conf->rpc, xprt,
|
|
|
3604df |
&server_cbk_prog,
|
|
|
3604df |
cbk_procnum,
|
|
|
3604df |
- NULL, 0);
|
|
|
3604df |
+ NULL, 0, NULL);
|
|
|
3604df |
}
|
|
|
3604df |
}
|
|
|
3604df |
pthread_mutex_unlock (&conf->mutex);
|
|
|
3604df |
--
|
|
|
3604df |
2.9.3
|
|
|
3604df |
|