2021-05-03 15:23:37

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 00/29] server-side lockd XDR overhaul

Same approach as what has been done for NFSv2, NFSv3, and NFSv4: XDR
decoding and encoding functions have been updated to use xdr_stream.
This adopts common XDR infrastructure for these functions and makes
constructing and parsing more secure and robust.

---

Chuck Lever (29):
lockd: Remove stale comments
lockd: Create a simplified .vs_dispatch method for NLM requests
lockd: Common NLM XDR helpers
lockd: Update the NLMv1 void argument decoder to use struct xdr_stream
lockd: Update the NLMv1 TEST arguments decoder to use struct xdr_stream
lockd: Update the NLMv1 LOCK arguments decoder to use struct xdr_stream
lockd: Update the NLMv1 CANCEL arguments decoder to use struct xdr_stream
lockd: Update the NLMv1 UNLOCK arguments decoder to use struct xdr_stream
lockd: Update the NLMv1 nlm_res arguments decoder to use struct xdr_stream
lockd: Update the NLMv1 SM_NOTIFY arguments decoder to use struct xdr_stream
lockd: Update the NLMv1 SHARE arguments decoder to use struct xdr_stream
lockd: Update the NLMv1 FREE_ALL arguments decoder to use struct xdr_stream
lockd: Update the NLMv1 void results encoder to use struct xdr_stream
lockd: Update the NLMv1 TEST results encoder to use struct xdr_stream
lockd: Update the NLMv1 nlm_res results encoder to use struct xdr_stream
lockd: Update the NLMv1 SHARE results encoder to use struct xdr_stream
lockd: Update the NLMv4 void arguments decoder to use struct xdr_stream
lockd: Update the NLMv4 TEST arguments decoder to use struct xdr_stream
lockd: Update the NLMv4 LOCK arguments decoder to use struct xdr_stream
lockd: Update the NLMv4 CANCEL arguments decoder to use struct xdr_stream
lockd: Update the NLMv4 UNLOCK arguments decoder to use struct xdr_stream
lockd: Update the NLMv4 nlm_res arguments decoder to use struct xdr_stream
lockd: Update the NLMv4 SM_NOTIFY arguments decoder to use struct xdr_stream
lockd: Update the NLMv4 SHARE arguments decoder to use struct xdr_stream
lockd: Update the NLMv4 FREE_ALL arguments decoder to use struct xdr_stream
lockd: Update the NLMv4 void results encoder to use struct xdr_stream
lockd: Update the NLMv4 TEST results encoder to use struct xdr_stream
lockd: Update the NLMv4 nlm_res results encoder to use struct xdr_stream
lockd: Update the NLMv4 SHARE results encoder to use struct xdr_stream


fs/lockd/svc.c | 43 ++++
fs/lockd/svcxdr.h | 151 ++++++++++++++
fs/lockd/xdr.c | 402 ++++++++++++++++++------------------
fs/lockd/xdr4.c | 403 +++++++++++++++++++------------------
include/linux/lockd/xdr.h | 6 -
include/linux/lockd/xdr4.h | 7 +-
6 files changed, 610 insertions(+), 402 deletions(-)
create mode 100644 fs/lockd/svcxdr.h

--
Chuck Lever


2021-05-03 15:23:42

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 03/29] lockd: Common NLM XDR helpers

Add a .h file containing xdr_stream-based XDR helpers common to both
NLMv3 and NLMv4.

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/svcxdr.h | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 151 insertions(+)
create mode 100644 fs/lockd/svcxdr.h

diff --git a/fs/lockd/svcxdr.h b/fs/lockd/svcxdr.h
new file mode 100644
index 000000000000..c69a0bb76c94
--- /dev/null
+++ b/fs/lockd/svcxdr.h
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Encode/decode NLM basic data types
+ *
+ * Basic NLMv3 XDR data types are not defined in an IETF standards
+ * document. X/Open has a description of these data types that
+ * is useful. See Chapter 10 of "Protocols for Interworking:
+ * XNFS, Version 3W".
+ *
+ * Basic NLMv4 XDR data types are defined in Appendix II.1.4 of
+ * RFC 1813: "NFS Version 3 Protocol Specification".
+ *
+ * Author: Chuck Lever <[email protected]>
+ *
+ * Copyright (c) 2020, Oracle and/or its affiliates.
+ */
+
+#ifndef _LOCKD_SVCXDR_H_
+#define _LOCKD_SVCXDR_H_
+
+static inline bool
+svcxdr_decode_stats(struct xdr_stream *xdr, __be32 *status)
+{
+ __be32 *p;
+
+ p = xdr_inline_decode(xdr, XDR_UNIT);
+ if (!p)
+ return false;
+ *status = *p;
+
+ return true;
+}
+
+static inline bool
+svcxdr_encode_stats(struct xdr_stream *xdr, __be32 status)
+{
+ __be32 *p;
+
+ p = xdr_reserve_space(xdr, XDR_UNIT);
+ if (!p)
+ return false;
+ *p = status;
+
+ return true;
+}
+
+static inline bool
+svcxdr_decode_string(struct xdr_stream *xdr, char **data, unsigned int *data_len)
+{
+ __be32 *p;
+ u32 len;
+
+ if (xdr_stream_decode_u32(xdr, &len) < 0)
+ return false;
+ if (len > NLM_MAXSTRLEN)
+ return false;
+ p = xdr_inline_decode(xdr, len);
+ if (!p)
+ return false;
+ *data_len = len;
+ *data = (char *)p;
+
+ return true;
+}
+
+/*
+ * NLM cookies are defined by specification to be a variable-length
+ * XDR opaque no longer than 1024 bytes. However, this implementation
+ * limits their length to 32 bytes, and treats zero-length cookies
+ * specially.
+ */
+static inline bool
+svcxdr_decode_cookie(struct xdr_stream *xdr, struct nlm_cookie *cookie)
+{
+ __be32 *p;
+ u32 len;
+
+ if (xdr_stream_decode_u32(xdr, &len) < 0)
+ return false;
+ if (len > NLM_MAXCOOKIELEN)
+ return false;
+ if (!len)
+ goto out_hpux;
+
+ p = xdr_inline_decode(xdr, len);
+ if (!p)
+ return false;
+ cookie->len = len;
+ memcpy(cookie->data, p, len);
+
+ return true;
+
+ /* apparently HPUX can return empty cookies */
+out_hpux:
+ cookie->len = 4;
+ memset(cookie->data, 0, 4);
+ return true;
+}
+
+static inline bool
+svcxdr_encode_cookie(struct xdr_stream *xdr, const struct nlm_cookie *cookie)
+{
+ __be32 *p;
+
+ if (xdr_stream_encode_u32(xdr, cookie->len) < 0)
+ return false;
+ p = xdr_reserve_space(xdr, cookie->len);
+ if (!p)
+ return false;
+ memcpy(p, cookie->data, cookie->len);
+
+ return true;
+}
+
+static inline bool
+svcxdr_decode_owner(struct xdr_stream *xdr, struct xdr_netobj *obj)
+{
+ __be32 *p;
+ u32 len;
+
+ if (xdr_stream_decode_u32(xdr, &len) < 0)
+ return false;
+ if (len > XDR_MAX_NETOBJ)
+ return false;
+ p = xdr_inline_decode(xdr, len);
+ if (!p)
+ return false;
+ obj->len = len;
+ obj->data = (u8 *)p;
+
+ return true;
+}
+
+static inline bool
+svcxdr_encode_owner(struct xdr_stream *xdr, const struct xdr_netobj *obj)
+{
+ unsigned int quadlen = XDR_QUADLEN(obj->len);
+ __be32 *p;
+
+ if (xdr_stream_encode_u32(xdr, obj->len) < 0)
+ return false;
+ p = xdr_reserve_space(xdr, obj->len);
+ if (!p)
+ return false;
+ p[quadlen - 1] = 0; /* XDR pad */
+ memcpy(p, obj->data, obj->len);
+
+ return true;
+}
+
+#endif /* _LOCKD_SVCXDR_H_ */


2021-05-03 15:23:47

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 04/29] lockd: Update the NLMv1 void argument decoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index 982629f7b120..8be42a23679e 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -19,6 +19,8 @@

#include <uapi/linux/nfs2.h>

+#include "svcxdr.h"
+
#define NLMDBG_FACILITY NLMDBG_XDR


@@ -178,8 +180,15 @@ nlm_encode_testres(__be32 *p, struct nlm_res *resp)


/*
- * First, the server side XDR functions
+ * Decode Call arguments
*/
+
+int
+nlmsvc_decode_void(struct svc_rqst *rqstp, __be32 *p)
+{
+ return 1;
+}
+
int
nlmsvc_decode_testargs(struct svc_rqst *rqstp, __be32 *p)
{
@@ -339,12 +348,6 @@ nlmsvc_decode_res(struct svc_rqst *rqstp, __be32 *p)
return xdr_argsize_check(rqstp, p);
}

-int
-nlmsvc_decode_void(struct svc_rqst *rqstp, __be32 *p)
-{
- return xdr_argsize_check(rqstp, p);
-}
-
int
nlmsvc_encode_void(struct svc_rqst *rqstp, __be32 *p)
{


2021-05-03 15:23:52

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 05/29] lockd: Update the NLMv1 TEST arguments decoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 66 insertions(+), 6 deletions(-)

diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index 8be42a23679e..56982edd4766 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -98,6 +98,33 @@ nlm_decode_fh(__be32 *p, struct nfs_fh *f)
return p + XDR_QUADLEN(NFS2_FHSIZE);
}

+/*
+ * NLM file handles are defined by specification to be a variable-length
+ * XDR opaque no longer than 1024 bytes. However, this implementation
+ * constrains their length to exactly the length of an NFSv2 file
+ * handle.
+ */
+static bool
+svcxdr_decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)
+{
+ __be32 *p;
+ u32 len;
+
+ if (xdr_stream_decode_u32(xdr, &len) < 0)
+ return false;
+ if (len != NFS2_FHSIZE)
+ return false;
+
+ p = xdr_inline_decode(xdr, len);
+ if (!p)
+ return false;
+ fh->size = NFS2_FHSIZE;
+ memcpy(fh->data, p, len);
+ memset(fh->data + NFS2_FHSIZE, 0, sizeof(fh->data) - NFS2_FHSIZE);
+
+ return true;
+}
+
/*
* Encode and decode owner handle
*/
@@ -143,6 +170,38 @@ nlm_decode_lock(__be32 *p, struct nlm_lock *lock)
return p;
}

+static bool
+svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)
+{
+ struct file_lock *fl = &lock->fl;
+ s32 start, len, end;
+
+ if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
+ return false;
+ if (!svcxdr_decode_fhandle(xdr, &lock->fh))
+ return false;
+ if (!svcxdr_decode_owner(xdr, &lock->oh))
+ return false;
+ if (xdr_stream_decode_u32(xdr, &lock->svid) < 0)
+ return false;
+ if (xdr_stream_decode_u32(xdr, &start) < 0)
+ return false;
+ if (xdr_stream_decode_u32(xdr, &len) < 0)
+ return false;
+
+ locks_init_lock(fl);
+ fl->fl_flags = FL_POSIX;
+ fl->fl_type = F_RDLCK;
+ end = start + len - 1;
+ fl->fl_start = s32_to_loff_t(start);
+ if (len == 0 || end < 0)
+ fl->fl_end = OFFSET_MAX;
+ else
+ fl->fl_end = s32_to_loff_t(end);
+
+ return true;
+}
+
/*
* Encode result of a TEST/TEST_MSG call
*/
@@ -192,19 +251,20 @@ nlmsvc_decode_void(struct svc_rqst *rqstp, __be32 *p)
int
nlmsvc_decode_testargs(struct svc_rqst *rqstp, __be32 *p)
{
+ struct xdr_stream *xdr = &rqstp->rq_arg_stream;
struct nlm_args *argp = rqstp->rq_argp;
- u32 exclusive;
+ u32 exclusive;

- if (!(p = nlm_decode_cookie(p, &argp->cookie)))
+ if (!svcxdr_decode_cookie(xdr, &argp->cookie))
return 0;
-
- exclusive = ntohl(*p++);
- if (!(p = nlm_decode_lock(p, &argp->lock)))
+ if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
+ return 0;
+ if (!svcxdr_decode_lock(xdr, &argp->lock))
return 0;
if (exclusive)
argp->lock.fl.fl_type = F_WRLCK;

- return xdr_argsize_check(rqstp, p);
+ return 1;
}

int


2021-05-03 15:23:59

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 06/29] lockd: Update the NLMv1 LOCK arguments decoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr.c | 41 +++++++++++++++++++++++------------------
1 file changed, 23 insertions(+), 18 deletions(-)

diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index 56982edd4766..8a9f02e45df2 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -267,35 +267,40 @@ nlmsvc_decode_testargs(struct svc_rqst *rqstp, __be32 *p)
return 1;
}

-int
-nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
-{
- struct nlm_res *resp = rqstp->rq_resp;
-
- if (!(p = nlm_encode_testres(p, resp)))
- return 0;
- return xdr_ressize_check(rqstp, p);
-}
-
int
nlmsvc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p)
{
+ struct xdr_stream *xdr = &rqstp->rq_arg_stream;
struct nlm_args *argp = rqstp->rq_argp;
- u32 exclusive;
+ u32 exclusive;

- if (!(p = nlm_decode_cookie(p, &argp->cookie)))
+ if (!svcxdr_decode_cookie(xdr, &argp->cookie))
return 0;
- argp->block = ntohl(*p++);
- exclusive = ntohl(*p++);
- if (!(p = nlm_decode_lock(p, &argp->lock)))
+ if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
+ return 0;
+ if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
+ return 0;
+ if (!svcxdr_decode_lock(xdr, &argp->lock))
return 0;
if (exclusive)
argp->lock.fl.fl_type = F_WRLCK;
- argp->reclaim = ntohl(*p++);
- argp->state = ntohl(*p++);
+ if (xdr_stream_decode_bool(xdr, &argp->reclaim) < 0)
+ return 0;
+ if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
+ return 0;
argp->monitor = 1; /* monitor client by default */

- return xdr_argsize_check(rqstp, p);
+ return 1;
+}
+
+int
+nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
+{
+ struct nlm_res *resp = rqstp->rq_resp;
+
+ if (!(p = nlm_encode_testres(p, resp)))
+ return 0;
+ return xdr_ressize_check(rqstp, p);
}

int


2021-05-03 15:24:02

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 01/29] lockd: Remove stale comments

Signed-off-by: Chuck Lever <[email protected]>
---
include/linux/lockd/xdr.h | 6 ------
include/linux/lockd/xdr4.h | 7 +------
2 files changed, 1 insertion(+), 12 deletions(-)

diff --git a/include/linux/lockd/xdr.h b/include/linux/lockd/xdr.h
index 7ab9f264313f..a98309c0121c 100644
--- a/include/linux/lockd/xdr.h
+++ b/include/linux/lockd/xdr.h
@@ -109,11 +109,5 @@ int nlmsvc_decode_shareargs(struct svc_rqst *, __be32 *);
int nlmsvc_encode_shareres(struct svc_rqst *, __be32 *);
int nlmsvc_decode_notify(struct svc_rqst *, __be32 *);
int nlmsvc_decode_reboot(struct svc_rqst *, __be32 *);
-/*
-int nlmclt_encode_testargs(struct rpc_rqst *, u32 *, struct nlm_args *);
-int nlmclt_encode_lockargs(struct rpc_rqst *, u32 *, struct nlm_args *);
-int nlmclt_encode_cancargs(struct rpc_rqst *, u32 *, struct nlm_args *);
-int nlmclt_encode_unlockargs(struct rpc_rqst *, u32 *, struct nlm_args *);
- */

#endif /* LOCKD_XDR_H */
diff --git a/include/linux/lockd/xdr4.h b/include/linux/lockd/xdr4.h
index e709fe5924f2..5ae766f26e04 100644
--- a/include/linux/lockd/xdr4.h
+++ b/include/linux/lockd/xdr4.h
@@ -37,12 +37,7 @@ int nlm4svc_decode_shareargs(struct svc_rqst *, __be32 *);
int nlm4svc_encode_shareres(struct svc_rqst *, __be32 *);
int nlm4svc_decode_notify(struct svc_rqst *, __be32 *);
int nlm4svc_decode_reboot(struct svc_rqst *, __be32 *);
-/*
-int nlmclt_encode_testargs(struct rpc_rqst *, u32 *, struct nlm_args *);
-int nlmclt_encode_lockargs(struct rpc_rqst *, u32 *, struct nlm_args *);
-int nlmclt_encode_cancargs(struct rpc_rqst *, u32 *, struct nlm_args *);
-int nlmclt_encode_unlockargs(struct rpc_rqst *, u32 *, struct nlm_args *);
- */
+
extern const struct rpc_version nlm_version4;

#endif /* LOCKD_XDR4_H */


2021-05-03 15:24:09

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 07/29] lockd: Update the NLMv1 CANCEL arguments decoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr.c | 34 +++++++++++++++++++---------------
1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index 8a9f02e45df2..ef38f07d1224 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -294,30 +294,34 @@ nlmsvc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p)
}

int
-nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
+nlmsvc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p)
{
- struct nlm_res *resp = rqstp->rq_resp;
+ struct xdr_stream *xdr = &rqstp->rq_arg_stream;
+ struct nlm_args *argp = rqstp->rq_argp;
+ u32 exclusive;

- if (!(p = nlm_encode_testres(p, resp)))
+ if (!svcxdr_decode_cookie(xdr, &argp->cookie))
return 0;
- return xdr_ressize_check(rqstp, p);
+ if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
+ return 0;
+ if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
+ return 0;
+ if (!svcxdr_decode_lock(xdr, &argp->lock))
+ return 0;
+ if (exclusive)
+ argp->lock.fl.fl_type = F_WRLCK;
+
+ return 1;
}

