From 7a31bf9a8a35f7c076fa8f6d9879353d73525c08 Mon Sep 17 00:00:00 2001 From: Nodir Temirkhodjaev Date: Tue, 10 Dec 2019 15:18:54 +0500 Subject: [PATCH] Driver: Use hash-map for app exe paths. --- src/common/fortconf.c | 53 ++++++++++++++- src/common/fortconf.h | 4 ++ src/common/version.h | 2 +- src/driver/fortcnf.c | 119 ++++++++++++++++++++++++++++++++-- src/driver/fortdrv.c | 3 +- src/tests/confutil/test.cpp | 2 +- src/ui/fortcommon.cpp | 3 +- src/ui/util/conf/confutil.cpp | 3 +- 8 files changed, 178 insertions(+), 11 deletions(-) diff --git a/src/common/fortconf.c b/src/common/fortconf.c index 232f4f38..6a8e2544 100644 --- a/src/common/fortconf.c +++ b/src/common/fortconf.c @@ -99,6 +99,52 @@ fort_conf_ip_included (const PFORT_CONF conf, UINT32 remote_ip, #define fort_conf_ip_inet_included(conf, remote_ip) \ fort_conf_ip_included((conf), (remote_ip), 1) +static BOOL +fort_conf_app_exe_equal (UINT32 path_len, const char *path, + PFORT_APP_ENTRY app_entry) +{ + const char *app_path = (const char *) (app_entry + 1); + const UINT32 app_path_len = app_entry->path_len; + + if (path_len != app_path_len) + return FALSE; + + return fort_memcmp(path, app_path, path_len) == 0; +} + +static FORT_APP_FLAGS +fort_conf_app_exe_find (const PFORT_CONF conf, + UINT32 path_len, const char *path) +{ + FORT_APP_FLAGS app_flags; + const char *data; + const char *app_entries; + UINT16 count = conf->exe_apps_n; + + if (count == 0) + goto not_found; + + data = conf->data; + app_entries = (const char *) (data + conf->exe_apps_off); + + do { + const PFORT_APP_ENTRY app_entry = (const PFORT_APP_ENTRY) app_entries; + + if (fort_conf_app_exe_equal(path_len, path, app_entry)) { + app_flags = app_entry->flags; + goto end; + } + + app_entries += FORT_CONF_APP_ENTRY_SIZE(app_entry->path_len); + } while (--count != 0); + + not_found: + app_flags.v = 0; + + end: + return app_flags; +} + static int fort_conf_app_prefix_cmp (UINT32 path_len, const char *path, PFORT_APP_ENTRY app_entry) @@ -191,10 +237,15 @@ fort_conf_app_wild_find (const PFORT_CONF conf, const char *path) static FORT_APP_FLAGS fort_conf_app_find (const PFORT_CONF conf, - UINT32 path_len, const char *path) + UINT32 path_len, const char *path, + fort_conf_app_exe_find_func *exe_find_func) { FORT_APP_FLAGS app_flags; + app_flags = exe_find_func(conf, path_len, path); + if (app_flags.v != 0) + goto end; + app_flags = fort_conf_app_prefix_find(conf, path_len, path); if (app_flags.v != 0) goto end; diff --git a/src/common/fortconf.h b/src/common/fortconf.h index 54fe7e67..548dddd9 100644 --- a/src/common/fortconf.h +++ b/src/common/fortconf.h @@ -108,6 +108,7 @@ typedef struct fort_conf { UINT16 wild_apps_n; UINT16 prefix_apps_n; + UINT16 exe_apps_n; UINT32 app_perms_block_mask; UINT32 app_perms_allow_mask; @@ -139,4 +140,7 @@ typedef struct fort_conf_io { #define FORT_CONF_IO_CONF_OFF offsetof(FORT_CONF_IO, conf) #define FORT_CONF_ADDR_DATA_OFF offsetof(FORT_CONF_ADDR_GROUP, ip) +typedef FORT_APP_FLAGS fort_conf_app_exe_find_func( + const PFORT_CONF conf, UINT32 path_len, const char *path); + #endif FORTCONF_H diff --git a/src/common/version.h b/src/common/version.h index f654e868..821160fc 100644 --- a/src/common/version.h +++ b/src/common/version.h @@ -14,6 +14,6 @@ #define APP_UPDATES_URL "https://github.com/tnodir/fort/releases" #define APP_UPDATES_API_URL "https://api.github.com/repos/tnodir/fort/releases/latest" -#define DRIVER_VERSION 16 +#define DRIVER_VERSION 17 #endif // VERSION_H diff --git a/src/driver/fortcnf.c b/src/driver/fortcnf.c index 48128766..9ee7a688 100644 --- a/src/driver/fortcnf.c +++ b/src/driver/fortcnf.c @@ -1,8 +1,33 @@ /* Fort Firewall Configuration */ +#define FORT_CONF_BLOCK_SIZE (8 * 1024) + +/* Synchronize with tommy_node! */ +typedef struct fort_conf_block { + struct fort_conf_block *next; + struct fort_conf_block *prev; + + UINT16 top; +} FORT_CONF_BLOCK, *PFORT_CONF_BLOCK; + +/* Synchronize with tommy_hashdyn_node! */ +typedef struct fort_conf_exe_node { + struct fort_conf_exe_node *next; + struct fort_conf_exe_node *prev; + + PFORT_APP_ENTRY app_entry; + + tommy_key_t path_hash; +} FORT_CONF_EXE_NODE, *PFORT_CONF_EXE_NODE; + typedef struct fort_conf_ref { UINT32 volatile refcount; + tommy_list exe_blocks; + + tommy_arrayof exe_nodes; + tommy_hashdyn exe_map; + FORT_CONF conf; } FORT_CONF_REF, *PFORT_CONF_REF; @@ -46,21 +71,107 @@ fort_device_flag (PFORT_DEVICE_CONF device_conf, UCHAR flag) return fort_device_flags(device_conf) & flag; } +static FORT_APP_FLAGS +fort_conf_ref_exe_find (const PFORT_CONF conf, + UINT32 path_len, const char *path) +{ + PFORT_CONF_REF conf_ref = (PFORT_CONF_REF) ((char *) conf - offsetof(FORT_CONF_REF, conf)); + const tommy_key_t path_hash = (tommy_key_t) tommy_hash_u64( + 0, path, path_len); + + PFORT_CONF_EXE_NODE node = (PFORT_CONF_EXE_NODE) tommy_hashdyn_bucket( + &conf_ref->exe_map, path_hash); + + FORT_APP_FLAGS app_flags; + app_flags.v = 0; + + while (node != NULL) { + PFORT_APP_ENTRY entry = node->app_entry; + + if (node->path_hash == path_hash + && fort_conf_app_exe_equal(path_len, path, entry)) { + app_flags = entry->flags; + break; + } + + node = node->next; + } + + return app_flags; +} + +static void +fort_conf_ref_exe_fill (PFORT_CONF_REF conf_ref) +{ + tommy_arrayof *exe_nodes = &conf_ref->exe_nodes; + tommy_hashdyn *exe_map = &conf_ref->exe_map; + + const PFORT_CONF conf = &conf_ref->conf; + const char *app_entries = (const char *) (conf->data + conf->exe_apps_off); + + const int count = conf->exe_apps_n; + int i; + + tommy_arrayof_grow(exe_nodes, count); + + for (i = 0; i < count; ++i) { + const PFORT_APP_ENTRY entry = (const PFORT_APP_ENTRY) app_entries; + const char *path = (const char *) (entry + 1); + const UINT16 path_len = entry->path_len; + const tommy_key_t path_hash = (tommy_key_t) tommy_hash_u64(0, path, path_len); + + tommy_hashdyn_node *node = tommy_arrayof_ref(exe_nodes, i); + + tommy_hashdyn_insert(exe_map, node, entry, path_hash); + + app_entries += FORT_CONF_APP_ENTRY_SIZE(path_len); + } +} + +static void +fort_conf_ref_init (PFORT_CONF_REF conf_ref) +{ + conf_ref->refcount = 0; + + tommy_list_init(&conf_ref->exe_blocks); + + tommy_arrayof_init(&conf_ref->exe_nodes, sizeof(FORT_CONF_EXE_NODE)); + tommy_hashdyn_init(&conf_ref->exe_map); +} + static PFORT_CONF_REF fort_conf_ref_new (const PFORT_CONF conf, ULONG len) { const ULONG ref_len = len + offsetof(FORT_CONF_REF, conf); - PFORT_CONF_REF conf_ref = fort_mem_alloc(ref_len, FORT_DEVICE_POOL_TAG); + PFORT_CONF_REF conf_ref = tommy_malloc(ref_len); if (conf_ref != NULL) { - conf_ref->refcount = 0; - RtlCopyMemory(&conf_ref->conf, conf, len); + + fort_conf_ref_init(conf_ref); + fort_conf_ref_exe_fill(conf_ref); } return conf_ref; } +static void +fort_conf_ref_del (PFORT_CONF_REF conf_ref) +{ + /* Delete exe blocks */ + tommy_node *exe_block = tommy_list_head(&conf_ref->exe_blocks); + while (exe_block) { + tommy_node *next = exe_block->next; + tommy_free(exe_block); + exe_block = next; + } + + tommy_hashdyn_done(&conf_ref->exe_map); + tommy_arrayof_done(&conf_ref->exe_nodes); + + tommy_free(conf_ref); +} + static void fort_conf_ref_put (PFORT_DEVICE_CONF device_conf, PFORT_CONF_REF conf_ref) { @@ -71,7 +182,7 @@ fort_conf_ref_put (PFORT_DEVICE_CONF device_conf, PFORT_CONF_REF conf_ref) const UINT32 refcount = --conf_ref->refcount; if (refcount == 0 && conf_ref != device_conf->ref) { - fort_mem_free(conf_ref, FORT_DEVICE_POOL_TAG); + fort_conf_ref_del(conf_ref); } } KeReleaseInStackQueuedSpinLock(&lock_queue); diff --git a/src/driver/fortdrv.c b/src/driver/fortdrv.c index 1bc637fb..97b2b374 100644 --- a/src/driver/fortdrv.c +++ b/src/driver/fortdrv.c @@ -142,7 +142,8 @@ fort_callout_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues, path = inMetaValues->processPath->data; if (fort_conf_ip_inet_included(&conf_ref->conf, remote_ip)) { - const FORT_APP_FLAGS app_flags = fort_conf_app_find(&conf_ref->conf, path_len, path); + const FORT_APP_FLAGS app_flags = fort_conf_app_find( + &conf_ref->conf, path_len, path, fort_conf_ref_exe_find); if (!fort_conf_app_blocked(&conf_ref->conf, app_flags)) { if (conf_flags.log_stat) { diff --git a/src/tests/confutil/test.cpp b/src/tests/confutil/test.cpp index edad0ae5..082d6f2f 100644 --- a/src/tests/confutil/test.cpp +++ b/src/tests/confutil/test.cpp @@ -39,7 +39,7 @@ void Test::confWriteRead() ); appGroup1->setAllowText( "C:\\Program Files\\Skype\\Phone\\Skype.exe\n" - "C:\\Utils\\Dev\\Git\\\n" + "C:\\Utils\\Dev\\Git\\**\n" "D:\\**\\Programs\\**\n" ); diff --git a/src/ui/fortcommon.cpp b/src/ui/fortcommon.cpp index da845b09..bc191332 100644 --- a/src/ui/fortcommon.cpp +++ b/src/ui/fortcommon.cpp @@ -169,7 +169,8 @@ quint16 FortCommon::confAppFind(const void *drvConf, const wchar_t *p = (const wchar_t *) kernelPathLower.utf16(); const FORT_APP_FLAGS app_flags = - fort_conf_app_find(conf, len, (const char *) p); + fort_conf_app_find(conf, len, (const char *) p, + fort_conf_app_exe_find); return app_flags.v; } diff --git a/src/ui/util/conf/confutil.cpp b/src/ui/util/conf/confutil.cpp index 3c3e2219..cd18d085 100644 --- a/src/ui/util/conf/confutil.cpp +++ b/src/ui/util/conf/confutil.cpp @@ -268,8 +268,6 @@ bool ConfUtil::parseApps(int groupOffset, bool blocked, const QString &text, if (appPath.isEmpty()) continue; - isPrefix = !isWild; // TODO: Remove after hash find impl - appentry_map_t &appsMap = isWild ? wildAppsMap : isPrefix ? prefixAppsMap : exeAppsMap; @@ -400,6 +398,7 @@ void ConfUtil::writeData(char *output, const FirewallConf &conf, drvConf->wild_apps_n = quint16(wildAppsMap.size()); drvConf->prefix_apps_n = quint16(prefixAppsMap.size()); + drvConf->exe_apps_n = quint16(exeAppsMap.size()); drvConf->addr_groups_off = addrGroupsOff;