]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
Merge tag 'pull-revalidate' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 30 Jan 2025 17:13:35 +0000 (09:13 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 30 Jan 2025 17:13:35 +0000 (09:13 -0800)
Pull vfs d_revalidate updates from Al Viro:
 "Provide stable parent and name to ->d_revalidate() instances

  Most of the filesystem methods where we care about dentry name and
  parent have their stability guaranteed by the callers;
  ->d_revalidate() is the major exception.

  It's easy enough for callers to supply stable values for expected name
  and expected parent of the dentry being validated. That kills quite a
  bit of boilerplate in ->d_revalidate() instances, along with a bunch
  of races where they used to access ->d_name without sufficient
  precautions"

* tag 'pull-revalidate' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  9p: fix ->rename_sem exclusion
  orangefs_d_revalidate(): use stable parent inode and name passed by caller
  ocfs2_dentry_revalidate(): use stable parent inode and name passed by caller
  nfs: fix ->d_revalidate() UAF on ->d_name accesses
  nfs{,4}_lookup_validate(): use stable parent inode passed by caller
  gfs2_drevalidate(): use stable parent inode and name passed by caller
  fuse_dentry_revalidate(): use stable parent inode and name passed by caller
  vfat_revalidate{,_ci}(): use stable parent inode passed by caller
  exfat_d_revalidate(): use stable parent inode passed by caller
  fscrypt_d_revalidate(): use stable parent inode passed by caller
  ceph_d_revalidate(): propagate stable name down into request encoding
  ceph_d_revalidate(): use stable parent inode passed by caller
  afs_d_revalidate(): use stable name and parent inode passed by caller
  Pass parent directory inode and expected name to ->d_revalidate()
  generic_ci_d_compare(): use shortname_storage
  ext4 fast_commit: make use of name_snapshot primitives
  dissolve external_name.u into separate members
  make take_dentry_name_snapshot() lockless
  dcache: back inline names with a struct-wrapped array of unsigned long
  make sure that DNAME_INLINE_LEN is a multiple of word size

13 files changed:
1  2 
Documentation/filesystems/porting.rst
fs/afs/dir.c
fs/ceph/mds_client.c
fs/dcache.c
fs/exfat/namei.c
fs/fuse/dir.c
fs/libfs.c
fs/namei.c
fs/nfs/nfs3proc.c
fs/nfs/nfs4proc.c
fs/proc/base.c
fs/smb/client/dir.c
include/linux/nfs_xdr.h

Simple merge
diff --cc fs/afs/dir.c
index a843c36fc471268502ee68688c555fcee5e7bd30,e04cffe4beb11fc9d08c857b9b589c2ef0f64b11..02cbf38e1a7762b95a97a31e4dcd1d8335c2df75
@@@ -597,8 -607,8 +598,8 @@@ static bool afs_lookup_one_filldir(stru
   * Do a lookup of a single name in a directory
   * - just returns the FID the dentry name maps to if found
   */
- static int afs_do_lookup_one(struct inode *dir, struct dentry *dentry,
+ static int afs_do_lookup_one(struct inode *dir, const struct qstr *name,
 -                           struct afs_fid *fid, struct key *key,
 +                           struct afs_fid *fid,
                             afs_dataversion_t *_dir_version)
  {
        struct afs_super_info *as = dir->i_sb->s_fs_info;
        };
        int ret;
  
-       _enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry);
+       _enter("{%lu},{%.*s},", dir->i_ino, name->len, name->name);
  
        /* search the directory */
 -      ret = afs_dir_iterate(dir, &cookie.ctx, key, _dir_version);
 +      ret = afs_dir_iterate(dir, &cookie.ctx, NULL, _dir_version);
        if (ret < 0) {
                _leave(" = %d [iter]", ret);
                return ret;
@@@ -1127,7 -1142,7 +1114,7 @@@ static int afs_d_revalidate(struct inod
        afs_stat_v(dir, n_reval);
  
        /* search the directory for this vnode */
-       ret = afs_do_lookup_one(&dir->netfs.inode, dentry, &fid, &dir_version);
 -      ret = afs_do_lookup_one(&dir->netfs.inode, name, &fid, key, &dir_version);
++      ret = afs_do_lookup_one(&dir->netfs.inode, name, &fid, &dir_version);
        switch (ret) {
        case 0:
                /* the filename maps to something */
Simple merge
diff --cc fs/dcache.c
Simple merge
Simple merge
diff --cc fs/fuse/dir.c
index be693a8a10109d1ceeeebaf1976b42cb33dc1ffc,3019bc1d9f9de4018b078963a6cfccfb61dd9308..198862b086ff7bad4007ec2f3200377d12a78385
@@@ -175,10 -175,11 +175,12 @@@ static void fuse_lookup_init(struct fus
        memset(outarg, 0, sizeof(struct fuse_entry_out));
        args->opcode = FUSE_LOOKUP;
        args->nodeid = nodeid;
--      args->in_numargs = 2;
 -      args->in_args[0].size = name->len;
 -      args->in_args[0].value = name->name;
 -      args->in_args[1].size = 1;
 -      args->in_args[1].value = "";
++      args->in_numargs = 3;
 +      fuse_set_zero_arg0(args);
-       args->in_args[1].size = name->len + 1;
++      args->in_args[1].size = name->len;
 +      args->in_args[1].value = name->name;
++      args->in_args[2].size = 1;
++      args->in_args[2].value = "";
        args->out_numargs = 1;
        args->out_args[0].size = sizeof(struct fuse_entry_out);
        args->out_args[0].value = outarg;
diff --cc fs/libfs.c
Simple merge
diff --cc fs/namei.c
Simple merge
Simple merge
Simple merge
diff --cc fs/proc/base.c
Simple merge
Simple merge
Simple merge