int
-nlmsvc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p)
+nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
{
- struct nlm_args *argp = rqstp->rq_argp;
- u32 exclusive;
+ struct nlm_res *resp = rqstp->rq_resp;

- if (!(p = nlm_decode_cookie(p, &argp->cookie)))
- return 0;
- argp->block = ntohl(*p++);
- exclusive = ntohl(*p++);
- if (!(p = nlm_decode_lock(p, &argp->lock)))
+ if (!(p = nlm_encode_testres(p, resp)))
return 0;
- if (exclusive)
- argp->lock.fl.fl_type = F_WRLCK;
- return xdr_argsize_check(rqstp, p);
+ return xdr_ressize_check(rqstp, p);
}

int


2021-05-03 15:24:14

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 08/29] lockd: Update the NLMv1 UNLOCK arguments decoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr.c | 53 +++++++++++++----------------------------------------
1 file changed, 13 insertions(+), 40 deletions(-)

diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index ef38f07d1224..b59e02b4417c 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -140,36 +140,6 @@ nlm_encode_oh(__be32 *p, struct xdr_netobj *oh)
return xdr_encode_netobj(p, oh);
}

-static __be32 *
-nlm_decode_lock(__be32 *p, struct nlm_lock *lock)
-{
- struct file_lock *fl = &lock->fl;
- s32 start, len, end;
-
- if (!(p = xdr_decode_string_inplace(p, &lock->caller,
- &lock->len,
- NLM_MAXSTRLEN))
- || !(p = nlm_decode_fh(p, &lock->fh))
- || !(p = nlm_decode_oh(p, &lock->oh)))
- return NULL;
- lock->svid = ntohl(*p++);
-
- locks_init_lock(fl);
- fl->fl_flags = FL_POSIX;
- fl->fl_type = F_RDLCK; /* as good as anything else */
- start = ntohl(*p++);
- len = ntohl(*p++);
- end = start + len - 1;
-
- fl->fl_start = s32_to_loff_t(start);
-
- if (len == 0 || end < 0)
- fl->fl_end = OFFSET_MAX;
- else
- fl->fl_end = s32_to_loff_t(end);
- return p;
-}
-
static bool
svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)
{
@@ -315,25 +285,28 @@ nlmsvc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p)
}

int
-nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
+nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p)
{
- struct nlm_res *resp = rqstp->rq_resp;
+ struct xdr_stream *xdr = &rqstp->rq_arg_stream;
+ struct nlm_args *argp = rqstp->rq_argp;

- if (!(p = nlm_encode_testres(p, resp)))
+ if (!svcxdr_decode_cookie(xdr, &argp->cookie))
return 0;
- return xdr_ressize_check(rqstp, p);
+ if (!svcxdr_decode_lock(xdr, &argp->lock))
+ return 0;
+ argp->lock.fl.fl_type = F_UNLCK;
+
+ return 1;
}

int
-nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p)
+nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
{
- struct nlm_args *argp = rqstp->rq_argp;
+ struct nlm_res *resp = rqstp->rq_resp;

- if (!(p = nlm_decode_cookie(p, &argp->cookie))
- || !(p = nlm_decode_lock(p, &argp->lock)))
+ if (!(p = nlm_encode_testres(p, resp)))
return 0;
- argp->lock.fl.fl_type = F_UNLCK;
- return xdr_argsize_check(rqstp, p);
+ return xdr_ressize_check(rqstp, p);
}

int


2021-05-03 15:24:18

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 09/29] lockd: Update the NLMv1 nlm_res arguments decoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr.c | 25 ++++++++++++++-----------
1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index b59e02b4417c..911b6377a6da 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -299,6 +299,20 @@ nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p)
return 1;
}

+int
+nlmsvc_decode_res(struct svc_rqst *rqstp, __be32 *p)
+{
+ struct xdr_stream *xdr = &rqstp->rq_arg_stream;
+ struct nlm_res *resp = rqstp->rq_argp;
+
+ if (!svcxdr_decode_cookie(xdr, &resp->cookie))
+ return 0;
+ if (!svcxdr_decode_stats(xdr, &resp->status))
+ return 0;
+
+ return 1;
+}
+
int
nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
{
@@ -379,17 +393,6 @@ nlmsvc_decode_reboot(struct svc_rqst *rqstp, __be32 *p)
return xdr_argsize_check(rqstp, p);
}

-int
-nlmsvc_decode_res(struct svc_rqst *rqstp, __be32 *p)
-{
- struct nlm_res *resp = rqstp->rq_argp;
-
- if (!(p = nlm_decode_cookie(p, &resp->cookie)))
- return 0;
- resp->status = *p++;
- return xdr_argsize_check(rqstp, p);
-}
-
int
nlmsvc_encode_void(struct svc_rqst *rqstp, __be32 *p)
{


2021-05-03 15:24:20

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 10/29] lockd: Update the NLMv1 SM_NOTIFY arguments decoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr.c | 39 ++++++++++++++++++++++++++-------------
1 file changed, 26 insertions(+), 13 deletions(-)

diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index 911b6377a6da..421613170e5f 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -313,6 +313,32 @@ nlmsvc_decode_res(struct svc_rqst *rqstp, __be32 *p)
return 1;
}

+int
+nlmsvc_decode_reboot(struct svc_rqst *rqstp, __be32 *p)
+{
+ struct xdr_stream *xdr = &rqstp->rq_arg_stream;
+ struct nlm_reboot *argp = rqstp->rq_argp;
+ u32 len;
+
+ if (xdr_stream_decode_u32(xdr, &len) < 0)
+ return 0;
+ if (len > SM_MAXSTRLEN)
+ return 0;
+ p = xdr_inline_decode(xdr, len);
+ if (!p)
+ return 0;
+ argp->len = len;
+ argp->mon = (char *)p;
+ if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
+ return 0;
+ p = xdr_inline_decode(xdr, SM_PRIV_SIZE);
+ if (!p)
+ return 0;
+ memcpy(&argp->priv.data, p, sizeof(argp->priv.data));
+
+ return 1;
+}
+
int
nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
{
@@ -380,19 +406,6 @@ nlmsvc_decode_notify(struct svc_rqst *rqstp, __be32 *p)
return xdr_argsize_check(rqstp, p);
}

-int
-nlmsvc_decode_reboot(struct svc_rqst *rqstp, __be32 *p)
-{
- struct nlm_reboot *argp = rqstp->rq_argp;
-
- if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN)))
- return 0;
- argp->state = ntohl(*p++);
- memcpy(&argp->priv.data, p, sizeof(argp->priv.data));
- p += XDR_QUADLEN(SM_PRIV_SIZE);
- return xdr_argsize_check(rqstp, p);
-}
-
int
nlmsvc_encode_void(struct svc_rqst *rqstp, __be32 *p)
{


2021-05-03 15:24:25

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 11/29] lockd: Update the NLMv1 SHARE arguments decoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr.c | 96 +++++++++++++++-----------------------------------------
1 file changed, 26 insertions(+), 70 deletions(-)

diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index 421613170e5f..c496f18eff06 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -21,8 +21,6 @@

#include "svcxdr.h"

-#define NLMDBG_FACILITY NLMDBG_XDR
-

static inline loff_t
s32_to_loff_t(__s32 offset)
@@ -46,33 +44,6 @@ loff_t_to_s32(loff_t offset)
/*
* XDR functions for basic NLM types
*/
-static __be32 *nlm_decode_cookie(__be32 *p, struct nlm_cookie *c)
-{
- unsigned int len;
-
- len = ntohl(*p++);
-
- if(len==0)
- {
- c->len=4;
- memset(c->data, 0, 4); /* hockeypux brain damage */
- }
- else if(len<=NLM_MAXCOOKIELEN)
- {
- c->len=len;
- memcpy(c->data, p, len);
- p+=XDR_QUADLEN(len);
- }
- else
- {
- dprintk("lockd: bad cookie size %d (only cookies under "
- "%d bytes are supported.)\n",
- len, NLM_MAXCOOKIELEN);
- return NULL;
- }
- return p;
-}
-
static inline __be32 *
nlm_encode_cookie(__be32 *p, struct nlm_cookie *c)
{
@@ -82,22 +53,6 @@ nlm_encode_cookie(__be32 *p, struct nlm_cookie *c)
return p;
}

-static __be32 *
-nlm_decode_fh(__be32 *p, struct nfs_fh *f)
-{
- unsigned int len;
-
- if ((len = ntohl(*p++)) != NFS2_FHSIZE) {
- dprintk("lockd: bad fhandle size %d (should be %d)\n",
- len, NFS2_FHSIZE);
- return NULL;
- }
- f->size = NFS2_FHSIZE;
- memset(f->data, 0, sizeof(f->data));
- memcpy(f->data, p, NFS2_FHSIZE);
- return p + XDR_QUADLEN(NFS2_FHSIZE);
-}
-
/*
* NLM file handles are defined by specification to be a variable-length
* XDR opaque no longer than 1024 bytes. However, this implementation
@@ -128,12 +83,6 @@ svcxdr_decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)
/*
* Encode and decode owner handle
*/
-static inline __be32 *
-nlm_decode_oh(__be32 *p, struct xdr_netobj *oh)
-{
- return xdr_decode_netobj(p, oh);
-}
-
static inline __be32 *
nlm_encode_oh(__be32 *p, struct xdr_netobj *oh)
{
@@ -339,35 +288,42 @@ nlmsvc_decode_reboot(struct svc_rqst *rqstp, __be32 *p)
return 1;
}

