Use after free in GWin32FileMonitor
On Win32 platform, when a GFileMonitor
gets cancelled with g_file_monitor_cancel()
, the underlying HANDLE object monitor->hDirectory
gets closed, then the OS will notify us through g_win32_fs_monitor_callback()
, which checks the cancelled flag and, if set, will free the GWin32FSMonitorPrivate
instance, even before it's disposed!
In case g_win32_fs_monitor_finalize
gets called afterwards, it will try to free again the GWin32FSMonitorPrivate instance members, and will crash if it has been overwritten on the heap since the previous free from the callback.
Typical reproducer: in Python, the disposal/finalization is done at garbage collection, which can happen a long time after the cancellation callback was processed, letting enough time to corrupt the heap where the GFileMonitor was allocated.
Typical "good" trace
When the GFileMonitor gets freed immediately after the "cancel" (typically how it happens in C code), we observe this kind of trace:
--- User calls g_free(my_gfilemonitor)
GLocalFileMonitor dispose
GFileMonitorSource dispose
GFileMonitor dispose
GWin32FileMonitor finalize
GWin32FSMonitorPrivate finalize
\_ sets monitor->self = NULL
GLocalFileMonitor finalize
GFileMonitorSource finalize
...
--- Win32 notifies CloseHandle result
g_win32_fs_monitor_callback
\_ if (monitor->self == NULL) g_free (monitor);
Typical "bad" trace
When the GFileMonitor gets freed late after the "cancel" (typically a late garbage collection from Python), we observe this kind of trace:
--- Win32 notifies CloseHandle result
g_win32_fs_monitor_callback
\_ if (g_file_monitor_is_cancelled (monitor->self)) g_free (monitor);
...
(app running, something overwrites the heap)
...
--- python gc.collect()
GLocalFileMonitor dispose
GFileMonitorSource dispose
GFileMonitor dispose
GWin32FileMonitor finalize
GWin32FSMonitorPrivate finalize
\_ g_free (monitor->wfullpath_with_long_prefix); --> pointer address corrupted --> BOOM!!!
Backtrace
Crash (use-after-free), when g_win32_fs_monitor_finalize
tries to free the file paths:
Additional information
Observed on Windows10 + msys2, official package mingw-w64-ucrt-x86_64-glib2 2.78.4-2
Debugged on today's git commit d8e4f39a, self-compiled.