]> Git Repo - linux.git/commitdiff
Merge tag 'fsnotify_for_v6.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <[email protected]>
Thu, 29 Jun 2023 20:31:44 +0000 (13:31 -0700)
committerLinus Torvalds <[email protected]>
Thu, 29 Jun 2023 20:31:44 +0000 (13:31 -0700)
Pull fsnotify updates from Jan Kara:

 - Support for fanotify events returning file handles for filesystems
   not exportable via NFS

 - Improved error handling exportfs functions

 - Add missing FS_OPEN events when unusual open helpers are used

* tag 'fsnotify_for_v6.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
  fsnotify: move fsnotify_open() hook into do_dentry_open()
  exportfs: check for error return value from exportfs_encode_*()
  fanotify: support reporting non-decodeable file handles
  exportfs: allow exporting non-decodeable file handles to userspace
  exportfs: add explicit flag to request non-decodeable file handles
  exportfs: change connectable argument to bit flags

1  2 
fs/exec.c
fs/nfsd/nfsfh.c
fs/open.c

diff --combined fs/exec.c
index 80b8611c416d3250fa86d859ad5515ed12b5a813,238473de1ec5382091dbf37b97dbabe30ce7c43a..1a827d55ba9475463eeeffa951cc243676442c58
+++ b/fs/exec.c
@@@ -152,8 -152,6 +152,6 @@@ SYSCALL_DEFINE1(uselib, const char __us
                         path_noexec(&file->f_path)))
                goto exit;
  
-       fsnotify_open(file);
        error = -ENOEXEC;
  
        read_lock(&binfmt_lock);
@@@ -200,39 -198,33 +198,39 @@@ static struct page *get_arg_page(struc
                int write)
  {
        struct page *page;
 +      struct vm_area_struct *vma = bprm->vma;
 +      struct mm_struct *mm = bprm->mm;
        int ret;
 -      unsigned int gup_flags = 0;
  
 -#ifdef CONFIG_STACK_GROWSUP
 -      if (write) {
 -              ret = expand_downwards(bprm->vma, pos);
 -              if (ret < 0)
 +      /*
 +       * Avoid relying on expanding the stack down in GUP (which
 +       * does not work for STACK_GROWSUP anyway), and just do it
 +       * by hand ahead of time.
 +       */
 +      if (write && pos < vma->vm_start) {
 +              mmap_write_lock(mm);
 +              ret = expand_downwards(vma, pos);
 +              if (unlikely(ret < 0)) {
 +                      mmap_write_unlock(mm);
                        return NULL;
 -      }
 -#endif
 -
 -      if (write)
 -              gup_flags |= FOLL_WRITE;
 +              }
 +              mmap_write_downgrade(mm);
 +      } else
 +              mmap_read_lock(mm);
  
        /*
         * We are doing an exec().  'current' is the process
 -       * doing the exec and bprm->mm is the new process's mm.
 +       * doing the exec and 'mm' is the new process's mm.
         */
 -      mmap_read_lock(bprm->mm);
 -      ret = get_user_pages_remote(bprm->mm, pos, 1, gup_flags,
 -                      &page, NULL, NULL);
 -      mmap_read_unlock(bprm->mm);
 +      ret = get_user_pages_remote(mm, pos, 1,
 +                      write ? FOLL_WRITE : 0,
 +                      &page, NULL);
 +      mmap_read_unlock(mm);
        if (ret <= 0)
                return NULL;
  
        if (write)
 -              acct_arg_size(bprm, vma_pages(bprm->vma));
 +              acct_arg_size(bprm, vma_pages(vma));
  
        return page;
  }
