lockd: set other missing fields when unlocking files
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Sun, 6 Nov 2022 19:02:39 +0000 (14:02 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 31 Dec 2022 12:32:00 +0000 (13:32 +0100)
[ Upstream commit 18ebd35b61b4693a0ddc270b6d4f18def232e770 ]

vfs_lock_file() expects the struct file_lock to be fully initialised by
the caller. Re-exported NFSv3 has been seen to Oops if the fl_file field
is NULL.

Fixes: aec158242b87 ("lockd: set fl_owner when unlocking files")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=216582
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/lockd/svcsubs.c

index e1c4617..3515f17 100644 (file)
@@ -176,7 +176,7 @@ nlm_delete_file(struct nlm_file *file)
        }
 }
 
-static int nlm_unlock_files(struct nlm_file *file, fl_owner_t owner)
+static int nlm_unlock_files(struct nlm_file *file, const struct file_lock *fl)
 {
        struct file_lock lock;
 
@@ -184,12 +184,15 @@ static int nlm_unlock_files(struct nlm_file *file, fl_owner_t owner)
        lock.fl_type  = F_UNLCK;
        lock.fl_start = 0;
        lock.fl_end   = OFFSET_MAX;
-       lock.fl_owner = owner;
-       if (file->f_file[O_RDONLY] &&
-           vfs_lock_file(file->f_file[O_RDONLY], F_SETLK, &lock, NULL))
+       lock.fl_owner = fl->fl_owner;
+       lock.fl_pid   = fl->fl_pid;
+       lock.fl_flags = FL_POSIX;
+
+       lock.fl_file = file->f_file[O_RDONLY];
+       if (lock.fl_file && vfs_lock_file(lock.fl_file, F_SETLK, &lock, NULL))
                goto out_err;
-       if (file->f_file[O_WRONLY] &&
-           vfs_lock_file(file->f_file[O_WRONLY], F_SETLK, &lock, NULL))
+       lock.fl_file = file->f_file[O_WRONLY];
+       if (lock.fl_file && vfs_lock_file(lock.fl_file, F_SETLK, &lock, NULL))
                goto out_err;
        return 0;
 out_err:
@@ -226,7 +229,7 @@ again:
                if (match(lockhost, host)) {
 
                        spin_unlock(&flctx->flc_lock);
-                       if (nlm_unlock_files(file, fl->fl_owner))
+                       if (nlm_unlock_files(file, fl))
                                return 1;
                        goto again;
                }