Driver: Collect logs in the pending buffer.

This commit is contained in:
Nodir Temirkhodjaev 2017-11-19 08:19:34 +05:00
parent 970b63d005
commit 1b0f2c251a
3 changed files with 57 additions and 34 deletions

View File

@ -14,6 +14,8 @@
((FORT_LOG_BLOCKED_HEADER_SIZE + (path_len) \
+ (FORT_LOG_ALIGN - 1)) & ~(FORT_LOG_ALIGN - 1))
#define FORT_LOG_BLOCKED_SIZE_MAX FORT_LOG_BLOCKED_SIZE(FORT_LOG_PATH_MAX)
#define fort_log_type(p) (*((UINT32 *) (p)) & FORT_LOG_FLAG_TYPE_MASK)

View File

@ -41,7 +41,7 @@ fort_buffer_blocked_write (PFORT_BUFFER buf, UINT32 remote_ip, UINT32 pid,
UINT32 path_len, const PVOID path,
PIRP *irp, NTSTATUS *irp_status, ULONG_PTR *info)
{
UINT32 len;
UINT32 len, new_top;
PCHAR out;
KIRQL irq;
NTSTATUS status = STATUS_SUCCESS;
@ -54,34 +54,36 @@ fort_buffer_blocked_write (PFORT_BUFFER buf, UINT32 remote_ip, UINT32 pid,
KeAcquireSpinLock(&buf->lock, &irq);
new_top = buf->top + len;
/* Try to directly write to pending client */
if (buf->irp) {
*irp = buf->irp;
buf->irp = NULL;
if (buf->irp != NULL) {
if (FORT_LOG_BLOCKED_SIZE_MAX > buf->out_len - new_top) {
*irp = buf->irp;
buf->irp = NULL;
*info = len;
if (buf->out_len < len) {
*irp_status = STATUS_BUFFER_TOO_SMALL;
/* fallback to buffer */
} else {
out = buf->out;
*irp_status = STATUS_SUCCESS;
goto log_blocked;
*info = new_top;
new_top = 0;
}
out = buf->out;
} else {
if (new_top > FORT_BUFFER_SIZE) {
status = STATUS_BUFFER_TOO_SMALL;
goto end; /* drop on buffer overflow */
}
out = buf->data;
}
if (len > FORT_BUFFER_SIZE - buf->top) {
status = STATUS_BUFFER_TOO_SMALL;
goto end; /* drop on buffer overflow */
}
out += buf->top;
out = buf->data + buf->top;
buf->top += len;
log_blocked:
fort_log_blocked_write(out, remote_ip, pid, path_len, path);
buf->top = new_top;
end:
KeReleaseSpinLock(&buf->lock, irq);
@ -100,8 +102,10 @@ fort_buffer_xmove (PFORT_BUFFER buf, PIRP irp, PVOID out, ULONG out_len,
*info = buf->top;
if (!buf->top) {
if (buf->irp) {
if (buf->irp != NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
} else if (out_len < FORT_LOG_BLOCKED_SIZE_MAX) {
status = STATUS_BUFFER_TOO_SMALL;
} else {
buf->irp = irp;
buf->out = out;
@ -125,14 +129,26 @@ fort_buffer_xmove (PFORT_BUFFER buf, PIRP irp, PVOID out, ULONG out_len,
return status;
}
static void
fort_buffer_cancel_pending (PFORT_BUFFER buf, PIRP irp)
static NTSTATUS
fort_buffer_cancel_pending (PFORT_BUFFER buf, PIRP irp, ULONG_PTR *info)
{
NTSTATUS status = STATUS_CANCELLED;
KIRQL irq;
*info = 0;
KeAcquireSpinLock(&buf->lock, &irq);
if (irp == buf->irp) {
buf->irp = NULL;
if (buf->top) {
*info = buf->top;
buf->top = 0;
status = STATUS_SUCCESS;
}
}
KeReleaseSpinLock(&buf->lock, irq);
return status;
}

View File

@ -212,20 +212,22 @@ fort_callout_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues,
if (conf_flags.log_blocked) {
PIRP irp = NULL;
NTSTATUS irp_status;
ULONG_PTR info;
NTSTATUS irp_status, status;
if (!NT_SUCCESS(fort_buffer_blocked_write(
status = fort_buffer_blocked_write(
&g_device->buffer, remote_ip,
(UINT32) inMetaValues->processId, path_len, path,
&irp, &irp_status, &info))) {
DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL,
"FORT: Classify v4: Log buffer underflow: %d\n",
FORT_LOG_BLOCKED_SIZE(path_len));
}
&irp, &irp_status, &info);
if (irp != NULL) {
fort_request_complete_info(irp, irp_status, info);
if (NT_SUCCESS(status)) {
if (irp != NULL) {
fort_request_complete_info(irp, irp_status, info);
}
} else {
DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL,
"FORT: Classify v4: Log buffer error: %d (path len: %d)\n",
status, path_len);
}
}
@ -468,13 +470,16 @@ fort_device_cleanup (PDEVICE_OBJECT device, PIRP irp)
static void
fort_device_cancel_pending (PDEVICE_OBJECT device, PIRP irp)
{
ULONG_PTR info;
NTSTATUS irp_status;
UNUSED(device);
fort_buffer_cancel_pending(&g_device->buffer, irp);
irp_status = fort_buffer_cancel_pending(&g_device->buffer, irp, &info);
IoReleaseCancelSpinLock(irp->CancelIrql); /* before IoCompleteRequest()! */
fort_request_complete(irp, STATUS_CANCELLED);
fort_request_complete_info(irp, irp_status, info);
}
static NTSTATUS