@@@ -859,7 -851,7 +857,7 @@@ int setup_arg_pages(struct linux_binpr
        stack_base = vma->vm_end - stack_expand;
  #endif
        current->mm->start_stack = bprm->p;
 -      ret = expand_stack(vma, stack_base);
 +      ret = expand_stack_locked(vma, stack_base);
        if (ret)
                ret = -EFAULT;
  
@@@ -940,9 -932,6 +938,6 @@@ static struct file *do_open_execat(int 
        if (err)
                goto exit;
  
-       if (name->name[0] != '\0')
-               fsnotify_open(file);
  out:
        return file;
  
diff --combined fs/nfsd/nfsfh.c
index e8e13ae72e3c55c86b7c399812ca8671c63bbabd,0f5eacae5f43ee1154714b94d4a513b51a67f517..c291389a1d71dd44e88185443f0dba7cb549aac7
@@@ -414,10 -414,13 +414,13 @@@ static void _fh_update(struct svc_fh *f
                struct fid *fid = (struct fid *)
                        (fhp->fh_handle.fh_fsid + fhp->fh_handle.fh_size/4 - 1);
                int maxsize = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4;
-               int subtreecheck = !(exp->ex_flags & NFSEXP_NOSUBTREECHECK);
+               int fh_flags = (exp->ex_flags & NFSEXP_NOSUBTREECHECK) ? 0 :
+                               EXPORT_FH_CONNECTABLE;
+               int fileid_type =
+                       exportfs_encode_fh(dentry, fid, &maxsize, fh_flags);
  
                fhp->fh_handle.fh_fileid_type =
-                       exportfs_encode_fh(dentry, fid, &maxsize, subtreecheck);
+                       fileid_type > 0 ? fileid_type : FILEID_INVALID;
                fhp->fh_handle.fh_size += maxsize * 4;
        } else {
                fhp->fh_handle.fh_fileid_type = FILEID_ROOT;
@@@ -623,9 -626,16 +626,9 @@@ void fh_fill_pre_attrs(struct svc_fh *f
  
        inode = d_inode(fhp->fh_dentry);
        err = fh_getattr(fhp, &stat);
 -      if (err) {
 -              /* Grab the times from inode anyway */
 -              stat.mtime = inode->i_mtime;
 -              stat.ctime = inode->i_ctime;
 -              stat.size  = inode->i_size;
 -              if (v4 && IS_I_VERSION(inode)) {
 -                      stat.change_cookie = inode_query_iversion(inode);
 -                      stat.result_mask |= STATX_CHANGE_COOKIE;
 -              }
 -      }
 +      if (err)
 +              return;
 +
        if (v4)
                fhp->fh_pre_change = nfsd4_change_attribute(&stat, inode);
  
@@@ -653,10 -663,15 +656,10 @@@ void fh_fill_post_attrs(struct svc_fh *
                printk("nfsd: inode locked twice during operation.\n");
  
        err = fh_getattr(fhp, &fhp->fh_post_attr);
 -      if (err) {
 -              fhp->fh_post_saved = false;
 -              fhp->fh_post_attr.ctime = inode->i_ctime;
 -              if (v4 && IS_I_VERSION(inode)) {
 -                      fhp->fh_post_attr.change_cookie = inode_query_iversion(inode);
 -                      fhp->fh_post_attr.result_mask |= STATX_CHANGE_COOKIE;
 -              }
 -      } else
 -              fhp->fh_post_saved = true;
 +      if (err)
 +              return;
 +
 +      fhp->fh_post_saved = true;
        if (v4)
                fhp->fh_post_change =
                        nfsd4_change_attribute(&fhp->fh_post_attr, inode);
diff --combined fs/open.c
index fb07b2840eb4008a5a934cb0656d589211e69d4d,005ca91a173bd7e3534280f5eded980cfffbd475..0c55c8e7f837d8ef03ab19b5645b40401205ee42
+++ b/fs/open.c
@@@ -700,7 -700,10 +700,7 @@@ SYSCALL_DEFINE2(chmod, const char __use
        return do_fchmodat(AT_FDCWD, filename, mode);
  }
  
 -/**
 - * setattr_vfsuid - check and set ia_fsuid attribute
 - * @kuid: new inode owner
 - *
 +/*
   * Check whether @kuid is valid and if so generate and set vfsuid_t in
   * ia_vfsuid.
   *
@@@ -715,7 -718,10 +715,7 @@@ static inline bool setattr_vfsuid(struc
        return true;
  }
  
 -/**
 - * setattr_vfsgid - check and set ia_fsgid attribute
 - * @kgid: new inode owner
 - *
 +/*
   * Check whether @kgid is valid and if so generate and set vfsgid_t in
   * ia_vfsgid.
   *
@@@ -963,6 -969,11 +963,11 @@@ static int do_dentry_open(struct file *
                }
        }
  
+       /*
+        * Once we return a file with FMODE_OPENED, __fput() will call
+        * fsnotify_close(), so we need fsnotify_open() here for symmetry.
+        */
+       fsnotify_open(f);
        return 0;
  
  cleanup_all:
@@@ -983,6 -994,7 +988,6 @@@ cleanup_file
   * @file: file pointer
   * @dentry: pointer to dentry
   * @open: open callback
 - * @opened: state of open
   *
   * This can be used to finish opening a file passed to i_op->atomic_open().
   *
@@@ -1036,6 -1048,7 +1041,6 @@@ EXPORT_SYMBOL(file_path)
   * vfs_open - open the file at the given path
   * @path: path to open
   * @file: newly allocated file with f_flag initialized
 - * @cred: credentials to use
   */
  int vfs_open(const struct path *path, struct file *file)
  {
@@@ -1108,77 -1121,23 +1113,77 @@@ struct file *dentry_create(const struc
  }
  EXPORT_SYMBOL(dentry_create);
  
 -struct file *open_with_fake_path(const struct path *path, int flags,
 +/**
 + * kernel_file_open - open a file for kernel internal use
 + * @path:     path of the file to open
 + * @flags:    open flags
 + * @inode:    the inode
 + * @cred:     credentials for open
 + *
 + * Open a file for use by in-kernel consumers. The file is not accounted
 + * against nr_files and must not be installed into the file descriptor
 + * table.
 + *
 + * Return: Opened file on success, an error pointer on failure.
 + */
 +struct file *kernel_file_open(const struct path *path, int flags,
                                struct inode *inode, const struct cred *cred)
  {
 -      struct file *f = alloc_empty_file_noaccount(flags, cred);
 -      if (!IS_ERR(f)) {
 -              int error;
 +      struct file *f;
 +      int error;
  
 -              f->f_path = *path;
 -              error = do_dentry_open(f, inode, NULL);
 -              if (error) {
 -                      fput(f);
 -                      f = ERR_PTR(error);
 -              }
 +      f = alloc_empty_file_noaccount(flags, cred);
 +      if (IS_ERR(f))
 +              return f;
 +
 +      f->f_path = *path;
 +      error = do_dentry_open(f, inode, NULL);
 +      if (error) {
 +              fput(f);
 +              f = ERR_PTR(error);
        }
        return f;
  }
 -EXPORT_SYMBOL(open_with_fake_path);
 +EXPORT_SYMBOL_GPL(kernel_file_open);
 +
 +/**
 + * backing_file_open - open a backing file for kernel internal use
 + * @path:     path of the file to open
 + * @flags:    open flags
 + * @path:     path of the backing file
 + * @cred:     credentials for open
 + *
 + * Open a backing file for a stackable filesystem (e.g., overlayfs).
 + * @path may be on the stackable filesystem and backing inode on the
 + * underlying filesystem. In this case, we want to be able to return
 + * the @real_path of the backing inode. This is done by embedding the
 + * returned file into a container structure that also stores the path of
 + * the backing inode on the underlying filesystem, which can be
 + * retrieved using backing_file_real_path().
 + */
 +struct file *backing_file_open(const struct path *path, int flags,
 +                             const struct path *real_path,
 +                             const struct cred *cred)
 +{
 +      struct file *f;
 +      int error;
 +
 +      f = alloc_empty_backing_file(flags, cred);
 +      if (IS_ERR(f))
 +              return f;
 +
 +      f->f_path = *path;
 +      path_get(real_path);
 +      *backing_file_real_path(f) = *real_path;
 +      error = do_dentry_open(f, d_inode(real_path->dentry), NULL);
 +      if (error) {
 +              fput(f);
 +              f = ERR_PTR(error);
 +      }
 +
 +      return f;
 +}
 +EXPORT_SYMBOL_GPL(backing_file_open);
  
  #define WILL_CREATE(flags)    (flags & (O_CREAT | __O_TMPFILE))
  #define O_PATH_FLAGS          (O_DIRECTORY | O_NOFOLLOW | O_PATH | O_CLOEXEC)
@@@ -1202,7 -1161,7 +1207,7 @@@ inline struct open_how build_open_how(i
  inline int build_open_flags(const struct open_how *how, struct open_flags *op)
  {
        u64 flags = how->flags;
 -      u64 strip = FMODE_NONOTIFY | O_CLOEXEC;
 +      u64 strip = __FMODE_NONOTIFY | O_CLOEXEC;
        int lookup_flags = 0;
        int acc_mode = ACC_MODE(flags);
  
@@@ -1404,7 -1363,6 +1409,6 @@@ static long do_sys_openat2(int dfd, con
                        put_unused_fd(fd);
                        fd = PTR_ERR(f);
                } else {
-                       fsnotify_open(f);
                        fd_install(fd, f);
                }
        }
This page took 0.123644 seconds and 4 git commands to generate.