wine/dlls/combase
Jinoh Kang e308b19ac8 combase: Prevent use-after-free due to a race with proxy_manager_destroy.
Today, find_proxy_manager() may return a proxy manager that is about to
be freed.  This happens when the proxy manager's reference count reaches
zero, but proxy_manager_destroy() has not removed the proxy manager from
the apartment proxy list.

Fix this by incrementing the reference count only if it is already
nonzero.  If the reference count is zero, any reference to the proxy
manager will become invalid after the current thread leaves the critical
section (apt->cs).  This is because proxy_manager_destroy() will proceed
to destroy the proxy manager after the apartment lock (apt->cs) is
released.

An alternative solution would be to prevent find_proxy_manager from
observing the zero reference count in the first place.  Multiple
approaches have been considered for implementing this solution, but were
eventually dropped due to several disadvantages when applied to the
current Wine codebase:

1. Always acquire the apartment lock from the proxy manager's Release()
   method, and hold the lock until the proxy manager is completely
   removed from the list if the reference count drops to zero.

   This requires handling the special case when the proxy manager's
   parent apartment has been destroyed.  When an apartment is destroyed,
   it sets the `parent` field of each proxy manager that was previously
   owned by the apartment to NULL.  This means that each access to
   `This->parent->cs` has to be guarded by a NULL check for
   `This->parent`.

   Even if `parent` were never NULL, unconditionally acquiring a lock
   may unnecessarily block the subroutine and introduce contention.

2. Opportunistically decrement the reference count without holding the
   lock, but only if the count is greater than 1.  This approach is
   still not free from the NULL parent apartment problem.

3. Check for any concurrent reference count change from
   proxy_manager_destroy(), and bail out if such change has occurred.
   This makes it possible for the proxy manager's AddRef() method to
   return 1, which is unusual.
2023-05-18 05:27:44 -05:00
..
tests combase: Lookup activatable class library in the activation context. 2022-05-20 12:24:38 +02:00
apartment.c combase: Use CRT memory allocation functions. 2022-05-20 12:24:38 +02:00
combase.c combase: Avoid calling RtlInitUnicodeString on a static constant. 2023-02-07 17:46:14 +01:00
combase.spec combase: Add RoSetErrorReportingFlags() stub. 2022-03-02 20:17:25 +01:00
combase_private.h combase: Use CRT memory allocation functions. 2022-05-20 12:24:38 +02:00
dcom.idl
errorinfo.c include: Use proper dllimports for OLE functions. 2022-12-07 13:51:37 +01:00
hglobalstream.c combase: Fix reading from beyond the end of a HGLOBAL stream. 2023-05-15 11:26:12 -05:00
irpcss.idl
Makefile.in include: Use proper dllimports for OLE functions. 2022-12-07 13:51:37 +01:00
malloc.c combase: Use CRT memory allocation functions. 2022-05-20 12:24:38 +02:00
marshal.c combase: Prevent use-after-free due to a race with proxy_manager_destroy. 2023-05-18 05:27:44 -05:00
roapi.c combase: Lookup activatable class library in the activation context. 2022-05-20 12:24:38 +02:00
rpc.c combase: Execute local server for correct architecture in a WoW64 setup. 2022-07-04 23:33:23 +02:00
string.c combase: Use CRT memory allocation functions. 2022-05-20 12:24:38 +02:00
stubmanager.c combase: Check that process ID matches before searching the MTA for a stub manager. 2023-05-08 20:01:10 +02:00
usrmarshal.c combase: Use CRT memory allocation functions. 2022-05-20 12:24:38 +02:00