Commit 682f8623a8 for qemu.org
commit 682f8623a85c9e4febb7cbf309b827c778a3493e
Author: Marc-André Lureau <marcandre.lureau@redhat.com>
Date: Mon Sep 7 14:50:00 2026 +0400
qga/vss-win32: fix race condition in COM Release() methods
All three Release() implementations checked the member m_nRefCount
after InterlockedDecrement instead of using the local return value.
In a multi-threaded context (vssvc), two threads decrementing
concurrently could both read m_nRefCount as 0 and double-free.
Fixes: b39297aedfab ("qemu-ga: Add Windows VSS provider and requester as DLL")
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Kostiantyn Kostiuk <kkostiuk@redhat.com>
Link: https://lore.kernel.org/qemu-devel/20260907-qga-v1-2-86456ad356e2@redhat.com
Signed-off-by: Kostiantyn Kostiuk <kkostiuk@redhat.com>
diff --git a/qga/vss-win32/provider.cpp b/qga/vss-win32/provider.cpp
index 2b5c6f8e8e..79906dcc24 100644
--- a/qga/vss-win32/provider.cpp
+++ b/qga/vss-win32/provider.cpp
@@ -108,7 +108,7 @@ STDMETHODIMP_(ULONG) CQGAVSSEnumObject::AddRef()
STDMETHODIMP_(ULONG) CQGAVSSEnumObject::Release()
{
long nRefCount = InterlockedDecrement(&m_nRefCount);
- if (m_nRefCount == 0) {
+ if (nRefCount == 0) {
delete this;
}
return nRefCount;
@@ -244,7 +244,7 @@ STDMETHODIMP_(ULONG) CQGAVssProvider::AddRef()
STDMETHODIMP_(ULONG) CQGAVssProvider::Release()
{
long nRefCount = InterlockedDecrement(&m_nRefCount);
- if (m_nRefCount == 0) {
+ if (nRefCount == 0) {
delete this;
}
return nRefCount;
@@ -477,7 +477,7 @@ STDMETHODIMP_(ULONG) CQGAVssProviderFactory::AddRef()
STDMETHODIMP_(ULONG) CQGAVssProviderFactory::Release()
{
long nRefCount = InterlockedDecrement(&m_nRefCount);
- if (m_nRefCount == 0) {
+ if (nRefCount == 0) {
delete this;
}
return nRefCount;