Skip to content
  • David Meybohm's avatar
    [PATCH] preempt race in getppid · 4c5640cb
    David Meybohm authored
    
    
    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: default avatarDavid Meybohm <dmeybohmlkml@bellsouth.net>
    Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
    4c5640cb