-int
-nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
-{
- struct nlm_res *resp = rqstp->rq_resp;
-
- if (!(p = nlm_encode_testres(p, resp)))
- return 0;
- return xdr_ressize_check(rqstp, p);
-}
-
int
nlmsvc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p)
{
+ struct xdr_stream *xdr = &rqstp->rq_arg_stream;
struct nlm_args *argp = rqstp->rq_argp;
struct nlm_lock *lock = &argp->lock;

memset(lock, 0, sizeof(*lock));
locks_init_lock(&lock->fl);
- lock->svid = ~(u32) 0;
+ lock->svid = ~(u32)0;

- if (!(p = nlm_decode_cookie(p, &argp->cookie))
- || !(p = xdr_decode_string_inplace(p, &lock->caller,
- &lock->len, NLM_MAXSTRLEN))
- || !(p = nlm_decode_fh(p, &lock->fh))
- || !(p = nlm_decode_oh(p, &lock->oh)))
+ if (!svcxdr_decode_cookie(xdr, &argp->cookie))
return 0;
- argp->fsm_mode = ntohl(*p++);
- argp->fsm_access = ntohl(*p++);
- return xdr_argsize_check(rqstp, p);
+ if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
+ return 0;
+ if (!svcxdr_decode_fhandle(xdr, &lock->fh))
+ return 0;
+ if (!svcxdr_decode_owner(xdr, &lock->oh))
+ return 0;
+ /* XXX: Range checks are missing in the original code */
+ if (xdr_stream_decode_u32(xdr, &argp->fsm_mode) < 0)
+ return 0;
+ if (xdr_stream_decode_u32(xdr, &argp->fsm_access) < 0)
+ return 0;
+
+ return 1;
+}
+
+int
+nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
+{
+ struct nlm_res *resp = rqstp->rq_resp;
+
+ if (!(p = nlm_encode_testres(p, resp)))
+ return 0;
+ return xdr_ressize_check(rqstp, p);
}

int


2021-05-03 15:24:27

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 12/29] lockd: Update the NLMv1 FREE_ALL arguments decoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr.c | 28 +++++++++++++++-------------
1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index c496f18eff06..091c8c463ab4 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -316,6 +316,21 @@ nlmsvc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p)
return 1;
}

+int
+nlmsvc_decode_notify(struct svc_rqst *rqstp, __be32 *p)
+{
+ struct xdr_stream *xdr = &rqstp->rq_arg_stream;
+ struct nlm_args *argp = rqstp->rq_argp;
+ struct nlm_lock *lock = &argp->lock;
+
+ if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
+ return 0;
+ if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
+ return 0;
+
+ return 1;
+}
+
int
nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
{
@@ -349,19 +364,6 @@ nlmsvc_encode_res(struct svc_rqst *rqstp, __be32 *p)
return xdr_ressize_check(rqstp, p);
}

-int
-nlmsvc_decode_notify(struct svc_rqst *rqstp, __be32 *p)
-{
- struct nlm_args *argp = rqstp->rq_argp;
- struct nlm_lock *lock = &argp->lock;
-
- if (!(p = xdr_decode_string_inplace(p, &lock->caller,
- &lock->len, NLM_MAXSTRLEN)))
- return 0;
- argp->state = ntohl(*p++);
- return xdr_argsize_check(rqstp, p);
-}
-
int
nlmsvc_encode_void(struct svc_rqst *rqstp, __be32 *p)
{


2021-05-03 15:24:35

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 13/29] lockd: Update the NLMv1 void results encoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index 091c8c463ab4..840fa8ff8426 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -331,6 +331,17 @@ nlmsvc_decode_notify(struct svc_rqst *rqstp, __be32 *p)
return 1;
}

+
+/*
+ * Encode Reply results
+ */
+
+int
+nlmsvc_encode_void(struct svc_rqst *rqstp, __be32 *p)
+{
+ return 1;
+}
+
int
nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
{
@@ -363,9 +374,3 @@ nlmsvc_encode_res(struct svc_rqst *rqstp, __be32 *p)
*p++ = resp->status;
return xdr_ressize_check(rqstp, p);
}
-
-int
-nlmsvc_encode_void(struct svc_rqst *rqstp, __be32 *p)
-{
- return xdr_ressize_check(rqstp, p);
-}


2021-05-03 15:24:40

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 14/29] lockd: Update the NLMv1 TEST results encoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr.c | 74 ++++++++++++++++++++++++++------------------------------
1 file changed, 35 insertions(+), 39 deletions(-)

diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index 840fa8ff8426..daf3524040d6 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -80,15 +80,6 @@ svcxdr_decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)
return true;
}

-/*
- * Encode and decode owner handle
- */
-static inline __be32 *
-nlm_encode_oh(__be32 *p, struct xdr_netobj *oh)
-{
- return xdr_encode_netobj(p, oh);
-}
-
static bool
svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)
{
@@ -121,39 +112,44 @@ svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)
return true;
}

-/*
- * Encode result of a TEST/TEST_MSG call
- */
-static __be32 *
-nlm_encode_testres(__be32 *p, struct nlm_res *resp)
+static bool
+svcxdr_encode_holder(struct xdr_stream *xdr, const struct nlm_lock *lock)
{
- s32 start, len;
-
- if (!(p = nlm_encode_cookie(p, &resp->cookie)))
- return NULL;
- *p++ = resp->status;
+ const struct file_lock *fl = &lock->fl;
+ s32 start, len;

- if (resp->status == nlm_lck_denied) {
- struct file_lock *fl = &resp->lock.fl;
-
- *p++ = (fl->fl_type == F_RDLCK)? xdr_zero : xdr_one;
- *p++ = htonl(resp->lock.svid);
-
- /* Encode owner handle. */
- if (!(p = xdr_encode_netobj(p, &resp->lock.oh)))
- return NULL;
+ /* exclusive */
+ if (xdr_stream_encode_bool(xdr, fl->fl_type != F_RDLCK) < 0)
+ return false;
+ if (xdr_stream_encode_u32(xdr, lock->svid) < 0)
+ return false;
+ if (!svcxdr_encode_owner(xdr, &lock->oh))
+ return false;
+ start = loff_t_to_s32(fl->fl_start);
+ if (fl->fl_end == OFFSET_MAX)
+ len = 0;
+ else
+ len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1);
+ if (xdr_stream_encode_u32(xdr, start) < 0)
+ return false;
+ if (xdr_stream_encode_u32(xdr, len) < 0)
+ return false;

- start = loff_t_to_s32(fl->fl_start);
- if (fl->fl_end == OFFSET_MAX)
- len = 0;
- else
- len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1);
+ return true;
+}

- *p++ = htonl(start);
- *p++ = htonl(len);
+static bool
+svcxdr_encode_testrply(struct xdr_stream *xdr, const struct nlm_res *resp)
+{
+ if (!svcxdr_encode_stats(xdr, resp->status))
+ return false;
+ switch (resp->status) {
+ case nlm_lck_denied:
+ if (!svcxdr_encode_holder(xdr, &resp->lock))
+ return false;
}

- return p;
+ return true;
}


@@ -345,11 +341,11 @@ nlmsvc_encode_void(struct svc_rqst *rqstp, __be32 *p)
int
nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
{
+ struct xdr_stream *xdr = &rqstp->rq_res_stream;
struct nlm_res *resp = rqstp->rq_resp;

- if (!(p = nlm_encode_testres(p, resp)))
- return 0;
- return xdr_ressize_check(rqstp, p);
+ return svcxdr_encode_cookie(xdr, &resp->cookie) &&
+ svcxdr_encode_testrply(xdr, resp);
}

int


2021-05-03 15:24:49

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 15/29] lockd: Update the NLMv1 nlm_res results encoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index daf3524040d6..4fb6090bc915 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -349,24 +349,23 @@ nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
}

int
-nlmsvc_encode_shareres(struct svc_rqst *rqstp, __be32 *p)
+nlmsvc_encode_res(struct svc_rqst *rqstp, __be32 *p)
{
+ struct xdr_stream *xdr = &rqstp->rq_res_stream;
struct nlm_res *resp = rqstp->rq_resp;

- if (!(p = nlm_encode_cookie(p, &resp->cookie)))
- return 0;
- *p++ = resp->status;
- *p++ = xdr_zero; /* sequence argument */
- return xdr_ressize_check(rqstp, p);
+ return svcxdr_encode_cookie(xdr, &resp->cookie) &&
+ svcxdr_encode_stats(xdr, resp->status);
}

int
-nlmsvc_encode_res(struct svc_rqst *rqstp, __be32 *p)
+nlmsvc_encode_shareres(struct svc_rqst *rqstp, __be32 *p)
{
struct nlm_res *resp = rqstp->rq_resp;

if (!(p = nlm_encode_cookie(p, &resp->cookie)))
return 0;
*p++ = resp->status;
+ *p++ = xdr_zero; /* sequence argument */
return xdr_ressize_check(rqstp, p);
}


