Driver: Add log buffer.

This commit is contained in:
Nodir Temirkhodjaev 2015-01-09 17:23:17 +05:00
parent da9c0a10d9
commit 92762a5389
6 changed files with 205 additions and 25 deletions

View File

@ -1,8 +1,18 @@
/* Windows IP Filter Log Buffer */
#define WIPF_BUFFER_SIZE 4 * 1024
#define WIPF_BUFFER_SIZE_MAX 32 * 1024
#include "../wipflog.c"
typedef struct wipf_buffer {
UINT32 top, size;
PVOID data;
PIRP irp; /* pending */
PVOID out;
ULONG out_len;
KSPIN_LOCK lock;
} WIPF_BUFFER, *PWIPF_BUFFER;
@ -21,9 +31,121 @@ wipf_buffer_close (PWIPF_BUFFER buf)
}
}
static BOOL
static NTSTATUS
wipf_buffer_write (PWIPF_BUFFER buf, UINT32 remote_ip, UINT64 pid,
UINT32 path_len, const PVOID path)
UINT32 path_len, const PVOID path,
PIRP *irp, NTSTATUS *irp_status, ULONG_PTR *info)
{
return TRUE;
const UINT32 len = sizeof(UINT32) + sizeof(UINT64)
+ sizeof(UINT32) + path_len;
UINT32 size;
KIRQL irq;
NTSTATUS status = STATUS_SUCCESS;
KeAcquireSpinLock(&buf->lock, &irq);
/* Try to directly write to pending client */
if (buf->irp) {
*irp = buf->irp;
buf->irp = NULL;
*info = len;
if (buf->out_len < len) {
*irp_status = STATUS_BUFFER_TOO_SMALL;
/* fallback to buffer */
} else {
wipf_log_write(buf->out, remote_ip, pid, path_len, path);
*irp_status = STATUS_SUCCESS;
goto end;
}
}
size = buf->size;
if (len > WIPF_BUFFER_SIZE) {
status = STATUS_INVALID_PARAMETER;
goto end; /* drop too long path */
}
if (len > size - buf->top) {
size *= 2;
}
if (size > WIPF_BUFFER_SIZE_MAX) {
status = STATUS_BUFFER_TOO_SMALL;
goto end; /* drop on overflow of buffer */
}
/* resize the buffer */
if (size != buf->size) {
PVOID data = ExAllocatePoolWithTag(NonPagedPool, size, WIPF_POOL_TAG);
if (data == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto end; /* drop on OOM */
}
RtlCopyMemory(data, buf->data, buf->top);
wipf_buffer_close(buf);
buf->data = data;
buf->size = size;
}
buf->top += len;
wipf_log_write(buf->data, remote_ip, pid, path_len, path);
end:
KeReleaseSpinLock(&buf->lock, irq);
return status;
}
static NTSTATUS
wipf_buffer_xmove (PWIPF_BUFFER buf, PIRP irp, PVOID out, ULONG out_len,
ULONG_PTR *info)
{
KIRQL irq;
NTSTATUS status = STATUS_SUCCESS;
KeAcquireSpinLock(&buf->lock, &irq);
*info = buf->top;
if (!buf->top) {
if (buf->irp) {
status = STATUS_INSUFFICIENT_RESOURCES;
} else {
buf->irp = irp;
buf->out = out;
buf->out_len = out_len;
status = STATUS_PENDING;
}
goto end;
}
if (out_len < buf->top) {
status = STATUS_BUFFER_TOO_SMALL;
goto end;
}
RtlCopyMemory(out, buf->data, buf->top);
buf->top = 0;
end:
KeReleaseSpinLock(&buf->lock, irq);
return status;
}
static void
wipf_buffer_cancel_pending (PWIPF_BUFFER buf, PIRP irp)
{
KIRQL irq;
KeAcquireSpinLock(&buf->lock, &irq);
if (irp == buf->irp) {
buf->irp = NULL;
}
KeReleaseSpinLock(&buf->lock, irq);
}

View File

@ -108,9 +108,8 @@ wipf_callout_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues,
{
PWIPF_CONF_REF conf_ref;
UINT32 local_ip, remote_ip;
UINT64 pid;
UINT32 path_len;
PVOID path = NULL;
PVOID path;
BOOL blocked, notify;
UNUSED(packet);
@ -123,12 +122,10 @@ wipf_callout_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues,
local_ip = inFixedValues->incomingValue[localIpField].value.uint32;
remote_ip = inFixedValues->incomingValue[remoteIpField].value.uint32;
path_len = inMetaValues->processPath->size;
path = inMetaValues->processPath->data;
if (local_ip != remote_ip) {
pid = inMetaValues->processId;
path_len = inMetaValues->processPath->size;
path = inMetaValues->processPath->data;
blocked = wipf_conf_ipblocked(&conf_ref->conf, remote_ip,
path_len, path, &notify);
} else {
@ -144,8 +141,19 @@ wipf_callout_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues,
} else {
classifyOut->actionType = FWP_ACTION_CONTINUE;
if (notify)
wipf_buffer_write(&g_device->buffer, remote_ip, pid, path_len, path);
if (notify) {
PIRP irp = NULL;
NTSTATUS irp_status;
ULONG_PTR info;
wipf_buffer_write(&g_device->buffer, remote_ip,
inMetaValues->processId, path_len, path,
&irp, &irp_status, &info);
if (irp) {
wipf_request_complete_info(irp, irp_status, info);
}
}
}
return STATUS_SUCCESS;
@ -228,10 +236,23 @@ wipf_driver_complete (PDEVICE_OBJECT device, PIRP irp)
return STATUS_SUCCESS;
}
static void
wipf_driver_cancel_pending (PDEVICE_OBJECT device, PIRP irp)
{
UNUSED(device);
wipf_buffer_cancel_pending(&g_device->buffer, irp);
IoReleaseCancelSpinLock(irp->CancelIrql); /* before IoCompleteRequest()! */
wipf_request_complete(irp, STATUS_CANCELLED);
}
static NTSTATUS
wipf_driver_control (PDEVICE_OBJECT device, PIRP irp)
{
PIO_STACK_LOCATION irp_stack;
ULONG_PTR info = 0;
NTSTATUS status = STATUS_INVALID_PARAMETER;
UNUSED(device);
@ -255,23 +276,27 @@ wipf_driver_control (PDEVICE_OBJECT device, PIRP irp)
}
break;
}
#if 0
case WIPF_IOCTL_GETLOG: {
PVOID data = irp->AssociatedIrp.SystemBuffer;
const ULONG len = irp_stack->Parameters.DeviceIoControl.OutputBufferLength;
PVOID out = irp->AssociatedIrp.SystemBuffer;
const ULONG out_len = irp_stack->Parameters.DeviceIoControl.OutputBufferLength;
status = wipf_buffer_read_result(&g_device->buffer, irp);
status = wipf_buffer_xmove(&g_device->buffer, irp, out, out_len, &info);
if (status == STATUS_PENDING) {
KIRQL cirq;
IoMarkIrpPending(irp);
IoAcquireCancelSpinLock(&cirq);
IoSetCancelRoutine(irp, wipf_driver_cancel_pending);
IoReleaseCancelSpinLock(cirq);
}
break;
}
#endif
default: break;
}
if (!NT_SUCCESS(status)) {
DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, "wipf: Control: Error: %d\n", status);
}
wipf_request_complete(irp, status);
wipf_request_complete_info(irp, status, info);
return status;
}

View File

@ -6,11 +6,14 @@
#define WIPF_POOL_TAG 'WIPF'
#define wipf_request_complete(irp, status) \
#define wipf_request_complete_info(irp, status, info) \
do { \
(irp)->IoStatus.Status = (status); \
(irp)->IoStatus.Information = 0; \
(irp)->IoStatus.Information = (info); \
IoCompleteRequest((irp), IO_NO_INCREMENT); \
} while(0)
#define wipf_request_complete(irp, status) \
wipf_request_complete_info((irp), (status), 0)
#endif WIPFDRV_H

View File

@ -3,7 +3,7 @@
typedef struct wipf_conf {
UINT32 len;
UCHAR data[1];
UCHAR data[4];
} WIPF_CONF, *PWIPF_CONF;
#endif WIPFCONF_H

View File

@ -7,6 +7,7 @@ static BOOL
wipf_conf_ipblocked (const PWIPF_CONF conf, UINT32 remote_ip,
UINT32 path_len, const PVOID path, PBOOL notify)
{
return TRUE;
*notify = TRUE;
return FALSE;
}

29
src/wipflog.c Normal file
View File

@ -0,0 +1,29 @@
/* Windows IP Filter Log */
static void
wipf_log_write (char *p, UINT32 remote_ip, UINT64 pid,
UINT32 path_len, const char *path)
{
*((UINT32 *) p)++ = remote_ip;
*((UINT64 *) p)++ = pid;
*((UINT32 *) p)++ = path_len;
if (path_len) {
RtlCopyMemory(p, path, path_len);
}
}
static void
wipf_log_read (const char **p, UINT32 *remote_ip, UINT64 *pid,
UINT32 *path_len, const char **path)
{
*remote_ip = *((UINT32 *) *p)++;
*pid = *((UINT64 *) *p)++;
*path_len = *((UINT32 *) *p)++;
if (*path_len) {
*path = *p;
*p += *path_len;
}
}