Server IP : 103.169.32.36 / Your IP : 216.73.217.13 Web Server : Apache System : Linux web.dpmptsp 3.10.0-1160.119.1.el7.x86_64 #1 SMP Tue Jun 4 14:43:51 UTC 2024 x86_64 User : apache ( 48) PHP Version : 5.6.40 Disable Function : NONE MySQL : ON | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /var/opt/eset/efs/eventd/eset_rtp/ |
Upload File : |
| Current File : /var/opt/eset/efs/eventd/eset_rtp/ertp_event_queue.c |
/*
* eset_rtp (ESET Real-time file system protection module)
* Copyright (C) 1992-2023 ESET, spol. s r.o.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* In case of any questions, you can contact us at ESET, spol. s r.o., Einsteinova 24, 851 01 Bratislava, Slovakia.
*/
#include "ertp_event_queue.h"
#include "ertp.h"
#include "ertp_cache.h"
#include "ertp_event.h"
#include "ertp_event_container.h"
#include "ertp_logs.h"
#include "ertp_memory_dev.h"
#include <linux/spinlock.h>
#include <linux/wait.h>
struct ertp_event_queue_t {
struct ertp_event_container events;
struct ertp_event_container swap;
bool disabled;
};
static DEFINE_SPINLOCK(ertp_event_queue_lock);
static DECLARE_WAIT_QUEUE_HEAD(ertp_event_queue_request_available);
static struct ertp_event_queue_t ertp_event_queue;
int ertp_event_queue_init(void) {
int ret;
ertp_event_queue.disabled = true;
ret = ertp_event_container_init(&ertp_event_queue.events);
if (ret) {
return ret;
}
ret = ertp_event_container_init(&ertp_event_queue.swap);
if (ret) {
ertp_event_container_deinit(&ertp_event_queue.events);
}
return ret;
}
void ertp_event_queue_deinit(void) {
ertp_event_queue.disabled = true;
ertp_event_container_deinit(&ertp_event_queue.events);
ertp_event_container_deinit(&ertp_event_queue.swap);
}
void ertp_event_queue_enable(void) {
spin_lock(&ertp_event_queue_lock);
ertp_event_queue.disabled = false;
spin_unlock(&ertp_event_queue_lock);
}
void ertp_event_queue_disable(void) {
spin_lock(&ertp_event_queue_lock);
ertp_event_queue.disabled = true;
spin_unlock(&ertp_event_queue_lock);
}
bool ertp_event_queue_is_disabled(void) {
bool ret;
spin_lock(&ertp_event_queue_lock);
ret = ertp_event_queue.disabled;
spin_unlock(&ertp_event_queue_lock);
return ret;
}
void ertp_event_queue_clear(void) {
spin_lock(&ertp_event_queue_lock);
ertp_event_queue.disabled = true;
ertp_event_container_scanner_unblock_all(&ertp_event_queue.events);
ertp_event_container_swap(&ertp_event_queue.events, &ertp_event_queue.swap);
spin_unlock(&ertp_event_queue_lock);
ertp_event_container_clear(&ertp_event_queue.swap);
}
struct ertp_event *ertp_event_queue_get_next(void) {
struct ertp_event *event;
spin_lock(&ertp_event_queue_lock);
event = ertp_event_container_scanner_add_next(&ertp_event_queue.events);
spin_unlock(&ertp_event_queue_lock);
return event;
}
struct ertp_event *ertp_event_queue_remove_scanned_event(int32_t id) {
struct ertp_event *event = NULL;
spin_lock(&ertp_event_queue_lock);
event = ertp_event_container_scanner_remove(&ertp_event_queue.events, id);
spin_unlock(&ertp_event_queue_lock);
return event;
}
bool ertp_event_queue_reinsert_not_sent_event(struct ertp_event *event) {
bool reinserted = true;
struct ertp_event *event_removed;
spin_lock(&ertp_event_queue_lock);
event_removed =
ertp_event_container_scanner_remove(&ertp_event_queue.events, event->id);
if (ertp_event_queue.disabled) {
reinserted = false;
goto end;
}
ertp_event_container_prepared_add_first(&ertp_event_queue.events, event);
end:
spin_unlock(&ertp_event_queue_lock);
ertp_event_unref(event_removed);
return reinserted;
}
unsigned int ertp_event_queue_wait(struct file *file, poll_table *wait) {
unsigned int mask;
bool event_prepared;
poll_wait(file, &ertp_event_queue_request_available, wait);
spin_lock(&ertp_event_queue_lock);
event_prepared = ertp_event_container_prepared(&ertp_event_queue.events);
spin_unlock(&ertp_event_queue_lock);
mask = POLLOUT | POLLWRNORM;
if (event_prepared) {
mask |= POLLIN | POLLRDNORM;
}
return mask;
}
static bool ertp_event_queue_push(struct ertp_event *event) {
bool ret = false;
spin_lock(&ertp_event_queue_lock);
if (!ertp_event_queue.disabled) {
ertp_event_container_prepared_add(&ertp_event_queue.events, event);
wake_up_interruptible(&ertp_event_queue_request_available);
ret = true;
}
spin_unlock(&ertp_event_queue_lock);
return ret;
}
static void ertp_event_queue_remove(struct ertp_event *event) {
spin_lock(&ertp_event_queue_lock);
ertp_event_container_remove(&ertp_event_queue.events, event);
spin_unlock(&ertp_event_queue_lock);
}
static int process_new_generic_event(
const struct ertp_event_generic_info *event_info) {
int rv = ERTP_UNKNOWN;
struct ertp_event *event = ertp_event_generic_new(event_info);
if (IS_ERR(event)) {
return rv;
}
if (ertp_event_queue_push(event)) {
if (event->wait_for_result(event) == 0) {
rv = (ERTP_EVENT_GENERIC(event))->result;
}
ertp_event_queue_remove(event);
}
ertp_event_unref(event);
return rv;
}
int ertp_event_queue_handle_generic_event(
const struct ertp_event_generic_info *event_info) {
int rv = ERTP_UNKNOWN;
struct ertp_event *event = NULL;
spin_lock(&ertp_event_queue_lock);
event =
ertp_event_container_find_by_info(&ertp_event_queue.events, event_info);
spin_unlock(&ertp_event_queue_lock);
if (!event) {
rv = process_new_generic_event(event_info);
} else {
if (event->wait_for_result(event) == 0) {
rv = (ERTP_EVENT_GENERIC(event))->result;
}
ertp_event_unref(event);
}
return rv;
}
int ertp_event_queue_handle_memory_event(
const struct ertp_event_memory_info *event_info) {
int rv = ERTP_UNKNOWN;
struct ertp_event *event = ertp_event_memory_new(event_info);
if (IS_ERR(event)) {
return rv;
}
if (ertp_event_queue_push(event)) {
if (event->wait_for_result(event) == 0) {
rv = (ERTP_EVENT_MEMORY(event))->result;
}
ertp_event_queue_remove(event);
}
ertp_mem_dev_destroy(ERTP_EVENT_MEMORY(event));
ertp_event_unref(event);
return rv;
}
void ertp_event_queue_handle_remove_event(struct path *path) {
struct ertp_event *event = ertp_event_remove_new(path);
if (!IS_ERR(event)) {
ertp_cache_remove((ERTP_EVENT_REMOVE(event))->ino,
(ERTP_EVENT_REMOVE(event))->dev);
if (ertp_event_queue_push(event)) {
event->wait_for_result(event);
ertp_event_queue_remove(event);
}
ertp_event_unref(event);
}
}
void ertp_event_queue_handle_rename(const struct path *path) {
struct ertp_event *event;
spin_lock(&ertp_event_queue_lock);
event = ertp_event_container_find_by_path(&ertp_event_queue.events, path);
spin_unlock(&ertp_event_queue_lock);
if (event) {
event->wait_for_result(event);
ertp_event_unref(event);
}
}