12.09.2019 16:56, Max Reitz wrote: > mirror_exit_common() may be called twice (if it is called from > mirror_prepare() and fails, it will be called from mirror_abort() > again). > > In such a case, many of the pointers in the MirrorBlockJob object will > already be freed. This can be seen most reliably for s->target, which > is set to NULL (and then dereferenced by blk_bs()). > > Cc: qemu-sta...@nongnu.org > Fixes: 737efc1eda23b904fbe0e66b37715fb0e5c3e58b > Signed-off-by: Max Reitz <mre...@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com> > --- > block/mirror.c | 13 +++++++++---- > 1 file changed, 9 insertions(+), 4 deletions(-) > > diff --git a/block/mirror.c b/block/mirror.c > index fe984efb90..706d80fced 100644 > --- a/block/mirror.c > +++ b/block/mirror.c > @@ -620,11 +620,11 @@ static int mirror_exit_common(Job *job) > { > MirrorBlockJob *s = container_of(job, MirrorBlockJob, common.job); > BlockJob *bjob = &s->common; > - MirrorBDSOpaque *bs_opaque = s->mirror_top_bs->opaque; > + MirrorBDSOpaque *bs_opaque; > AioContext *replace_aio_context = NULL; > - BlockDriverState *src = s->mirror_top_bs->backing->bs; > - BlockDriverState *target_bs = blk_bs(s->target); > - BlockDriverState *mirror_top_bs = s->mirror_top_bs; > + BlockDriverState *src; > + BlockDriverState *target_bs; > + BlockDriverState *mirror_top_bs; > Error *local_err = NULL; > bool abort = job->ret < 0; > int ret = 0; > @@ -634,6 +634,11 @@ static int mirror_exit_common(Job *job) > } > s->prepared = true; > > + mirror_top_bs = s->mirror_top_bs; > + bs_opaque = mirror_top_bs->opaque; > + src = mirror_top_bs->backing->bs; > + target_bs = blk_bs(s->target); > + > if (bdrv_chain_contains(src, target_bs)) { > bdrv_unfreeze_backing_chain(mirror_top_bs, target_bs); > } > -- Best regards, Vladimir