mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-11-27 01:11:31 +00:00
With CONFIG_PREEMPT && !CONFIG_SMP, it's possible for sys_getppid to
return a bogus value if the parent's task_struct gets reallocated after
current->group_leader->real_parent is read:
asmlinkage long sys_getppid(void)
{
int pid;
struct task_struct *me = current;
struct task_struct *parent;
parent = me->group_leader->real_parent;
RACE HERE => for (;;) {
pid = parent->tgid;
#ifdef CONFIG_SMP
{
struct task_struct *old = parent;
/*
* Make sure we read the pid before re-reading the
* parent pointer:
*/
smp_rmb();
parent = me->group_leader->real_parent;
if (old != parent)
continue;
}
#endif
break;
}
return pid;
}
If the process gets preempted at the indicated point, the parent process
can go ahead and call exit() and then get wait()'d on to reap its
task_struct. When the preempted process gets resumed, it will not do any
further checks of the parent pointer on !CONFIG_SMP: it will read the
bad pid and return.
So, the same algorithm used when SMP is enabled should be used when
preempt is enabled, which will recheck ->real_parent in this case.
Signed-off-by: David Meybohm <dmeybohmlkml@bellsouth.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
||
|---|---|---|
| .. | ||
| irq | ||
| power | ||
| acct.c | ||
| audit.c | ||
| auditsc.c | ||
| capability.c | ||
| compat.c | ||
| configs.c | ||
| cpu.c | ||
| cpuset.c | ||
| crash_dump.c | ||
| dma.c | ||
| exec_domain.c | ||
| exit.c | ||
| extable.c | ||
| fork.c | ||
| futex.c | ||
| intermodule.c | ||
| itimer.c | ||
| kallsyms.c | ||
| Kconfig.hz | ||
| Kconfig.preempt | ||
| kexec.c | ||
| kfifo.c | ||
| kmod.c | ||
| kprobes.c | ||
| ksysfs.c | ||
| kthread.c | ||
| Makefile | ||
| module.c | ||
| panic.c | ||
| params.c | ||
| pid.c | ||
| posix-cpu-timers.c | ||
| posix-timers.c | ||
| printk.c | ||
| profile.c | ||
| ptrace.c | ||
| rcupdate.c | ||
| resource.c | ||
| sched.c | ||
| seccomp.c | ||
| signal.c | ||
| softirq.c | ||
| spinlock.c | ||
| stop_machine.c | ||
| sys.c | ||
| sys_ni.c | ||
| sysctl.c | ||
| time.c | ||
| timer.c | ||
| uid16.c | ||
| user.c | ||
| wait.c | ||
| workqueue.c | ||