Merge tag 'v6.6-fs.proc.uapi' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 28 Aug 2023 18:43:19 +0000 (11:43 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 28 Aug 2023 18:43:19 +0000 (11:43 -0700)
Pull procfs fixes from Christian Brauner:
 "Mode changes to files under /proc/<pid>/ aren't supported ever since
  commit 6d76fa58b050 ("Don't allow chmod() on the /proc/<pid>/ files").

  Due to an oversight in commit 1b3044e39a89 ("procfs: fix pthread
  cross-thread naming if !PR_DUMPABLE") in switching from REG to NOD,
  mode changes on /proc/thread-self/comm were accidently allowed.

  Similar, mode changes for all files beneath /proc/<pid>/net/ are
  blocked but mode changes on /proc/<pid>/net itself were accidently
  allowed.

  Both issues come down to not using the generic proc_setattr() helper
  which blocks all mode changes. This is rectified with this pull
  request.

  This also removes a strange nolibc test that abused /proc/<pid>/net
  for testing mode changes. Using procfs for this test never made a lot
  of sense given procfs has special semantics for almost everything
  anway.

  Both changes are minor user-visible changes. It is however very
  unlikely that mode changes on proc/<pid>/net and
  /proc/thread-self/comm are something that userspace relies on"

* tag 'v6.6-fs.proc.uapi' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
  procfs: block chmod on /proc/thread-self/comm
  proc: use generic setattr() for /proc/$PID/net
  selftests/nolibc: drop test chmod_net

1  2 
fs/proc/base.c
fs/proc/proc_net.c

diff --combined fs/proc/base.c
@@@ -1902,7 -1902,7 +1902,7 @@@ struct inode *proc_pid_make_inode(struc
        ei = PROC_I(inode);
        inode->i_mode = mode;
        inode->i_ino = get_next_ino();
 -      inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
 +      inode->i_mtime = inode->i_atime = inode_set_ctime_current(inode);
        inode->i_op = &proc_def_inode_operations;
  
        /*
@@@ -1966,7 -1966,7 +1966,7 @@@ int pid_getattr(struct mnt_idmap *idmap
        struct proc_fs_info *fs_info = proc_sb_info(inode->i_sb);
        struct task_struct *task;
  
 -      generic_fillattr(&nop_mnt_idmap, inode, stat);
 +      generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat);
  
        stat->uid = GLOBAL_ROOT_UID;
        stat->gid = GLOBAL_ROOT_GID;
@@@ -2817,7 -2817,7 +2817,7 @@@ static int proc_##LSM##_attr_dir_iterat
  \
  static const struct file_operations proc_##LSM##_attr_dir_ops = { \
        .read           = generic_read_dir, \
 -      .iterate        = proc_##LSM##_attr_dir_iterate, \
 +      .iterate_shared = proc_##LSM##_attr_dir_iterate, \
        .llseek         = default_llseek, \
  }; \
  \
@@@ -3583,7 -3583,8 +3583,8 @@@ static int proc_tid_comm_permission(str
  }
  
  static const struct inode_operations proc_tid_comm_inode_operations = {
-               .permission = proc_tid_comm_permission,
+               .setattr        = proc_setattr,
+               .permission     = proc_tid_comm_permission,
  };
  
  /*
@@@ -3899,7 -3900,7 +3900,7 @@@ static int proc_task_getattr(struct mnt
  {
        struct inode *inode = d_inode(path->dentry);
        struct task_struct *p = get_proc_task(inode);
 -      generic_fillattr(&nop_mnt_idmap, inode, stat);
 +      generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat);
  
        if (p) {
                stat->nlink += get_nr_threads(p);
diff --combined fs/proc/proc_net.c
@@@ -308,7 -308,7 +308,7 @@@ static int proc_tgid_net_getattr(struc
  
        net = get_proc_task_net(inode);
  
 -      generic_fillattr(&nop_mnt_idmap, inode, stat);
 +      generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat);
  
        if (net != NULL) {
                stat->nlink = net->proc_net->nlink;
  const struct inode_operations proc_net_inode_operations = {
        .lookup         = proc_tgid_net_lookup,
        .getattr        = proc_tgid_net_getattr,
+       .setattr        = proc_setattr,
  };
  
  static int proc_tgid_net_readdir(struct file *file, struct dir_context *ctx)