2022-06-13 17:57:33

by Benjamin Coddington

[permalink] [raw]
Subject: [PATCH] NLM: Defend against file_lock changes after vfs_test_lock()

Instead of trusting that struct file_lock returns completely unchanged
after vfs_test_lock() when there's no conflicting lock, stash away our
nlm_lockowner reference so we can properly release it for all cases.

This defends against another file_lock implementation overwriting fl_owner
when the return type is F_UNLCK.

Reported-by: Roberto Bergantinos Corpas <[email protected]>
Tested-by: Roberto Bergantinos Corpas <[email protected]>
Signed-off-by: Benjamin Coddington <[email protected]>
---
fs/lockd/svc4proc.c | 4 +++-
fs/lockd/svclock.c | 10 +---------
fs/lockd/svcproc.c | 5 ++++-
include/linux/lockd/lockd.h | 1 +
4 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index 176b468a61c7..4f247ab8be61 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -87,6 +87,7 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
struct nlm_args *argp = rqstp->rq_argp;
struct nlm_host *host;
struct nlm_file *file;
+ struct nlm_lockowner *test_owner;
__be32 rc = rpc_success;

dprintk("lockd: TEST4 called\n");
@@ -96,6 +97,7 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;

+ test_owner = argp->lock.fl.fl_owner;
/* Now check for conflicting locks */
resp->status = nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie);
if (resp->status == nlm_drop_reply)
@@ -103,7 +105,7 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
else
dprintk("lockd: TEST4 status %d\n", ntohl(resp->status));

- nlmsvc_release_lockowner(&argp->lock);
+ nlmsvc_put_lockowner(test_owner);
nlmsvc_release_host(host);
nlm_release_file(file);
return rc;
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index cb3658ab9b7a..9c1aa75441e1 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -340,7 +340,7 @@ nlmsvc_get_lockowner(struct nlm_lockowner *lockowner)
return lockowner;
}

-static void nlmsvc_put_lockowner(struct nlm_lockowner *lockowner)
+void nlmsvc_put_lockowner(struct nlm_lockowner *lockowner)
{
if (!refcount_dec_and_lock(&lockowner->count, &lockowner->host->h_lock))
return;
@@ -590,7 +590,6 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
int error;
int mode;
__be32 ret;
- struct nlm_lockowner *test_owner;

dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n",
nlmsvc_file_inode(file)->i_sb->s_id,
@@ -604,9 +603,6 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
goto out;
}

- /* If there's a conflicting lock, remember to clean up the test lock */
- test_owner = (struct nlm_lockowner *)lock->fl.fl_owner;
-
mode = lock_to_openmode(&lock->fl);
error = vfs_test_lock(file->f_file[mode], &lock->fl);
if (error) {
@@ -635,10 +631,6 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
conflock->fl.fl_end = lock->fl.fl_end;
locks_release_private(&lock->fl);

- /* Clean up the test lock */
- lock->fl.fl_owner = NULL;
- nlmsvc_put_lockowner(test_owner);
-
ret = nlm_lck_denied;
out:
return ret;
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 4dc1b40a489a..b09ca35b527c 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -116,6 +116,7 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
struct nlm_args *argp = rqstp->rq_argp;
struct nlm_host *host;
struct nlm_file *file;
+ struct nlm_lockowner *test_owner;
__be32 rc = rpc_success;

dprintk("lockd: TEST called\n");
@@ -125,6 +126,8 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;

+ test_owner = argp->lock.fl.fl_owner;
+
/* Now check for conflicting locks */
resp->status = cast_status(nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie));
if (resp->status == nlm_drop_reply)
@@ -133,7 +136,7 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
dprintk("lockd: TEST status %d vers %d\n",
ntohl(resp->status), rqstp->rq_vers);

