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 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?


>
> > ---
> > 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
>
>
>




[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