2021-05-03 15:24:56

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 16/29] lockd: Update the NLMv1 SHARE results encoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr.c | 25 +++++++++----------------
1 file changed, 9 insertions(+), 16 deletions(-)

diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index 4fb6090bc915..9235e60b1769 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -41,18 +41,6 @@ loff_t_to_s32(loff_t offset)
return res;
}

-/*
- * XDR functions for basic NLM types
- */
-static inline __be32 *
-nlm_encode_cookie(__be32 *p, struct nlm_cookie *c)
-{
- *p++ = htonl(c->len);
- memcpy(p, c->data, c->len);
- p+=XDR_QUADLEN(c->len);
- return p;
-}
-
/*
* NLM file handles are defined by specification to be a variable-length
* XDR opaque no longer than 1024 bytes. However, this implementation
@@ -361,11 +349,16 @@ nlmsvc_encode_res(struct svc_rqst *rqstp, __be32 *p)
int
nlmsvc_encode_shareres(struct svc_rqst *rqstp, __be32 *p)
{
+ struct xdr_stream *xdr = &rqstp->rq_res_stream;
struct nlm_res *resp = rqstp->rq_resp;

- if (!(p = nlm_encode_cookie(p, &resp->cookie)))
+ if (!svcxdr_encode_cookie(xdr, &resp->cookie))
return 0;
- *p++ = resp->status;
- *p++ = xdr_zero; /* sequence argument */
- return xdr_ressize_check(rqstp, p);
+ if (!svcxdr_encode_stats(xdr, resp->status))
+ return 0;
+ /* sequence */
+ if (xdr_stream_encode_u32(xdr, 0) < 0)
+ return 0;
+
+ return 1;
}


2021-05-03 15:25:00

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 17/29] lockd: Update the NLMv4 void arguments decoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr4.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index 5fa9f48a9dba..d0960a8551f8 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -18,6 +18,8 @@
#include <linux/sunrpc/stats.h>
#include <linux/lockd/lockd.h>

+#include "svcxdr.h"
+
#define NLMDBG_FACILITY NLMDBG_XDR

static inline loff_t
@@ -175,8 +177,15 @@ nlm4_encode_testres(__be32 *p, struct nlm_res *resp)


/*
- * First, the server side XDR functions
+ * Decode Call arguments
*/
+
+int
+nlm4svc_decode_void(struct svc_rqst *rqstp, __be32 *p)
+{
+ return 1;
+}
+
int
nlm4svc_decode_testargs(struct svc_rqst *rqstp, __be32 *p)
{
@@ -336,12 +345,6 @@ nlm4svc_decode_res(struct svc_rqst *rqstp, __be32 *p)
return xdr_argsize_check(rqstp, p);
}

-int
-nlm4svc_decode_void(struct svc_rqst *rqstp, __be32 *p)
-{
- return xdr_argsize_check(rqstp, p);
-}
-
int
nlm4svc_encode_void(struct svc_rqst *rqstp, __be32 *p)
{


2021-05-03 15:25:07

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 18/29] lockd: Update the NLMv4 TEST arguments decoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr4.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 66 insertions(+), 6 deletions(-)

diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index d0960a8551f8..cf64794fdc1f 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -96,6 +96,32 @@ nlm4_decode_fh(__be32 *p, struct nfs_fh *f)
return p + XDR_QUADLEN(f->size);
}

+/*
+ * NLM file handles are defined by specification to be a variable-length
+ * XDR opaque no longer than 1024 bytes. However, this implementation
+ * limits their length to the size of an NFSv3 file handle.
+ */
+static bool
+svcxdr_decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)
+{
+ __be32 *p;
+ u32 len;
+
+ if (xdr_stream_decode_u32(xdr, &len) < 0)
+ return false;
+ if (len > NFS_MAXFHSIZE)
+ return false;
+
+ p = xdr_inline_decode(xdr, len);
+ if (!p)
+ return false;
+ fh->size = len;
+ memcpy(fh->data, p, len);
+ memset(fh->data + len, 0, sizeof(fh->data) - len);
+
+ return true;
+}
+
/*
* Encode and decode owner handle
*/
@@ -135,6 +161,39 @@ nlm4_decode_lock(__be32 *p, struct nlm_lock *lock)
return p;
}

+static bool
+svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)
+{
+ struct file_lock *fl = &lock->fl;
+ u64 len, start;
+ s64 end;
+
+ if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
+ return false;
+ if (!svcxdr_decode_fhandle(xdr, &lock->fh))
+ return false;
+ if (!svcxdr_decode_owner(xdr, &lock->oh))
+ return false;
+ if (xdr_stream_decode_u32(xdr, &lock->svid) < 0)
+ return false;
+ if (xdr_stream_decode_u64(xdr, &start) < 0)
+ return false;
+ if (xdr_stream_decode_u64(xdr, &len) < 0)
+ return false;
+
+ locks_init_lock(fl);
+ fl->fl_flags = FL_POSIX;
+ fl->fl_type = F_RDLCK;
+ end = start + len - 1;
+ fl->fl_start = s64_to_loff_t(start);
+ if (len == 0 || end < 0)
+ fl->fl_end = OFFSET_MAX;
+ else
+ fl->fl_end = s64_to_loff_t(end);
+
+ return true;
+}
+
/*
* Encode result of a TEST/TEST_MSG call
*/
@@ -189,19 +248,20 @@ nlm4svc_decode_void(struct svc_rqst *rqstp, __be32 *p)
int
nlm4svc_decode_testargs(struct svc_rqst *rqstp, __be32 *p)
{
+ struct xdr_stream *xdr = &rqstp->rq_arg_stream;
struct nlm_args *argp = rqstp->rq_argp;
- u32 exclusive;
+ u32 exclusive;

- if (!(p = nlm4_decode_cookie(p, &argp->cookie)))
+ if (!svcxdr_decode_cookie(xdr, &argp->cookie))
return 0;
-
- exclusive = ntohl(*p++);
- if (!(p = nlm4_decode_lock(p, &argp->lock)))
+ if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
+ return 0;
+ if (!svcxdr_decode_lock(xdr, &argp->lock))
return 0;
if (exclusive)
argp->lock.fl.fl_type = F_WRLCK;

- return xdr_argsize_check(rqstp, p);
+ return 1;
}

int


2021-05-03 15:25:13

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 19/29] lockd: Update the NLMv4 LOCK arguments decoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr4.c | 41 +++++++++++++++++++++++------------------
1 file changed, 23 insertions(+), 18 deletions(-)

diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index cf64794fdc1f..1d3e780c25fd 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -264,35 +264,40 @@ nlm4svc_decode_testargs(struct svc_rqst *rqstp, __be32 *p)
return 1;
}

-int
-nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
-{
- struct nlm_res *resp = rqstp->rq_resp;
-
- if (!(p = nlm4_encode_testres(p, resp)))
- return 0;
- return xdr_ressize_check(rqstp, p);
-}
-
int
nlm4svc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p)
{
+ struct xdr_stream *xdr = &rqstp->rq_arg_stream;
struct nlm_args *argp = rqstp->rq_argp;
- u32 exclusive;
+ u32 exclusive;

- if (!(p = nlm4_decode_cookie(p, &argp->cookie)))
+ if (!svcxdr_decode_cookie(xdr, &argp->cookie))
return 0;
- argp->block = ntohl(*p++);
- exclusive = ntohl(*p++);
- if (!(p = nlm4_decode_lock(p, &argp->lock)))
+ if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
+ return 0;
+ if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
+ return 0;
+ if (!svcxdr_decode_lock(xdr, &argp->lock))
return 0;
if (exclusive)
argp->lock.fl.fl_type = F_WRLCK;
- argp->reclaim = ntohl(*p++);
- argp->state = ntohl(*p++);
+ if (xdr_stream_decode_bool(xdr, &argp->reclaim) < 0)
+ return 0;
+ if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
+ return 0;
argp->monitor = 1; /* monitor client by default */

- return xdr_argsize_check(rqstp, p);
+ return 1;
+}
+
+int
+nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
+{
+ struct nlm_res *resp = rqstp->rq_resp;
+
+ if (!(p = nlm4_encode_testres(p, resp)))
+ return 0;
+ return xdr_ressize_check(rqstp, p);
}

int


2021-05-03 15:25:16

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 20/29] lockd: Update the NLMv4 CANCEL arguments decoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr4.c | 33 ++++++++++++++++++---------------
1 file changed, 18 insertions(+), 15 deletions(-)

diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index 1d3e780c25fd..37d45f1d7199 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -291,30 +291,33 @@ nlm4svc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p)
}

int
-nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
+nlm4svc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p)
{
- struct nlm_res *resp = rqstp->rq_resp;
+ struct xdr_stream *xdr = &rqstp->rq_arg_stream;
+ struct nlm_args *argp = rqstp->rq_argp;
+ u32 exclusive;

- if (!(p = nlm4_encode_testres(p, resp)))
+ if (!svcxdr_decode_cookie(xdr, &argp->cookie))
return 0;
- return xdr_ressize_check(rqstp, p);
+ if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
+ return 0;
+ if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
+ return 0;
+ if (!svcxdr_decode_lock(xdr, &argp->lock))
+ return 0;
+ if (exclusive)
+ argp->lock.fl.fl_type = F_WRLCK;
+ return 1;
}