- nlmsvc_release_lockowner(&argp->lock);
+ nlmsvc_put_lockowner(test_owner);
nlmsvc_release_host(host);
nlm_release_file(file);
return rc;
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index fcef192e5e45..70ce419e2709 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -292,6 +292,7 @@ void nlmsvc_locks_init_private(struct file_lock *, struct nlm_host *, pid_t);
__be32 nlm_lookup_file(struct svc_rqst *, struct nlm_file **,
struct nlm_lock *);
void nlm_release_file(struct nlm_file *);
+void nlmsvc_put_lockowner(struct nlm_lockowner *);
void nlmsvc_release_lockowner(struct nlm_lock *);
void nlmsvc_mark_resources(struct net *);
void nlmsvc_free_host_resources(struct nlm_host *);
--
2.31.1


2022-06-13 20:09:47

by Chuck Lever

[permalink] [raw]
Subject: Re: [PATCH] NLM: Defend against file_lock changes after vfs_test_lock()



> On Jun 13, 2022, at 9:40 AM, Benjamin Coddington <[email protected]> wrote:
>
> Instead of trusting that struct file_lock returns completely unchanged
> after vfs_test_lock() when there's no conflicting lock, stash away our
> nlm_lockowner reference so we can properly release it for all cases.
>
> This defends against another file_lock implementation overwriting fl_owner
> when the return type is F_UNLCK.
>
> Reported-by: Roberto Bergantinos Corpas <[email protected]>
> Tested-by: Roberto Bergantinos Corpas <[email protected]>
> Signed-off-by: Benjamin Coddington <[email protected]>

LGTM. Applied internally for more testing. Comment period
still open.


