|
|
21ab4e |
From c1ff78dc03af63b226289ea0d1618223addfbd58 Mon Sep 17 00:00:00 2001
|
|
|
21ab4e |
From: Niels de Vos <ndevos@redhat.com>
|
|
|
21ab4e |
Date: Fri, 23 Jun 2017 10:01:27 +0200
|
|
|
21ab4e |
Subject: [PATCH 546/557] nfs: make nfs3_call_state_t refcounted
|
|
|
21ab4e |
|
|
|
21ab4e |
There is no refcounting done of the nfs3_call_state_t structure, which
|
|
|
21ab4e |
seems to result in use-after-free problems in the NLM part of
|
|
|
21ab4e |
Gluster/NFS. The structure is initialized with two different functions,
|
|
|
21ab4e |
it is easier to have a single place to do this.
|
|
|
21ab4e |
|
|
|
21ab4e |
The Gluster/NFS part will not use the refcounting, for now. This is
|
|
|
21ab4e |
being added to make the NLM code more stable. nfs3_call_state_wipe()
|
|
|
21ab4e |
will behave as before for Gluster/NFS, but cleanup is triggered through
|
|
|
21ab4e |
the refcounting now. This prevents major changes to the stable part of
|
|
|
21ab4e |
the NFS-server, and makes it possible to improve the NLM component
|
|
|
21ab4e |
separately.
|
|
|
21ab4e |
|
|
|
21ab4e |
Cherry picked from commit daed52b8ebcac7ef36f11e944f83826f46593867:
|
|
|
21ab4e |
> Change-Id: I2e15bcf12af74e8a46c2727e4a160e9444d29ece
|
|
|
21ab4e |
> BUG: 1467313
|
|
|
21ab4e |
> Signed-off-by: Niels de Vos <ndevos@redhat.com>
|
|
|
21ab4e |
> Reviewed-on: https://review.gluster.org/17696
|
|
|
21ab4e |
> Smoke: Gluster Build System <jenkins@build.gluster.org>
|
|
|
21ab4e |
> Reviewed-by: Amar Tumballi <amarts@redhat.com>
|
|
|
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: I2e15bcf12af74e8a46c2727e4a160e9444d29ece
|
|
|
21ab4e |
BUG: 1411344
|
|
|
21ab4e |
Signed-off-by: Niels de Vos <ndevos@redhat.com>
|
|
|
21ab4e |
Reviewed-on: https://code.engineering.redhat.com/gerrit/111765
|
|
|
21ab4e |
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
|
|
|
21ab4e |
---
|
|
|
21ab4e |
xlators/nfs/server/src/nfs3.c | 63 ++++++++++++++++++++++++-------------------
|
|
|
21ab4e |
xlators/nfs/server/src/nfs3.h | 3 +++
|
|
|
21ab4e |
xlators/nfs/server/src/nlm4.c | 15 +++--------
|
|
|
21ab4e |
3 files changed, 42 insertions(+), 39 deletions(-)
|
|
|
21ab4e |
|
|
|
21ab4e |
diff --git a/xlators/nfs/server/src/nfs3.c b/xlators/nfs/server/src/nfs3.c
|
|
|
21ab4e |
index 8b1d62b..bb68bc1 100644
|
|
|
21ab4e |
--- a/xlators/nfs/server/src/nfs3.c
|
|
|
21ab4e |
+++ b/xlators/nfs/server/src/nfs3.c
|
|
|
21ab4e |
@@ -483,6 +483,38 @@ nfs3_solaris_zerolen_fh (struct nfs3_fh *fh, int fhlen)
|
|
|
21ab4e |
*/
|
|
|
21ab4e |
typedef ssize_t (*nfs3_serializer) (struct iovec outmsg, void *args);
|
|
|
21ab4e |
|
|
|
21ab4e |
+static void
|
|
|
21ab4e |
+__nfs3_call_state_wipe (nfs3_call_state_t *cs)
|
|
|
21ab4e |
+{
|
|
|
21ab4e |
+ if (!cs)
|
|
|
21ab4e |
+ return;
|
|
|
21ab4e |
+
|
|
|
21ab4e |
+ if (cs->fd) {
|
|
|
21ab4e |
+ gf_msg_trace (GF_NFS3, 0, "fd 0x%lx ref: %d",
|
|
|
21ab4e |
+ (long)cs->fd, cs->fd->refcount);
|
|
|
21ab4e |
+ fd_unref (cs->fd);
|
|
|
21ab4e |
+ }
|
|
|
21ab4e |
+
|
|
|
21ab4e |
+ GF_FREE (cs->resolventry);
|
|
|
21ab4e |
+
|
|
|
21ab4e |
+ GF_FREE (cs->pathname);
|
|
|
21ab4e |
+
|
|
|
21ab4e |
+ if (!list_empty (&cs->entries.list))
|
|
|
21ab4e |
+ gf_dirent_free (&cs->entries);
|
|
|
21ab4e |
+
|
|
|
21ab4e |
+ nfs_loc_wipe (&cs->oploc);
|
|
|
21ab4e |
+ nfs_loc_wipe (&cs->resolvedloc);
|
|
|
21ab4e |
+ if (cs->iob)
|
|
|
21ab4e |
+ iobuf_unref (cs->iob);
|
|
|
21ab4e |
+ if (cs->iobref)
|
|
|
21ab4e |
+ iobref_unref (cs->iobref);
|
|
|
21ab4e |
+ if (cs->trans)
|
|
|
21ab4e |
+ rpc_transport_unref (cs->trans);
|
|
|
21ab4e |
+ memset (cs, 0, sizeof (*cs));
|
|
|
21ab4e |
+ mem_put (cs);
|
|
|
21ab4e |
+ /* Already refd by fd_lookup, so no need to ref again. */
|
|
|
21ab4e |
+}
|
|
|
21ab4e |
+
|
|
|
21ab4e |
nfs3_call_state_t *
|
|
|
21ab4e |
nfs3_call_state_init (struct nfs3_state *s, rpcsvc_request_t *req, xlator_t *v)
|
|
|
21ab4e |
{
|
|
|
21ab4e |
@@ -490,7 +522,7 @@ nfs3_call_state_init (struct nfs3_state *s, rpcsvc_request_t *req, xlator_t *v)
|
|
|
21ab4e |
|
|
|
21ab4e |
GF_VALIDATE_OR_GOTO (GF_NFS3, s, err);
|
|
|
21ab4e |
GF_VALIDATE_OR_GOTO (GF_NFS3, req, err);
|
|
|
21ab4e |
- GF_VALIDATE_OR_GOTO (GF_NFS3, v, err);
|
|
|
21ab4e |
+ /* GF_VALIDATE_OR_GOTO (GF_NFS3, v, err); NLM sets this later */
|
|
|
21ab4e |
|
|
|
21ab4e |
cs = (nfs3_call_state_t *) mem_get (s->localpool);
|
|
|
21ab4e |
if (!cs) {
|
|
|
21ab4e |
@@ -500,6 +532,7 @@ nfs3_call_state_init (struct nfs3_state *s, rpcsvc_request_t *req, xlator_t *v)
|
|
|
21ab4e |
}
|
|
|
21ab4e |
|
|
|
21ab4e |
memset (cs, 0, sizeof (*cs));
|
|
|
21ab4e |
+ GF_REF_INIT (cs, __nfs3_call_state_wipe);
|
|
|
21ab4e |
INIT_LIST_HEAD (&cs->entries.list);
|
|
|
21ab4e |
INIT_LIST_HEAD (&cs->openwait_q);
|
|
|
21ab4e |
cs->operrno = EINVAL;
|
|
|
21ab4e |
@@ -514,33 +547,7 @@ err:
|
|
|
21ab4e |
void
|
|
|
21ab4e |
nfs3_call_state_wipe (nfs3_call_state_t *cs)
|
|
|
21ab4e |
{
|
|
|
21ab4e |
- if (!cs)
|
|
|
21ab4e |
- return;
|
|
|
21ab4e |
-
|
|
|
21ab4e |
- if (cs->fd) {
|
|
|
21ab4e |
- gf_msg_trace (GF_NFS3, 0, "fd 0x%lx ref: %d",
|
|
|
21ab4e |
- (long)cs->fd, cs->fd->refcount);
|
|
|
21ab4e |
- fd_unref (cs->fd);
|
|
|
21ab4e |
- }
|
|
|
21ab4e |
-
|
|
|
21ab4e |
- GF_FREE (cs->resolventry);
|
|
|
21ab4e |
-
|
|
|
21ab4e |
- GF_FREE (cs->pathname);
|
|
|
21ab4e |
-
|
|
|
21ab4e |
- if (!list_empty (&cs->entries.list))
|
|
|
21ab4e |
- gf_dirent_free (&cs->entries);
|
|
|
21ab4e |
-
|
|
|
21ab4e |
- nfs_loc_wipe (&cs->oploc);
|
|
|
21ab4e |
- nfs_loc_wipe (&cs->resolvedloc);
|
|
|
21ab4e |
- if (cs->iob)
|
|
|
21ab4e |
- iobuf_unref (cs->iob);
|
|
|
21ab4e |
- if (cs->iobref)
|
|
|
21ab4e |
- iobref_unref (cs->iobref);
|
|
|
21ab4e |
- if (cs->trans)
|
|
|
21ab4e |
- rpc_transport_unref (cs->trans);
|
|
|
21ab4e |
- memset (cs, 0, sizeof (*cs));
|
|
|
21ab4e |
- mem_put (cs);
|
|
|
21ab4e |
- /* Already refd by fd_lookup, so no need to ref again. */
|
|
|
21ab4e |
+ GF_REF_PUT (cs);
|
|
|
21ab4e |
}
|
|
|
21ab4e |
|
|
|
21ab4e |
|
|
|
21ab4e |
diff --git a/xlators/nfs/server/src/nfs3.h b/xlators/nfs/server/src/nfs3.h
|
|
|
21ab4e |
index 4cb3e67..187fb7e 100644
|
|
|
21ab4e |
--- a/xlators/nfs/server/src/nfs3.h
|
|
|
21ab4e |
+++ b/xlators/nfs/server/src/nfs3.h
|
|
|
21ab4e |
@@ -23,6 +23,7 @@
|
|
|
21ab4e |
#include "nlm4.h"
|
|
|
21ab4e |
#include "acl3-xdr.h"
|
|
|
21ab4e |
#include "acl3.h"
|
|
|
21ab4e |
+#include "refcount.h"
|
|
|
21ab4e |
#include <sys/statvfs.h>
|
|
|
21ab4e |
|
|
|
21ab4e |
#define GF_NFS3 GF_NFS"-nfsv3"
|
|
|
21ab4e |
@@ -184,6 +185,8 @@ typedef int (*nfs3_resume_fn_t) (void *cs);
|
|
|
21ab4e |
* Imagine the chaos if we need a mem-pool for each one of those sub-structures.
|
|
|
21ab4e |
*/
|
|
|
21ab4e |
struct nfs3_local {
|
|
|
21ab4e |
+ GF_REF_DECL;
|
|
|
21ab4e |
+
|
|
|
21ab4e |
rpcsvc_request_t *req;
|
|
|
21ab4e |
xlator_t *vol;
|
|
|
21ab4e |
nfs3_resume_fn_t resume_fn;
|
|
|
21ab4e |
diff --git a/xlators/nfs/server/src/nlm4.c b/xlators/nfs/server/src/nlm4.c
|
|
|
21ab4e |
index 8580448..dc7d23d 100644
|
|
|
21ab4e |
--- a/xlators/nfs/server/src/nlm4.c
|
|
|
21ab4e |
+++ b/xlators/nfs/server/src/nlm4.c
|
|
|
21ab4e |
@@ -52,6 +52,9 @@ typedef ssize_t (*nlm4_serializer) (struct iovec outmsg, void *args);
|
|
|
21ab4e |
|
|
|
21ab4e |
extern void nfs3_call_state_wipe (nfs3_call_state_t *cs);
|
|
|
21ab4e |
|
|
|
21ab4e |
+nfs3_call_state_t *
|
|
|
21ab4e |
+nfs3_call_state_init (struct nfs3_state *s, rpcsvc_request_t *req, xlator_t *v);
|
|
|
21ab4e |
+
|
|
|
21ab4e |
struct list_head nlm_client_list;
|
|
|
21ab4e |
gf_lock_t nlm_client_list_lk;
|
|
|
21ab4e |
|
|
|
21ab4e |
@@ -71,9 +74,6 @@ int nlm_grace_period = 50;
|
|
|
21ab4e |
} \
|
|
|
21ab4e |
} while (0); \
|
|
|
21ab4e |
|
|
|
21ab4e |
-nfs3_call_state_t *
|
|
|
21ab4e |
-nfs3_call_state_init (struct nfs3_state *s, rpcsvc_request_t *req, xlator_t *v);
|
|
|
21ab4e |
-
|
|
|
21ab4e |
#define nlm4_handle_call_state_init(nfs3state, calls, rq, opstat, errlabel)\
|
|
|
21ab4e |
do { \
|
|
|
21ab4e |
calls = nlm4_call_state_init ((nfs3state), (rq)); \
|
|
|
21ab4e |
@@ -271,17 +271,10 @@ nlm4_call_state_init (struct nfs3_state *s, rpcsvc_request_t *req)
|
|
|
21ab4e |
if ((!s) || (!req))
|
|
|
21ab4e |
return NULL;
|
|
|
21ab4e |
|
|
|
21ab4e |
- cs = (nfs3_call_state_t *) mem_get (s->localpool);
|
|
|
21ab4e |
+ cs = nfs3_call_state_init (s, req, NULL);
|
|
|
21ab4e |
if (!cs)
|
|
|
21ab4e |
return NULL;
|
|
|
21ab4e |
|
|
|
21ab4e |
- memset (cs, 0, sizeof (*cs));
|
|
|
21ab4e |
- INIT_LIST_HEAD (&cs->entries.list);
|
|
|
21ab4e |
- INIT_LIST_HEAD (&cs->openwait_q);
|
|
|
21ab4e |
- cs->operrno = EINVAL;
|
|
|
21ab4e |
- cs->req = req;
|
|
|
21ab4e |
- cs->nfsx = s->nfsx;
|
|
|
21ab4e |
- cs->nfs3state = s;
|
|
|
21ab4e |
cs->monitor = 1;
|
|
|
21ab4e |
|
|
|
21ab4e |
return cs;
|
|
|
21ab4e |
--
|
|
|
21ab4e |
1.8.3.1
|
|
|
21ab4e |
|