Merge branch 'exec-for-v5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiede...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 16 Dec 2020 03:29:43 +0000 (19:29 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 16 Dec 2020 03:29:43 +0000 (19:29 -0800)
Pull execve updates from Eric Biederman:
 "This set of changes ultimately fixes the interaction of posix file
  lock and exec. Fundamentally most of the change is just moving where
  unshare_files is called during exec, and tweaking the users of
  files_struct so that the count of files_struct is not unnecessarily
  played with.

  Along the way fcheck and related helpers were renamed to more
  accurately reflect what they do.

  There were also many other small changes that fell out, as this is the
  first time in a long time much of this code has been touched.

  Benchmarks haven't turned up any practical issues but Al Viro has
  observed a possibility for a lot of pounding on task_lock. So I have
  some changes in progress to convert put_files_struct to always rcu
  free files_struct. That wasn't ready for the merge window so that will
  have to wait until next time"

* 'exec-for-v5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace: (27 commits)
  exec: Move io_uring_task_cancel after the point of no return
  coredump: Document coredump code exclusively used by cell spufs
  file: Remove get_files_struct
  file: Rename __close_fd_get_file close_fd_get_file
  file: Replace ksys_close with close_fd
  file: Rename __close_fd to close_fd and remove the files parameter
  file: Merge __alloc_fd into alloc_fd
  file: In f_dupfd read RLIMIT_NOFILE once.
  file: Merge __fd_install into fd_install
  proc/fd: In fdinfo seq_show don't use get_files_struct
  bpf/task_iter: In task_file_seq_get_next use task_lookup_next_fd_rcu
  proc/fd: In proc_readfd_common use task_lookup_next_fd_rcu
  file: Implement task_lookup_next_fd_rcu
  kcmp: In get_file_raw_ptr use task_lookup_fd_rcu
  proc/fd: In tid_fd_mode use task_lookup_fd_rcu
  file: Implement task_lookup_fd_rcu
  file: Rename fcheck lookup_fd_rcu
  file: Replace fcheck_files with files_lookup_fd_rcu
  file: Factor files_lookup_fd_locked out of fcheck_files
  file: Rename __fcheck_files to files_lookup_fd_raw
  ...

1  2 
drivers/android/binder.c
fs/binfmt_elf.c
fs/coredump.c
fs/exec.c
fs/file.c
fs/io_uring.c
fs/locks.c
fs/open.c
kernel/bpf/syscall.c
kernel/bpf/task_iter.c
kernel/fork.c

Simple merge
diff --cc fs/binfmt_elf.c
Simple merge
diff --cc fs/coredump.c
Simple merge
diff --cc fs/exec.c
Simple merge
diff --cc fs/file.c
+++ b/fs/file.c
@@@ -672,37 -627,8 +627,37 @@@ int close_fd(unsigned fd
  
        return filp_close(file, files);
  }
- EXPORT_SYMBOL(__close_fd); /* for ksys_close() */
+ EXPORT_SYMBOL(close_fd); /* for ksys_close() */
  
 +static inline void __range_cloexec(struct files_struct *cur_fds,
 +                                 unsigned int fd, unsigned int max_fd)
 +{
 +      struct fdtable *fdt;
 +
 +      if (fd > max_fd)
 +              return;
 +
 +      spin_lock(&cur_fds->file_lock);
 +      fdt = files_fdtable(cur_fds);
 +      bitmap_set(fdt->close_on_exec, fd, max_fd - fd + 1);
 +      spin_unlock(&cur_fds->file_lock);
 +}
 +
 +static inline void __range_close(struct files_struct *cur_fds, unsigned int fd,
 +                               unsigned int max_fd)
 +{
 +      while (fd <= max_fd) {
 +              struct file *file;
 +
 +              file = pick_file(cur_fds, fd++);
 +              if (!file)
 +                      continue;
 +
 +              filp_close(file, cur_fds);
 +              cond_resched();
 +      }
 +}
 +
  /**
   * __close_range() - Close all file descriptors in a given range.
   *
diff --cc fs/io_uring.c
Simple merge
diff --cc fs/locks.c
Simple merge
diff --cc fs/open.c
Simple merge
Simple merge
@@@ -136,41 -135,29 +135,30 @@@ struct bpf_iter_seq_task_file_info 
  };
  
  static struct file *
 -task_file_seq_get_next(struct bpf_iter_seq_task_file_info *info,
 -                     struct task_struct **task)
 +task_file_seq_get_next(struct bpf_iter_seq_task_file_info *info)
  {
        struct pid_namespace *ns = info->common.ns;
-       u32 curr_tid = info->tid, max_fds;
-       struct files_struct *curr_files;
+       u32 curr_tid = info->tid;
        struct task_struct *curr_task;
-       int curr_fd = info->fd;
+       unsigned int curr_fd = info->fd;
  
        /* If this function returns a non-NULL file object,
-        * it held a reference to the task/files_struct/file.
+        * it held a reference to the task/file.
         * Otherwise, it does not hold any reference.
         */
  again:
 -      if (*task) {
 -              curr_task = *task;
 +      if (info->task) {
 +              curr_task = info->task;
-               curr_files = info->files;
                curr_fd = info->fd;
        } else {
                curr_task = task_seq_get_next(ns, &curr_tid, true);
 -              if (!curr_task)
 +              if (!curr_task) {
 +                      info->task = NULL;
-                       info->files = NULL;
                        return NULL;
 +              }
  
-               curr_files = get_files_struct(curr_task);
-               if (!curr_files) {
-                       put_task_struct(curr_task);
-                       curr_tid = ++(info->tid);
-                       info->fd = 0;
-                       goto again;
-               }
-               info->files = curr_files;
 -              /* set *task and info->tid */
 -              *task = curr_task;
++              /* set info->task and info->tid */
 +              info->task = curr_task;
                if (curr_tid == info->tid) {
                        curr_fd = info->fd;
                } else {
  
        /* the current task is done, go to the next task */
        rcu_read_unlock();
-       put_files_struct(curr_files);
        put_task_struct(curr_task);
 -      *task = NULL;
 +      info->task = NULL;
-       info->files = NULL;
        info->fd = 0;
        curr_tid = ++(info->tid);
        goto again;
  static void *task_file_seq_start(struct seq_file *seq, loff_t *pos)
  {
        struct bpf_iter_seq_task_file_info *info = seq->private;
 -      struct task_struct *task = NULL;
        struct file *file;
  
 -      file = task_file_seq_get_next(info, &task);
 -      if (!file) {
 -              info->task = NULL;
 -              return NULL;
 -      }
 -
 -      if (*pos == 0)
 +      info->task = NULL;
-       info->files = NULL;
 +      file = task_file_seq_get_next(info);
 +      if (file && *pos == 0)
                ++*pos;
 -      info->task = task;
  
        return file;
  }
diff --cc kernel/fork.c
Simple merge