Skip to content

Commit 1b3044e

Browse files
Janis Danisevskistorvalds
authored andcommitted
procfs: fix pthread cross-thread naming if !PR_DUMPABLE
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]>
1 parent 3e42979 commit 1b3044e

File tree

1 file changed

+41
-1
lines changed

1 file changed

+41
-1
lines changed

fs/proc/base.c

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3162,6 +3162,44 @@ int proc_pid_readdir(struct file *file, struct dir_context *ctx)
31623162
return 0;
31633163
}
31643164

3165+
/*
3166+
* proc_tid_comm_permission is a special permission function exclusively
3167+
* used for the node /proc/<pid>/task/<tid>/comm.
3168+
* It bypasses generic permission checks in the case where a task of the same
3169+
* task group attempts to access the node.
3170+
* The rationale behind this is that glibc and bionic access this node for
3171+
* cross thread naming (pthread_set/getname_np(!self)). However, if
3172+
* PR_SET_DUMPABLE gets set to 0 this node among others becomes uid=0 gid=0,
3173+
* which locks out the cross thread naming implementation.
3174+
* This function makes sure that the node is always accessible for members of
3175+
* same thread group.
3176+
*/
3177+
static int proc_tid_comm_permission(struct inode *inode, int mask)
3178+
{
3179+
bool is_same_tgroup;
3180+
struct task_struct *task;
3181+
3182+
task = get_proc_task(inode);
3183+
if (!task)
3184+
return -ESRCH;
3185+
is_same_tgroup = same_thread_group(current, task);
3186+
put_task_struct(task);
3187+
3188+
if (likely(is_same_tgroup && !(mask & MAY_EXEC))) {
3189+
/* This file (/proc/<pid>/task/<tid>/comm) can always be
3190+
* read or written by the members of the corresponding
3191+
* thread group.
3192+
*/
3193+
return 0;
3194+
}
3195+
3196+
return generic_permission(inode, mask);
3197+
}
3198+
3199+
static const struct inode_operations proc_tid_comm_inode_operations = {
3200+
.permission = proc_tid_comm_permission,
3201+
};
3202+
31653203
/*
31663204
* Tasks
31673205
*/
@@ -3180,7 +3218,9 @@ static const struct pid_entry tid_base_stuff[] = {
31803218
#ifdef CONFIG_SCHED_DEBUG
31813219
REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations),
31823220
#endif
3183-
REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations),
3221+
NOD("comm", S_IFREG|S_IRUGO|S_IWUSR,
3222+
&proc_tid_comm_inode_operations,
3223+
&proc_pid_set_comm_operations, {}),
31843224
#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
31853225
ONE("syscall", S_IRUSR, proc_pid_syscall),
31863226
#endif

0 commit comments

Comments
 (0)