Driver: Use hash-map for app exe paths.

This commit is contained in:
Nodir Temirkhodjaev 2019-12-10 15:18:54 +05:00
parent 90318506fd
commit 7a31bf9a8a
8 changed files with 178 additions and 11 deletions

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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) {

View File

@ -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"
);

View File

@ -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;
}

View File

@ -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;