|
|
21ab4e |
From 3cbb78a63b282d8c0d7c75f3b6c3816a7deb06c1 Mon Sep 17 00:00:00 2001
|
|
|
21ab4e |
From: Niels de Vos <ndevos@redhat.com>
|
|
|
21ab4e |
Date: Tue, 4 Jul 2017 20:11:11 +0200
|
|
|
21ab4e |
Subject: [PATCH 550/557] nfs/nlm: keep track of the call-state and frame for
|
|
|
21ab4e |
notifications
|
|
|
21ab4e |
|
|
|
21ab4e |
When blocking locks are used, a new frame is allocated that is used to
|
|
|
21ab4e |
send the notification to the client once once the lock becomes
|
|
|
21ab4e |
available. In all other cases, the frame that contains the request from
|
|
|
21ab4e |
the client will be used for the reply.
|
|
|
21ab4e |
|
|
|
21ab4e |
Because there was no way to track the different clients with their
|
|
|
21ab4e |
requests (captured in the call-state), the call-state could be free'd
|
|
|
21ab4e |
before the notification was sent to the client. This caused a
|
|
|
21ab4e |
use-after-free of the call-state and could trigger segfaults of the
|
|
|
21ab4e |
Gluster/NFS server or incorrect replies on (un)lock requests.
|
|
|
21ab4e |
|
|
|
21ab4e |
By introducing a nlm4_notify_args structure, the call-state and frame
|
|
|
21ab4e |
can be tracked better. This prevents the possibility of segfaulting when
|
|
|
21ab4e |
the call-state is used after being free'd.
|
|
|
21ab4e |
|
|
|
21ab4e |
Cherry picked from commit b81997264f079983fa02bd5fa2b3715224942b00:
|
|
|
21ab4e |
> BUG: 1467313
|
|
|
21ab4e |
> Change-Id: I285d2bc552f509e5145653b7a50afcff827cd612
|
|
|
21ab4e |
> Signed-off-by: Niels de Vos <ndevos@redhat.com>
|
|
|
21ab4e |
> Reviewed-on: https://review.gluster.org/17700
|
|
|
21ab4e |
> Smoke: Gluster Build System <jenkins@build.gluster.org>
|
|
|
21ab4e |
> CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
|
|
|
21ab4e |
> Reviewed-by: Kaleb KEITHLEY <kkeithle@redhat.com>
|
|
|
21ab4e |
> Reviewed-by: jiffin tony Thottan <jthottan@redhat.com>
|
|
|
21ab4e |
|
|
|
21ab4e |
Change-Id: I285d2bc552f509e5145653b7a50afcff827cd612
|
|
|
21ab4e |
BUG: 1411344
|
|
|
21ab4e |
Signed-off-by: Niels de Vos <ndevos@redhat.com>
|
|
|
21ab4e |
Reviewed-on: https://code.engineering.redhat.com/gerrit/111769
|
|
|
21ab4e |
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
|
|
|
21ab4e |
---
|
|
|
21ab4e |
xlators/nfs/server/src/nfs-mem-types.h | 1 +
|
|
|
21ab4e |
xlators/nfs/server/src/nlm4.c | 107 +++++++++++++++++++++++++--------
|
|
|
21ab4e |
2 files changed, 84 insertions(+), 24 deletions(-)
|
|
|
21ab4e |
|
|
|
21ab4e |
diff --git a/xlators/nfs/server/src/nfs-mem-types.h b/xlators/nfs/server/src/nfs-mem-types.h
|
|
|
21ab4e |
index 88c688f..5cac0eb 100644
|
|
|
21ab4e |
--- a/xlators/nfs/server/src/nfs-mem-types.h
|
|
|
21ab4e |
+++ b/xlators/nfs/server/src/nfs-mem-types.h
|
|
|
21ab4e |
@@ -50,6 +50,7 @@ enum gf_nfs_mem_types_ {
|
|
|
21ab4e |
gf_nfs_mt_arr,
|
|
|
21ab4e |
gf_nfs_mt_auth_cache,
|
|
|
21ab4e |
gf_nfs_mt_auth_cache_entry,
|
|
|
21ab4e |
+ gf_nfs_mt_nlm4_notify,
|
|
|
21ab4e |
gf_nfs_mt_end
|
|
|
21ab4e |
};
|
|
|
21ab4e |
#endif
|
|
|
21ab4e |
diff --git a/xlators/nfs/server/src/nlm4.c b/xlators/nfs/server/src/nlm4.c
|
|
|
21ab4e |
index d678edc..8b7c747 100644
|
|
|
21ab4e |
--- a/xlators/nfs/server/src/nlm4.c
|
|
|
21ab4e |
+++ b/xlators/nfs/server/src/nlm4.c
|
|
|
21ab4e |
@@ -922,28 +922,64 @@ rpcerr:
|
|
|
21ab4e |
return ret;
|
|
|
21ab4e |
}
|
|
|
21ab4e |
|
|
|
21ab4e |
-int
|
|
|
21ab4e |
+struct nlm4_notify_args {
|
|
|
21ab4e |
+ GF_REF_DECL; /* refcounting */
|
|
|
21ab4e |
+
|
|
|
21ab4e |
+ nfs3_call_state_t *cs; /* call state, w/ lock request details */
|
|
|
21ab4e |
+ call_frame_t *frame; /* frame to us for the reply */
|
|
|
21ab4e |
+};
|
|
|
21ab4e |
+
|
|
|
21ab4e |
+static int
|
|
|
21ab4e |
nlm4svc_send_granted_cbk (struct rpc_req *req, struct iovec *iov, int count,
|
|
|
21ab4e |
void *myframe)
|
|
|
21ab4e |
{
|
|
|
21ab4e |
- STACK_DESTROY (((call_frame_t*)myframe)->root);
|
|
|
21ab4e |
+ call_frame_t *frame = myframe;
|
|
|
21ab4e |
+ struct nlm4_notify_args *args = frame->local;
|
|
|
21ab4e |
+
|
|
|
21ab4e |
+ GF_REF_PUT (args);
|
|
|
21ab4e |
return 0;
|
|
|
21ab4e |
}
|
|
|
21ab4e |
|
|
|
21ab4e |
+static void
|
|
|
21ab4e |
+nlm4_notify_free (struct nlm4_notify_args *ncf)
|
|
|
21ab4e |
+{
|
|
|
21ab4e |
+ GF_REF_PUT (ncf->cs);
|
|
|
21ab4e |
+ STACK_DESTROY (ncf->frame->root);
|
|
|
21ab4e |
+ GF_FREE (ncf);
|
|
|
21ab4e |
+}
|
|
|
21ab4e |
+
|
|
|
21ab4e |
+static struct nlm4_notify_args*
|
|
|
21ab4e |
+nlm4_notify_init (nfs3_call_state_t *cs)
|
|
|
21ab4e |
+{
|
|
|
21ab4e |
+ struct nlm4_notify_args *ncf = NULL;
|
|
|
21ab4e |
+
|
|
|
21ab4e |
+ ncf = GF_CALLOC (1, sizeof (struct nlm4_notify_args),
|
|
|
21ab4e |
+ gf_nfs_mt_nlm4_notify);
|
|
|
21ab4e |
+ if (!ncf)
|
|
|
21ab4e |
+ /* GF_CALLOW will log the ENOMEM error */
|
|
|
21ab4e |
+ goto out;
|
|
|
21ab4e |
+
|
|
|
21ab4e |
+ GF_REF_INIT (ncf, nlm4_notify_free);
|
|
|
21ab4e |
+ ncf->cs = GF_REF_GET (cs);
|
|
|
21ab4e |
+
|
|
|
21ab4e |
+out:
|
|
|
21ab4e |
+ return ncf;
|
|
|
21ab4e |
+}
|
|
|
21ab4e |
+
|
|
|
21ab4e |
static int
|
|
|
21ab4e |
-nlm_handle_connect (struct rpc_clnt *rpc_clnt, nfs3_call_state_t *cs);
|
|
|
21ab4e |
+nlm_handle_connect (struct rpc_clnt *rpc_clnt, struct nlm4_notify_args *ncf);
|
|
|
21ab4e |
|
|
|
21ab4e |
int
|
|
|
21ab4e |
nlm_rpcclnt_notify (struct rpc_clnt *rpc_clnt, void *mydata,
|
|
|
21ab4e |
rpc_clnt_event_t fn, void *data)
|
|
|
21ab4e |
{
|
|
|
21ab4e |
- nfs3_call_state_t *cs = NULL;
|
|
|
21ab4e |
+ struct nlm4_notify_args *ncf = mydata;
|
|
|
21ab4e |
|
|
|
21ab4e |
- cs = mydata;
|
|
|
21ab4e |
+ GF_VALIDATE_OR_GOTO ("NLM4-notify", ncf, out);
|
|
|
21ab4e |
|
|
|
21ab4e |
switch (fn) {
|
|
|
21ab4e |
case RPC_CLNT_CONNECT:
|
|
|
21ab4e |
- nlm_handle_connect (rpc_clnt, cs);
|
|
|
21ab4e |
+ nlm_handle_connect (rpc_clnt, ncf);
|
|
|
21ab4e |
break;
|
|
|
21ab4e |
|
|
|
21ab4e |
case RPC_CLNT_MSG:
|
|
|
21ab4e |
@@ -952,18 +988,22 @@ nlm_rpcclnt_notify (struct rpc_clnt *rpc_clnt, void *mydata,
|
|
|
21ab4e |
case RPC_CLNT_DISCONNECT:
|
|
|
21ab4e |
nlm_unset_rpc_clnt (rpc_clnt);
|
|
|
21ab4e |
break;
|
|
|
21ab4e |
+
|
|
|
21ab4e |
+ case RPC_CLNT_DESTROY:
|
|
|
21ab4e |
+ GF_REF_PUT (ncf);
|
|
|
21ab4e |
+ break;
|
|
|
21ab4e |
+
|
|
|
21ab4e |
default:
|
|
|
21ab4e |
break;
|
|
|
21ab4e |
}
|
|
|
21ab4e |
-
|
|
|
21ab4e |
+out:
|
|
|
21ab4e |
return 0;
|
|
|
21ab4e |
}
|
|
|
21ab4e |
|
|
|
21ab4e |
void *
|
|
|
21ab4e |
-nlm4_establish_callback (void *csarg)
|
|
|
21ab4e |
+nlm4_establish_callback (nfs3_call_state_t *cs, call_frame_t *cbk_frame)
|
|
|
21ab4e |
{
|
|
|
21ab4e |
int ret = -1;
|
|
|
21ab4e |
- nfs3_call_state_t *cs = NULL;
|
|
|
21ab4e |
union gf_sock_union sock_union;
|
|
|
21ab4e |
dict_t *options = NULL;
|
|
|
21ab4e |
char peerip[INET6_ADDRSTRLEN+1] = {0};
|
|
|
21ab4e |
@@ -971,9 +1011,8 @@ nlm4_establish_callback (void *csarg)
|
|
|
21ab4e |
char myip[INET6_ADDRSTRLEN+1] = {0};
|
|
|
21ab4e |
rpc_clnt_t *rpc_clnt = NULL;
|
|
|
21ab4e |
int port = -1;
|
|
|
21ab4e |
+ struct nlm4_notify_args *ncf = NULL;
|
|
|
21ab4e |
|
|
|
21ab4e |
-
|
|
|
21ab4e |
- cs = (nfs3_call_state_t *) csarg;
|
|
|
21ab4e |
glusterfs_this_set (cs->nfsx);
|
|
|
21ab4e |
|
|
|
21ab4e |
rpc_transport_get_peeraddr (cs->trans, NULL, 0, &sock_union.storage,
|
|
|
21ab4e |
@@ -1056,6 +1095,15 @@ nlm4_establish_callback (void *csarg)
|
|
|
21ab4e |
goto err;
|
|
|
21ab4e |
}
|
|
|
21ab4e |
|
|
|
21ab4e |
+ ncf = nlm4_notify_init (cs);
|
|
|
21ab4e |
+ if (!ncf) {
|
|
|
21ab4e |
+ ret = -1;
|
|
|
21ab4e |
+ goto err;
|
|
|
21ab4e |
+ }
|
|
|
21ab4e |
+
|
|
|
21ab4e |
+ ncf->frame = cbk_frame;
|
|
|
21ab4e |
+ ncf->frame->local = ncf;
|
|
|
21ab4e |
+
|
|
|
21ab4e |
/* TODO: is 32 frames in transit enough ? */
|
|
|
21ab4e |
rpc_clnt = rpc_clnt_new (options, cs->nfsx, "NLM-client", 32);
|
|
|
21ab4e |
if (rpc_clnt == NULL) {
|
|
|
21ab4e |
@@ -1064,7 +1112,7 @@ nlm4_establish_callback (void *csarg)
|
|
|
21ab4e |
goto err;
|
|
|
21ab4e |
}
|
|
|
21ab4e |
|
|
|
21ab4e |
- ret = rpc_clnt_register_notify (rpc_clnt, nlm_rpcclnt_notify, cs);
|
|
|
21ab4e |
+ ret = rpc_clnt_register_notify (rpc_clnt, nlm_rpcclnt_notify, ncf);
|
|
|
21ab4e |
if (ret == -1) {
|
|
|
21ab4e |
gf_msg (GF_NLM, GF_LOG_ERROR, errno, NFS_MSG_RPC_CLNT_ERROR,
|
|
|
21ab4e |
"rpc_clnt_register_connect error");
|
|
|
21ab4e |
@@ -1078,17 +1126,21 @@ nlm4_establish_callback (void *csarg)
|
|
|
21ab4e |
ret = 0;
|
|
|
21ab4e |
|
|
|
21ab4e |
err:
|
|
|
21ab4e |
- if (ret == -1 && rpc_clnt) {
|
|
|
21ab4e |
- rpc_clnt_unref (rpc_clnt);
|
|
|
21ab4e |
+ if (ret == -1) {
|
|
|
21ab4e |
+ if (rpc_clnt)
|
|
|
21ab4e |
+ rpc_clnt_unref (rpc_clnt);
|
|
|
21ab4e |
+ if (ncf)
|
|
|
21ab4e |
+ GF_REF_PUT (ncf);
|
|
|
21ab4e |
}
|
|
|
21ab4e |
|
|
|
21ab4e |
return rpc_clnt;
|
|
|
21ab4e |
}
|
|
|
21ab4e |
|
|
|
21ab4e |
-void
|
|
|
21ab4e |
-nlm4svc_send_granted (nfs3_call_state_t *cs)
|
|
|
21ab4e |
+static void
|
|
|
21ab4e |
+nlm4svc_send_granted (struct nlm4_notify_args *ncf)
|
|
|
21ab4e |
{
|
|
|
21ab4e |
int ret = -1;
|
|
|
21ab4e |
+ nfs3_call_state_t *cs = ncf->cs;
|
|
|
21ab4e |
rpc_clnt_t *rpc_clnt = NULL;
|
|
|
21ab4e |
struct iovec outmsg = {0, };
|
|
|
21ab4e |
nlm4_testargs testargs;
|
|
|
21ab4e |
@@ -1099,7 +1151,7 @@ nlm4svc_send_granted (nfs3_call_state_t *cs)
|
|
|
21ab4e |
|
|
|
21ab4e |
rpc_clnt = nlm_get_rpc_clnt (cs->args.nlm4_lockargs.alock.caller_name);
|
|
|
21ab4e |
if (rpc_clnt == NULL) {
|
|
|
21ab4e |
- nlm4_establish_callback ((void*)cs);
|
|
|
21ab4e |
+ nlm4_establish_callback (cs, ncf->frame);
|
|
|
21ab4e |
return;
|
|
|
21ab4e |
}
|
|
|
21ab4e |
|
|
|
21ab4e |
@@ -1150,9 +1202,10 @@ nlm4svc_send_granted (nfs3_call_state_t *cs)
|
|
|
21ab4e |
goto ret;
|
|
|
21ab4e |
}
|
|
|
21ab4e |
|
|
|
21ab4e |
+ GF_REF_GET (ncf);
|
|
|
21ab4e |
ret = rpc_clnt_submit (rpc_clnt, &nlm4clntprog, NLM4_GRANTED,
|
|
|
21ab4e |
nlm4svc_send_granted_cbk, &outmsg, 1,
|
|
|
21ab4e |
- NULL, 0, iobref, cs->frame, NULL, 0,
|
|
|
21ab4e |
+ NULL, 0, iobref, ncf->frame, NULL, 0,
|
|
|
21ab4e |
NULL, 0, NULL);
|
|
|
21ab4e |
|
|
|
21ab4e |
if (ret < 0) {
|
|
|
21ab4e |
@@ -1167,7 +1220,6 @@ ret:
|
|
|
21ab4e |
iobuf_unref (iobuf);
|
|
|
21ab4e |
|
|
|
21ab4e |
rpc_clnt_unref (rpc_clnt);
|
|
|
21ab4e |
- nfs3_call_state_wipe (cs);
|
|
|
21ab4e |
return;
|
|
|
21ab4e |
}
|
|
|
21ab4e |
|
|
|
21ab4e |
@@ -1338,6 +1390,7 @@ nlm4svc_lock_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
|
|
21ab4e |
char *caller_name = NULL;
|
|
|
21ab4e |
nfs3_call_state_t *cs = NULL;
|
|
|
21ab4e |
pthread_t thr;
|
|
|
21ab4e |
+ struct nlm4_notify_args *ncf = NULL;
|
|
|
21ab4e |
|
|
|
21ab4e |
cs = frame->local;
|
|
|
21ab4e |
caller_name = cs->args.nlm4_lockargs.alock.caller_name;
|
|
|
21ab4e |
@@ -1359,14 +1412,18 @@ nlm4svc_lock_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
|
|
21ab4e |
|
|
|
21ab4e |
err:
|
|
|
21ab4e |
if (cs->args.nlm4_lockargs.block) {
|
|
|
21ab4e |
- cs->frame = copy_frame (frame);
|
|
|
21ab4e |
- frame->local = NULL;
|
|
|
21ab4e |
- nlm4svc_send_granted (cs);
|
|
|
21ab4e |
+ ncf = nlm4_notify_init (cs);
|
|
|
21ab4e |
+ if (ncf) {
|
|
|
21ab4e |
+ ncf->frame = copy_frame (frame);
|
|
|
21ab4e |
+ ncf->frame->local = ncf;
|
|
|
21ab4e |
+ nlm4svc_send_granted (ncf);
|
|
|
21ab4e |
+ }
|
|
|
21ab4e |
} else {
|
|
|
21ab4e |
nlm4_generic_reply (cs->req, cs->args.nlm4_lockargs.cookie,
|
|
|
21ab4e |
stat);
|
|
|
21ab4e |
nfs3_call_state_wipe (cs);
|
|
|
21ab4e |
}
|
|
|
21ab4e |
+
|
|
|
21ab4e |
return 0;
|
|
|
21ab4e |
}
|
|
|
21ab4e |
|
|
|
21ab4e |
@@ -2378,13 +2435,15 @@ nlm4svc_sm_notify (struct nlm_sm_status *status)
|
|
|
21ab4e |
/* RPC_CLNT_CONNECT gets called on (re)connects and should be able to handle
|
|
|
21ab4e |
* different NLM requests. */
|
|
|
21ab4e |
static int
|
|
|
21ab4e |
-nlm_handle_connect (struct rpc_clnt *rpc_clnt, nfs3_call_state_t *cs)
|
|
|
21ab4e |
+nlm_handle_connect (struct rpc_clnt *rpc_clnt, struct nlm4_notify_args *ncf)
|
|
|
21ab4e |
{
|
|
|
21ab4e |
int ret = -1;
|
|
|
21ab4e |
int nlm_proc = NLM4_NULL;
|
|
|
21ab4e |
+ nfs3_call_state_t *cs = NULL;
|
|
|
21ab4e |
struct nlm4_lock *alock = NULL;
|
|
|
21ab4e |
char *caller_name = NULL;
|
|
|
21ab4e |
|
|
|
21ab4e |
+ cs = GF_REF_GET (ncf->cs);
|
|
|
21ab4e |
if (!cs || !cs->req) {
|
|
|
21ab4e |
gf_msg (GF_NLM, GF_LOG_ERROR, EINVAL, NFS_MSG_RPC_CLNT_ERROR,
|
|
|
21ab4e |
"Spurious notify?!");
|
|
|
21ab4e |
@@ -2426,7 +2485,7 @@ nlm_handle_connect (struct rpc_clnt *rpc_clnt, nfs3_call_state_t *cs)
|
|
|
21ab4e |
/* extra ref taken with nlm_set_rpc_clnt() */
|
|
|
21ab4e |
rpc_clnt_unref (rpc_clnt);
|
|
|
21ab4e |
|
|
|
21ab4e |
- nlm4svc_send_granted (cs);
|
|
|
21ab4e |
+ nlm4svc_send_granted (ncf);
|
|
|
21ab4e |
break;
|
|
|
21ab4e |
|
|
|
21ab4e |
case NLM4_CANCEL:
|
|
|
21ab4e |
--
|
|
|
21ab4e |
1.8.3.1
|
|
|
21ab4e |
|