diff options
author | Oleg Nesterov <oleg@redhat.com> | 2009-06-17 19:27:38 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-18 16:03:52 -0400 |
commit | 3b34fc5880a2dcc7e5ed9837ef8d6bae051ab266 (patch) | |
tree | 477b9a29135cc7b8815ce7ce19201bce371c56a1 | |
parent | 72a1de39f89325a834a8c70b2a0d8f71d919f640 (diff) |
elf_core_dump: use rcu_read_lock() to access ->real_parent
In theory it is not safe to dereference ->parent/real_parent without
tasklist or rcu lock, we can race with re-parenting.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Roland McGrath <roland@redhat.com>
Cc: David Howells <dhowells@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/binfmt_elf.c | 8 | ||||
-rw-r--r-- | fs/binfmt_elf_fdpic.c | 8 |
2 files changed, 12 insertions, 4 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 40381df34869..9fa212b014a5 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -1340,8 +1340,10 @@ static void fill_prstatus(struct elf_prstatus *prstatus, | |||
1340 | prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; | 1340 | prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; |
1341 | prstatus->pr_sigpend = p->pending.signal.sig[0]; | 1341 | prstatus->pr_sigpend = p->pending.signal.sig[0]; |
1342 | prstatus->pr_sighold = p->blocked.sig[0]; | 1342 | prstatus->pr_sighold = p->blocked.sig[0]; |
1343 | rcu_read_lock(); | ||
1344 | prstatus->pr_ppid = task_pid_vnr(rcu_dereference(p->real_parent)); | ||
1345 | rcu_read_unlock(); | ||
1343 | prstatus->pr_pid = task_pid_vnr(p); | 1346 | prstatus->pr_pid = task_pid_vnr(p); |
1344 | prstatus->pr_ppid = task_pid_vnr(p->real_parent); | ||
1345 | prstatus->pr_pgrp = task_pgrp_vnr(p); | 1347 | prstatus->pr_pgrp = task_pgrp_vnr(p); |
1346 | prstatus->pr_sid = task_session_vnr(p); | 1348 | prstatus->pr_sid = task_session_vnr(p); |
1347 | if (thread_group_leader(p)) { | 1349 | if (thread_group_leader(p)) { |
@@ -1382,8 +1384,10 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, | |||
1382 | psinfo->pr_psargs[i] = ' '; | 1384 | psinfo->pr_psargs[i] = ' '; |
1383 | psinfo->pr_psargs[len] = 0; | 1385 | psinfo->pr_psargs[len] = 0; |
1384 | 1386 | ||
1387 | rcu_read_lock(); | ||
1388 | psinfo->pr_ppid = task_pid_vnr(rcu_dereference(p->real_parent)); | ||
1389 | rcu_read_unlock(); | ||
1385 | psinfo->pr_pid = task_pid_vnr(p); | 1390 | psinfo->pr_pid = task_pid_vnr(p); |
1386 | psinfo->pr_ppid = task_pid_vnr(p->real_parent); | ||
1387 | psinfo->pr_pgrp = task_pgrp_vnr(p); | 1391 | psinfo->pr_pgrp = task_pgrp_vnr(p); |
1388 | psinfo->pr_sid = task_session_vnr(p); | 1392 | psinfo->pr_sid = task_session_vnr(p); |
1389 | 1393 | ||
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index fdb66faa24f1..20fbeced472b 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c | |||
@@ -1387,8 +1387,10 @@ static void fill_prstatus(struct elf_prstatus *prstatus, | |||
1387 | prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; | 1387 | prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; |
1388 | prstatus->pr_sigpend = p->pending.signal.sig[0]; | 1388 | prstatus->pr_sigpend = p->pending.signal.sig[0]; |
1389 | prstatus->pr_sighold = p->blocked.sig[0]; | 1389 | prstatus->pr_sighold = p->blocked.sig[0]; |
1390 | rcu_read_lock(); | ||
1391 | prstatus->pr_ppid = task_pid_vnr(rcu_dereference(p->real_parent)); | ||
1392 | rcu_read_unlock(); | ||
1390 | prstatus->pr_pid = task_pid_vnr(p); | 1393 | prstatus->pr_pid = task_pid_vnr(p); |
1391 | prstatus->pr_ppid = task_pid_vnr(p->real_parent); | ||
1392 | prstatus->pr_pgrp = task_pgrp_vnr(p); | 1394 | prstatus->pr_pgrp = task_pgrp_vnr(p); |
1393 | prstatus->pr_sid = task_session_vnr(p); | 1395 | prstatus->pr_sid = task_session_vnr(p); |
1394 | if (thread_group_leader(p)) { | 1396 | if (thread_group_leader(p)) { |
@@ -1432,8 +1434,10 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, | |||
1432 | psinfo->pr_psargs[i] = ' '; | 1434 | psinfo->pr_psargs[i] = ' '; |
1433 | psinfo->pr_psargs[len] = 0; | 1435 | psinfo->pr_psargs[len] = 0; |
1434 | 1436 | ||
1437 | rcu_read_lock(); | ||
1438 | psinfo->pr_ppid = task_pid_vnr(rcu_dereference(p->real_parent)); | ||
1439 | rcu_read_unlock(); | ||
1435 | psinfo->pr_pid = task_pid_vnr(p); | 1440 | psinfo->pr_pid = task_pid_vnr(p); |
1436 | psinfo->pr_ppid = task_pid_vnr(p->real_parent); | ||
1437 | psinfo->pr_pgrp = task_pgrp_vnr(p); | 1441 | psinfo->pr_pgrp = task_pgrp_vnr(p); |
1438 | psinfo->pr_sid = task_session_vnr(p); | 1442 | psinfo->pr_sid = task_session_vnr(p); |
1439 | 1443 | ||