> ---
> fs/lockd/svc4proc.c | 4 +++-
> fs/lockd/svclock.c | 10 +---------
> fs/lockd/svcproc.c | 5 ++++-
> include/linux/lockd/lockd.h | 1 +
> 4 files changed, 9 insertions(+), 11 deletions(-)
>
> diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
> index 176b468a61c7..4f247ab8be61 100644
> --- a/fs/lockd/svc4proc.c
> +++ b/fs/lockd/svc4proc.c
> @@ -87,6 +87,7 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
> struct nlm_args *argp = rqstp->rq_argp;
> struct nlm_host *host;
> struct nlm_file *file;
> + struct nlm_lockowner *test_owner;
> __be32 rc = rpc_success;
>
> dprintk("lockd: TEST4 called\n");
> @@ -96,6 +97,7 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
> if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
> return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
>
> + test_owner = argp->lock.fl.fl_owner;
> /* Now check for conflicting locks */
> resp->status = nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie);
> if (resp->status == nlm_drop_reply)
> @@ -103,7 +105,7 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
> else
> dprintk("lockd: TEST4 status %d\n", ntohl(resp->status));
>
> - nlmsvc_release_lockowner(&argp->lock);
> + nlmsvc_put_lockowner(test_owner);
> nlmsvc_release_host(host);
> nlm_release_file(file);
> return rc;
> diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
> index cb3658ab9b7a..9c1aa75441e1 100644
> --- a/fs/lockd/svclock.c
> +++ b/fs/lockd/svclock.c
> @@ -340,7 +340,7 @@ nlmsvc_get_lockowner(struct nlm_lockowner *lockowner)
> return lockowner;
> }
>
> -static void nlmsvc_put_lockowner(struct nlm_lockowner *lockowner)
> +void nlmsvc_put_lockowner(struct nlm_lockowner *lockowner)
> {
> if (!refcount_dec_and_lock(&lockowner->count, &lockowner->host->h_lock))
> return;
> @@ -590,7 +590,6 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
> int error;
> int mode;
> __be32 ret;
> - struct nlm_lockowner *test_owner;
>
> dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n",
> nlmsvc_file_inode(file)->i_sb->s_id,
> @@ -604,9 +603,6 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
> goto out;
> }
>
> - /* If there's a conflicting lock, remember to clean up the test lock */
> - test_owner = (struct nlm_lockowner *)lock->fl.fl_owner;
> -
> mode = lock_to_openmode(&lock->fl);
> error = vfs_test_lock(file->f_file[mode], &lock->fl);
> if (error) {
> @@ -635,10 +631,6 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
> conflock->fl.fl_end = lock->fl.fl_end;
> locks_release_private(&lock->fl);
>
> - /* Clean up the test lock */
> - lock->fl.fl_owner = NULL;
> - nlmsvc_put_lockowner(test_owner);
> -
> ret = nlm_lck_denied;
> out:
> return ret;
> diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
> index 4dc1b40a489a..b09ca35b527c 100644
> --- a/fs/lockd/svcproc.c
> +++ b/fs/lockd/svcproc.c
> @@ -116,6 +116,7 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
> struct nlm_args *argp = rqstp->rq_argp;
> struct nlm_host *host;
> struct nlm_file *file;
> + struct nlm_lockowner *test_owner;
> __be32 rc = rpc_success;
>
> dprintk("lockd: TEST called\n");
> @@ -125,6 +126,8 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
> if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
> return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
>
> + test_owner = argp->lock.fl.fl_owner;
> +
> /* Now check for conflicting locks */
> resp->status = cast_status(nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie));
> if (resp->status == nlm_drop_reply)
> @@ -133,7 +136,7 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
> dprintk("lockd: TEST status %d vers %d\n",
> ntohl(resp->status), rqstp->rq_vers);
>
> - nlmsvc_release_lockowner(&argp->lock);
> + nlmsvc_put_lockowner(test_owner);
> nlmsvc_release_host(host);
> nlm_release_file(file);
> return rc;
> diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
> index fcef192e5e45..70ce419e2709 100644
> --- a/include/linux/lockd/lockd.h
> +++ b/include/linux/lockd/lockd.h
> @@ -292,6 +292,7 @@ void nlmsvc_locks_init_private(struct file_lock *, struct nlm_host *, pid_t);
> __be32 nlm_lookup_file(struct svc_rqst *, struct nlm_file **,
> struct nlm_lock *);
> void nlm_release_file(struct nlm_file *);
> +void nlmsvc_put_lockowner(struct nlm_lockowner *);
> void nlmsvc_release_lockowner(struct nlm_lock *);
> void nlmsvc_mark_resources(struct net *);
> void nlmsvc_free_host_resources(struct nlm_host *);
> --
> 2.31.1
>

--
Chuck Lever



2022-06-27 13:00:50

by David Wysochanski

[permalink] [raw]
Subject: Re: [PATCH] NLM: Defend against file_lock changes after vfs_test_lock()

On Mon, Jun 13, 2022 at 4:01 PM Chuck Lever III <[email protected]> wrote:
>
>
>
> > On Jun 13, 2022, at 9:40 AM, Benjamin Coddington <[email protected]> wrote:
> >
> > Instead of trusting that struct file_lock returns completely unchanged
> > after vfs_test_lock() when there's no conflicting lock, stash away our
> > nlm_lockowner reference so we can properly release it for all cases.
> >
> > This defends against another file_lock implementation overwriting fl_owner
> > when the return type is F_UNLCK.
> >
> > Reported-by: Roberto Bergantinos Corpas <[email protected]>
> > Tested-by: Roberto Bergantinos Corpas <[email protected]>
> > Signed-off-by: Benjamin Coddington <[email protected]>
>
> LGTM. Applied internally for more testing. Comment period
> still open.
>

Chuck,

Are you planning to take this in the next merge window, or what is the
status of this patch?


