Skip to content
  • Roman Kagan's avatar
    ddde5ee7
    block/nbd: only enter connection coroutine if it's present · ddde5ee7
    Roman Kagan authored
    
    
    When an NBD block driver state is moved from one aio_context to another
    (e.g. when doing a drain in a migration thread),
    nbd_client_attach_aio_context_bh is executed that enters the connection
    coroutine.
    
    However, the assumption that ->connection_co is always present here
    appears incorrect: the connection may have encountered an error other
    than -EIO in the underlying transport, and thus may have decided to quit
    rather than keep trying to reconnect, and therefore it may have
    terminated the connection coroutine.  As a result an attempt to reassign
    the client in this state (NBD_CLIENT_QUIT) to a different aio_context
    leads to a null pointer dereference:
    
      #0  qio_channel_detach_aio_context (ioc=0x0)
          at /build/qemu-gYtjVn/qemu-5.0.1/io/channel.c:452
      #1  0x0000562a242824b3 in bdrv_detach_aio_context (bs=0x562a268d6a00)
          at /build/qemu-gYtjVn/qemu-5.0.1/block.c:6151
      #2  bdrv_set_aio_context_ignore (bs=bs@entry=0x562a268d6a00,
          new_context=new_context@entry=0x562a260c9580,
          ignore=ignore@entry=0x7feeadc9b780)
          at /build/qemu-gYtjVn/qemu-5.0.1/block.c:6230
      #3  0x0000562a24282969 in bdrv_child_try_set_aio_context
          (bs=bs@entry=0x562a268d6a00, ctx=0x562a260c9580,
          ignore_child=<optimized out>, errp=<optimized out>)
          at /build/qemu-gYtjVn/qemu-5.0.1/block.c:6332
      #4  0x0000562a242bb7db in blk_do_set_aio_context (blk=0x562a2735d0d0,
          new_context=0x562a260c9580,
          update_root_node=update_root_node@entry=true, errp=errp@entry=0x0)
          at /build/qemu-gYtjVn/qemu-5.0.1/block/block-backend.c:1989
      #5  0x0000562a242be0bd in blk_set_aio_context (blk=<optimized out>,
          new_context=<optimized out>, errp=errp@entry=0x0)
          at /build/qemu-gYtjVn/qemu-5.0.1/block/block-backend.c:2010
      #6  0x0000562a23fbd953 in virtio_blk_data_plane_stop (vdev=<optimized
          out>)
          at /build/qemu-gYtjVn/qemu-5.0.1/hw/block/dataplane/virtio-blk.c:292
      #7  0x0000562a241fc7bf in virtio_bus_stop_ioeventfd (bus=0x562a260dbf08)
          at /build/qemu-gYtjVn/qemu-5.0.1/hw/virtio/virtio-bus.c:245
      #8  0x0000562a23fefb2e in virtio_vmstate_change (opaque=0x562a260dbf90,
          running=0, state=<optimized out>)
          at /build/qemu-gYtjVn/qemu-5.0.1/hw/virtio/virtio.c:3220
      #9  0x0000562a2402ebfd in vm_state_notify (running=running@entry=0,
          state=state@entry=RUN_STATE_FINISH_MIGRATE)
          at /build/qemu-gYtjVn/qemu-5.0.1/softmmu/vl.c:1275
      #10 0x0000562a23f7bc02 in do_vm_stop (state=RUN_STATE_FINISH_MIGRATE,
          send_stop=<optimized out>)
          at /build/qemu-gYtjVn/qemu-5.0.1/cpus.c:1032
      #11 0x0000562a24209765 in migration_completion (s=0x562a260e83a0)
          at /build/qemu-gYtjVn/qemu-5.0.1/migration/migration.c:2914
      #12 migration_iteration_run (s=0x562a260e83a0)
          at /build/qemu-gYtjVn/qemu-5.0.1/migration/migration.c:3275
      #13 migration_thread (opaque=opaque@entry=0x562a260e83a0)
          at /build/qemu-gYtjVn/qemu-5.0.1/migration/migration.c:3439
      #14 0x0000562a2435ca96 in qemu_thread_start (args=<optimized out>)
          at /build/qemu-gYtjVn/qemu-5.0.1/util/qemu-thread-posix.c:519
      #15 0x00007feed31466ba in start_thread (arg=0x7feeadc9c700)
          at pthread_create.c:333
      #16 0x00007feed2e7c41d in __GI___sysctl (name=0x0, nlen=608471908,
          oldval=0x562a2452b138, oldlenp=0x0, newval=0x562a2452c5e0
          <__func__.28102>, newlen=0)
          at ../sysdeps/unix/sysv/linux/sysctl.c:30
      #17 0x0000000000000000 in ?? ()
    
    Fix it by checking that the connection coroutine is non-null before
    trying to enter it.  If it is null, no entering is needed, as the
    connection is probably going down anyway.
    
    Signed-off-by: default avatarRoman Kagan <rvkagan@yandex-team.ru>
    Reviewed-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
    Message-Id: <20210129073859.683063-3-rvkagan@yandex-team.ru>
    Signed-off-by: default avatarEric Blake <eblake@redhat.com>
    ddde5ee7
    block/nbd: only enter connection coroutine if it's present
    Roman Kagan authored
    
    
    When an NBD block driver state is moved from one aio_context to another
    (e.g. when doing a drain in a migration thread),
    nbd_client_attach_aio_context_bh is executed that enters the connection
    coroutine.
    
    However, the assumption that ->connection_co is always present here
    appears incorrect: the connection may have encountered an error other
    than -EIO in the underlying transport, and thus may have decided to quit
    rather than keep trying to reconnect, and therefore it may have
    terminated the connection coroutine.  As a result an attempt to reassign
    the client in this state (NBD_CLIENT_QUIT) to a different aio_context
    leads to a null pointer dereference:
    
      #0  qio_channel_detach_aio_context (ioc=0x0)
          at /build/qemu-gYtjVn/qemu-5.0.1/io/channel.c:452
      #1  0x0000562a242824b3 in bdrv_detach_aio_context (bs=0x562a268d6a00)
          at /build/qemu-gYtjVn/qemu-5.0.1/block.c:6151
      #2  bdrv_set_aio_context_ignore (bs=bs@entry=0x562a268d6a00,
          new_context=new_context@entry=0x562a260c9580,
          ignore=ignore@entry=0x7feeadc9b780)
          at /build/qemu-gYtjVn/qemu-5.0.1/block.c:6230
      #3  0x0000562a24282969 in bdrv_child_try_set_aio_context
          (bs=bs@entry=0x562a268d6a00, ctx=0x562a260c9580,
          ignore_child=<optimized out>, errp=<optimized out>)
          at /build/qemu-gYtjVn/qemu-5.0.1/block.c:6332
      #4  0x0000562a242bb7db in blk_do_set_aio_context (blk=0x562a2735d0d0,
          new_context=0x562a260c9580,
          update_root_node=update_root_node@entry=true, errp=errp@entry=0x0)
          at /build/qemu-gYtjVn/qemu-5.0.1/block/block-backend.c:1989
      #5  0x0000562a242be0bd in blk_set_aio_context (blk=<optimized out>,
          new_context=<optimized out>, errp=errp@entry=0x0)
          at /build/qemu-gYtjVn/qemu-5.0.1/block/block-backend.c:2010
      #6  0x0000562a23fbd953 in virtio_blk_data_plane_stop (vdev=<optimized
          out>)
          at /build/qemu-gYtjVn/qemu-5.0.1/hw/block/dataplane/virtio-blk.c:292
      #7  0x0000562a241fc7bf in virtio_bus_stop_ioeventfd (bus=0x562a260dbf08)
          at /build/qemu-gYtjVn/qemu-5.0.1/hw/virtio/virtio-bus.c:245
      #8  0x0000562a23fefb2e in virtio_vmstate_change (opaque=0x562a260dbf90,
          running=0, state=<optimized out>)
          at /build/qemu-gYtjVn/qemu-5.0.1/hw/virtio/virtio.c:3220
      #9  0x0000562a2402ebfd in vm_state_notify (running=running@entry=0,
          state=state@entry=RUN_STATE_FINISH_MIGRATE)
          at /build/qemu-gYtjVn/qemu-5.0.1/softmmu/vl.c:1275
      #10 0x0000562a23f7bc02 in do_vm_stop (state=RUN_STATE_FINISH_MIGRATE,
          send_stop=<optimized out>)
          at /build/qemu-gYtjVn/qemu-5.0.1/cpus.c:1032
      #11 0x0000562a24209765 in migration_completion (s=0x562a260e83a0)
          at /build/qemu-gYtjVn/qemu-5.0.1/migration/migration.c:2914
      #12 migration_iteration_run (s=0x562a260e83a0)
          at /build/qemu-gYtjVn/qemu-5.0.1/migration/migration.c:3275
      #13 migration_thread (opaque=opaque@entry=0x562a260e83a0)
          at /build/qemu-gYtjVn/qemu-5.0.1/migration/migration.c:3439
      #14 0x0000562a2435ca96 in qemu_thread_start (args=<optimized out>)
          at /build/qemu-gYtjVn/qemu-5.0.1/util/qemu-thread-posix.c:519
      #15 0x00007feed31466ba in start_thread (arg=0x7feeadc9c700)
          at pthread_create.c:333
      #16 0x00007feed2e7c41d in __GI___sysctl (name=0x0, nlen=608471908,
          oldval=0x562a2452b138, oldlenp=0x0, newval=0x562a2452c5e0
          <__func__.28102>, newlen=0)
          at ../sysdeps/unix/sysv/linux/sysctl.c:30
      #17 0x0000000000000000 in ?? ()
    
    Fix it by checking that the connection coroutine is non-null before
    trying to enter it.  If it is null, no entering is needed, as the
    connection is probably going down anyway.
    
    Signed-off-by: default avatarRoman Kagan <rvkagan@yandex-team.ru>
    Reviewed-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
    Message-Id: <20210129073859.683063-3-rvkagan@yandex-team.ru>
    Signed-off-by: default avatarEric Blake <eblake@redhat.com>
Loading