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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




> On Jun 27, 2022, at 8:48 AM, David Wysochanski <dwysocha@xxxxxxxxxx> wrote:
> 
> On Mon, Jun 13, 2022 at 4:01 PM Chuck Lever III <chuck.lever@xxxxxxxxxx> wrote:
>> 
>> 
>> 
>>> On Jun 13, 2022, at 9:40 AM, Benjamin Coddington <bcodding@xxxxxxxxxx> 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 <rbergant@xxxxxxxxxx>
>>> Tested-by: Roberto Bergantinos Corpas <rbergant@xxxxxxxxxx>
>>> Signed-off-by: Benjamin Coddington <bcodding@xxxxxxxxxx>
>> 
>> 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







[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux