opt
/
kaspersky
/
kav4fs
/
src
/
kernel
/
module.linux
➕ New
📤 Upload
✎ Editing:
queue.c
← Back
/* * This source file is a part of a Kaspersky Antivirus Monitor. * Copyright (C) Kaspersky Lab, 1997-2010 * See License.txt for details * */ #include "module.h" static int Monitor_queue_ref(mqueue_entry_t* queue); static int Monitor_queue_rel(mqueue_entry_t* queue); static lock_declare(queue_lock); /* Sleep the process until there is at least one item in the queue */ static KLIST_HEAD(monitor_queue); compat_atomic_t last_queue_id; queue_stats_t queue_stats; int Monitor_queue_init(void) { KINIT_LIST_HEAD(&monitor_queue); lock_init(&queue_lock, "kavmonitor queue"); atomic_set(&last_queue_id, 0); atomic_long_set(&queue_stats.allocs, 0); atomic_long_set(&queue_stats.releases, 0); atomic_long_set(&queue_stats.requests, 0); atomic_long_set(&queue_stats.detects, 0); return 0; } void Monitor_queue_cleanup() { struct list_head* q_list; mqueue_entry_t* queue; /* #ifdef __linux__ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,14) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) touch_softlockup_watchdog(); #endif #endif */ /* Wake up all processes in the queue */ write_lock(&queue_lock); list_for_each(q_list, &monitor_queue) { queue = list_entry(q_list, mqueue_entry_t, list); if (queue->flags) { if (!queue->blocked) wake_up_interruptible(&queue->waitq); else wake_up(&queue->waitq); } } write_unlock(&queue_lock); } int Monitor_queue_get_id(void) { u_short queue_id; struct list_head* q_list; mqueue_entry_t* queue; /* #ifdef __linux__ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,14) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) touch_softlockup_watchdog(); #endif #endif */ read_lock(&queue_lock); again: queue_id = (u_short)compat_atomic_inc_return(&last_queue_id); list_for_each(q_list, &monitor_queue) { queue = list_entry(q_list, mqueue_entry_t, list); if (queue->queue_id == queue_id) goto again; } read_unlock(&queue_lock); return queue_id; } void Monitor_queue_set_answer(u_short queue_id, int answer) { struct list_head* q_list; mqueue_entry_t* queue; read_lock(&queue_lock); list_for_each(q_list, &monitor_queue) { queue = list_entry(q_list, mqueue_entry_t, list); if (queue->queue_id == queue_id) { Monitor_queue_ref(queue); queue->answer = answer; if (answer == FILE_ACCESS_DENY) atomic_long_inc(&queue_stats.detects); read_unlock(&queue_lock); Monitor_queue_rel(queue); return; } } read_unlock(&queue_lock); } void Monitor_queue_wakeup(u_short queue_id) { struct list_head* q_list; mqueue_entry_t* queue; read_lock(&queue_lock); list_for_each(q_list, &monitor_queue) { queue = list_entry(q_list, mqueue_entry_t, list); if (queue->queue_id == queue_id && queue->flags) { read_unlock(&queue_lock); read_lock(&queue->lock); if (!queue->blocked) wake_up_interruptible(&queue->waitq); else wake_up(&queue->waitq); read_unlock(&queue->lock); return; } } read_unlock(&queue_lock); } int Monitor_queue_ref(mqueue_entry_t* queue) { int i; write_lock(&queue->lock); if (!queue->refcnt) { PRN("%s: called with cnt=0", __FUNCTION__); } i = ++queue->refcnt; write_unlock(&queue->lock); return i; } int Monitor_queue_rel(mqueue_entry_t* queue) { int i; write_lock(&queue_lock); write_lock(&queue->lock); if (!queue->refcnt) { PRN("%s: called with cnt=0", __FUNCTION__); } i = --queue->refcnt; if (i != 0) { write_unlock(&queue_lock); write_unlock(&queue->lock); return i; } list_del(&queue->list); write_unlock(&queue_lock); write_unlock(&queue->lock); lock_finit(&queue->lock); MEM_FREE(queue); return i; } #if defined(__FreeBSD__) int Monitor_queue_add(u_short queue_id, int block, PackedBuffer* request, enum FileAccessType* answer) { mqueue_entry_t* queue; /* Add a new request */ queue = MEM_ALLOC(sizeof(mqueue_entry_t)); if (!queue) { PRN("Queue memory allocation error"); *answer = FILE_ACCESS_ACCEPT; FinitPackedBuffer(request); return 0; } if (!monitor_started) { MEM_FREE(queue); *answer = FILE_ACCESS_ACCEPT; FinitPackedBuffer(request); return 0; } queue->queue_id = queue_id; queue->answer = *answer; lock_init(&queue->lock, "queue item lock"); queue->refcnt = 1; queue->flags = O_MQUEUE_READY; queue->blocked = block; write_lock(&queue_lock); list_add(&queue->list, &monitor_queue); init_waitqueue_head(&queue->waitq); /* Indicate new data availability to the interface process */ { int err; Monitor_ins_use(); #ifdef MSLEEP_LOCK write_lock(&queue->lock); #endif write_unlock(&queue_lock); Monitor_module_send_data(request); FinitPackedBuffer(request); err = SLEEP(queue, block); if (err == ERESTART) err = EINTR; Monitor_dec_use(); *answer = queue->answer; queue->flags &= ~O_MQUEUE_TESTING; #ifdef MSLEEP_LOCK write_unlock(&queue->lock); #endif Monitor_queue_rel(queue); if (err) return err; } return 0; } #elif defined(__linux__) int Monitor_timedqueue_add(u_short queue_id, int block, check_req_data_t* reqd, enum FileAccessType* answer, unsigned long int timeout) { mqueue_entry_t* queue; int res, remaining; /* Add a new request */ wait_queue_t wait; queue = MEM_ALLOC(sizeof(mqueue_entry_t)); if (!queue) { PRN("Queue memory allocation error"); return -ENOMEM; } if (!atomic_read(&monitor_started)) { MEM_FREE(queue); *answer = FILE_ACCESS_ACCEPT; return 0; } queue->queue_id = queue_id; queue->answer = *answer; lock_init(&queue->lock, "queue item lock"); queue->refcnt = 1; queue->flags = O_MQUEUE_READY; queue->blocked = block; write_lock(&queue_lock); list_add(&queue->list, &monitor_queue); init_waitqueue_head(&queue->waitq); Monitor_ins_use(); init_waitqueue_entry(&wait, current); add_wait_queue(&queue->waitq, &wait); set_current_state(TASK_INTERRUPTIBLE); reqd->queue_id = queue_id; Monitor_module_send_data(reqd); write_unlock(&queue_lock); remaining = schedule_timeout(timeout); remove_wait_queue(&queue->waitq, &wait); queue->flags &= ~O_MQUEUE_TESTING; res = queue->answer; Monitor_queue_rel(queue); Monitor_dec_use(); if (signal_pending(current)) { return -ERESTARTSYS; } if (!remaining) return 1; return 0; } int Monitor_queue_add(u_short queue_id, int block, check_req_data_t* reqd, enum FileAccessType* answer) { mqueue_entry_t* queue; int res; /* Add a new request */ wait_queue_t wait; queue = MEM_ALLOC(sizeof(mqueue_entry_t)); if (!queue) { PRN("Queue memory allocation error"); return -ENOMEM; } if (!atomic_read(&monitor_started)) { MEM_FREE(queue); *answer = FILE_ACCESS_ACCEPT; return 0; } queue->queue_id = queue_id; queue->answer = *answer; lock_init(&queue->lock, "queue item lock"); queue->refcnt = 1; queue->flags = O_MQUEUE_READY; queue->blocked = block; write_lock(&queue_lock); list_add(&queue->list, &monitor_queue); init_waitqueue_head(&queue->waitq); Monitor_ins_use(); init_waitqueue_entry(&wait, current); add_wait_queue(&queue->waitq, &wait); set_current_state(block ? TASK_UNINTERRUPTIBLE : TASK_INTERRUPTIBLE); reqd->queue_id = queue_id; Monitor_module_send_data(reqd); write_unlock(&queue_lock); schedule(); remove_wait_queue(&queue->waitq, &wait); queue->flags &= ~O_MQUEUE_TESTING; res = queue->answer; Monitor_queue_rel(queue); Monitor_dec_use(); if (signal_pending(current)) { return -ERESTARTSYS; } if (res < 0) return res; *answer = res; return 0; } static KLIST_HEAD(check_req_queue); static lock_declare(check_req_queue_lock); int check_req_queue_init(void) { KINIT_LIST_HEAD(&check_req_queue); lock_init(&check_req_queue_lock, "kavmonitor check_req_queue lock"); return 0; } static void check_req_free(check_req_data_t* reqd) { if (reqd->name) kfree(reqd->name); if (reqd->parent) dput(reqd->parent); if (reqd->vfsmnt) mntput(reqd->vfsmnt); MEM_FREE(reqd); atomic_long_inc(&queue_stats.releases); } void check_req_queue_add(check_req_data_t* reqd) { write_lock(&check_req_queue_lock); atomic_inc(&reqd->refcnt); atomic_long_inc(&queue_stats.requests); list_add_tail(&reqd->list, &check_req_queue); write_unlock(&check_req_queue_lock); } check_req_data_t* check_req_queue_get(void) { check_req_data_t* res; write_lock(&check_req_queue_lock); if (list_empty(&check_req_queue)) res = NULL; else { res = list_entry(check_req_queue.next, check_req_data_t, list); list_del_init(&res->list); } write_unlock(&check_req_queue_lock); return res; } int check_req_queue_put(check_req_data_t* reqd) { write_lock(&check_req_queue_lock); if (atomic_dec_and_test(&reqd->refcnt)) { if (!list_empty(&reqd->list)) list_del_init(&reqd->list); write_unlock(&check_req_queue_lock); check_req_free(reqd); return 0; } write_unlock(&check_req_queue_lock); return 1; } void check_req_queue_release(check_req_data_t* reqd) { if (check_req_queue_put(reqd)) { check_req_queue_put(reqd); } } int check_req_queue_empty(void) { int res; read_lock(&check_req_queue_lock); res = list_empty(&check_req_queue); read_unlock(&check_req_queue_lock); return res; } #endif /*__linux__*/
💾 Save Changes
Cancel
📤 Upload File
×
Select File
Upload
Cancel
➕ Create New
×
Type
📄 File
📁 Folder
Name
Create
Cancel
✎ Rename Item
×
Current Name
New Name
Rename
Cancel
🔐 Change Permissions
×
Target File
Permission (e.g., 0755, 0644)
0755
0644
0777
Apply
Cancel