Merge tag 'nfsd-5.17-1' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 2 Feb 2022 18:14:31 +0000 (10:14 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 2 Feb 2022 18:14:31 +0000 (10:14 -0800)
Pull nfsd fixes from Chuck Lever:
 "Notable bug fixes:

   - Ensure SM_NOTIFY doesn't crash the NFS server host

   - Ensure NLM locks are cleaned up after client reboot

   - Fix a leak of internal NFSv4 lease information"

* tag 'nfsd-5.17-1' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux:
  nfsd: nfsd4_setclientid_confirm mistakenly expires confirmed client.
  lockd: fix failure to cleanup client locks
  lockd: fix server crash on reboot of client holding lock

fs/lockd/svcsubs.c
fs/nfsd/nfs4state.c

index cb3a751..0a22a2f 100644 (file)
@@ -179,19 +179,21 @@ nlm_delete_file(struct nlm_file *file)
 static int nlm_unlock_files(struct nlm_file *file)
 {
        struct file_lock lock;
-       struct file *f;
 
+       locks_init_lock(&lock);
        lock.fl_type  = F_UNLCK;
        lock.fl_start = 0;
        lock.fl_end   = OFFSET_MAX;
-       for (f = file->f_file[0]; f <= file->f_file[1]; f++) {
-               if (f && vfs_lock_file(f, F_SETLK, &lock, NULL) < 0) {
-                       pr_warn("lockd: unlock failure in %s:%d\n",
-                               __FILE__, __LINE__);
-                       return 1;
-               }
-       }
+       if (file->f_file[O_RDONLY] &&
+           vfs_lock_file(file->f_file[O_RDONLY], 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))
+               goto out_err;
        return 0;
+out_err:
+       pr_warn("lockd: unlock failure in %s:%d\n", __FILE__, __LINE__);
+       return 1;
 }
 
 /*
index 72900b8..3206373 100644 (file)
@@ -4130,8 +4130,10 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
                        status = nfserr_clid_inuse;
                        if (client_has_state(old)
                                        && !same_creds(&unconf->cl_cred,
-                                                       &old->cl_cred))
+                                                       &old->cl_cred)) {
+                               old = NULL;
                                goto out;
+                       }
                        status = mark_client_expired_locked(old);
                        if (status) {
                                old = NULL;