shell bypass 403

Cubjrnet7 Shell


name : fsnotify_events.c
/**
@file     fsnotify_events.h
@brief    fsnotify events
@details  Copyright (c) 2024 Acronis International GmbH
@author   Denis Kopyrin ([email protected])
@since    $Id: $
*/

#include "fsnotify_events.h"

#include <linux/fsnotify.h>
#include <linux/fsnotify_backend.h>

#include "fs_event.h"
#include "lsm_common.h"
#include "path_tools.h"
#include "task_info_map.h"
#include "task_tools.h"

#if defined(FS_IN_ISDIR) && !defined(FS_ISDIR)
#define FS_ISDIR FS_IN_ISDIR
#endif

static void send_fsnotify_event(struct dentry* dentry, struct inode* inode, const void* dentry_name_ptr, uint64_t flags)
{
	task_info_t* task_info;
	transport_ids_t transport_ids;
	msg_type_t type;
	file_key_t key;
	bool always_send = false;

	if (flags & FS_CREATE) {
		type = FP_SI_OT_NOTIFY_FSNOTIFY_CREATE;
		always_send = true;
	}

	if (flags & (FS_DELETE | FS_DELETE_SELF)) {
		type = FP_SI_OT_NOTIFY_FSNOTIFY_UNLINK;
		always_send = true;
	}

	if (flags & FS_MOVE_SELF)
		type = FP_SI_OT_NOTIFY_FSNOTIFY_RENAME;

	if (flags & FS_OPEN)
		type = FP_SI_OT_NOTIFY_FSNOTIFY_OPEN;

	if (flags & FS_MODIFY)
		type = FP_SI_OT_NOTIFY_FSNOTIFY_MODIFY;

	if (!(transport_global_get_combined_mask() & MSG_TYPE_TO_EVENT_MASK(type)))
		return;

	if (!always_send && transport_process_belongs_to_control(current))
		return;

	task_info = task_info_map_get(current);
	if (!task_info)
		return;

	if (!always_send) {
		transport_global_get_ids(&transport_ids);
		if (task_info_can_skip(task_info, &transport_ids, MSG_TYPE_TO_EVENT_MASK(type)))
			goto out;
	}

	if (((FS_CREATE | FS_ISDIR) & flags) == (FS_CREATE | FS_ISDIR)) {
		fs_event_fsnotify_mkdir(task_info, inode, dentry, dentry ? dentry->d_name.name : dentry_name_ptr, flags, type, fs_generic_subtype(inode));
	} else {
		make_key_from_inode(&key, inode);
		fs_event_fsnotify(task_info, &key, flags, type, fs_generic_subtype(inode));
	}

out:
	task_info_put(task_info);
}

struct fsnotify_target {
	struct inode *inode;
	struct dentry *dentry;
};

static struct fsnotify_target fsnotify_event_handler_target(const void *data, int data_type)
{
	struct fsnotify_target target = (struct fsnotify_target){ 0 };
	if (!data)
		return target;

	switch (data_type)
	{
		case FSNOTIFY_EVENT_PATH:
		{
			struct path *path = (struct path *)data;
			struct dentry* dentry = path->dentry;
			if (dentry) {
				target.inode = dentry->d_inode;
				target.dentry = dentry;
			}
			break;
		}
		case FSNOTIFY_EVENT_INODE:
		{
			target.inode = (struct inode *)data;
			break;
		}
#ifdef HAVE_FSNOTIFY_EVENT_DENTRY
		case FSNOTIFY_EVENT_DENTRY:
		{
			struct dentry *dentry = (struct dentry *)data;
			target.dentry = dentry;
			if (dentry)
				target.inode = dentry->d_inode;

			break;
		}
#endif
		default:
			break;
	}

	return target;
}

static void pre_close(const struct path *path, bool modified)
{
	task_info_t* task_info;
	transport_ids_t transport_ids;
	int flags = modified ? O_RDWR : O_RDONLY;
	const uint64_t generatedEventsMask = MSG_TYPE_TO_EVENT_MASK(FP_SI_OT_SYNC_FILE_PRE_CLOSE)
	                                   | MSG_TYPE_TO_EVENT_MASK(FP_SI_OT_NOTIFY_FILE_PRE_CLOSE);
	subtypes_t subtypes;

	if (!path_is_usable(path))
		return;

	if (!(transport_global_get_combined_mask() & generatedEventsMask))
		return;

	subtypes = fs_close_subtypes(modified, path->dentry->d_inode);
	if (!transport_global_subtype_needed(subtypes.sync)
	 && !transport_global_subtype_needed(subtypes.notify))
		return;

	if (transport_process_belongs_to_control(current))
		return;

	task_info = task_info_map_get(current);
	if (!task_info)
		return;

	transport_global_get_ids(&transport_ids);
	refresh_task(task_info, &transport_ids);

	if (task_info_can_skip(task_info, &transport_ids, generatedEventsMask))
		goto err_skipped;

	if (!path_is_valid(path))
		goto err_skipped;

	DPRINTF("calling fs_event_pre_close(flags=0o%o/0x%x)", flags, flags);
	fs_event_pre_close(task_info, flags, path);
	DPRINTF("finished fs_event_pre_close(flags=0o%o/0x%x)", flags, flags);

err_skipped:
	task_info_put(task_info);
}

static void add_file_modify_cache_for_pre_close(const struct inode *inode)
{
	task_info_t *task_info;
	transport_ids_t transport_ids;
	file_context_info_t info = {0};
	const uint64_t generatedEventsMask = MSG_TYPE_TO_EVENT_MASK(FP_SI_OT_SYNC_FILE_PRE_CLOSE) | MSG_TYPE_TO_EVENT_MASK(FP_SI_OT_NOTIFY_FILE_PRE_CLOSE);

	if (!(transport_global_get_combined_mask() & generatedEventsMask))
		return;

	if (transport_process_belongs_to_control(current))
		return;

	task_info = task_info_map_get(current);
	if (!task_info)
		return;

	transport_global_get_ids(&transport_ids);
	refresh_task(task_info, &transport_ids);

	if (!task_info_can_skip(task_info, &transport_ids, generatedEventsMask))
	{
		make_file_context_info_with_inode(&info, inode, make_unique_pid(current));
		add_file_modify_cache(&info);
	}
	task_info_put(task_info);
}

void handle_fsnotify_event(u32 mask, const void *data, int data_type, const void* dentry_name_ptr)
{
	struct fsnotify_target target;
	uint32_t want_mask;
	if (data_type == FSNOTIFY_EVENT_PATH && (mask & (FS_CLOSE_NOWRITE | FS_CLOSE_WRITE)))
	{
		const struct path *path = (const struct path *)data;
		return pre_close(path, (mask & FS_CLOSE_WRITE) != 0);
	}

	want_mask = wanted_fsnotify_events();
	if (!(mask & want_mask))
		return;

	target = fsnotify_event_handler_target(data, data_type);
	if (!inode_is_valid(target.inode))
		return;

	if (mask & FS_MODIFY)
	{
		add_file_modify_cache_for_pre_close(target.inode);
	}

	send_fsnotify_event(target.dentry, target.inode, dentry_name_ptr, mask);
	if (mask & (FS_DELETE_SELF | FS_CREATE))
	{
		file_key_t key;
		make_key_from_inode(&key, target.inode);
		remove_common_cache_all(&key);
	}
}

© 2025 Cubjrnet7