]> Git Repo - linux.git/commitdiff
procfs: fix pthread cross-thread naming if !PR_DUMPABLE
authorJanis Danisevskis <[email protected]>
Sat, 21 May 2016 00:00:08 +0000 (17:00 -0700)
committerLinus Torvalds <[email protected]>
Sat, 21 May 2016 00:58:30 +0000 (17:58 -0700)
The PR_DUMPABLE flag causes the pid related paths of the proc file
system to be owned by ROOT.

The implementation of pthread_set/getname_np however needs access to
/proc/<pid>/task/<tid>/comm.  If PR_DUMPABLE is false this
implementation is locked out.

This patch installs a special permission function for the file "comm"
that grants read and write access to all threads of the same group
regardless of the ownership of the inode.  For all other threads the
function falls back to the generic inode permission check.

[[email protected]: fix spello in comment]
Signed-off-by: Janis Danisevskis <[email protected]>
Acked-by: Kees Cook <[email protected]>
Cc: Al Viro <[email protected]>
Cc: Cyrill Gorcunov <[email protected]>
Cc: Alexey Dobriyan <[email protected]>
Cc: Colin Ian King <[email protected]>
Cc: David Rientjes <[email protected]>
Cc: Minfei Huang <[email protected]>
Cc: John Stultz <[email protected]>
Cc: Calvin Owens <[email protected]>
Cc: Jann Horn <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
fs/proc/base.c

index ff4527dd69b77ff99805b073904f285b3c551165..a11eb7196ec8b814ce1e9ed098253e0f6cfd24a5 100644 (file)
@@ -3162,6 +3162,44 @@ int proc_pid_readdir(struct file *file, struct dir_context *ctx)
        return 0;
 }
 
+/*
+ * proc_tid_comm_permission is a special permission function exclusively
+ * used for the node /proc/<pid>/task/<tid>/comm.
+ * It bypasses generic permission checks in the case where a task of the same
+ * task group attempts to access the node.
+ * The rationale behind this is that glibc and bionic access this node for
+ * cross thread naming (pthread_set/getname_np(!self)). However, if
+ * PR_SET_DUMPABLE gets set to 0 this node among others becomes uid=0 gid=0,
+ * which locks out the cross thread naming implementation.
+ * This function makes sure that the node is always accessible for members of
+ * same thread group.
+ */
+static int proc_tid_comm_permission(struct inode *inode, int mask)
+{
+       bool is_same_tgroup;
+       struct task_struct *task;
+
+       task = get_proc_task(inode);
+       if (!task)
+               return -ESRCH;
+       is_same_tgroup = same_thread_group(current, task);
+       put_task_struct(task);
+
+       if (likely(is_same_tgroup && !(mask & MAY_EXEC))) {
+               /* This file (/proc/<pid>/task/<tid>/comm) can always be
+                * read or written by the members of the corresponding
+                * thread group.
+                */
+               return 0;
+       }
+
+       return generic_permission(inode, mask);
+}
+
+static const struct inode_operations proc_tid_comm_inode_operations = {
+               .permission = proc_tid_comm_permission,
+};
+
 /*
  * Tasks
  */
@@ -3180,7 +3218,9 @@ static const struct pid_entry tid_base_stuff[] = {
 #ifdef CONFIG_SCHED_DEBUG
        REG("sched",     S_IRUGO|S_IWUSR, proc_pid_sched_operations),
 #endif
-       REG("comm",      S_IRUGO|S_IWUSR, proc_pid_set_comm_operations),
+       NOD("comm",      S_IFREG|S_IRUGO|S_IWUSR,
+                        &proc_tid_comm_inode_operations,
+                        &proc_pid_set_comm_operations, {}),
 #ifdef CONFIG_HAVE_ARCH_TRACEHOOK
        ONE("syscall",   S_IRUSR, proc_pid_syscall),
 #endif
This page took 0.061099 seconds and 4 git commands to generate.