>
> > ---
> > fs/lockd/svc4proc.c | 4 +++-
> > fs/lockd/svclock.c | 10 +---------
> > fs/lockd/svcproc.c | 5 ++++-
> > include/linux/lockd/lockd.h | 1 +
> > 4 files changed, 9 insertions(+), 11 deletions(-)
> >
> > diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
> > index 176b468a61c7..4f247ab8be61 100644
> > --- a/fs/lockd/svc4proc.c
> > +++ b/fs/lockd/svc4proc.c
> > @@ -87,6 +87,7 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
> > struct nlm_args *argp = rqstp->rq_argp;
> > struct nlm_host *host;
> > struct nlm_file *file;
> > + struct nlm_lockowner *test_owner;
> > __be32 rc = rpc_success;
> >
> > dprintk("lockd: TEST4 called\n");
> > @@ -96,6 +97,7 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
> > if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
> > return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
> >
> > + test_owner = argp->lock.fl.fl_owner;
> > /* Now check for conflicting locks */
> > resp->status = nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie);
> > if (resp->status == nlm_drop_reply)
> > @@ -103,7 +105,7 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
> > else
> > dprintk("lockd: TEST4 status %d\n", ntohl(resp->status));
> >
> > - nlmsvc_release_lockowner(&argp->lock);
> > + nlmsvc_put_lockowner(test_owner);
> > nlmsvc_release_host(host);
> > nlm_release_file(file);
> > return rc;
> > diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
> > index cb3658ab9b7a..9c1aa75441e1 100644
> > --- a/fs/lockd/svclock.c
> > +++ b/fs/lockd/svclock.c
> > @@ -340,7 +340,7 @@ nlmsvc_get_lockowner(struct nlm_lockowner *lockowner)
> > return lockowner;
> > }
> >
> > -static void nlmsvc_put_lockowner(struct nlm_lockowner *lockowner)
> > +void nlmsvc_put_lockowner(struct nlm_lockowner *lockowner)
> > {
> > if (!refcount_dec_and_lock(&lockowner->count, &lockowner->host->h_lock))
> > return;
> > @@ -590,7 +590,6 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
> > int error;
> > int mode;
> > __be32 ret;
> > - struct nlm_lockowner *test_owner;
> >
> > dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n",
> > nlmsvc_file_inode(file)->i_sb->s_id,
> > @@ -604,9 +603,6 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
> > goto out;
> > }
> >
> > - /* If there's a conflicting lock, remember to clean up the test lock */
> > - test_owner = (struct nlm_lockowner *)lock->fl.fl_owner;
> > -
> > mode = lock_to_openmode(&lock->fl);
> > error = vfs_test_lock(file->f_file[mode], &lock->fl);
> > if (error) {
> > @@ -635,10 +631,6 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
> > conflock->fl.fl_end = lock->fl.fl_end;
> > locks_release_private(&lock->fl);
> >
> > - /* Clean up the test lock */
> > - lock->fl.fl_owner = NULL;
> > - nlmsvc_put_lockowner(test_owner);
> > -
> > ret = nlm_lck_denied;
> > out:
> > return ret;
> > diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
> > index 4dc1b40a489a..b09ca35b527c 100644
> > --- a/fs/lockd/svcproc.c
> > +++ b/fs/lockd/svcproc.c
> > @@ -116,6 +116,7 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
> > struct nlm_args *argp = rqstp->rq_argp;
> > struct nlm_host *host;
> > struct nlm_file *file;
> > + struct nlm_lockowner *test_owner;
> > __be32 rc = rpc_success;
> >
> > dprintk("lockd: TEST called\n");
> > @@ -125,6 +126,8 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
> > if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
> > return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
> >
> > + test_owner = argp->lock.fl.fl_owner;
> > +
> > /* Now check for conflicting locks */
> > resp->status = cast_status(nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie));
> > if (resp->status == nlm_drop_reply)
> > @@ -133,7 +136,7 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
> > dprintk("lockd: TEST status %d vers %d\n",
> > ntohl(resp->status), rqstp->rq_vers);
> >
> > - nlmsvc_release_lockowner(&argp->lock);
> > + nlmsvc_put_lockowner(test_owner);
> > nlmsvc_release_host(host);
> > nlm_release_file(file);
> > return rc;
> > diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
> > index fcef192e5e45..70ce419e2709 100644
> > --- a/include/linux/lockd/lockd.h
> > +++ b/include/linux/lockd/lockd.h
> > @@ -292,6 +292,7 @@ void nlmsvc_locks_init_private(struct file_lock *, struct nlm_host *, pid_t);
> > __be32 nlm_lookup_file(struct svc_rqst *, struct nlm_file **,
> > struct nlm_lock *);
> > void nlm_release_file(struct nlm_file *);
> > +void nlmsvc_put_lockowner(struct nlm_lockowner *);
> > void nlmsvc_release_lockowner(struct nlm_lock *);
> > void nlmsvc_mark_resources(struct net *);
> > void nlmsvc_free_host_resources(struct nlm_host *);
> > --
> > 2.31.1
> >
>
> --
> Chuck Lever
>
>
>

