From 447b0d0b9ee8a0ac216c3186e0f3c427a1001f0c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 21 Sep 2017 14:32:47 +0200 Subject: memory: avoid "resurrection" of dead FlatViews It's possible for address_space_get_flatview() as it currently stands to cause a use-after-free for the returned FlatView, if the reference count is incremented after the FlatView has been replaced by a writer: thread 1 thread 2 RCU thread ------------------------------------------------------------- rcu_read_lock read as->current_map set as->current_map flatview_unref '--> call_rcu flatview_ref [ref=1] rcu_read_unlock flatview_destroy Since FlatViews are not updated very often, we can just detect the situation using a new atomic op atomic_fetch_inc_nonzero, similar to Linux's atomic_inc_not_zero, which performs the refcount increment only if it hasn't already hit zero. This is similar to Linux commit de09a9771a53 ("CRED: Fix get_task_cred() and task_state() to not resurrect dead credentials", 2010-07-29). Signed-off-by: Paolo Bonzini --- include/qemu/atomic.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include/qemu/atomic.h') diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h index b6b62fb771..d73c9e14d7 100644 --- a/include/qemu/atomic.h +++ b/include/qemu/atomic.h @@ -442,4 +442,12 @@ } while(0) #endif +#define atomic_fetch_inc_nonzero(ptr) ({ \ + typeof_strip_qual(*ptr) _oldn = atomic_read(ptr); \ + while (_oldn && atomic_cmpxchg(ptr, _oldn, _oldn + 1) != _oldn) { \ + _oldn = atomic_read(ptr); \ + } \ + _oldn; \ +}) + #endif /* QEMU_ATOMIC_H */ -- cgit 1.4.1