diff mbox series

[5.15] lockd: set file_lock start and end when decoding nlm4 testargs

Message ID 20230321104628.37323-1-amir73il@gmail.com (mailing list archive)
State New, archived
Headers show
Series [5.15] lockd: set file_lock start and end when decoding nlm4 testargs | expand

Commit Message

Amir Goldstein March 21, 2023, 10:46 a.m. UTC
From: Jeff Layton <jlayton@kernel.org>

commit 7ff84910c66c9144cc0de9d9deed9fb84c03aff0 upstream.

Commit 6930bcbfb6ce dropped the setting of the file_lock range when
decoding a nlm_lock off the wire. This causes the client side grant
callback to miss matching blocks and reject the lock, only to rerequest
it 30s later.

Add a helper function to set the file_lock range from the start and end
values that the protocol uses, and have the nlm_lock decoder call that to
set up the file_lock args properly.

Fixes: 6930bcbfb6ce ("lockd: detect and reject lock arguments that overflow")
Reported-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Tested-by: Amir Goldstein <amir73il@gmail.com>
Cc: stable@vger.kernel.org #6.0
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---

Greg,

The upstream fix applies cleanly to 6.1.y and 6.2.y, so as the
Cc stable mentions, please apply upstream fix to those trees.

Alas, the regressing commit was also applied to v5.15.61,
so please apply this backport to fix 5.15.y.

Thanks,
Amir.

 fs/lockd/clnt4xdr.c        |  9 +--------
 fs/lockd/xdr4.c            | 13 ++++++++++++-
 include/linux/lockd/xdr4.h |  1 +
 3 files changed, 14 insertions(+), 9 deletions(-)

Comments

Greg KH March 28, 2023, 11:57 a.m. UTC | #1
On Tue, Mar 21, 2023 at 12:46:28PM +0200, Amir Goldstein wrote:
> From: Jeff Layton <jlayton@kernel.org>
> 
> commit 7ff84910c66c9144cc0de9d9deed9fb84c03aff0 upstream.
> 
> Commit 6930bcbfb6ce dropped the setting of the file_lock range when
> decoding a nlm_lock off the wire. This causes the client side grant
> callback to miss matching blocks and reject the lock, only to rerequest
> it 30s later.
> 
> Add a helper function to set the file_lock range from the start and end
> values that the protocol uses, and have the nlm_lock decoder call that to
> set up the file_lock args properly.
> 
> Fixes: 6930bcbfb6ce ("lockd: detect and reject lock arguments that overflow")
> Reported-by: Amir Goldstein <amir73il@gmail.com>
> Signed-off-by: Jeff Layton <jlayton@kernel.org>
> Tested-by: Amir Goldstein <amir73il@gmail.com>
> Cc: stable@vger.kernel.org #6.0
> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
> Signed-off-by: Amir Goldstein <amir73il@gmail.com>
> ---
> 
> Greg,
> 
> The upstream fix applies cleanly to 6.1.y and 6.2.y, so as the
> Cc stable mentions, please apply upstream fix to those trees.
> 
> Alas, the regressing commit was also applied to v5.15.61,
> so please apply this backport to fix 5.15.y.

Now queued up, thanks.

greg k-h
diff mbox series

Patch

diff --git a/fs/lockd/clnt4xdr.c b/fs/lockd/clnt4xdr.c
index 7df6324ccb8a..8161667c976f 100644
--- a/fs/lockd/clnt4xdr.c
+++ b/fs/lockd/clnt4xdr.c
@@ -261,7 +261,6 @@  static int decode_nlm4_holder(struct xdr_stream *xdr, struct nlm_res *result)
 	u32 exclusive;
 	int error;
 	__be32 *p;
-	s32 end;
 
 	memset(lock, 0, sizeof(*lock));
 	locks_init_lock(fl);
@@ -285,13 +284,7 @@  static int decode_nlm4_holder(struct xdr_stream *xdr, struct nlm_res *result)
 	fl->fl_type  = exclusive != 0 ? F_WRLCK : F_RDLCK;
 	p = xdr_decode_hyper(p, &l_offset);
 	xdr_decode_hyper(p, &l_len);
-	end = l_offset + l_len - 1;
-
-	fl->fl_start = (loff_t)l_offset;
-	if (l_len == 0 || end < 0)
-		fl->fl_end = OFFSET_MAX;
-	else
-		fl->fl_end = (loff_t)end;
+	nlm4svc_set_file_lock_range(fl, l_offset, l_len);
 	error = 0;
 out:
 	return error;
diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index 72f7d190fb3b..b303ecd74f33 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -33,6 +33,17 @@  loff_t_to_s64(loff_t offset)
 	return res;
 }
 
+void nlm4svc_set_file_lock_range(struct file_lock *fl, u64 off, u64 len)
+{
+	s64 end = off + len - 1;
+
+	fl->fl_start = off;
+	if (len == 0 || end < 0)
+		fl->fl_end = OFFSET_MAX;
+	else
+		fl->fl_end = end;
+}
+
 /*
  * NLM file handles are defined by specification to be a variable-length
  * XDR opaque no longer than 1024 bytes. However, this implementation
@@ -80,7 +91,7 @@  svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)
 	locks_init_lock(fl);
 	fl->fl_flags = FL_POSIX;
 	fl->fl_type  = F_RDLCK;
-
+	nlm4svc_set_file_lock_range(fl, lock->lock_start, lock->lock_len);
 	return true;
 }
 
diff --git a/include/linux/lockd/xdr4.h b/include/linux/lockd/xdr4.h
index 5ae766f26e04..025250ade98e 100644
--- a/include/linux/lockd/xdr4.h
+++ b/include/linux/lockd/xdr4.h
@@ -24,6 +24,7 @@ 
 
 
 
+void	nlm4svc_set_file_lock_range(struct file_lock *fl, u64 off, u64 len);
 int	nlm4svc_decode_testargs(struct svc_rqst *, __be32 *);
 int	nlm4svc_encode_testres(struct svc_rqst *, __be32 *);
 int	nlm4svc_decode_lockargs(struct svc_rqst *, __be32 *);