Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

proc_fork_connector: a lockless ->real_parent usage is not safe

proc_fork_connector() uses ->real_parent lockless. This is not safe if
copy_process() was called with CLONE_THREAD or CLONE_PARENT, in this case
the parent != current can go away at any moment.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Cc: Vladimir Zapolskiy <vzapolskiy@gmail.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Evgeniy Polyakov <zbr@ioremap.net>
Cc: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Oleg Nesterov and committed by
David S. Miller
9e8f90df 177c27bf

+6 -2
+6 -2
drivers/connector/cn_proc.c
··· 57 57 struct proc_event *ev; 58 58 __u8 buffer[CN_PROC_MSG_SIZE]; 59 59 struct timespec ts; 60 + struct task_struct *parent; 60 61 61 62 if (atomic_read(&proc_event_num_listeners) < 1) 62 63 return; ··· 68 67 ktime_get_ts(&ts); /* get high res monotonic timestamp */ 69 68 put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); 70 69 ev->what = PROC_EVENT_FORK; 71 - ev->event_data.fork.parent_pid = task->real_parent->pid; 72 - ev->event_data.fork.parent_tgid = task->real_parent->tgid; 70 + rcu_read_lock(); 71 + parent = rcu_dereference(task->real_parent); 72 + ev->event_data.fork.parent_pid = parent->pid; 73 + ev->event_data.fork.parent_tgid = parent->tgid; 74 + rcu_read_unlock(); 73 75 ev->event_data.fork.child_pid = task->pid; 74 76 ev->event_data.fork.child_tgid = task->tgid; 75 77