diff --git a/src/common/fortconf.c b/src/common/fortconf.c index d14366dd..a2bb23aa 100644 --- a/src/common/fortconf.c +++ b/src/common/fortconf.c @@ -175,7 +175,7 @@ fort_conf_app_period_bits (const PFORT_CONF conf, int hour1, int hour2, { const char *data; const CHAR *app_periods; - UINT16 group_bits, period_bits; + UINT16 period_bits; UINT8 count = conf->app_periods_n; int n, i; @@ -184,8 +184,7 @@ fort_conf_app_period_bits (const PFORT_CONF conf, int hour1, int hour2, data = conf->data; app_periods = (const CHAR *) (data + conf->app_periods_off); - group_bits = (UINT16) conf->flags.group_bits; - period_bits = group_bits; + period_bits = (UINT16) conf->flags.group_bits; n = 0; for (i = 0; i < FORT_CONF_GROUP_MAX; ++i) { @@ -193,7 +192,7 @@ fort_conf_app_period_bits (const PFORT_CONF conf, int hour1, int hour2, const int periodFrom = *app_periods++; const int periodTo = *app_periods++; - if ((group_bits & bit) != 0 + if ((period_bits & bit) != 0 && (periodFrom != 0 || periodTo != 0)) { if (!(is_hour_between(hour1, periodFrom, periodTo) && (hour1 == hour2 || is_hour_between(hour2, periodFrom, periodTo)))) { diff --git a/src/common/fortprov.c b/src/common/fortprov.c index c1eb3a3e..5991ad5e 100644 --- a/src/common/fortprov.c +++ b/src/common/fortprov.c @@ -173,7 +173,7 @@ fort_prov_register (HANDLE transEngine, BOOL is_boot) } if (!transEngine) { - if (!status) { + if (NT_SUCCESS(status)) { status = fort_prov_trans_commit(engine); } @@ -251,7 +251,7 @@ fort_prov_flow_register (HANDLE transEngine, BOOL filter_transport) } if (!transEngine) { - if (!status) { + if (NT_SUCCESS(status)) { status = fort_prov_trans_commit(engine); } @@ -297,7 +297,7 @@ fort_prov_reauth (HANDLE transEngine) } status = FwpmFilterDeleteByKey0(engine, (GUID *) &FORT_GUID_FILTER_REAUTH_IN); - if (!status) { + if (NT_SUCCESS(status)) { FwpmFilterDeleteByKey0(engine, (GUID *) &FORT_GUID_FILTER_REAUTH_OUT); } else { FWPM_FILTER0 ifilter, ofilter; @@ -323,7 +323,7 @@ fort_prov_reauth (HANDLE transEngine) } if (!transEngine) { - if (!status) { + if (NT_SUCCESS(status)) { status = fort_prov_trans_commit(engine); } else { fort_prov_trans_abort(engine); diff --git a/src/driver/fortdrv.c b/src/driver/fortdrv.c index a010c899..bf84ce39 100644 --- a/src/driver/fortdrv.c +++ b/src/driver/fortdrv.c @@ -24,6 +24,7 @@ #include "fortpkt.c" #include "fortstat.c" #include "forttmr.c" +#include "fortwrk.c" typedef struct fort_conf_ref { UINT32 volatile refcount; @@ -55,6 +56,7 @@ typedef struct fort_device { FORT_DEFER defer; FORT_TIMER log_timer; FORT_TIMER app_timer; + FORT_WORKER worker; } FORT_DEVICE, *PFORT_DEVICE; static PFORT_DEVICE g_device = NULL; @@ -719,8 +721,7 @@ fort_callout_defer_flush (BOOL dispatchLevel) } static NTSTATUS -fort_callout_force_reauth (PDEVICE_OBJECT device, - const FORT_CONF_FLAGS old_conf_flags, +fort_callout_force_reauth (const FORT_CONF_FLAGS old_conf_flags, const FORT_CONF_FLAGS conf_flags) { PFORT_STAT stat = &g_device->stat; @@ -728,8 +729,6 @@ fort_callout_force_reauth (PDEVICE_OBJECT device, HANDLE engine; NTSTATUS status; - UNUSED(device); - fort_timer_update(&g_device->log_timer, FALSE); fort_timer_update(&g_device->app_timer, FALSE); @@ -868,8 +867,7 @@ static void fort_app_period_timer (void) { if (fort_conf_period_update(NULL)) { - /* Force reauth filter */ - fort_prov_reauth(NULL); + fort_worker_queue(&g_device->worker, FORT_WORKER_REAUTH); } } @@ -919,7 +917,7 @@ fort_device_cleanup (PDEVICE_OBJECT device, PIRP irp) RtlZeroMemory(&conf_flags, sizeof(FORT_CONF_FLAGS)); conf_flags.prov_boot = g_device->prov_boot; - fort_callout_force_reauth(device, old_conf_flags, conf_flags); + fort_callout_force_reauth(old_conf_flags, conf_flags); } /* Clear buffer */ @@ -982,7 +980,7 @@ fort_device_control (PDEVICE_OBJECT device, PIRP irp) fort_stat_update_limits(&g_device->stat, conf_io); - status = fort_callout_force_reauth(device, old_conf_flags, conf_flags); + status = fort_callout_force_reauth(old_conf_flags, conf_flags); } } break; @@ -994,7 +992,7 @@ fort_device_control (PDEVICE_OBJECT device, PIRP irp) if (len == sizeof(FORT_CONF_FLAGS)) { const FORT_CONF_FLAGS old_conf_flags = fort_conf_ref_flags_set(conf_flags); - status = fort_callout_force_reauth(device, old_conf_flags, *conf_flags); + status = fort_callout_force_reauth(old_conf_flags, *conf_flags); } break; } @@ -1142,6 +1140,8 @@ fort_driver_unload (PDRIVER_OBJECT driver) fort_stat_close(&g_device->stat); fort_buffer_close(&g_device->buffer); + fort_worker_unregister(&g_device->worker); + fort_power_callback_unregister(); fort_systime_callback_unregister(); @@ -1218,8 +1218,8 @@ DriverEntry (PDRIVER_OBJECT driver, PUNICODE_STRING reg_path) fort_buffer_open(&g_device->buffer); fort_stat_open(&g_device->stat); fort_defer_open(&g_device->defer); - fort_timer_open(&g_device->log_timer, 500, &fort_callout_timer); - fort_timer_open(&g_device->app_timer, 60000, &fort_app_period_timer); + fort_timer_open(&g_device->log_timer, 500, FALSE, &fort_callout_timer); + fort_timer_open(&g_device->app_timer, 60000, TRUE, &fort_app_period_timer); KeInitializeSpinLock(&g_device->conf_lock); @@ -1233,6 +1233,11 @@ DriverEntry (PDRIVER_OBJECT driver, PUNICODE_STRING reg_path) /* Install callouts */ status = fort_callout_install(device); + /* Register worker */ + if (NT_SUCCESS(status)) { + status = fort_worker_register(device, &g_device->worker); + } + /* Register filters provider */ if (NT_SUCCESS(status)) { status = fort_prov_register(0, g_device->prov_boot); diff --git a/src/driver/forttmr.c b/src/driver/forttmr.c index ea7421e4..34d3c755 100644 --- a/src/driver/forttmr.c +++ b/src/driver/forttmr.c @@ -4,7 +4,8 @@ typedef void (*FORT_TIMER_FUNC) (void); typedef struct fort_timer { UINT32 running : 1; - UINT32 period : 31; /* milliseconds */ + UINT32 coalescable : 1; + UINT32 period : 30; /* milliseconds */ FORT_TIMER_FUNC callback; @@ -26,8 +27,10 @@ fort_timer_callback (PKDPC dpc, PFORT_TIMER timer, PVOID arg1, PVOID arg2) } static void -fort_timer_open (PFORT_TIMER timer, int period, FORT_TIMER_FUNC callback) +fort_timer_open (PFORT_TIMER timer, int period, BOOL coalescable, + FORT_TIMER_FUNC callback) { + timer->coalescable = coalescable; timer->period = period; timer->callback = callback; @@ -56,11 +59,12 @@ fort_timer_update (PFORT_TIMER timer, BOOL run) timer->running = run; if (run) { - const LONG period = timer->period; + const ULONG period = timer->period; + const ULONG delay = timer->coalescable ? 500 : 0; LARGE_INTEGER due; due.QuadPart = period * -10000; /* ms -> us */ - KeSetTimerEx(&timer->id, due, period, &timer->dpc); + KeSetCoalescableTimer(&timer->id, due, period, delay, &timer->dpc); } else { KeCancelTimer(&timer->id); } diff --git a/src/driver/fortwrk.c b/src/driver/fortwrk.c new file mode 100644 index 00000000..9889926c --- /dev/null +++ b/src/driver/fortwrk.c @@ -0,0 +1,70 @@ +/* Fort Firewall Worker for PASSIVE_LEVEL calls */ + +#define FORT_WORKER_REAUTH 0x01 + +typedef struct fort_worker { + LONG volatile id_bits; + + PIO_WORKITEM item; +} FORT_WORKER, *PFORT_WORKER; + + +static void +fort_worker_reauth (void) +{ + NTSTATUS status; + + /* Force reauth filter */ + status = fort_prov_reauth(NULL); + + if (!NT_SUCCESS(status)) { + DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, + "FORT: Worker Reauth: Error: %x\n", status); + } +} + +static void +fort_worker_callback (PVOID device, PVOID context, PIO_WORKITEM item) +{ + PFORT_WORKER worker = (PFORT_WORKER) context; + const LONG id_bits = InterlockedAnd(&worker->id_bits, 0); + + UNUSED(device); + UNUSED(item); + + if (id_bits & FORT_WORKER_REAUTH) { + fort_worker_reauth(); + } +} + +static void +fort_worker_queue (PFORT_WORKER worker, int work_id) +{ + const LONG id_bits = InterlockedOr(&worker->id_bits, work_id); + + if (id_bits == 0) { + IoQueueWorkItemEx(worker->item, &fort_worker_callback, + DelayedWorkQueue, worker); + } +} + +static NTSTATUS +fort_worker_register (PDEVICE_OBJECT device, PFORT_WORKER worker) +{ + PIO_WORKITEM item = IoAllocateWorkItem(device); + if (item == NULL) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + worker->item = item; + + return STATUS_SUCCESS; +} + +static void +fort_worker_unregister (PFORT_WORKER worker) +{ + if (worker->item != NULL) { + IoFreeWorkItem(worker->item); + } +}