From b6acae43b667db289e1d678a6555a878f80dd3ca Mon Sep 17 00:00:00 2001 From: Vladimir Stoilov Date: Fri, 12 Aug 2022 02:26:42 -0700 Subject: [PATCH 1/4] Clear cache function --- col/packet_cache.c | 13 +++++++++++++ col/verdict_cache.c | 20 +++++++++++++++++++- dll/pm_api.c | 5 +++++ include/packet_cache.h | 8 ++++++++ include/pm_api.h | 8 ++++++++ include/pm_callouts.h | 2 ++ include/pm_common.h | 4 +++- include/verdict_cache.h | 9 +++++++++ sys/pm_callouts.c | 22 +++++++++++++++++++++- sys/pm_kernel.c | 7 ++++++- 10 files changed, 94 insertions(+), 4 deletions(-) diff --git a/col/packet_cache.c b/col/packet_cache.c index cccc8db..4236a88 100644 --- a/col/packet_cache.c +++ b/col/packet_cache.c @@ -230,3 +230,16 @@ int get_packet(packet_cache_t* packet_cache, uint32_t packet_id, void** packet, } return 1; } + +void clear_all_entries_from_packet_cache(packet_cache_t* packet_cache) { + packet_cache_item_t *item = packet_cache->head; + while(item != NULL) { + packet_cache_item_t *next = item->next; + _FREE(item); + item = next; + } + packet_cache->size = 0; + packet_cache->head = NULL; + packet_cache->tail = NULL; + packet_cache->next_packet_id = 1; +} diff --git a/col/verdict_cache.c b/col/verdict_cache.c index c3af595..7996656 100644 --- a/col/verdict_cache.c +++ b/col/verdict_cache.c @@ -88,6 +88,24 @@ int clean_verdict_cache(verdict_cache_t* verdict_cache, pportmaster_packet_info* return 1; } +/** + * @brief Remove all items from verdict cache + * + * @par verdict_cache = verdict_cache to use + * + */ +void clear_all_entries_from_verdict_cache(verdict_cache_t* verdict_cache) { + verdict_cache_item_t *item = verdict_cache->head; + while(item != NULL) { + verdict_cache_item_t *next = item->next; + _FREE(item); + item = next; + } + verdict_cache->size = 0; + verdict_cache->head = NULL; + verdict_cache->tail = NULL; +} + /** * @brief Tears down the verdict cache @@ -166,7 +184,7 @@ verdict_t check_verdict(verdict_cache_t* verdict_cache, pportmaster_packet_info // check first item if (compare_full_packet_info(packet_info, verdict_cache->head->packet_info)) { - DEBUG("compare_full_packet_info sucessful"); + DEBUG("compare_full_packet_info successful"); return verdict_cache->head->verdict; } diff --git a/dll/pm_api.c b/dll/pm_api.c index b646f84..9357b9e 100644 --- a/dll/pm_api.c +++ b/dll/pm_api.c @@ -186,6 +186,11 @@ extern _EXPORT UINT32 PortmasterGetPayload(UINT32 packet_id, UINT8* buf, UINT32* return rc; } +extern _EXPORT int PortmasterClearCache() { + int rc = 0; + rc = DeviceIoControl(handle, IOCTL_CLEAR_CACHE, NULL, 0, NULL, 0, NULL, NULL); + return rc; +} #ifdef DEBUG_ON diff --git a/include/packet_cache.h b/include/packet_cache.h index 5ac2334..6af2fa4 100644 --- a/include/packet_cache.h +++ b/include/packet_cache.h @@ -71,6 +71,14 @@ int create_packet_cache(uint32_t max_size, packet_cache_t** packet_cache); */ int clean_packet_cache(packet_cache_t* packet_cache, pportmaster_packet_info * packet_info, void** packet); +/** + * @brief Remove all items from packet cache + * + * @par packet_cache = packet_cache to use + * + */ +void clear_all_entries_from_packet_cache(packet_cache_t* packet_cache); + /** * @brief Tears down the packet cache * diff --git a/include/pm_api.h b/include/pm_api.h index 33a5324..2142d53 100644 --- a/include/pm_api.h +++ b/include/pm_api.h @@ -101,6 +101,14 @@ extern _EXPORT int PortmasterSetVerdict(__in UINT32 packet_id, __in verdict_t ve */ extern _EXPORT UINT32 PortmasterGetPayload(__in UINT32 packet_id, __out UINT8* buf, __inout UINT32* len); +/* + * Get Reset connection cache + * + * returns: ERROR_SUCCESS: SUCCESS + any GetLastError(): in case of unsuccessful communication with kernel (DeviceIoControl) + */ +extern _EXPORT int PortmasterClearCache(); + #ifdef __cplusplus } #endif diff --git a/include/pm_callouts.h b/include/pm_callouts.h index d21a220..de38fbc 100644 --- a/include/pm_callouts.h +++ b/include/pm_callouts.h @@ -104,5 +104,7 @@ extern void redir(pportmaster_packet_info packet_info, pportmaster_packet_info r //extern void redir(FWPS_CLASSIFY_OUT* classifyOut, pportmaster_packet_info packet_info, PNET_BUFFER nb, BOOL dns); extern NTSTATUS genericFlowDelete(UINT16 layerId, UINT32 calloutId, UINT64 flowContext); extern void destroyCalloutStructure(); +void clearCache(); + #endif // include guard diff --git a/include/pm_common.h b/include/pm_common.h index 1a4e2a1..12eb8dc 100644 --- a/include/pm_common.h +++ b/include/pm_common.h @@ -196,8 +196,10 @@ typedef struct { CTL_CODE(SIOCTL_TYPE, 0x803, METHOD_BUFFERED, FILE_READ_DATA|FILE_WRITE_DATA) #define IOCTL_GET_PAYLOAD \ -CTL_CODE(SIOCTL_TYPE, 0x804, METHOD_BUFFERED, FILE_READ_DATA|FILE_WRITE_DATA) + CTL_CODE(SIOCTL_TYPE, 0x804, METHOD_BUFFERED, FILE_READ_DATA|FILE_WRITE_DATA) +#define IOCTL_CLEAR_CACHE \ + CTL_CODE(SIOCTL_TYPE, 0x805, METHOD_BUFFERED, FILE_READ_DATA|FILE_WRITE_DATA) /****************************************************************************/ /* MISC */ diff --git a/include/verdict_cache.h b/include/verdict_cache.h index 9f1b4fe..03825b9 100644 --- a/include/verdict_cache.h +++ b/include/verdict_cache.h @@ -44,6 +44,7 @@ typedef struct verdict_cache { */ extern int create_verdict_cache(UINT32 max_size, verdict_cache_t** verdict_cache); + /** * @brief Cleans the verdict cache * @@ -54,6 +55,14 @@ extern int create_verdict_cache(UINT32 max_size, verdict_cache_t** verdict_cache */ extern int clean_verdict_cache(verdict_cache_t* verdict_cache, portmaster_packet_info** packet_info); +/** + * @brief Remove all items from verdict cache + * + * @par verdict_cache = verdict_cache to use + * + */ +void clear_all_entries_from_verdict_cache(verdict_cache_t* verdict_cache); + /** * @brief Tears down the verdict cache * diff --git a/sys/pm_callouts.c b/sys/pm_callouts.c index 407e463..ab7c035 100644 --- a/sys/pm_callouts.c +++ b/sys/pm_callouts.c @@ -1530,7 +1530,7 @@ void classifyInboundIPv6( classifyOut->actionType = FWP_ACTION_BLOCK; return; } - + inboundV6PacketInfo.direction = 1; inboundV6PacketInfo.ipV6 = 1; @@ -1618,3 +1618,23 @@ void classifyOutboundIPv6( classifyMultiple(&outboundV6PacketInfo, verdictCacheV6, &verdictCacheV6Lock, inMetaValues, layerData, classifyOut); return; } + +void clearCache() { + KLOCK_QUEUE_HANDLE lock_handle; + INFO("Cleaning all cache"); + + // Clear IPv4 verdict cache + KeAcquireInStackQueuedSpinLock(&verdictCacheV4Lock, &lock_handle); + clear_all_entries_from_verdict_cache(verdictCacheV4); + KeReleaseInStackQueuedSpinLock(&lock_handle); + + // Clear IPv6 verdict cache + KeAcquireInStackQueuedSpinLock(&verdictCacheV6Lock, &lock_handle); + clear_all_entries_from_verdict_cache(verdictCacheV6); + KeReleaseInStackQueuedSpinLock(&lock_handle); + + // Clear packet cache + KeAcquireInStackQueuedSpinLock(&packetCacheLock, &lock_handle); + clear_all_entries_from_packet_cache(packetCache); + KeReleaseInStackQueuedSpinLock(&lock_handle); +} \ No newline at end of file diff --git a/sys/pm_kernel.c b/sys/pm_kernel.c index 3f5a29f..bbc9867 100644 --- a/sys/pm_kernel.c +++ b/sys/pm_kernel.c @@ -463,7 +463,12 @@ NTSTATUS driver_device_control(__in PDEVICE_OBJECT pDeviceObject, __inout PIRP IoCompleteRequest(Irp, IO_NO_INCREMENT); return rc; } - + case IOCTL_CLEAR_CACHE: { + clearCache(); + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp,IO_NO_INCREMENT); + return STATUS_SUCCESS; + } default: { ERR("Don't know how to deal with IoControlCode 0x%x", IoControlCode); Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; From 3ba977c7db3b850e0aa635d162e4ee1993da42ad Mon Sep 17 00:00:00 2001 From: Vladimir Stoilov Date: Fri, 12 Aug 2022 02:26:42 -0700 Subject: [PATCH 2/4] Clear cache function --- include/packet_cache.h | 8 ++++++++ include/pm_api.h | 8 ++++++++ include/pm_callouts.h | 2 ++ include/pm_common.h | 4 +++- include/verdict_cache.h | 9 +++++++++ pm_kext/col/packet_cache.c | 13 +++++++++++++ pm_kext/col/verdict_cache.c | 20 +++++++++++++++++++- pm_kext/src/pm_callouts.c | 22 +++++++++++++++++++++- pm_kext/src/pm_kernel.c | 7 ++++++- pm_kext_glue_dll/src/pm_api.c | 5 +++++ 10 files changed, 94 insertions(+), 4 deletions(-) diff --git a/include/packet_cache.h b/include/packet_cache.h index 5ac2334..6af2fa4 100644 --- a/include/packet_cache.h +++ b/include/packet_cache.h @@ -71,6 +71,14 @@ int create_packet_cache(uint32_t max_size, packet_cache_t** packet_cache); */ int clean_packet_cache(packet_cache_t* packet_cache, pportmaster_packet_info * packet_info, void** packet); +/** + * @brief Remove all items from packet cache + * + * @par packet_cache = packet_cache to use + * + */ +void clear_all_entries_from_packet_cache(packet_cache_t* packet_cache); + /** * @brief Tears down the packet cache * diff --git a/include/pm_api.h b/include/pm_api.h index ee1cb11..615dde9 100644 --- a/include/pm_api.h +++ b/include/pm_api.h @@ -101,6 +101,14 @@ extern _EXPORT int PortmasterSetVerdict(__in UINT32 packet_id, __in verdict_t ve */ extern _EXPORT UINT32 PortmasterGetPayload(__in UINT32 packet_id, __out UINT8* buf, __inout UINT32* len); +/* + * Get Reset connection cache + * + * returns: ERROR_SUCCESS: SUCCESS + any GetLastError(): in case of unsuccessful communication with kernel (DeviceIoControl) + */ +extern _EXPORT int PortmasterClearCache(); + #ifdef __cplusplus } #endif diff --git a/include/pm_callouts.h b/include/pm_callouts.h index d21a220..de38fbc 100644 --- a/include/pm_callouts.h +++ b/include/pm_callouts.h @@ -104,5 +104,7 @@ extern void redir(pportmaster_packet_info packet_info, pportmaster_packet_info r //extern void redir(FWPS_CLASSIFY_OUT* classifyOut, pportmaster_packet_info packet_info, PNET_BUFFER nb, BOOL dns); extern NTSTATUS genericFlowDelete(UINT16 layerId, UINT32 calloutId, UINT64 flowContext); extern void destroyCalloutStructure(); +void clearCache(); + #endif // include guard diff --git a/include/pm_common.h b/include/pm_common.h index 2cf57de..58e0040 100644 --- a/include/pm_common.h +++ b/include/pm_common.h @@ -209,8 +209,10 @@ typedef struct { CTL_CODE(SIOCTL_TYPE, 0x803, METHOD_BUFFERED, FILE_READ_DATA|FILE_WRITE_DATA) #define IOCTL_GET_PAYLOAD \ -CTL_CODE(SIOCTL_TYPE, 0x804, METHOD_BUFFERED, FILE_READ_DATA|FILE_WRITE_DATA) + CTL_CODE(SIOCTL_TYPE, 0x804, METHOD_BUFFERED, FILE_READ_DATA|FILE_WRITE_DATA) +#define IOCTL_CLEAR_CACHE \ + CTL_CODE(SIOCTL_TYPE, 0x805, METHOD_BUFFERED, FILE_READ_DATA|FILE_WRITE_DATA) /****************************************************************************/ /* MISC */ diff --git a/include/verdict_cache.h b/include/verdict_cache.h index 9f1b4fe..03825b9 100644 --- a/include/verdict_cache.h +++ b/include/verdict_cache.h @@ -44,6 +44,7 @@ typedef struct verdict_cache { */ extern int create_verdict_cache(UINT32 max_size, verdict_cache_t** verdict_cache); + /** * @brief Cleans the verdict cache * @@ -54,6 +55,14 @@ extern int create_verdict_cache(UINT32 max_size, verdict_cache_t** verdict_cache */ extern int clean_verdict_cache(verdict_cache_t* verdict_cache, portmaster_packet_info** packet_info); +/** + * @brief Remove all items from verdict cache + * + * @par verdict_cache = verdict_cache to use + * + */ +void clear_all_entries_from_verdict_cache(verdict_cache_t* verdict_cache); + /** * @brief Tears down the verdict cache * diff --git a/pm_kext/col/packet_cache.c b/pm_kext/col/packet_cache.c index 5efc8b8..5bdf787 100644 --- a/pm_kext/col/packet_cache.c +++ b/pm_kext/col/packet_cache.c @@ -237,3 +237,16 @@ int get_packet(packet_cache_t* packet_cache, uint32_t packet_id, void** packet, } return 1; } + +void clear_all_entries_from_packet_cache(packet_cache_t* packet_cache) { + packet_cache_item_t *item = packet_cache->head; + while(item != NULL) { + packet_cache_item_t *next = item->next; + _FREE(item); + item = next; + } + packet_cache->size = 0; + packet_cache->head = NULL; + packet_cache->tail = NULL; + packet_cache->next_packet_id = 1; +} diff --git a/pm_kext/col/verdict_cache.c b/pm_kext/col/verdict_cache.c index e3a2d98..51aeadd 100644 --- a/pm_kext/col/verdict_cache.c +++ b/pm_kext/col/verdict_cache.c @@ -91,6 +91,24 @@ int clean_verdict_cache(verdict_cache_t* verdict_cache, pportmaster_packet_info* return 1; } +/** + * @brief Remove all items from verdict cache + * + * @par verdict_cache = verdict_cache to use + * + */ +void clear_all_entries_from_verdict_cache(verdict_cache_t* verdict_cache) { + verdict_cache_item_t *item = verdict_cache->head; + while(item != NULL) { + verdict_cache_item_t *next = item->next; + _FREE(item); + item = next; + } + verdict_cache->size = 0; + verdict_cache->head = NULL; + verdict_cache->tail = NULL; +} + /** * @brief Tears down the verdict cache @@ -169,7 +187,7 @@ verdict_t check_verdict(verdict_cache_t* verdict_cache, pportmaster_packet_info // check first item if (compare_full_packet_info(packet_info, verdict_cache->head->packet_info)) { - DEBUG("compare_full_packet_info sucessful"); + DEBUG("compare_full_packet_info successful"); return verdict_cache->head->verdict; } diff --git a/pm_kext/src/pm_callouts.c b/pm_kext/src/pm_callouts.c index 3818f55..c7f8030 100644 --- a/pm_kext/src/pm_callouts.c +++ b/pm_kext/src/pm_callouts.c @@ -1532,7 +1532,7 @@ void classifyInboundIPv6( classifyOut->actionType = FWP_ACTION_BLOCK; return; } - + inboundV6PacketInfo.direction = 1; inboundV6PacketInfo.ipV6 = 1; @@ -1620,3 +1620,23 @@ void classifyOutboundIPv6( classifyMultiple(&outboundV6PacketInfo, verdictCacheV6, &verdictCacheV6Lock, inMetaValues, layerData, classifyOut); return; } + +void clearCache() { + KLOCK_QUEUE_HANDLE lock_handle; + INFO("Cleaning all cache"); + + // Clear IPv4 verdict cache + KeAcquireInStackQueuedSpinLock(&verdictCacheV4Lock, &lock_handle); + clear_all_entries_from_verdict_cache(verdictCacheV4); + KeReleaseInStackQueuedSpinLock(&lock_handle); + + // Clear IPv6 verdict cache + KeAcquireInStackQueuedSpinLock(&verdictCacheV6Lock, &lock_handle); + clear_all_entries_from_verdict_cache(verdictCacheV6); + KeReleaseInStackQueuedSpinLock(&lock_handle); + + // Clear packet cache + KeAcquireInStackQueuedSpinLock(&packetCacheLock, &lock_handle); + clear_all_entries_from_packet_cache(packetCache); + KeReleaseInStackQueuedSpinLock(&lock_handle); +} \ No newline at end of file diff --git a/pm_kext/src/pm_kernel.c b/pm_kext/src/pm_kernel.c index 3f5a29f..bbc9867 100644 --- a/pm_kext/src/pm_kernel.c +++ b/pm_kext/src/pm_kernel.c @@ -463,7 +463,12 @@ NTSTATUS driver_device_control(__in PDEVICE_OBJECT pDeviceObject, __inout PIRP IoCompleteRequest(Irp, IO_NO_INCREMENT); return rc; } - + case IOCTL_CLEAR_CACHE: { + clearCache(); + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp,IO_NO_INCREMENT); + return STATUS_SUCCESS; + } default: { ERR("Don't know how to deal with IoControlCode 0x%x", IoControlCode); Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; diff --git a/pm_kext_glue_dll/src/pm_api.c b/pm_kext_glue_dll/src/pm_api.c index f15e7bb..71c1c55 100644 --- a/pm_kext_glue_dll/src/pm_api.c +++ b/pm_kext_glue_dll/src/pm_api.c @@ -186,6 +186,11 @@ extern _EXPORT UINT32 PortmasterGetPayload(UINT32 packet_id, UINT8* buf, UINT32* return rc; } +extern _EXPORT int PortmasterClearCache() { + int rc = 0; + rc = DeviceIoControl(handle, IOCTL_CLEAR_CACHE, NULL, 0, NULL, 0, NULL, NULL); + return rc; +} #ifdef DEBUG_ON From 62643185c9824ea3671eb97c0d5158bac3ab8701 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Wed, 7 Sep 2022 07:52:51 -0700 Subject: [PATCH 3/4] Refactoring --- deploy.bat | 24 ++++++------ include/pm_common.h | 6 ++- pm_kext/col/verdict_cache.c | 25 +++++++++++-- pm_kext/include/pm_callouts.h | 3 ++ pm_kext/include/verdict_cache.h | 8 ++++ pm_kext/src/pm_callouts.c | 15 ++++++++ pm_kext/src/pm_kernel.c | 7 +++- pm_kext_glue_dll/include/pm_api.h | 18 ++++++--- pm_kext_glue_dll/src/pm_api.c | 61 +++++++++++++++---------------- 9 files changed, 113 insertions(+), 54 deletions(-) diff --git a/deploy.bat b/deploy.bat index 0906b6b..bb283bf 100644 --- a/deploy.bat +++ b/deploy.bat @@ -1,13 +1,13 @@ -echo Compile, Sign and Copy the Kernel Driver with the dll -set WDDK_SOURCE=install\WDDK\x64\Debug\pm_kernel64.sys -del WDDK_SOURCE - -set DLL_SOURCE=install\DLL\x64\pm_kernel_glue.dll -del DLL_SOURCE - -msbuild /t:Build /p:Configuration=Debug /p:Platform=x64 -SignTool sign /v /s TestCertStoreName /n TestCertName /fd SHA256 %WDDK_SOURCE% - -echo Copy the Kernel Driver to Portmaster updates dir as dev version -copy %WDDK_SOURCE% C:\ProgramData\Safing\Portmaster\updates\windows_amd64\kext\portmaster-kext_v0-0-0.sys +echo Compile, Sign and Copy the Kernel Driver with the dll +set WDDK_SOURCE=install\WDDK\x64\Debug\pm_kernel64.sys +del WDDK_SOURCE + +set DLL_SOURCE=install\DLL\x64\Debug\pm_kernel_glue.dll +del DLL_SOURCE + +msbuild /t:Build /p:Configuration=Debug /p:Platform=x64 +SignTool sign /v /s TestCertStoreName /n TestCertName /fd SHA256 %WDDK_SOURCE% + +echo Copy the Kernel Driver to Portmaster updates dir as dev version +copy %WDDK_SOURCE% C:\ProgramData\Safing\Portmaster\updates\windows_amd64\kext\portmaster-kext_v0-0-0.sys copy %DLL_SOURCE% C:\ProgramData\Safing\Portmaster\updates\windows_amd64\kext\portmaster-kext_v0-0-0.dll \ No newline at end of file diff --git a/include/pm_common.h b/include/pm_common.h index 3c4e4cf..30397f4 100644 --- a/include/pm_common.h +++ b/include/pm_common.h @@ -203,14 +203,16 @@ typedef struct { CTL_CODE(SIOCTL_TYPE, 0x801, METHOD_BUFFERED, FILE_READ_DATA|FILE_WRITE_DATA) #define IOCTL_RECV_VERDICT_REQ \ - CTL_CODE(SIOCTL_TYPE, 0x802, METHOD_BUFFERED, FILE_READ_DATA|FILE_WRITE_DATA) + CTL_CODE(SIOCTL_TYPE, 0x802, METHOD_BUFFERED, FILE_READ_DATA|FILE_WRITE_DATA) #define IOCTL_SET_VERDICT \ CTL_CODE(SIOCTL_TYPE, 0x803, METHOD_BUFFERED, FILE_READ_DATA|FILE_WRITE_DATA) #define IOCTL_GET_PAYLOAD \ -CTL_CODE(SIOCTL_TYPE, 0x804, METHOD_BUFFERED, FILE_READ_DATA|FILE_WRITE_DATA) + CTL_CODE(SIOCTL_TYPE, 0x804, METHOD_BUFFERED, FILE_READ_DATA|FILE_WRITE_DATA) +#define IOCTL_CLEAR_CACHE \ + CTL_CODE(SIOCTL_TYPE, 0x805, METHOD_BUFFERED, FILE_READ_DATA|FILE_WRITE_DATA) /****************************************************************************/ /* MISC */ diff --git a/pm_kext/col/verdict_cache.c b/pm_kext/col/verdict_cache.c index 75783e7..25034d0 100644 --- a/pm_kext/col/verdict_cache.c +++ b/pm_kext/col/verdict_cache.c @@ -76,8 +76,9 @@ int cleanVerdictCache(VerdictCache *verdictCache, PortmasterPacketInfo **packetI // delete next of new last item lastItem->prev->next = NULL; } else { - // reset tail (list is empty!) + // list is empty! reset it verdictCache->tail = NULL; + verdictCache->head = NULL; } // set return value @@ -93,6 +94,24 @@ int cleanVerdictCache(VerdictCache *verdictCache, PortmasterPacketInfo **packetI return 1; } +/** + * @brief Remove all items from verdict cache + * + * @par verdictCache = verdict_cache to use + * + */ +void clearAllEntriesFromVerdictCache(VerdictCache *verdictCache) { + VerdictCacheItem *item = verdictCache->head; + while(item != NULL) { + VerdictCacheItem *next = item->next; + _FREE(item); + item = next; + } + verdictCache->size = 0; + verdictCache->head = NULL; + verdictCache->tail = NULL; +} + /** * @brief Tears down the verdict cache @@ -132,14 +151,14 @@ int addVerdict(VerdictCache *verdictCache, PortmasterPacketInfo *packetInfo, ver newItem->verdict = verdict; // insert as first item - if (verdictCache->head) { + if (verdictCache->head != NULL) { newItem->next = verdictCache->head; verdictCache->head->prev = newItem; } verdictCache->head = newItem; // set tail if only item - if (!verdictCache->tail) { + if (verdictCache->tail == NULL) { verdictCache->tail = newItem; } diff --git a/pm_kext/include/pm_callouts.h b/pm_kext/include/pm_callouts.h index c55df7c..637db9c 100644 --- a/pm_kext/include/pm_callouts.h +++ b/pm_kext/include/pm_callouts.h @@ -64,4 +64,7 @@ NTSTATUS genericFlowDelete(UINT16 layerId, UINT32 calloutId, UINT64 flowContext) void respondWithVerdict(UINT32 id, verdict_t verdict); + +void clearCache(); + #endif // PM_CALLOUTS_H diff --git a/pm_kext/include/verdict_cache.h b/pm_kext/include/verdict_cache.h index d8b396a..2a104bf 100644 --- a/pm_kext/include/verdict_cache.h +++ b/pm_kext/include/verdict_cache.h @@ -53,6 +53,14 @@ int createVerdictCache(UINT32 maxSize, VerdictCache **verdict_cache); */ int cleanVerdictCache(VerdictCache *verdictCache, PortmasterPacketInfo **packetInfo); +/** + * @brief Remove all items from verdict cache + * + * @par verdict_cache = verdict_cache to use + * + */ +void clearAllEntriesFromVerdictCache(VerdictCache *verdictCache); + /** * @brief Tears down the verdict cache * diff --git a/pm_kext/src/pm_callouts.c b/pm_kext/src/pm_callouts.c index 3699b46..068f238 100644 --- a/pm_kext/src/pm_callouts.c +++ b/pm_kext/src/pm_callouts.c @@ -959,3 +959,18 @@ void classifyOutboundIPv6( } classifyMultiple(&outboundV6PacketInfo, verdictCacheV6, &verdictCacheV6Lock, inMetaValues, layerData, classifyOut); } + +void clearCache() { + INFO("Cleaning all verdict cache"); + KLOCK_QUEUE_HANDLE lockHandle = {0}; + + // Clear IPv4 verdict cache + KeAcquireInStackQueuedSpinLock(&verdictCacheV4Lock, &lockHandle); + clearAllEntriesFromVerdictCache(verdictCacheV4); + KeReleaseInStackQueuedSpinLock(&lockHandle); + + // Clear IPv6 verdict cache + KeAcquireInStackQueuedSpinLock(&verdictCacheV6Lock, &lockHandle); + clearAllEntriesFromVerdictCache(verdictCacheV6); + KeReleaseInStackQueuedSpinLock(&lockHandle); +} \ No newline at end of file diff --git a/pm_kext/src/pm_kernel.c b/pm_kext/src/pm_kernel.c index 30e3003..9334794 100644 --- a/pm_kext/src/pm_kernel.c +++ b/pm_kext/src/pm_kernel.c @@ -451,7 +451,12 @@ NTSTATUS driverDeviceControl(__in PDEVICE_OBJECT pDeviceObject, __inout PIRP Irp IoCompleteRequest(Irp, IO_NO_INCREMENT); return rc; } - + case IOCTL_CLEAR_CACHE: { + clearCache(); + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp,IO_NO_INCREMENT); + return STATUS_SUCCESS; + } default: { ERR("Don't know how to deal with IoControlCode 0x%x", IoControlCode); Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; diff --git a/pm_kext_glue_dll/include/pm_api.h b/pm_kext_glue_dll/include/pm_api.h index 20a9875..9de9e32 100644 --- a/pm_kext_glue_dll/include/pm_api.h +++ b/pm_kext_glue_dll/include/pm_api.h @@ -35,7 +35,7 @@ extern "C" { /* * Internal initialization for the kernel extension. */ -extern _EXPORT int PortmasterInit(); +extern _EXPORT UINT32 PortmasterInit(); /* * Start intercepting packets. This is called once when Portmaster starts @@ -47,7 +47,7 @@ extern _EXPORT int PortmasterInit(); * ERROR_FILE_NOT_FOUND: path is invalid * Windows System Error Code: according to https://docs.microsoft.com/en-us/windows/desktop/Debug/system-error-codes */ -extern _EXPORT int PortmasterStart(__in const char *portmasterKextPath); +extern _EXPORT UINT32 PortmasterStart(__in const char *portmasterKextPath); /* * Stops the driver and unloads the kernel driver, which runs as a service @@ -55,7 +55,7 @@ extern _EXPORT int PortmasterStart(__in const char *portmasterKextPath); * returns: ERROR_SUCCESS: SUCCESS * windows System Error Code: according to https://docs.microsoft.com/en-us/windows/desktop/Debug/system-error-codes */ -extern _EXPORT int PortmasterStop(); +extern _EXPORT UINT32 PortmasterStop(); /* * "Blocks" the application till unknown packet is received. @@ -68,7 +68,7 @@ extern _EXPORT int PortmasterStop(); * ERROR_INVALID_DATA: No Data received (e.g. Timeout) * windows System Error Code: according to https://docs.microsoft.com/en-us/windows/desktop/Debug/system-error-codes */ -extern _EXPORT int PortmasterRecvVerdictRequest(__out PortmasterPacketInfo *packetInfo); +extern _EXPORT UINT32 PortmasterRecvVerdictRequest(__out PortmasterPacketInfo *packetInfo); /* @@ -84,7 +84,7 @@ extern _EXPORT int PortmasterRecvVerdictRequest(__out PortmasterPacketInfo *pack * returns: ERROR_SUCCESS: SUCCESS * windows System Error Code: according to https://docs.microsoft.com/en-us/windows/desktop/Debug/system-error-codes */ -extern _EXPORT int PortmasterSetVerdict(__in UINT32 packetID, __in verdict_t verdict); +extern _EXPORT UINT32 PortmasterSetVerdict(__in UINT32 packetID, __in verdict_t verdict); /* * Get Payload of packetID @@ -101,6 +101,14 @@ extern _EXPORT int PortmasterSetVerdict(__in UINT32 packetID, __in verdict_t ver */ extern _EXPORT UINT32 PortmasterGetPayload(__in UINT32 packetID, __out UINT8* buf, __inout UINT32* len); +/* + * Get Reset connection cache + * + * returns: ERROR_SUCCESS: on success + any GetLastError(): in case of unsuccessful communication with kernel (DeviceIoControl) + */ +extern _EXPORT UINT32 PortmasterClearCache(); + #ifdef __cplusplus } #endif diff --git a/pm_kext_glue_dll/src/pm_api.c b/pm_kext_glue_dll/src/pm_api.c index 532204e..3b8a2c8 100644 --- a/pm_kext_glue_dll/src/pm_api.c +++ b/pm_kext_glue_dll/src/pm_api.c @@ -49,15 +49,15 @@ int logLevel = LEVEL_DEBUG; * Internal initialization for the kernel extension. * This is a dummy function, since initialization is done in PortmasterStart(). */ -extern _EXPORT int PortmasterInit() { +extern _EXPORT UINT32 PortmasterInit() { INFO("Portmaster Kernel Extension initialized"); - return 0; + return ERROR_SUCCESS; } /* * Start intercepting packets. */ -extern _EXPORT int PortmasterStart(const char* portmasterKextPath) { +extern _EXPORT UINT32 PortmasterStart(const char* portmasterKextPath) { deviceHandle = portmasterKernelOpen(portmasterKextPath); if (deviceHandle == INVALID_HANDLE_VALUE) { DWORD rc = GetLastError(); @@ -65,40 +65,36 @@ extern _EXPORT int PortmasterStart(const char* portmasterKextPath) { return rc; } INFO("OPENED and STARTED Portmaster Kernel Extension"); - return 0; + return ERROR_SUCCESS; } /* * Stops the Portmaster */ -extern _EXPORT int PortmasterStop() { +extern _EXPORT UINT32 PortmasterStop() { int rc = 0; INFO("Stopping Service now"); - rc = CloseHandle(deviceHandle); + bool success = CloseHandle(deviceHandle); INFO("CloseHandle to Portmaster Kernel Extension returned= %d (nonzero is success)", rc); - if (rc == 0) + if (!success) { - rc = GetLastError(); + UINT32 rc = GetLastError(); WARN("GetLastError= 0x%x", rc); } - else - { - rc = 0; - } system("sc stop " PORTMASTER_DEVICE_NAME_C); //This is a question of taste, but it is a robust and solid solution - return rc; + return ERROR_SUCCESS; } -extern _EXPORT int PortmasterRecvVerdictRequest(PortmasterPacketInfo *packetInfo) { +extern _EXPORT UINT32 PortmasterRecvVerdictRequest(PortmasterPacketInfo *packetInfo) { // Check for verdict request char *welcome = "NA"; DWORD dwBytesRead = 0; char ReadBuffer[sizeof(PortmasterPacketInfo) + 1] = {0}; - int rc = DeviceIoControl(deviceHandle, IOCTL_RECV_VERDICT_REQ, welcome, (DWORD)strlen(welcome), ReadBuffer, sizeof(ReadBuffer), &dwBytesRead, NULL); - if (rc == false) { - rc = GetLastError(); + bool success = DeviceIoControl(deviceHandle, IOCTL_RECV_VERDICT_REQ, welcome, (DWORD)strlen(welcome), ReadBuffer, sizeof(ReadBuffer), &dwBytesRead, NULL); + if (!success) { + UINT32 rc = GetLastError(); WARN("DeviceIoControl did not succeed: GetLastError=%d, dwBytesRead=0x%X", rc, dwBytesRead); switch (rc) { default: @@ -108,22 +104,22 @@ extern _EXPORT int PortmasterRecvVerdictRequest(PortmasterPacketInfo *packetInfo } // Process verdict request - if ((rc == true) && (dwBytesRead > 0)) { + if (success && (dwBytesRead > 0)) { INFO("Bytes read : %d, rc = %d", dwBytesRead, rc); PortmasterPacketInfo *PacketInfoFromDevice = (PortmasterPacketInfo*)ReadBuffer; packetToString(PacketInfoFromDevice); memcpy(packetInfo, PacketInfoFromDevice, sizeof(PortmasterPacketInfo)); return ERROR_SUCCESS; } else { - rc = GetLastError(); + UINT32 rc = GetLastError(); WARN("DeviceIoControl returned true but no bytes received, GetLastError=%d", rc); memset(packetInfo, 0, sizeof(PortmasterPacketInfo)); return ERROR_INVALID_DATA; } - + return ERROR_SUCCESS; } -extern _EXPORT int PortmasterSetVerdict(UINT32 packet_id, verdict_t verdict) { +extern _EXPORT UINT32 PortmasterSetVerdict(UINT32 packet_id, verdict_t verdict) { PortmasterVerdictInfo verdictInfo = {0}; char* verdictInfoBuffer = (char*) &verdictInfo; DWORD dwBytesRead = 0; @@ -133,10 +129,10 @@ extern _EXPORT int PortmasterSetVerdict(UINT32 packet_id, verdict_t verdict) { verdictInfo.id = packet_id; verdictInfo.verdict = verdict; - int rc = DeviceIoControl(deviceHandle, IOCTL_SET_VERDICT, verdictInfoBuffer, sizeof(PortmasterVerdictInfo), ReadBuffer, sizeof(ReadBuffer), &dwBytesRead, NULL); - INFO("IOCTL_SET_VERDICT returned %d", rc); - if (rc == false) { - rc = GetLastError(); + bool success = DeviceIoControl(deviceHandle, IOCTL_SET_VERDICT, verdictInfoBuffer, sizeof(PortmasterVerdictInfo), ReadBuffer, sizeof(ReadBuffer), &dwBytesRead, NULL); + INFO("IOCTL_SET_VERDICT returned %d", success); + if (!success) { + UINT32 rc = GetLastError(); WARN("DeviceIoControl did not succeed: GetLastError=%d, dwBytesRead=0x%X", rc, dwBytesRead); switch (rc) { default: @@ -154,10 +150,9 @@ extern _EXPORT UINT32 PortmasterGetPayload(UINT32 packet_id, UINT8* buf, UINT32* PortmasterPayload payload = {0}; payload.id = packet_id; payload.len = *len; - - int rc = DeviceIoControl(deviceHandle, IOCTL_GET_PAYLOAD, (UINT8*) &payload, sizeof(PortmasterPayload), buf, *len, &bytesRead, NULL); - if (rc == false) { - rc = GetLastError(); + bool success = DeviceIoControl(deviceHandle, IOCTL_GET_PAYLOAD, (UINT8*) &payload, sizeof(PortmasterPayload), buf, *len, &bytesRead, NULL); + if (!success) { + UINT32 rc = GetLastError(); WARN("DeviceIoControl did not succeed: GetLastError=%d, bytesRead=0x%X", rc, bytesRead); switch (rc) { case ERROR_NO_SYSTEM_RESOURCES: @@ -173,11 +168,15 @@ extern _EXPORT UINT32 PortmasterGetPayload(UINT32 packet_id, UINT8* buf, UINT32* } *len = bytesRead; - INFO("payload: id=%u, rc=0x%X, len=%u", packet_id, rc, *len); + INFO("payload: id=%u, rc=0x%X, len=%u", packet_id, success, *len); return ERROR_SUCCESS; } +extern _EXPORT UINT32 PortmasterClearCache() { + UINT32 rc = DeviceIoControl(deviceHandle, IOCTL_CLEAR_CACHE, NULL, 0, NULL, 0, NULL, NULL); + return rc; +} #ifdef DEBUGON @@ -186,7 +185,7 @@ extern _EXPORT UINT32 PortmasterGetPayload(UINT32 packet_id, UINT8* buf, UINT32* * Returns the packet and expects the application to return a verdict, * like accept, block, drop, permanentAccept ... */ -extern _EXPORT int PortmasterRecvVerdictRequestHello(PortmasterPacketInfo *packetInfo) { +extern _EXPORT UINT32 PortmasterRecvVerdictRequestHello(PortmasterPacketInfo *packetInfo) { int rc = 0; char *welcome = "Hello from userland."; DWORD dwBytesRead = 0; From fb0f73fc62c84aa665101a2c12124be6da2300d3 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Wed, 7 Sep 2022 08:38:25 -0700 Subject: [PATCH 4/4] Fix compile error --- include/pm_debug.h | 10 +++++----- pm_kext_glue_dll/src/pm_api.c | 2 +- pm_kext_glue_dll/src/pm_debug.c | 3 ++- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/include/pm_debug.h b/include/pm_debug.h index f4613e4..63b07c2 100644 --- a/include/pm_debug.h +++ b/include/pm_debug.h @@ -44,12 +44,12 @@ extern int logLevel; //must be defined in dll and kernel object All we can do is write to a dedicated debug channel and adjust the loglevel at runtime. */ #ifdef DEBUG_ON - #define DEBUG(...) _DEBUG(0, ##__VA_ARGS__) - #define INFO(...) _DEBUG(1, ##__VA_ARGS__) - #define WARN(...) _DEBUG(2, ##__VA_ARGS__) - #define ERR(...) _DEBUG(3, ##__VA_ARGS__) //ERROR is already defined in wingdi.h + #define DEBUG(...) DEBUG_LOG(0, ##__VA_ARGS__) + #define INFO(...) DEBUG_LOG(1, ##__VA_ARGS__) + #define WARN(...) DEBUG_LOG(2, ##__VA_ARGS__) + #define ERR(...) DEBUG_LOG(3, ##__VA_ARGS__) //ERROR is already defined in wingdi.h - #define _DEBUG(level, format, ...) __DEBUG(LOGGER_NAME, level, __LINE__, format, ##__VA_ARGS__) + #define DEBUG_LOG(level, format, ...) __DEBUG(LOGGER_NAME, level, __LINE__, format, ##__VA_ARGS__) void __DEBUG(char *name, int level, int line, char *format, ...); void printIpHeader(char *buf, unsigned long buf_len, char *data, unsigned long dataLength); char* printIpv4Packet(void *packet); diff --git a/pm_kext_glue_dll/src/pm_api.c b/pm_kext_glue_dll/src/pm_api.c index d5139cc..b137c55 100644 --- a/pm_kext_glue_dll/src/pm_api.c +++ b/pm_kext_glue_dll/src/pm_api.c @@ -105,7 +105,7 @@ extern _EXPORT UINT32 PortmasterRecvVerdictRequest(PortmasterPacketInfo *packetI // Process verdict request if (success && (dwBytesRead > 0)) { - INFO("Bytes read : %d, rc = %d", dwBytesRead, rc); + INFO("Bytes read : %d, rc = %d", dwBytesRead, success); PortmasterPacketInfo *PacketInfoFromDevice = (PortmasterPacketInfo*)ReadBuffer; packetToString(PacketInfoFromDevice); memcpy(packetInfo, PacketInfoFromDevice, sizeof(PortmasterPacketInfo)); diff --git a/pm_kext_glue_dll/src/pm_debug.c b/pm_kext_glue_dll/src/pm_debug.c index b658c7f..d4f6a2b 100644 --- a/pm_kext_glue_dll/src/pm_debug.c +++ b/pm_kext_glue_dll/src/pm_debug.c @@ -18,6 +18,7 @@ #include #include +#include #include "pm_common.h" @@ -32,7 +33,7 @@ /* Portmaster Helpers */ /****************************************************************************/ #ifdef DEBUG_ON -void debugPrint(char* name, int level, int line, char* format, ...) { +void __DEBUG(char* name, int level, int line, char* format, ...) { if (level >= logLevel) { va_list args; static char buf[DEBUG_BUFSIZE+1];