int
-nlm4svc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p)
+nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
{
- struct nlm_args *argp = rqstp->rq_argp;
- u32 exclusive;
+ struct nlm_res *resp = rqstp->rq_resp;

- if (!(p = nlm4_decode_cookie(p, &argp->cookie)))
- return 0;
- argp->block = ntohl(*p++);
- exclusive = ntohl(*p++);
- if (!(p = nlm4_decode_lock(p, &argp->lock)))
+ if (!(p = nlm4_encode_testres(p, resp)))
return 0;
- if (exclusive)
- argp->lock.fl.fl_type = F_WRLCK;
- return xdr_argsize_check(rqstp, p);
+ return xdr_ressize_check(rqstp, p);
}

int


2021-05-03 15:25:26

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 21/29] lockd: Update the NLMv4 UNLOCK arguments decoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr4.c | 53 +++++++++++++----------------------------------------
1 file changed, 13 insertions(+), 40 deletions(-)

diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index 37d45f1d7199..47a87ea4a99b 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -131,36 +131,6 @@ nlm4_decode_oh(__be32 *p, struct xdr_netobj *oh)
return xdr_decode_netobj(p, oh);
}

-static __be32 *
-nlm4_decode_lock(__be32 *p, struct nlm_lock *lock)
-{
- struct file_lock *fl = &lock->fl;
- __u64 len, start;
- __s64 end;
-
- if (!(p = xdr_decode_string_inplace(p, &lock->caller,
- &lock->len, NLM_MAXSTRLEN))
- || !(p = nlm4_decode_fh(p, &lock->fh))
- || !(p = nlm4_decode_oh(p, &lock->oh)))
- return NULL;
- lock->svid = ntohl(*p++);
-
- locks_init_lock(fl);
- fl->fl_flags = FL_POSIX;
- fl->fl_type = F_RDLCK; /* as good as anything else */
- p = xdr_decode_hyper(p, &start);
- p = xdr_decode_hyper(p, &len);
- end = start + len - 1;
-
- fl->fl_start = s64_to_loff_t(start);
-
- if (len == 0 || end < 0)
- fl->fl_end = OFFSET_MAX;
- else
- fl->fl_end = s64_to_loff_t(end);
- return p;
-}
-
static bool
svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)
{
@@ -311,25 +281,28 @@ nlm4svc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p)
}

int
-nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
+nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p)
{
- struct nlm_res *resp = rqstp->rq_resp;
+ struct xdr_stream *xdr = &rqstp->rq_arg_stream;
+ struct nlm_args *argp = rqstp->rq_argp;

- if (!(p = nlm4_encode_testres(p, resp)))
+ if (!svcxdr_decode_cookie(xdr, &argp->cookie))
return 0;
- return xdr_ressize_check(rqstp, p);
+ if (!svcxdr_decode_lock(xdr, &argp->lock))
+ return 0;
+ argp->lock.fl.fl_type = F_UNLCK;
+
+ return 1;
}

int
-nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p)
+nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
{
- struct nlm_args *argp = rqstp->rq_argp;
+ struct nlm_res *resp = rqstp->rq_resp;

- if (!(p = nlm4_decode_cookie(p, &argp->cookie))
- || !(p = nlm4_decode_lock(p, &argp->lock)))
+ if (!(p = nlm4_encode_testres(p, resp)))
return 0;
- argp->lock.fl.fl_type = F_UNLCK;
- return xdr_argsize_check(rqstp, p);
+ return xdr_ressize_check(rqstp, p);
}

int


2021-05-03 15:25:31

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 22/29] lockd: Update the NLMv4 nlm_res arguments decoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr4.c | 25 ++++++++++++++-----------
1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index 47a87ea4a99b..6bd3bfb69ed7 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -295,6 +295,20 @@ nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p)
return 1;
}

+int
+nlm4svc_decode_res(struct svc_rqst *rqstp, __be32 *p)
+{
+ struct xdr_stream *xdr = &rqstp->rq_arg_stream;
+ struct nlm_res *resp = rqstp->rq_argp;
+
+ if (!svcxdr_decode_cookie(xdr, &resp->cookie))
+ return 0;
+ if (!svcxdr_decode_stats(xdr, &resp->status))
+ return 0;
+
+ return 1;
+}
+
int
nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
{
@@ -375,17 +389,6 @@ nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p)
return xdr_argsize_check(rqstp, p);
}

-int
-nlm4svc_decode_res(struct svc_rqst *rqstp, __be32 *p)
-{
- struct nlm_res *resp = rqstp->rq_argp;
-
- if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
- return 0;
- resp->status = *p++;
- return xdr_argsize_check(rqstp, p);
-}
-
int
nlm4svc_encode_void(struct svc_rqst *rqstp, __be32 *p)
{


2021-05-03 15:25:42

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 23/29] lockd: Update the NLMv4 SM_NOTIFY arguments decoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr4.c | 39 ++++++++++++++++++++++++++-------------
1 file changed, 26 insertions(+), 13 deletions(-)

diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index 6bd3bfb69ed7..2dbf82c2726b 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -309,6 +309,32 @@ nlm4svc_decode_res(struct svc_rqst *rqstp, __be32 *p)
return 1;
}

+int
+nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p)
+{
+ struct xdr_stream *xdr = &rqstp->rq_arg_stream;
+ struct nlm_reboot *argp = rqstp->rq_argp;
+ u32 len;
+
+ if (xdr_stream_decode_u32(xdr, &len) < 0)
+ return 0;
+ if (len > SM_MAXSTRLEN)
+ return 0;
+ p = xdr_inline_decode(xdr, len);
+ if (!p)
+ return 0;
+ argp->len = len;
+ argp->mon = (char *)p;
+ if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
+ return 0;
+ p = xdr_inline_decode(xdr, SM_PRIV_SIZE);
+ if (!p)
+ return 0;
+ memcpy(&argp->priv.data, p, sizeof(argp->priv.data));
+
+ return 1;
+}
+
int
nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
{
@@ -376,19 +402,6 @@ nlm4svc_decode_notify(struct svc_rqst *rqstp, __be32 *p)
return xdr_argsize_check(rqstp, p);
}

-int
-nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p)
-{
- struct nlm_reboot *argp = rqstp->rq_argp;
-
- if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN)))
- return 0;
- argp->state = ntohl(*p++);
- memcpy(&argp->priv.data, p, sizeof(argp->priv.data));
- p += XDR_QUADLEN(SM_PRIV_SIZE);
- return xdr_argsize_check(rqstp, p);
-}
-
int
nlm4svc_encode_void(struct svc_rqst *rqstp, __be32 *p)
{


2021-05-03 15:25:52

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 25/29] lockd: Update the NLMv4 FREE_ALL arguments decoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr4.c | 28 +++++++++++++++-------------
1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index e6bab1d1e41f..6c5383bef2bf 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -309,6 +309,21 @@ nlm4svc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p)
return 1;
}

+int
+nlm4svc_decode_notify(struct svc_rqst *rqstp, __be32 *p)
+{
+ struct xdr_stream *xdr = &rqstp->rq_arg_stream;
+ struct nlm_args *argp = rqstp->rq_argp;
+ struct nlm_lock *lock = &argp->lock;
+
+ if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
+ return 0;
+ if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
+ return 0;
+
+ return 1;
+}
+
int
nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
{
@@ -342,19 +357,6 @@ nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p)
return xdr_ressize_check(rqstp, p);
}

-int
-nlm4svc_decode_notify(struct svc_rqst *rqstp, __be32 *p)
-{
- struct nlm_args *argp = rqstp->rq_argp;
- struct nlm_lock *lock = &argp->lock;
-
- if (!(p = xdr_decode_string_inplace(p, &lock->caller,
- &lock->len, NLM_MAXSTRLEN)))
- return 0;
- argp->state = ntohl(*p++);
- return xdr_argsize_check(rqstp, p);
-}
-
int
nlm4svc_encode_void(struct svc_rqst *rqstp, __be32 *p)
{


2021-05-03 15:26:12

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 26/29] lockd: Update the NLMv4 void results encoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr4.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index 6c5383bef2bf..0db142e203d2 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -324,6 +324,17 @@ nlm4svc_decode_notify(struct svc_rqst *rqstp, __be32 *p)
return 1;
}

+
+/*
+ * Encode Reply results
+ */
+
+int
+nlm4svc_encode_void(struct svc_rqst *rqstp, __be32 *p)
+{
+ return 1;
+}
+
int
nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
{
@@ -356,9 +367,3 @@ nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p)
*p++ = resp->status;
return xdr_ressize_check(rqstp, p);
}
-
-int
-nlm4svc_encode_void(struct svc_rqst *rqstp, __be32 *p)
-{
- return xdr_ressize_check(rqstp, p);
-}


2021-05-03 15:26:12

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 27/29] lockd: Update the NLMv4 TEST results encoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr4.c | 74 +++++++++++++++++++++++++++----------------------------
1 file changed, 36 insertions(+), 38 deletions(-)

diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index 0db142e203d2..9b8a7afb935c 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -20,8 +20,6 @@

#include "svcxdr.h"

-#define NLMDBG_FACILITY NLMDBG_XDR
-
static inline loff_t
s64_to_loff_t(__s64 offset)
{
@@ -110,44 +108,44 @@ svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)
return true;
}

-/*
- * Encode result of a TEST/TEST_MSG call
- */
-static __be32 *
-nlm4_encode_testres(__be32 *p, struct nlm_res *resp)
+static bool
+svcxdr_encode_holder(struct xdr_stream *xdr, const struct nlm_lock *lock)
{
- s64 start, len;
+ const struct file_lock *fl = &lock->fl;
+ s64 start, len;

- dprintk("xdr: before encode_testres (p %p resp %p)\n", p, resp);
- if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
- return NULL;
- *p++ = resp->status;
+ /* exclusive */
+ if (xdr_stream_encode_bool(xdr, fl->fl_type != F_RDLCK) < 0)
+ return false;
+ if (xdr_stream_encode_u32(xdr, lock->svid) < 0)
+ return false;
+ if (!svcxdr_encode_owner(xdr, &lock->oh))
+ return false;
+ start = loff_t_to_s64(fl->fl_start);
+ if (fl->fl_end == OFFSET_MAX)
+ len = 0;
+ else
+ len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1);
+ if (xdr_stream_encode_u64(xdr, start) < 0)
+ return false;
+ if (xdr_stream_encode_u64(xdr, len) < 0)
+ return false;
+
+ return true;
+}

- if (resp->status == nlm_lck_denied) {
- struct file_lock *fl = &resp->lock.fl;
-
- *p++ = (fl->fl_type == F_RDLCK)? xdr_zero : xdr_one;
- *p++ = htonl(resp->lock.svid);
-
- /* Encode owner handle. */
- if (!(p = xdr_encode_netobj(p, &resp->lock.oh)))
- return NULL;
-
- start = loff_t_to_s64(fl->fl_start);
- if (fl->fl_end == OFFSET_MAX)
- len = 0;
- else
- len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1);
-
- p = xdr_encode_hyper(p, start);
- p = xdr_encode_hyper(p, len);
- dprintk("xdr: encode_testres (status %u pid %d type %d start %Ld end %Ld)\n",
- resp->status, (int)resp->lock.svid, fl->fl_type,
- (long long)fl->fl_start, (long long)fl->fl_end);
+static bool
+svcxdr_encode_testrply(struct xdr_stream *xdr, const struct nlm_res *resp)
+{
+ if (!svcxdr_encode_stats(xdr, resp->status))
+ return false;
+ switch (resp->status) {
+ case nlm_lck_denied:
+ if (!svcxdr_encode_holder(xdr, &resp->lock))
+ return false;
}

- dprintk("xdr: after encode_testres (p %p resp %p)\n", p, resp);
- return p;
+ return true;
}


@@ -338,11 +336,11 @@ nlm4svc_encode_void(struct svc_rqst *rqstp, __be32 *p)
int
nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
{
+ struct xdr_stream *xdr = &rqstp->rq_res_stream;
struct nlm_res *resp = rqstp->rq_resp;

- if (!(p = nlm4_encode_testres(p, resp)))
- return 0;
- return xdr_ressize_check(rqstp, p);
+ return svcxdr_encode_cookie(xdr, &resp->cookie) &&
+ svcxdr_encode_testrply(xdr, resp);
}

int


2021-05-03 15:26:13

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 29/29] lockd: Update the NLMv4 SHARE results encoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr4.c | 22 +++++++++-------------
1 file changed, 9 insertions(+), 13 deletions(-)

diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index efdede71b951..98e957e4566c 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -40,15 +40,6 @@ loff_t_to_s64(loff_t offset)
return res;
}

-static __be32 *
-nlm4_encode_cookie(__be32 *p, struct nlm_cookie *c)
-{
- *p++ = htonl(c->len);
- memcpy(p, c->data, c->len);
- p+=XDR_QUADLEN(c->len);
- return p;
-}
-
/*
* NLM file handles are defined by specification to be a variable-length
* XDR opaque no longer than 1024 bytes. However, this implementation
@@ -356,11 +347,16 @@ nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p)
int
nlm4svc_encode_shareres(struct svc_rqst *rqstp, __be32 *p)
{
+ struct xdr_stream *xdr = &rqstp->rq_res_stream;
struct nlm_res *resp = rqstp->rq_resp;

- if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
+ if (!svcxdr_encode_cookie(xdr, &resp->cookie))
return 0;
- *p++ = resp->status;
- *p++ = xdr_zero; /* sequence argument */
- return xdr_ressize_check(rqstp, p);
+ if (!svcxdr_encode_stats(xdr, resp->status))
+ return 0;
+ /* sequence */
+ if (xdr_stream_encode_u32(xdr, 0) < 0)
+ return 0;
+
+ return 1;
}


2021-05-03 15:26:24

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 24/29] lockd: Update the NLMv4 SHARE arguments decoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr4.c | 99 ++++++++++++++-----------------------------------------
1 file changed, 26 insertions(+), 73 deletions(-)

diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index 2dbf82c2726b..e6bab1d1e41f 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -42,37 +42,6 @@ loff_t_to_s64(loff_t offset)
return res;
}

-/*
- * XDR functions for basic NLM types
- */
-static __be32 *
-nlm4_decode_cookie(__be32 *p, struct nlm_cookie *c)
-{
- unsigned int len;
-
- len = ntohl(*p++);
-
- if(len==0)
- {
- c->len=4;
- memset(c->data, 0, 4); /* hockeypux brain damage */
- }
- else if(len<=NLM_MAXCOOKIELEN)
- {
- c->len=len;
- memcpy(c->data, p, len);
- p+=XDR_QUADLEN(len);
- }
- else
- {
- dprintk("lockd: bad cookie size %d (only cookies under "
- "%d bytes are supported.)\n",
- len, NLM_MAXCOOKIELEN);
- return NULL;
- }
- return p;
-}
-
static __be32 *
nlm4_encode_cookie(__be32 *p, struct nlm_cookie *c)
{
@@ -82,20 +51,6 @@ nlm4_encode_cookie(__be32 *p, struct nlm_cookie *c)
return p;
}

-static __be32 *
-nlm4_decode_fh(__be32 *p, struct nfs_fh *f)
-{
- memset(f->data, 0, sizeof(f->data));
- f->size = ntohl(*p++);
- if (f->size > NFS_MAXFHSIZE) {
- dprintk("lockd: bad fhandle size %d (should be <=%d)\n",
- f->size, NFS_MAXFHSIZE);
- return NULL;
- }
- memcpy(f->data, p, f->size);
- return p + XDR_QUADLEN(f->size);
-}
-
/*
* NLM file handles are defined by specification to be a variable-length
* XDR opaque no longer than 1024 bytes. However, this implementation
@@ -122,15 +77,6 @@ svcxdr_decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)
return true;
}

-/*
- * Encode and decode owner handle
- */
-static __be32 *
-nlm4_decode_oh(__be32 *p, struct xdr_netobj *oh)
-{
- return xdr_decode_netobj(p, oh);
-}
-
static bool
svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)
{
@@ -335,35 +281,42 @@ nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p)
return 1;
}

-int
-nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
-{
- struct nlm_res *resp = rqstp->rq_resp;
-
- if (!(p = nlm4_encode_testres(p, resp)))
- return 0;
- return xdr_ressize_check(rqstp, p);
-}
-
int
nlm4svc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p)
{
+ struct xdr_stream *xdr = &rqstp->rq_arg_stream;
struct nlm_args *argp = rqstp->rq_argp;
struct nlm_lock *lock = &argp->lock;

memset(lock, 0, sizeof(*lock));
locks_init_lock(&lock->fl);
- lock->svid = ~(u32) 0;
+ lock->svid = ~(u32)0;

- if (!(p = nlm4_decode_cookie(p, &argp->cookie))
- || !(p = xdr_decode_string_inplace(p, &lock->caller,
- &lock->len, NLM_MAXSTRLEN))
- || !(p = nlm4_decode_fh(p, &lock->fh))
- || !(p = nlm4_decode_oh(p, &lock->oh)))
+ if (!svcxdr_decode_cookie(xdr, &argp->cookie))
return 0;
- argp->fsm_mode = ntohl(*p++);
- argp->fsm_access = ntohl(*p++);
- return xdr_argsize_check(rqstp, p);
+ if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
+ return 0;
+ if (!svcxdr_decode_fhandle(xdr, &lock->fh))
+ return 0;
+ if (!svcxdr_decode_owner(xdr, &lock->oh))
+ return 0;
+ /* XXX: Range checks are missing in the original code */
+ if (xdr_stream_decode_u32(xdr, &argp->fsm_mode) < 0)
+ return 0;
+ if (xdr_stream_decode_u32(xdr, &argp->fsm_access) < 0)
+ return 0;
+
+ return 1;
+}
+
+int
+nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
+{
+ struct nlm_res *resp = rqstp->rq_resp;
+
+ if (!(p = nlm4_encode_testres(p, resp)))
+ return 0;
+ return xdr_ressize_check(rqstp, p);
}

