Merge tag 'nfsd-6.3-2' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 10 Mar 2023 16:45:30 +0000 (08:45 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 10 Mar 2023 16:45:30 +0000 (08:45 -0800)
Pull nfsd fixes from Chuck Lever:

 - Protect NFSD writes against filesystem freezing

 - Fix a potential memory leak during server shutdown

* tag 'nfsd-6.3-2' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux:
  SUNRPC: Fix a server shutdown leak
  NFSD: Protect against filesystem freezing

1  2 
fs/nfsd/vfs.c

diff --combined fs/nfsd/vfs.c
index e7462b5e5f1e2bacd845896c9f7a5635ccf74be0,ba34a31a7c7027f640949294f1a405a9f765ba45..502e1b7742dbf604e8a30f502f34292fb38ed1cc
@@@ -430,7 -430,7 +430,7 @@@ static int __nfsd_setattr(struct dentr
                if (iap->ia_size < 0)
                        return -EFBIG;
  
 -              host_err = notify_change(&init_user_ns, dentry, &size_attr, NULL);
 +              host_err = notify_change(&nop_mnt_idmap, dentry, &size_attr, NULL);
                if (host_err)
                        return host_err;
                iap->ia_valid &= ~ATTR_SIZE;
                return 0;
  
        iap->ia_valid |= ATTR_CTIME;
 -      return notify_change(&init_user_ns, dentry, iap, NULL);
 +      return notify_change(&nop_mnt_idmap, dentry, iap, NULL);
  }
  
  /**
@@@ -546,12 -546,12 +546,12 @@@ nfsd_setattr(struct svc_rqst *rqstp, st
                attr->na_labelerr = security_inode_setsecctx(dentry,
                        attr->na_seclabel->data, attr->na_seclabel->len);
        if (IS_ENABLED(CONFIG_FS_POSIX_ACL) && attr->na_pacl)
 -              attr->na_aclerr = set_posix_acl(&init_user_ns,
 +              attr->na_aclerr = set_posix_acl(&nop_mnt_idmap,
                                                dentry, ACL_TYPE_ACCESS,
                                                attr->na_pacl);
        if (IS_ENABLED(CONFIG_FS_POSIX_ACL) &&
            !attr->na_aclerr && attr->na_dpacl && S_ISDIR(inode->i_mode))
 -              attr->na_aclerr = set_posix_acl(&init_user_ns,
 +              attr->na_aclerr = set_posix_acl(&nop_mnt_idmap,
                                                dentry, ACL_TYPE_DEFAULT,
                                                attr->na_dpacl);
        inode_unlock(inode);
@@@ -587,7 -587,7 +587,7 @@@ int nfsd4_is_junction(struct dentry *de
                return 0;
        if (!(inode->i_mode & S_ISVTX))
                return 0;
 -      if (vfs_getxattr(&init_user_ns, dentry, NFSD_JUNCTION_XATTR_NAME,
 +      if (vfs_getxattr(&nop_mnt_idmap, dentry, NFSD_JUNCTION_XATTR_NAME,
                         NULL, 0) <= 0)
                return 0;
        return 1;
@@@ -1104,7 -1104,9 +1104,9 @@@ nfsd_vfs_write(struct svc_rqst *rqstp, 
        since = READ_ONCE(file->f_wb_err);
        if (verf)
                nfsd_copy_write_verifier(verf, nn);
+       file_start_write(file);
        host_err = vfs_iter_write(file, &iter, &pos, flags);
+       file_end_write(file);
        if (host_err < 0) {
                nfsd_reset_write_verifier(nn);
                trace_nfsd_writeverf_reset(nn, rqstp, host_err);
@@@ -1367,13 -1369,12 +1369,13 @@@ nfsd_create_locked(struct svc_rqst *rqs
        err = 0;
        switch (type) {
        case S_IFREG:
 -              host_err = vfs_create(&init_user_ns, dirp, dchild, iap->ia_mode, true);
 +              host_err = vfs_create(&nop_mnt_idmap, dirp, dchild,
 +                                    iap->ia_mode, true);
                if (!host_err)
                        nfsd_check_ignore_resizing(iap);
                break;
        case S_IFDIR:
 -              host_err = vfs_mkdir(&init_user_ns, dirp, dchild, iap->ia_mode);
 +              host_err = vfs_mkdir(&nop_mnt_idmap, dirp, dchild, iap->ia_mode);
                if (!host_err && unlikely(d_unhashed(dchild))) {
                        struct dentry *d;
                        d = lookup_one_len(dchild->d_name.name,
        case S_IFBLK:
        case S_IFIFO:
        case S_IFSOCK:
 -              host_err = vfs_mknod(&init_user_ns, dirp, dchild,
 +              host_err = vfs_mknod(&nop_mnt_idmap, dirp, dchild,
                                     iap->ia_mode, rdev);
                break;
        default:
@@@ -1562,7 -1563,7 +1564,7 @@@ nfsd_symlink(struct svc_rqst *rqstp, st
                goto out_drop_write;
        }
        fh_fill_pre_attrs(fhp);
 -      host_err = vfs_symlink(&init_user_ns, d_inode(dentry), dnew, path);
 +      host_err = vfs_symlink(&nop_mnt_idmap, d_inode(dentry), dnew, path);
        err = nfserrno(host_err);
        cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp);
        if (!err)
@@@ -1630,7 -1631,7 +1632,7 @@@ nfsd_link(struct svc_rqst *rqstp, struc
        if (d_really_is_negative(dold))
                goto out_dput;
        fh_fill_pre_attrs(ffhp);
 -      host_err = vfs_link(dold, &init_user_ns, dirp, dnew, NULL);
 +      host_err = vfs_link(dold, &nop_mnt_idmap, dirp, dnew, NULL);
        fh_fill_post_attrs(ffhp);
        inode_unlock(dirp);
        if (!host_err) {
@@@ -1750,10 -1751,10 +1752,10 @@@ retry
                goto out_dput_old;
        } else {
                struct renamedata rd = {
 -                      .old_mnt_userns = &init_user_ns,
 +                      .old_mnt_idmap  = &nop_mnt_idmap,
                        .old_dir        = fdir,
                        .old_dentry     = odentry,
 -                      .new_mnt_userns = &init_user_ns,
 +                      .new_mnt_idmap  = &nop_mnt_idmap,
                        .new_dir        = tdir,
                        .new_dentry     = ndentry,
                };
@@@ -1855,14 -1856,14 +1857,14 @@@ nfsd_unlink(struct svc_rqst *rqstp, str
                        nfsd_close_cached_files(rdentry);
  
                for (retries = 1;;) {
 -                      host_err = vfs_unlink(&init_user_ns, dirp, rdentry, NULL);
 +                      host_err = vfs_unlink(&nop_mnt_idmap, dirp, rdentry, NULL);
                        if (host_err != -EAGAIN || !retries--)
                                break;
                        if (!nfsd_wait_for_delegreturn(rqstp, rinode))
                                break;
                }
        } else {
 -              host_err = vfs_rmdir(&init_user_ns, dirp, rdentry);
 +              host_err = vfs_rmdir(&nop_mnt_idmap, dirp, rdentry);
        }
        fh_fill_post_attrs(fhp);
  
@@@ -2134,7 -2135,7 +2136,7 @@@ nfsd_getxattr(struct svc_rqst *rqstp, s
  
        inode_lock_shared(inode);
  
 -      len = vfs_getxattr(&init_user_ns, dentry, name, NULL, 0);
 +      len = vfs_getxattr(&nop_mnt_idmap, dentry, name, NULL, 0);
  
        /*
         * Zero-length attribute, just return.
                goto out;
        }
  
 -      len = vfs_getxattr(&init_user_ns, dentry, name, buf, len);
 +      len = vfs_getxattr(&nop_mnt_idmap, dentry, name, buf, len);
        if (len <= 0) {
                kvfree(buf);
                buf = NULL;
@@@ -2272,7 -2273,7 +2274,7 @@@ nfsd_removexattr(struct svc_rqst *rqstp
        inode_lock(fhp->fh_dentry->d_inode);
        fh_fill_pre_attrs(fhp);
  
 -      ret = __vfs_removexattr_locked(&init_user_ns, fhp->fh_dentry,
 +      ret = __vfs_removexattr_locked(&nop_mnt_idmap, fhp->fh_dentry,
                                       name, NULL);
  
        fh_fill_post_attrs(fhp);
@@@ -2299,7 -2300,7 +2301,7 @@@ nfsd_setxattr(struct svc_rqst *rqstp, s
        inode_lock(fhp->fh_dentry->d_inode);
        fh_fill_pre_attrs(fhp);
  
 -      ret = __vfs_setxattr_locked(&init_user_ns, fhp->fh_dentry, name, buf,
 +      ret = __vfs_setxattr_locked(&nop_mnt_idmap, fhp->fh_dentry, name, buf,
                                    len, flags, NULL);
        fh_fill_post_attrs(fhp);
        inode_unlock(fhp->fh_dentry->d_inode);
@@@ -2383,14 -2384,14 +2385,14 @@@ nfsd_permission(struct svc_rqst *rqstp
                return 0;
  
        /* This assumes  NFSD_MAY_{READ,WRITE,EXEC} == MAY_{READ,WRITE,EXEC} */
 -      err = inode_permission(&init_user_ns, inode,
 +      err = inode_permission(&nop_mnt_idmap, inode,
                               acc & (MAY_READ | MAY_WRITE | MAY_EXEC));
  
        /* Allow read access to binaries even when mode 111 */
        if (err == -EACCES && S_ISREG(inode->i_mode) &&
             (acc == (NFSD_MAY_READ | NFSD_MAY_OWNER_OVERRIDE) ||
              acc == (NFSD_MAY_READ | NFSD_MAY_READ_IF_EXEC)))
 -              err = inode_permission(&init_user_ns, inode, MAY_EXEC);
 +              err = inode_permission(&nop_mnt_idmap, inode, MAY_EXEC);
  
        return err? nfserrno(err) : 0;
  }