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_cache.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_cache.h"
#include "ertp.h"
#include "ertp_cache_container.h"
#include "ertp_logs.h"
struct ertp_cache_t {
struct rb_root root;
struct list_head list;
size_t size;
size_t max_size;
};
static DEFINE_MUTEX(ertp_cache_mutex);
static struct ertp_cache_t ertp_cache = {
.root = RB_ROOT,
.list = LIST_HEAD_INIT(ertp_cache.list),
.size = 0,
.max_size = 10000,
};
int ertp_cache_init(void) {
int err = ertp_cache_item_allocator_init();
if (unlikely(err)) {
return err;
}
return 0;
}
void ertp_cache_deinit(void) {
ertp_cache_clear();
ertp_cache_item_allocator_deinit();
}
static void ertp_cache_remove_internal_unlocked(struct ertp_cache_item *item) {
--ertp_cache.size;
list_del_init(&item->time_list);
ertp_cache_container_erase(&ertp_cache.root, item);
}
static inline unsigned convert_event_type(enum ertp_event_type type) {
switch (type) {
case ERTP_EVENT_TYPE_OPEN:
return ERTP_CACHE_ET_OPEN;
case ERTP_EVENT_TYPE_CLOSE:
return ERTP_CACHE_ET_CLOSE;
case ERTP_EVENT_TYPE_EXEC:
return ERTP_CACHE_ET_EXEC;
default:
BUG();
}
return 0;
}
enum ertp_cache_result_t ertp_cache_check(
const struct ertp_event_generic_info *event_info) {
enum ertp_cache_result_t result = ERTP_CACHE_NOT_FOUND;
const struct inode *inode_ptr = ertp_get_inode(event_info->file);
struct ertp_cache_item *item;
struct ertp_cache_key key = {
.ino = inode_ptr->i_ino,
.dev = new_encode_dev(inode_ptr->i_sb->s_dev),
};
mutex_lock(&ertp_cache_mutex);
item = ertp_cache_container_find(&ertp_cache.root, &key, NULL);
if (!item) {
ertp_pr_log(ERTP_LOG_CACHE,
"cached result for event %d (%s), ino %lld, dev %lld and path "
"%s not found",
event_info->type, ertp_event_type_to_str(event_info->type),
key.ino, key.dev, event_info->file_path->ptr);
goto exit;
}
if (!ertp_timespec_equal(item->ctime, ertp_inode_get_ctime(inode_ptr))) {
result = ERTP_CACHE_MODIFIED;
ertp_pr_log(ERTP_LOG_CACHE,
"cached result for event %d (%s), ino %lld, dev %lld and path "
"%s is obsolete",
event_info->type, ertp_event_type_to_str(event_info->type),
key.ino, key.dev, event_info->file_path->ptr);
ertp_cache_remove_internal_unlocked(item);
goto exit;
}
if (!(item->event_type & convert_event_type(event_info->type))) {
ertp_pr_log(ERTP_LOG_CACHE,
"cached result for event %d (%s), ino %lld, dev %lld and path "
"%s not found (only event with mask %d present)",
event_info->type, ertp_event_type_to_str(event_info->type),
key.ino, key.dev, event_info->file_path->ptr, item->event_type);
goto exit;
}
ertp_pr_log(
ERTP_LOG_CACHE,
"cached result for event %d (%s), ino %lld, dev %lld and path %s found",
event_info->type, ertp_event_type_to_str(event_info->type), key.ino,
key.dev, event_info->file_path->ptr);
result = ERTP_CACHE_FOUND;
list_move_tail(&item->time_list, &ertp_cache.list);
exit:
mutex_unlock(&ertp_cache_mutex);
return result;
}
void ertp_cache_remove(uint64_t ino, uint64_t dev) {
struct ertp_cache_item *item;
struct ertp_cache_key key = {
.ino = ino,
.dev = dev,
};
mutex_lock(&ertp_cache_mutex);
item = ertp_cache_container_find(&ertp_cache.root, &key, NULL);
if (item) {
ertp_pr_log(ERTP_LOG_CACHE,
"removing obsolete item in cache with ino %lld and dev %lld,",
item->key.ino, item->key.dev);
ertp_cache_remove_internal_unlocked(item);
}
mutex_unlock(&ertp_cache_mutex);
}
void ertp_cache_add(const struct ertp_event_generic *event) {
struct ertp_cache_item *item;
struct ertp_cache_key key = {
.ino = event->ino,
.dev = event->dev,
};
mutex_lock(&ertp_cache_mutex);
item = ertp_cache_container_add(&ertp_cache.root, &key, event->ctime,
convert_event_type(event->type));
if (unlikely(!item)) {
goto exit;
}
if (list_empty(&item->time_list)) {
list_add_tail(&item->time_list, &ertp_cache.list);
++ertp_cache.size;
ertp_pr_log(ERTP_LOG_CACHE,
"adding item to cache with ino: %lld, dev: %lld, path: %s "
"(cache size: %lu)",
event->ino, event->dev, event->file_path->ptr, ertp_cache.size);
if (ertp_cache.size > ertp_cache.max_size) {
item =
list_entry(ertp_cache.list.next, struct ertp_cache_item, time_list);
ertp_cache_remove_internal_unlocked(item);
ertp_pr_log(ERTP_LOG_CACHE,
"removing oldest item in cache with ino %lld and dev %lld",
item->key.ino, item->key.dev);
}
} else {
list_move_tail(&item->time_list, &ertp_cache.list);
ertp_pr_log(ERTP_LOG_CACHE,
"updating item to cache with ino: %lld, dev: %lld, path: %s",
event->ino, event->dev, event->file_path->ptr);
}
exit:
mutex_unlock(&ertp_cache_mutex);
}
void ertp_cache_set_size(size_t max_size) {
mutex_lock(&ertp_cache_mutex);
ertp_cache.max_size = max_size;
mutex_unlock(&ertp_cache_mutex);
}
size_t ertp_cache_get_size(void) {
size_t result;
mutex_lock(&ertp_cache_mutex);
result = ertp_cache.max_size;
mutex_unlock(&ertp_cache_mutex);
return result;
}
void ertp_cache_clear(void) {
struct rb_root old_tree;
mutex_lock(&ertp_cache_mutex);
old_tree = ertp_cache.root;
INIT_LIST_HEAD(&ertp_cache.list);
ertp_cache.root = RB_ROOT;
ertp_cache.size = 0;
mutex_unlock(&ertp_cache_mutex);
ertp_cache_container_clear(&old_tree);
ertp_pr_log(ERTP_LOG_CACHE, "cache has been flushed");
}