2022-06-27 14:01:58

by Chuck Lever

[permalink] [raw]
Subject: Re: [PATCH] NLM: Defend against file_lock changes after vfs_test_lock()



> On Jun 27, 2022, at 8:48 AM, David Wysochanski <[email protected]> wrote:
>
> On Mon, Jun 13, 2022 at 4:01 PM Chuck Lever III <[email protected]> wrote:
>>
>>
>>
>>> On Jun 13, 2022, at 9:40 AM, Benjamin Coddington <[email protected]> wrote:
>>>
>>> Instead of trusting that struct file_lock returns completely unchanged
>>> after vfs_test_lock() when there's no conflicting lock, stash away our
>>> nlm_lockowner reference so we can properly release it for all cases.
>>>
>>> This defends against another file_lock implementation overwriting fl_owner
>>> when the return type is F_UNLCK.
>>>
>>> Reported-by: Roberto Bergantinos Corpas <[email protected]>
>>> Tested-by: Roberto Bergantinos Corpas <[email protected]>
>>> Signed-off-by: Benjamin Coddington <[email protected]>
>>
>> LGTM. Applied internally for more testing. Comment period
>> still open.
>>
>
> Chuck,
>
> Are you planning to take this in the next merge window, or what is the
> status of this patch?

It is destined for the next merge window. It will appear in the
for-next branch here:

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

In a week or two.


