Skip to content
  • Stefan Hajnoczi's avatar
    f0f81002
    util/async: hold AioContext ref to prevent use-after-free · f0f81002
    Stefan Hajnoczi authored
    
    
    The tests/test-bdrv-drain /bdrv-drain/iothread/drain test case does the
    following:
    
    1. The preadv coroutine calls aio_bh_schedule_oneshot() and then yields.
    2. The one-shot BH executes in another AioContext.  All it does is call
       aio_co_wakeup(preadv_co).
    3. The preadv coroutine is re-entered and returns.
    
    There is a race condition in aio_co_wake() where the preadv coroutine
    returns and the test case destroys the preadv IOThread.  aio_co_wake()
    can still be running in the other AioContext and it performs an access
    to the freed IOThread AioContext.
    
    Here is the race in aio_co_schedule():
    
      QSLIST_INSERT_HEAD_ATOMIC(&ctx->scheduled_coroutines,
                                co, co_scheduled_next);
      <-- race: co may execute before we invoke qemu_bh_schedule()!
      qemu_bh_schedule(ctx->co_schedule_bh);
    
    So if co causes ctx to be freed then we're in trouble.  Fix this problem
    by holding a reference to ctx.
    
    Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
    Reviewed-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
    Message-id: 20190723190623.21537-1-stefanha@redhat.com
    Message-Id: <20190723190623.21537-1-stefanha@redhat.com>
    Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
    f0f81002
    util/async: hold AioContext ref to prevent use-after-free
    Stefan Hajnoczi authored
    
    
    The tests/test-bdrv-drain /bdrv-drain/iothread/drain test case does the
    following:
    
    1. The preadv coroutine calls aio_bh_schedule_oneshot() and then yields.
    2. The one-shot BH executes in another AioContext.  All it does is call
       aio_co_wakeup(preadv_co).
    3. The preadv coroutine is re-entered and returns.
    
    There is a race condition in aio_co_wake() where the preadv coroutine
    returns and the test case destroys the preadv IOThread.  aio_co_wake()
    can still be running in the other AioContext and it performs an access
    to the freed IOThread AioContext.
    
    Here is the race in aio_co_schedule():
    
      QSLIST_INSERT_HEAD_ATOMIC(&ctx->scheduled_coroutines,
                                co, co_scheduled_next);
      <-- race: co may execute before we invoke qemu_bh_schedule()!
      qemu_bh_schedule(ctx->co_schedule_bh);
    
    So if co causes ctx to be freed then we're in trouble.  Fix this problem
    by holding a reference to ctx.
    
    Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
    Reviewed-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
    Message-id: 20190723190623.21537-1-stefanha@redhat.com
    Message-Id: <20190723190623.21537-1-stefanha@redhat.com>
    Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
Loading