shell bypass 403
UnknownSec Shell
:
/
usr
/
src
/
file_protector-1.1-1592
/
network
/ [
drwxr-xr-x
]
upload
mass deface
mass delete
console
info server
name :
raw_socket_manager.c
/** @file raw_socket_manager.cpp @brief Manager for RAW and netlink sockets @details Copyright (c) 2025 Acronis International GmbH @author Denis Kopyrin (denis.kopyrin@acronis.com) @since $Id: $ */ #include "raw_socket_manager.h" #include <linux/magic.h> #include <net/sock.h> #include "hashtable_compat.h" #include "memory.h" #include "net_events.h" #include "transport.h" #ifndef SOCKFS_MAGIC #define SOCKFS_MAGIC 0x534F434B #endif // MARK: Hashtables #define RAW_SOCKET_EVENTS_TABLE_SIZE_BITS 8 typedef struct { struct hlist_node hash_node; // used as a key const struct inode *inode; struct rcu_head rcu; } hashtable_raw_socket_node_t; typedef struct raw_socket_manager { struct mutex table_writer_lock; bool active; // First 'recvmsg' after 'bind' is added 'recvmsg_sniff_hashtable' to trigger 'recvmsg'. // In future, it is possible to keep sockets that needs to be sniffed in this hashtable // if multiple 'recvmsg' sniffing is required. DECLARE_HASHTABLE(recvmsg_sniff_hashtable, RAW_SOCKET_EVENTS_TABLE_SIZE_BITS); } raw_socket_manager_t; static raw_socket_manager_t global_raw_socket_manager; static void raw_socket_node_rcu_free(struct rcu_head *rcu) { hashtable_raw_socket_node_t *node = container_of(rcu, hashtable_raw_socket_node_t, rcu); mem_free(node); } static void raw_socket_table_free(struct hlist_head* heads, int size) { int idx; for (idx = 0; idx < size; idx++) { while (true) { hashtable_raw_socket_node_t* node; struct hlist_node* first = heads[idx].first; if (!first) break; node = hlist_entry(first, hashtable_raw_socket_node_t, hash_node); hlist_del_init_rcu(first); call_rcu(&node->rcu, raw_socket_node_rcu_free); } } } static bool raw_socket_table_is_inserted_rcu(const struct hlist_head* heads, int hash, const struct inode *inode) { hashtable_raw_socket_node_t *search_node; hlist_for_each_entry_rcu(search_node, &heads[hash], hash_node) { if (search_node->inode == inode) { return true; } } return false; } static bool raw_socket_table_erase_impl(struct hlist_head* heads, int hash, const struct inode *inode, hashtable_raw_socket_node_t **pnode) { bool found = false; hashtable_raw_socket_node_t* node; hlist_for_each_entry(node, &heads[hash], hash_node) { if (node->inode == inode) { found = true; break; } } if (found) hlist_del_init_rcu(&node->hash_node); *pnode = node; return found; } static bool raw_socket_table_erase(struct hlist_head* heads, const struct inode *inode) { bool found = false; hashtable_raw_socket_node_t *node; unsigned int hash = moremur_hash((uint64_t) inode, RAW_SOCKET_EVENTS_TABLE_SIZE_BITS); mutex_lock(&global_raw_socket_manager.table_writer_lock); found = raw_socket_table_erase_impl(heads, hash, inode, &node); mutex_unlock(&global_raw_socket_manager.table_writer_lock); if (found) { call_rcu(&node->rcu, raw_socket_node_rcu_free); } return found; } static void raw_socket_table_insert(struct hlist_head* heads, const struct inode *inode) { bool failed_to_insert = false; hashtable_raw_socket_node_t *search_node; hashtable_raw_socket_node_t *node; unsigned int hash = moremur_hash((uint64_t) inode, RAW_SOCKET_EVENTS_TABLE_SIZE_BITS); rcu_read_lock(); if (raw_socket_table_is_inserted_rcu(heads, hash, inode)) { rcu_read_unlock(); return; } rcu_read_unlock(); node = (hashtable_raw_socket_node_t*) mem_alloc(sizeof(*node)); if (!node) { return; } node->inode = inode; mutex_lock(&global_raw_socket_manager.table_writer_lock); if (global_raw_socket_manager.active) { hlist_for_each_entry(search_node, &heads[hash], hash_node) { if (search_node->inode == inode) { failed_to_insert = true; break; } } if (!failed_to_insert) { hlist_add_head_rcu(&node->hash_node, &heads[hash]); } } else { failed_to_insert = true; } mutex_unlock(&global_raw_socket_manager.table_writer_lock); if (failed_to_insert) { mem_free(node); } } static bool raw_socket_table_is_inserted(const struct hlist_head* heads, const struct inode *inode) { unsigned int hash = moremur_hash((uint64_t) inode, RAW_SOCKET_EVENTS_TABLE_SIZE_BITS); bool listed; rcu_read_lock(); listed = raw_socket_table_is_inserted_rcu(heads, hash, inode); rcu_read_unlock(); return listed; } static bool raw_recvmsg_sniff_is_inserted_rcu(const struct inode *inode, unsigned int hash) { return raw_socket_table_is_inserted_rcu(global_raw_socket_manager.recvmsg_sniff_hashtable, hash, inode); } static bool raw_recvmsg_sniff_needs_handling(const struct inode *inode) { struct hlist_head* heads = global_raw_socket_manager.recvmsg_sniff_hashtable; if (!raw_socket_table_is_inserted(heads, inode)) return false; return raw_socket_table_erase(heads, inode); } // MARK: APIs void raw_socket_manager_init(void) { mutex_init(&global_raw_socket_manager.table_writer_lock); global_raw_socket_manager.active = false; hash_init(global_raw_socket_manager.recvmsg_sniff_hashtable); } void raw_socket_manager_activate(void) { mutex_lock(&global_raw_socket_manager.table_writer_lock); global_raw_socket_manager.active = true; mutex_unlock(&global_raw_socket_manager.table_writer_lock); } void raw_socket_manager_deactivate(void) { mutex_lock(&global_raw_socket_manager.table_writer_lock); if (global_raw_socket_manager.active) { raw_socket_table_free(global_raw_socket_manager.recvmsg_sniff_hashtable , (int) ARRAY_SIZE(global_raw_socket_manager.recvmsg_sniff_hashtable)); global_raw_socket_manager.active = false; } mutex_unlock(&global_raw_socket_manager.table_writer_lock); } void raw_socket_manager_inode_free_security(const struct inode *inode) { unsigned int hash = moremur_hash((uint64_t) inode, RAW_SOCKET_EVENTS_TABLE_SIZE_BITS); bool listed; bool recvmsg_sniff_found = false; hashtable_raw_socket_node_t *recvmsg_sniff_node; if (!inode->i_sb) return; if (inode->i_sb->s_magic != SOCKFS_MAGIC) return; rcu_read_lock(); listed = raw_recvmsg_sniff_is_inserted_rcu(inode, hash); rcu_read_unlock(); if (!listed) return; mutex_lock(&global_raw_socket_manager.table_writer_lock); recvmsg_sniff_found = raw_socket_table_erase_impl(global_raw_socket_manager.recvmsg_sniff_hashtable, hash, inode, &recvmsg_sniff_node); mutex_unlock(&global_raw_socket_manager.table_writer_lock); if (recvmsg_sniff_found) { call_rcu(&recvmsg_sniff_node->rcu, raw_socket_node_rcu_free); } } void raw_socket_manager_will_sniff_recvmsg(task_info_t* task_info, struct socket *sock) { transport_ids_t transport_ids; const uint64_t generatedEventsMask = MSG_TYPE_TO_EVENT_MASK(FP_SI_OT_NOTIFY_SOCKET_RECVMSG_RAW); if (!(transport_global_get_combined_mask() & generatedEventsMask)) return; transport_global_get_ids(&transport_ids, generatedEventsMask); if (!task_info_can_skip(task_info, &transport_ids, generatedEventsMask)) { raw_socket_table_insert(global_raw_socket_manager.recvmsg_sniff_hashtable, SOCK_INODE(sock)); } } void raw_socket_manager_recvmsg(task_info_t* task_info, struct socket *sock) { struct inode *inode = SOCK_INODE(sock); transport_ids_t transport_ids; const uint64_t generatedEventsMask = MSG_TYPE_TO_EVENT_MASK(FP_SI_OT_NOTIFY_SOCKET_RECVMSG_RAW); if (!raw_recvmsg_sniff_needs_handling(inode)) return; if (!(transport_global_get_combined_mask() & generatedEventsMask)) return; transport_global_get_ids(&transport_ids, generatedEventsMask); if (!task_info_can_skip(task_info, &transport_ids, generatedEventsMask)) { net_event_recvmsg_raw(task_info, sock); } }
© 2026 UnknownSec