>>> ---
>>> fs/lockd/svc4proc.c | 4 +++-
>>> fs/lockd/svclock.c | 10 +---------
>>> fs/lockd/svcproc.c | 5 ++++-
>>> include/linux/lockd/lockd.h | 1 +
>>> 4 files changed, 9 insertions(+), 11 deletions(-)
>>>
>>> diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
>>> index 176b468a61c7..4f247ab8be61 100644
>>> --- a/fs/lockd/svc4proc.c
>>> +++ b/fs/lockd/svc4proc.c
>>> @@ -87,6 +87,7 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
>>> struct nlm_args *argp = rqstp->rq_argp;
>>> struct nlm_host *host;
>>> struct nlm_file *file;
>>> + struct nlm_lockowner *test_owner;
>>> __be32 rc = rpc_success;
>>>
>>> dprintk("lockd: TEST4 called\n");
>>> @@ -96,6 +97,7 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
>>> if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
>>> return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
>>>
>>> + test_owner = argp->lock.fl.fl_owner;
>>> /* Now check for conflicting locks */
>>> resp->status = nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie);
>>> if (resp->status == nlm_drop_reply)
>>> @@ -103,7 +105,7 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
>>> else
>>> dprintk("lockd: TEST4 status %d\n", ntohl(resp->status));
>>>
>>> - nlmsvc_release_lockowner(&argp->lock);
>>> + nlmsvc_put_lockowner(test_owner);
>>> nlmsvc_release_host(host);
>>> nlm_release_file(file);
>>> return rc;
>>> diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
>>> index cb3658ab9b7a..9c1aa75441e1 100644
>>> --- a/fs/lockd/svclock.c
>>> +++ b/fs/lockd/svclock.c
>>> @@ -340,7 +340,7 @@ nlmsvc_get_lockowner(struct nlm_lockowner *lockowner)
>>> return lockowner;
>>> }
>>>
>>> -static void nlmsvc_put_lockowner(struct nlm_lockowner *lockowner)
>>> +void nlmsvc_put_lockowner(struct nlm_lockowner *lockowner)
>>> {
>>> if (!refcount_dec_and_lock(&lockowner->count, &lockowner->host->h_lock))
>>> return;
>>> @@ -590,7 +590,6 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
>>> int error;
>>> int mode;
>>> __be32 ret;
>>> - struct nlm_lockowner *test_owner;
>>>
>>> dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n",
>>> nlmsvc_file_inode(file)->i_sb->s_id,
>>> @@ -604,9 +603,6 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
>>> goto out;
>>> }
>>>
>>> - /* If there's a conflicting lock, remember to clean up the test lock */
>>> - test_owner = (struct nlm_lockowner *)lock->fl.fl_owner;
>>> -
>>> mode = lock_to_openmode(&lock->fl);
>>> error = vfs_test_lock(file->f_file[mode], &lock->fl);
>>> if (error) {
>>> @@ -635,10 +631,6 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
>>> conflock->fl.fl_end = lock->fl.fl_end;
>>> locks_release_private(&lock->fl);
>>>
>>> - /* Clean up the test lock */
>>> - lock->fl.fl_owner = NULL;
>>> - nlmsvc_put_lockowner(test_owner);
>>> -
>>> ret = nlm_lck_denied;
>>> out:
>>> return ret;
>>> diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
>>> index 4dc1b40a489a..b09ca35b527c 100644
>>> --- a/fs/lockd/svcproc.c
>>> +++ b/fs/lockd/svcproc.c
>>> @@ -116,6 +116,7 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
>>> struct nlm_args *argp = rqstp->rq_argp;
>>> struct nlm_host *host;
>>> struct nlm_file *file;
>>> + struct nlm_lockowner *test_owner;
>>> __be32 rc = rpc_success;
>>>
>>> dprintk("lockd: TEST called\n");
>>> @@ -125,6 +126,8 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
>>> if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
>>> return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
>>>
>>> + test_owner = argp->lock.fl.fl_owner;
>>> +
>>> /* Now check for conflicting locks */
>>> resp->status = cast_status(nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie));
>>> if (resp->status == nlm_drop_reply)
>>> @@ -133,7 +136,7 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
>>> dprintk("lockd: TEST status %d vers %d\n",
>>> ntohl(resp->status), rqstp->rq_vers);
>>>
>>> - nlmsvc_release_lockowner(&argp->lock);
>>> + nlmsvc_put_lockowner(test_owner);
>>> nlmsvc_release_host(host);
>>> nlm_release_file(file);
>>> return rc;
>>> diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
>>> index fcef192e5e45..70ce419e2709 100644
>>> --- a/include/linux/lockd/lockd.h
>>> +++ b/include/linux/lockd/lockd.h
>>> @@ -292,6 +292,7 @@ void nlmsvc_locks_init_private(struct file_lock *, struct nlm_host *, pid_t);
>>> __be32 nlm_lookup_file(struct svc_rqst *, struct nlm_file **,
>>> struct nlm_lock *);
>>> void nlm_release_file(struct nlm_file *);
>>> +void nlmsvc_put_lockowner(struct nlm_lockowner *);
>>> void nlmsvc_release_lockowner(struct nlm_lock *);
>>> void nlmsvc_mark_resources(struct net *);
>>> void nlmsvc_free_host_resources(struct nlm_host *);
>>> --
>>> 2.31.1
>>>
>>
>> --
>> Chuck Lever

--
Chuck Lever