diff options
| author | David Lönnhager <david.l@mullvad.net> | 2025-09-01 21:53:37 +0200 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2025-09-08 16:13:40 +0200 |
| commit | f49ad36f034dfd8eb719a25c9d55d80d69f63bfa (patch) | |
| tree | 9c622ffdd3ae8b7611ad0222cca4a97571d4dd03 /windows | |
| parent | 5c5f1a18c5ab656fe9b4ec253f71e4b6d3587da3 (diff) | |
| download | mullvadvpn-f49ad36f034dfd8eb719a25c9d55d80d69f63bfa.tar.xz mullvadvpn-f49ad36f034dfd8eb719a25c9d55d80d69f63bfa.zip | |
Log active WFP sessions on transaction lock timeout
Diffstat (limited to 'windows')
| -rw-r--r-- | windows/winfw/src/winfw/winfw.cpp | 91 |
1 files changed, 90 insertions, 1 deletions
diff --git a/windows/winfw/src/winfw/winfw.cpp b/windows/winfw/src/winfw/winfw.cpp index d962965a19..064532235c 100644 --- a/windows/winfw/src/winfw/winfw.cpp +++ b/windows/winfw/src/winfw/winfw.cpp @@ -6,10 +6,15 @@ #include "rules/persistent/blockall.h" #include "rules/baseline/blockall.h" #include "libwfp/ipnetwork.h" +#include "libwfp/filterengine.h" +#include "libwfp/objectenumerator.h" #include <windows.h> #include <libcommon/error.h> #include <libcommon/string.h> #include <optional> +#include <psapi.h> +#include <sstream> +#include <set> namespace { @@ -21,6 +26,88 @@ void *g_logSinkContext = nullptr; FwContext *g_fwContext = nullptr; +// Log the filename of active WFP sessions as comma-separated values. Note that the path is not logged. +// If the process can not be opened or its filename can not be obtained, the process ID is logged instead. +void +LogActiveWfpSessions() +{ + if (nullptr == g_logSink) + { + return; + } + + try + { + auto engine = wfp::FilterEngine::DynamicSession(); + std::set<DWORD> sessionPids; + + wfp::ObjectEnumerator::Sessions(*engine, [&sessionPids](const FWPM_SESSION0 &session) -> bool + { + if (session.processId != 0) + { + sessionPids.insert(session.processId); + } + return true; + }); + + if (sessionPids.empty()) + { + g_logSink(MULLVAD_LOG_LEVEL_DEBUG, "No active WFP sessions found", g_logSinkContext); + return; + } + + std::stringstream ss; + ss << "Active WFP sessions from processes: "; + bool first = true; + + for (DWORD pid : sessionPids) + { + if (!first) + { + ss << ", "; + } + first = false; + + HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid); + if (nullptr == hProcess) + { + // Log pid only if we cannot open the process + ss << "PID:" << pid; + continue; + } + + wchar_t processPath[MAX_PATH]; + DWORD pathSize = MAX_PATH; + if (QueryFullProcessImageNameW(hProcess, 0, processPath, &pathSize)) + { + // Extract just the filename + wchar_t *filename = wcsrchr(processPath, L'\\'); + if (nullptr != filename) + { + filename++; + } + else + { + filename = processPath; + } + ss << common::string::ToAnsi(filename); + } + else + { + // Log pid only if we cannot obtain the path + ss << "PID:" << pid; + } + CloseHandle(hProcess); + } + + g_logSink(MULLVAD_LOG_LEVEL_DEBUG, ss.str().c_str(), g_logSinkContext); + } + catch (...) + { + g_logSink(MULLVAD_LOG_LEVEL_ERROR, "Failed to log WFP sessions", g_logSinkContext); + } +} + WINFW_POLICY_STATUS HandlePolicyException(const common::error::WindowsException &err) { @@ -31,7 +118,9 @@ HandlePolicyException(const common::error::WindowsException &err) if (FWP_E_TIMEOUT == err.errorCode()) { - // TODO: Detect software that may cause this + // Log processes potentially holding the transaction lock + LogActiveWfpSessions(); + return WINFW_POLICY_STATUS_LOCK_TIMEOUT; } |
