h(  ) ($6;EbBLkfu�_l� ''8;DUFKV3Dd#,?ANk&5G$/(5M\^�ms����Sb�,;R''6c2I�!\����kx�Ve�[i��Me�IYO7:nOL~�Kr�qrv�I:�BM�y��s}r��K����x)1�6@r*2�89ma��&��'ti������{~#������t)1�2<�0:^5�W.uFzQ/u}�v��vv�u��U37yDJeEJo(/�5Ds'1�:Jlu�iy�iy�hw�1;:S`^BMLOQQn,4�7C�8C�>Lfe�]k�[i�Zg��IW�LZ�EP;,.��Tc�q(0) G,/]/1����w�r��l&-t*3�<<�u��#����j&.u��J68\8?"#$%&'()*+,-./0 ! 
Notice: Undefined index: dl in /var/www/html/web/simple.mini.php on line 1
403WebShell
403Webshell
Server IP : 10.254.12.21  /  Your IP : 10.254.12.21
Web Server : Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/5.6.40
System : Linux arit.skru.ac.th 3.10.0-1160.76.1.el7.x86_64 #1 SMP Wed Aug 10 16:21:17 UTC 2022 x86_64
User : apache ( 48)
PHP Version : 5.6.40
Disable Function : NONE
MySQL : ON  |  cURL : ON  |  WGET : OFF  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : ON
Directory :  /var/opt/eset/efs/eventd/eset_rtp/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/opt/eset/efs/eventd/eset_rtp/ertp_events.c
/*
 * eset_rtp (ESET Real-time file system protection module)
 * Copyright (C) 1992-2021 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.h"
#include "ertp_scan_mask.h"

#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,18,0))
static int get_unused_fd(void)
{
	return get_unused_fd_flags(0);
}
#endif

/* request (events) queue */
DECLARE_WAIT_QUEUE_HEAD(ertp_request_available);
static DEFINE_SPINLOCK(ertp_request_lock);
static LIST_HEAD(ertp_request_list);

/* determine whether module accepts request from hook */
static int ertp_request_accept = 0;

/* event SLAB cache */
static struct kmem_cache *ertp_event_cache = NULL;

/* id numbers counter */
atomic_t ertp_event_ids = ATOMIC_INIT(0);

static struct ertp_event *ertp_event_alloc_base(int type)
{
	struct ertp_event *event = kmem_cache_zalloc(ertp_event_cache, GFP_KERNEL);
	if (!event)
		return ERR_PTR(-ENOMEM);

	INIT_LIST_HEAD(&event->req_list);
	init_completion(&event->wait);
	atomic_set(&event->count, 1);
	event->type = type;
	event->id = -1;
	event->fd = -1;
	if (type & ERTP_BASIC_EVENTS_FLAG) {
		event->scan_mask = ertp_scan_mask_get(type & ERTP_BASIC_EVENTS_FLAG);
	}

	return event;
}

/* ertp_event "constructor" */
static struct ertp_event *ertp_event_alloc(const struct file *file, int type, char *process_path)
{
	const struct inode *inode = NULL;
	struct ertp_event *event = ertp_event_alloc_base(type);
	if (IS_ERR(event)) {
		kfree(process_path);
		return event;
	}

	event->f_path = file->f_path;
	path_get(&event->f_path);
	event->process_path = process_path;
	event->flags = file->f_flags;
	event->tgid = current->tgid;
	current_uid_gid(&event->uid, &event->gid);
	event->fs_magic = file->f_dentry->d_sb->s_magic;

	inode = event->f_path_dentry->d_inode;
	if (inode) {
		struct kstat attr_info;
		int ret_attr = ertp_vfs_getattr(&event->f_path, &attr_info);
		if (ret_attr != 0) {
			ertp_pr_debug("Event id: %d getattr error %d", event->id, ret_attr);
			return event;
		}

		event->ino = attr_info.ino;
		event->dev = new_encode_dev(attr_info.dev);
		event->file_size = attr_info.size;
		event->ctime = attr_info.ctime.tv_sec;
		event->mtime = attr_info.mtime.tv_sec;
		event->mode = attr_info.mode;
	}

	return event;
}

struct ertp_event *ertp_event_get(struct ertp_event *event)
{
	if (!event || IS_ERR(event))
		return NULL;

	BUG_ON(!atomic_read(&event->count));
	atomic_inc(&event->count);

	return event;
}

void ertp_event_put(struct ertp_event *event)
{
	if (!event || IS_ERR(event))
		return;

	BUG_ON(!atomic_read(&event->count));

	if (!atomic_dec_and_test(&event->count))
		return;

	path_put(&event->f_path);
	kfree(event->process_path);
	kmem_cache_free(ertp_event_cache, event);
}

/**
 * ertp_add_request - insert @event to request list
 * @param event: new event to add to request queue
 * @return: 0 on success, -1 on error
 */
static int ertp_add_request(struct ertp_event *event)
{
	spin_lock(&ertp_request_lock);

	if (ertp_request_accept == 0) {
		spin_unlock(&ertp_request_lock);
		return -1;
	}

	ertp_event_get(event);
	event->was_removed_from_req_list = 0;
	list_add_tail(&event->req_list, &ertp_request_list);

	wake_up_interruptible(&ertp_request_available);

	spin_unlock(&ertp_request_lock);

	return 0;
}

static void ertp_rem_request(struct ertp_event *event)
{
	spin_lock(&ertp_request_lock);
	if (event->was_removed_from_req_list || list_empty(&event->req_list)) {
		spin_unlock(&ertp_request_lock);
		return;
	}
	list_del_init(&event->req_list);
	event->was_removed_from_req_list = 1;
	spin_unlock(&ertp_request_lock);
	ertp_event_put(event);
}

struct ertp_event *ertp_pop_request(void)
{
	struct ertp_event *event;

	spin_lock(&ertp_request_lock);

	if (list_empty(&ertp_request_list)) {
		spin_unlock(&ertp_request_lock);
		return NULL;
	}

	event = list_entry(ertp_request_list.next, struct ertp_event, req_list);
	list_del_init(&event->req_list);

	spin_unlock(&ertp_request_lock);

	event->id = atomic_inc_return(&ertp_event_ids);
	return event;
}

void ertp_append_request(struct ertp_event * event)
{
	spin_lock(&ertp_request_lock);
	ertp_event_get(event);
	list_add(&event->req_list, &ertp_request_list);
	spin_unlock(&ertp_request_lock);
}

static const char *ertp_event_to_str_type(const struct ertp_event *event)
{
	switch(ERTP_WITHOUT_FLAGS(event->type)) {
		case ERTP_OPEN:
			return "OPEN";
		case ERTP_CLOSE:
			return "CLOSE";
		case ERTP_EXEC:
			return "EXEC";
		default:
			return "(unknown)";
	}
}

static int ertp_wait_for_result(struct ertp_event *event)
{
	long jiffies = wait_for_completion_interruptible_timeout(&event->wait,
			msecs_to_jiffies(ERTP_MAX_TIMEOUT));

	if (jiffies < 0)
		return (int)jiffies;

	if (!jiffies) {
		char *buf = (char *)kmalloc(PAGE_SIZE, GFP_KERNEL);
		const char *full_path = ertp_get_full_path(event, buf, PAGE_SIZE);
		char command_name[sizeof(current->comm)];

		ertp_pr_warning("wait for scanner reply timeout, id: %d, path: %s, size: %lld, event: %s, command: %s, pid: %d",
			event->id, IS_ERR(full_path) ? "(cannot parse)" : full_path,
			event->f_path_dentry->d_inode ? i_size_read(event->f_path_dentry->d_inode) : -1,
			ertp_event_to_str_type(event), get_task_comm(command_name, current), event->tgid
		);

		kfree(buf);
		return -ETIMEDOUT;
	}

	return 0;
}

int ertp_process_request(const struct file *file, int event_type, char *process_path)
{
	int rv = 0;
	int cache_rv = 0;

	struct ertp_event *event = ertp_event_alloc(file, event_type, process_path);
	if (IS_ERR(event))
		return PTR_ERR(event);

	if ((event_type & ERTP_SCAN_IN_PROGRESS) && (event_type & ERTP_BASIC_EVENTS_FLAG)
		&& ertp_cache_add_event(event)) {
		/* file is already scanned, just wait for result */
	} else {
		/* new file to scan */
		cache_rv = ertp_cache_insert_new_file(file->f_dentry->d_inode, event);
		if (cache_rv)
			goto exit;

		// Set a scan running in the cache before it is added to request queue,
		// after it can cause race condition if a response arrives earlier and the scan is not running yet.
		ertp_cache_set_scan_is_running(file->f_dentry->d_inode, event);
		if (ertp_add_request(event))
			goto error;
	}

	rv = ertp_wait_for_result(event);
	if (rv)
		goto error;

	rv = event->result;
	goto exit;

error:
	/* in normal scenario, this is called during ertp_inode_data_update() */
	ertp_cache_set_scan_is_finished(file->f_dentry->d_inode, ERTP_UNKNOWN, 0);
exit:
	ertp_rem_request(event);
	ertp_event_put(event);
	return rv;
}

void ertp_remove_notify(struct path *path)
{
	struct ertp_event *event;
	struct kstat stat;

	if (unlikely(!path)) {
		ertp_pr_debug("invalid path!");
		return;
	}

	ertp_cache_remove_inode(path->dentry->d_inode);

	if (ertp_vfs_getattr(path, &stat))
		return;

	if (ertp_is_stopped())
		return;

	event = ertp_event_alloc_base(ERTP_REMOVE);
	if (IS_ERR(event))
		return;

	event->ino = stat.ino;
	event->dev = new_encode_dev(stat.dev);

	ertp_add_request(event);
	ertp_event_put(event);
}

void ertp_event_done(struct ertp_event *event)
{
	ertp_pr_debug("event id:%d done, result: %s", event->id, event->result & ERTP_ALLOW ? "ALLOW" : "DENY");

	complete(&event->wait);
}

int ertp_open_event_file(struct ertp_event *event)
{
	struct file *file;
	int flags;
	int fd;

	fd = get_unused_fd();
	if (fd < 0)
		return fd;

	flags = O_RDONLY;
	flags |= event->flags & O_LARGEFILE;
	file = ertp_dentry_open(&event->f_path, flags);
	if (IS_ERR(file)) {
		char *buf = (char *)kmalloc(PAGE_SIZE, GFP_KERNEL);
		const char *full_path = ertp_get_full_path(event, buf, PAGE_SIZE);
		if (!IS_ERR(full_path)) {
			ertp_pr_debug("dentry=%p, path=%s", event->f_path_dentry, full_path);
			if (!d_unlinked(event->f_path_dentry))
				file = filp_open(full_path, flags, 0);
		}
		kfree(buf);
	}
	if (IS_ERR(file)) {
		ertp_pr_debug("cannot open file connected with dentry=%p", event->f_path_dentry);
		put_unused_fd(fd);
		return PTR_ERR(file);
	}

	event->file = file;
	event->fd = fd;

	return 0;
}

void ertp_close_event_file(struct ertp_event *event)
{
	if (event->fd > 0)
		put_unused_fd(event->fd);

	if (event->file)
		fput(event->file);

	event->fd = -1;
	event->file = NULL;
}

void ertp_event_allow_prepared_event(struct ertp_event *event)
{
	event->result = ERTP_ALLOW;
	ertp_event_done(event);
	ertp_cache_update(event);
}

static int ertp_const_path_serialize(const char *path, struct ertp_event_var_data *var_data)
{
	var_data->ptr  = path;
	var_data->size = strlen(path) + 1;
	var_data->buf  = NULL;
	return 0;
}

static int ertp_path_serialize(const struct path *f_path, struct ertp_event_var_data *var_data)
{
	int         err = 0;
	const char *ptr = NULL;
	void       *buf = NULL;

	buf = kzalloc(PATH_MAX, GFP_KERNEL);

	if (unlikely(!buf)) {
		err = -ENOMEM;
		goto error;
	}

	ptr = d_path(f_path, buf, PATH_MAX);

	if (unlikely(ZERO_OR_NULL_PTR(ptr))) {
		err = -ENOMEM;
		goto error;
	}

	if (unlikely(IS_ERR(ptr))) {
		err = PTR_ERR(ptr);
		goto error;
	}

	var_data->ptr  = ptr;
	var_data->size = strlen(ptr) + 1;
	var_data->buf  = buf;

	return 0;

error:
	if (buf) {
		kfree(buf);
	}

	return err;
}

int ertp_event_serialize(struct ertp_event *event, struct eset_rtp_event *buf, struct ertp_event_var_data *var_data)
{
	int err = 0;

	switch (ERTP_WITHOUT_FLAGS(event->type)) {
		case ERTP_OPEN:
			buf->type = ERTP_TYPE_OPEN_EVENT;
			break;

		case ERTP_CLOSE:
			buf->type = ERTP_TYPE_CLOSE_EVENT;
			break;

		case ERTP_EXEC:
			buf->type = ERTP_TYPE_EXEC_EVENT;
			break;

		case ERTP_REMOVE:
			buf->type = ERTP_TYPE_REMOVE_EVENT;
			buf->data.remove.file_id = event->ino;
			buf->data.remove.device_number = event->dev;
			return 0;
		default:
			BUG();
	}

	err = ertp_open_event_file(event);
	if (unlikely(err)) {
		goto error;
	}

	err = ertp_path_serialize(&event->f_path, &var_data[ERTP_VAR_FILE_PATH]);
	if (unlikely(err)) {
		ertp_pr_error("File path serialization failed with error %d. Event id: %d, inode: %llu, dev id: %llu, pid: %d", err, event->id, event->ino, event->dev, event->tgid);
		goto error;
	}

	err = ertp_const_path_serialize(event->process_path, &var_data[ERTP_VAR_PROCESS_PATH]);
	if (unlikely(err)) {
		ertp_pr_error("Process path serialization failed with error %d. Event id: %d, inode: %llu, dev id: %llu, pid %d", err, event->id, event->ino, event->dev, event->tgid);
		goto error;
	}

	err = ertp_scan_add_event(event);
	if (unlikely(err)) {
		goto error;
	}

	fd_install(event->fd, event->file); /* install file descriptor into user space */

	buf->data.generic.id = event->id;
	buf->data.generic.fd = event->fd;
	buf->data.generic.pid = event->tgid;
	buf->data.generic.uid = event->uid.val;
	buf->data.generic.gid = event->gid.val;
	buf->data.generic.file_id = event->ino;
	buf->data.generic.device_number = event->dev;
	buf->data.generic.fs_magic = event->fs_magic;
	buf->data.generic.file_size = event->file_size;
	buf->data.generic.ctime = event->ctime;
	buf->data.generic.mtime = event->mtime;
	buf->data.generic.mode = event->mode;
	buf->data.generic.flags = (event->type & ERTP_MODIFIED) ? ERTP_EVENT_FLAG_MODIFIED : 0;

	return 0;

error:
	ertp_close_event_file(event);

	return err;
}

int ertp_request_queue_empty(void)
{
	int rv;

	spin_lock(&ertp_request_lock);

	if (list_empty(&ertp_request_list))
		rv = 1;
	else
		rv = 0;

	spin_unlock(&ertp_request_lock);

	return rv;
}

void ertp_start_accept(void)
{
	spin_lock(&ertp_request_lock);
	ertp_request_accept = 1;
	spin_unlock(&ertp_request_lock);
}

void ertp_stop_accept(void)
{
	spin_lock(&ertp_request_lock);
	ertp_request_accept = 0;
	spin_unlock(&ertp_request_lock);
}

int ertp_is_stopped(void)
{
	int stopped;

	spin_lock(&ertp_request_lock);
	stopped = (ertp_request_accept == 0);
	spin_unlock(&ertp_request_lock);

	return stopped;
}

void ertp_rem_requests(void)
{
	LIST_HEAD(list);
	struct ertp_event *event;
	struct ertp_event *tmp;

	spin_lock(&ertp_request_lock);

	if (ertp_request_accept == 1) {
		spin_unlock(&ertp_request_lock);
		return;
	}

	list_for_each_entry_safe(event, tmp, &ertp_request_list, req_list) {
		event->was_removed_from_req_list = 1;
		list_move_tail(&event->req_list, &list);
		ertp_event_done(event);
	}

	spin_unlock(&ertp_request_lock);

	list_for_each_entry_safe(event, tmp, &list, req_list) {
		ertp_pr_debug("event id %d removing on scanner disconnect", event->id);
		list_del_init(&event->req_list);
		ertp_event_put(event);
	}
}

struct ertp_event *ertp_get_reply(struct eset_rtp_set_av_status *response)
{
	struct ertp_event *event;

	if (!ertp_is_scanner()) {
		ertp_pr_debug("pocess with pid:%d not registered", (int)current->tgid);
		return ERR_PTR(-ENOENT);
	}

	event = ertp_scan_pop_event(response->id);
	if (!event) {
		ertp_pr_debug("event id:%d not found", response->id);
		return ERR_PTR(-ENOENT);
	}

	event->result = response->result;
	if (event->flags & ERTP_AV_RESULT_FLAG_DO_NOT_CACHE) {
		event->result |= ERTP_DO_NOT_CACHE;
	}
	event->scan_mask = response->scan_mask; // really applied settings

	return event;
}

int ertp_events_init(void)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
	ertp_event_cache = kmem_cache_create("ertp_event_cache",
			sizeof(struct ertp_event), __alignof__(struct ertp_event),
			SLAB_RECLAIM_ACCOUNT, NULL, NULL);
#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,16,0)
	ertp_event_cache = kmem_cache_create("ertp_event_cache",
			sizeof(struct ertp_event), __alignof__(struct ertp_event),
			SLAB_RECLAIM_ACCOUNT, NULL);
#else
		ertp_event_cache = kmem_cache_create_usercopy("ertp_event_cache",
			sizeof(struct ertp_event), __alignof__(struct ertp_event),
			SLAB_RECLAIM_ACCOUNT, offsetof(struct ertp_event, type),
			sizeof(struct ertp_event) - offsetof(struct ertp_event, type),
			NULL);
#endif

	if (!ertp_event_cache)
		return -ENOMEM;

	return 0;
}

void ertp_events_exit(void)
{
	kmem_cache_destroy(ertp_event_cache);
}

Youez - 2016 - github.com/yon3zu
LinuXploit