int


2021-05-03 15:26:54

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH v1 28/29] lockd: Update the NLMv4 nlm_res results encoder to use struct xdr_stream

Signed-off-by: Chuck Lever <[email protected]>
---
fs/lockd/xdr4.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index 9b8a7afb935c..efdede71b951 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -344,24 +344,23 @@ nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
}

int
-nlm4svc_encode_shareres(struct svc_rqst *rqstp, __be32 *p)
+nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p)
{
+ struct xdr_stream *xdr = &rqstp->rq_res_stream;
struct nlm_res *resp = rqstp->rq_resp;

- if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
- return 0;
- *p++ = resp->status;
- *p++ = xdr_zero; /* sequence argument */
- return xdr_ressize_check(rqstp, p);
+ return svcxdr_encode_cookie(xdr, &resp->cookie) &&
+ svcxdr_encode_stats(xdr, resp->status);
}

int
-nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p)
+nlm4svc_encode_shareres(struct svc_rqst *rqstp, __be32 *p)
{
struct nlm_res *resp = rqstp->rq_resp;

if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
return 0;
*p++ = resp->status;
+ *p++ = xdr_zero; /* sequence argument */
return xdr_ressize_check(rqstp, p);
}


2021-05-03 18:00:03

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [PATCH v1 00/29] server-side lockd XDR overhaul

On Mon, May 03, 2021 at 11:22:47AM -0400, Chuck Lever wrote:
> Same approach as what has been done for NFSv2, NFSv3, and NFSv4: XDR
> decoding and encoding functions have been updated to use xdr_stream.
> This adopts common XDR infrastructure for these functions and makes
> constructing and parsing more secure and robust.

Nothing objectionable to me on a quick skim, but it doesn't build when I
apply to 5.12 (fs/lockd/svc.c:794:9: error: implicit declaration of
function ‘svcxdr_init_encode’). Should I take it from a git tree?

--b.

>
> ---
>
> Chuck Lever (29):
> lockd: Remove stale comments
> lockd: Create a simplified .vs_dispatch method for NLM requests
> lockd: Common NLM XDR helpers
> lockd: Update the NLMv1 void argument decoder to use struct xdr_stream
> lockd: Update the NLMv1 TEST arguments decoder to use struct xdr_stream
> lockd: Update the NLMv1 LOCK arguments decoder to use struct xdr_stream
> lockd: Update the NLMv1 CANCEL arguments decoder to use struct xdr_stream
> lockd: Update the NLMv1 UNLOCK arguments decoder to use struct xdr_stream
> lockd: Update the NLMv1 nlm_res arguments decoder to use struct xdr_stream
> lockd: Update the NLMv1 SM_NOTIFY arguments decoder to use struct xdr_stream
> lockd: Update the NLMv1 SHARE arguments decoder to use struct xdr_stream
> lockd: Update the NLMv1 FREE_ALL arguments decoder to use struct xdr_stream
> lockd: Update the NLMv1 void results encoder to use struct xdr_stream
> lockd: Update the NLMv1 TEST results encoder to use struct xdr_stream
> lockd: Update the NLMv1 nlm_res results encoder to use struct xdr_stream
> lockd: Update the NLMv1 SHARE results encoder to use struct xdr_stream
> lockd: Update the NLMv4 void arguments decoder to use struct xdr_stream
> lockd: Update the NLMv4 TEST arguments decoder to use struct xdr_stream
> lockd: Update the NLMv4 LOCK arguments decoder to use struct xdr_stream
> lockd: Update the NLMv4 CANCEL arguments decoder to use struct xdr_stream
> lockd: Update the NLMv4 UNLOCK arguments decoder to use struct xdr_stream
> lockd: Update the NLMv4 nlm_res arguments decoder to use struct xdr_stream
> lockd: Update the NLMv4 SM_NOTIFY arguments decoder to use struct xdr_stream
> lockd: Update the NLMv4 SHARE arguments decoder to use struct xdr_stream
> lockd: Update the NLMv4 FREE_ALL arguments decoder to use struct xdr_stream
> lockd: Update the NLMv4 void results encoder to use struct xdr_stream
> lockd: Update the NLMv4 TEST results encoder to use struct xdr_stream
> lockd: Update the NLMv4 nlm_res results encoder to use struct xdr_stream
> lockd: Update the NLMv4 SHARE results encoder to use struct xdr_stream
>
>
> fs/lockd/svc.c | 43 ++++
> fs/lockd/svcxdr.h | 151 ++++++++++++++
> fs/lockd/xdr.c | 402 ++++++++++++++++++------------------
> fs/lockd/xdr4.c | 403 +++++++++++++++++++------------------
> include/linux/lockd/xdr.h | 6 -
> include/linux/lockd/xdr4.h | 7 +-
> 6 files changed, 610 insertions(+), 402 deletions(-)
> create mode 100644 fs/lockd/svcxdr.h
>
> --
> Chuck Lever

2021-05-03 18:16:15

by Chuck Lever III

[permalink] [raw]
Subject: Re: [PATCH v1 00/29] server-side lockd XDR overhaul



> On May 3, 2021, at 1:59 PM, J. Bruce Fields <[email protected]> wrote:
>
> On Mon, May 03, 2021 at 11:22:47AM -0400, Chuck Lever wrote:
>> Same approach as what has been done for NFSv2, NFSv3, and NFSv4: XDR
>> decoding and encoding functions have been updated to use xdr_stream.
>> This adopts common XDR infrastructure for these functions and makes
>> constructing and parsing more secure and robust.
>
> Nothing objectionable to me on a quick skim, but it doesn't build when I
> apply to 5.12 (fs/lockd/svc.c:794:9: error: implicit declaration of
> function ‘svcxdr_init_encode’). Should I take it from a git tree?

It assumes the latest v5.13, which contains svcxdr_init_encode. But it
is available in the nfsd_xdr_stream topic branch in this repo:

git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux.git


> --b.
>
>>
>> ---
>>
>> Chuck Lever (29):
>> lockd: Remove stale comments
>> lockd: Create a simplified .vs_dispatch method for NLM requests
>> lockd: Common NLM XDR helpers
>> lockd: Update the NLMv1 void argument decoder to use struct xdr_stream
>> lockd: Update the NLMv1 TEST arguments decoder to use struct xdr_stream
>> lockd: Update the NLMv1 LOCK arguments decoder to use struct xdr_stream
>> lockd: Update the NLMv1 CANCEL arguments decoder to use struct xdr_stream
>> lockd: Update the NLMv1 UNLOCK arguments decoder to use struct xdr_stream
>> lockd: Update the NLMv1 nlm_res arguments decoder to use struct xdr_stream
>> lockd: Update the NLMv1 SM_NOTIFY arguments decoder to use struct xdr_stream
>> lockd: Update the NLMv1 SHARE arguments decoder to use struct xdr_stream
>> lockd: Update the NLMv1 FREE_ALL arguments decoder to use struct xdr_stream
>> lockd: Update the NLMv1 void results encoder to use struct xdr_stream
>> lockd: Update the NLMv1 TEST results encoder to use struct xdr_stream
>> lockd: Update the NLMv1 nlm_res results encoder to use struct xdr_stream
>> lockd: Update the NLMv1 SHARE results encoder to use struct xdr_stream
>> lockd: Update the NLMv4 void arguments decoder to use struct xdr_stream
>> lockd: Update the NLMv4 TEST arguments decoder to use struct xdr_stream
>> lockd: Update the NLMv4 LOCK arguments decoder to use struct xdr_stream
>> lockd: Update the NLMv4 CANCEL arguments decoder to use struct xdr_stream
>> lockd: Update the NLMv4 UNLOCK arguments decoder to use struct xdr_stream
>> lockd: Update the NLMv4 nlm_res arguments decoder to use struct xdr_stream
>> lockd: Update the NLMv4 SM_NOTIFY arguments decoder to use struct xdr_stream
>> lockd: Update the NLMv4 SHARE arguments decoder to use struct xdr_stream
>> lockd: Update the NLMv4 FREE_ALL arguments decoder to use struct xdr_stream
>> lockd: Update the NLMv4 void results encoder to use struct xdr_stream
>> lockd: Update the NLMv4 TEST results encoder to use struct xdr_stream
>> lockd: Update the NLMv4 nlm_res results encoder to use struct xdr_stream
>> lockd: Update the NLMv4 SHARE results encoder to use struct xdr_stream
>>
>>
>> fs/lockd/svc.c | 43 ++++
>> fs/lockd/svcxdr.h | 151 ++++++++++++++
>> fs/lockd/xdr.c | 402 ++++++++++++++++++------------------
>> fs/lockd/xdr4.c | 403 +++++++++++++++++++------------------
>> include/linux/lockd/xdr.h | 6 -
>> include/linux/lockd/xdr4.h | 7 +-
>> 6 files changed, 610 insertions(+), 402 deletions(-)
>> create mode 100644 fs/lockd/svcxdr.h
>>
>> --
>> Chuck Lever

--
Chuck Lever