[lkml]   [2005]   [Dec]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
    Patch in this message
    Subject[PATCH 04/10] Cpuset: fork hook fix
    Fix obscure, never seen in real life, cpuset fork race.
    The cpuset_fork() call in fork.c was setting up the correct
    task->cpuset pointer after the tasklist_lock was dropped,
    which briefly exposed the newly forked process with an unsafe
    (copied from parent without locks or usage counter increment)
    cpuset pointer.

    In theory, that exposed cpuset pointer could have been pointing
    at a cpuset that was already freed and removed, and in theory
    another task that had been sitting on the tasklist_lock waiting
    to scan the task list could have raced down the entire tasklist,
    found our new child at the far end, and dereferenced that bogus
    cpuset pointer.

    To fix, setup up the correct cpuset pointer in the new child
    by calling cpuset_fork() before the new task is linked into the
    tasklist, and with that, add a fork failure case, to dereference
    that cpuset, if the fork fails along the way, after cpuset_fork()
    was called.

    Had to remove a BUG_ON() from cpuset_exit(), because it was
    no longer valid - the call to cpuset_exit() from a failed fork
    would not have PF_EXITING set.

    Signed-off-by: Paul Jackson <>


    kernel/cpuset.c | 4 +---
    kernel/fork.c | 6 ++++--
    2 files changed, 5 insertions(+), 5 deletions(-)

    --- 2.6.15-rc3-mm1.orig/kernel/cpuset.c 2005-12-08 02:05:37.457685051 -0800
    +++ 2.6.15-rc3-mm1/kernel/cpuset.c 2005-12-08 15:19:04.600207271 -0800
    @@ -1821,15 +1821,13 @@ void cpuset_fork(struct task_struct *chi
    * We don't need to task_lock() this reference to tsk->cpuset,
    * because tsk is already marked PF_EXITING, so attach_task() won't
    - * mess with it.
    + * mess with it, or task is a failed fork, never visible to attach_task.

    void cpuset_exit(struct task_struct *tsk)
    struct cpuset *cs;

    - BUG_ON(!(tsk->flags & PF_EXITING));
    cs = tsk->cpuset;
    tsk->cpuset = NULL;

    --- 2.6.15-rc3-mm1.orig/kernel/fork.c 2005-12-08 02:05:34.885390778 -0800
    +++ 2.6.15-rc3-mm1/kernel/fork.c 2005-12-08 15:19:50.203259819 -0800
    @@ -971,12 +971,13 @@ static task_t *copy_process(unsigned lon
    p->io_context = NULL;
    p->io_wait = NULL;
    p->audit_context = NULL;
    + cpuset_fork(p);
    #ifdef CONFIG_NUMA
    p->mempolicy = mpol_copy(p->mempolicy);
    if (IS_ERR(p->mempolicy)) {
    retval = PTR_ERR(p->mempolicy);
    p->mempolicy = NULL;
    - goto bad_fork_cleanup;
    + goto bad_fork_cleanup_cpuset;

    @@ -1147,7 +1148,6 @@ static task_t *copy_process(unsigned lon
    - cpuset_fork(p);
    retval = 0;

    @@ -1179,7 +1179,9 @@ bad_fork_cleanup_security:
    #ifdef CONFIG_NUMA
    + cpuset_exit(p);
    if (p->binfmt)
    I won't rest till it's the best ...
    Programmer, Linux Scalability
    Paul Jackson <> 1.650.933.1373
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to
    More majordomo info at
    Please read the FAQ at

     \ /
      Last update: 2005-12-10 09:25    [W:0.023 / U:0.104 seconds]
    ©2003-2017 Jasper Spaans. hosted at Digital OceanAdvertise on this site