shell bypass 403
UnknownSec Shell
:
/
usr
/
src
/
file_protector-1.1-1592
/ [
drwxr-xr-x
]
upload
mass deface
mass delete
console
info server
name :
lru_hashtable.c
/** @file lru_hashtable.c @brief LRU hashtable implementation @details Copyright (c) 2026 Acronis International GmbH @author Bruce Wang (bruce.wang@acronis.com) @since $Id: $ */ #include "lru_hashtable.h" #include "hash_fast.h" #include "path_tools.h" #include "memory.h" #include <linux/jiffies.h> #include <linux/list.h> #define LRU_TABLE_SIZE (1 << (LRU_TABLE_SIZE_BITS - 1)) // 16384 #define LRU_TABLE_CLEAN_SIZE 256 #ifndef list_first_entry_or_null #define list_first_entry_or_null(ptr, type, member) (list_empty(ptr) ? NULL : list_first_entry(ptr, type, member)) #endif #ifdef KERNEL_MOCK #include "mock/mock.h" #endif // 30 seconds #define TTL msecs_to_jiffies(30000) typedef struct { atomic_t refcount; struct hlist_node hash_node; struct list_head lru_list_node; bool lru_list_inserted; unsigned long lru_deadline; struct rcu_head rcu; lru_hashtable_key_t key; } lru_hashtable_node_t; // MARK: lru hashtable node static lru_hashtable_node_t *node_alloc(const lru_hashtable_key_t *key, lru_hashtable_key_type_t key_type) { lru_hashtable_node_t *node = mem_alloc(sizeof(lru_hashtable_node_t)); if (!node) return NULL; atomic_set(&node->refcount, 1); node->lru_list_inserted = false; INIT_HLIST_NODE(&node->hash_node); INIT_LIST_HEAD(&node->lru_list_node); switch (key_type) { case LRU_HASHTABLE_KEY_TYPE_PROCFS: node->key.procfs_key = key->procfs_key; break; case LRU_HASHTABLE_KEY_TYPE_PTRACE: node->key.ptrace_key = key->ptrace_key; break; default: mem_free(node); return NULL; } return node; } static void node_rcu_free(struct rcu_head *rcu) { lru_hashtable_node_t *node = container_of(rcu, lru_hashtable_node_t, rcu); mem_free(node); } static void node_put(lru_hashtable_node_t *node) { if (atomic_dec_and_test(&node->refcount)) call_rcu(&node->rcu, node_rcu_free); } static bool key_equal(const lru_hashtable_key_t *k1, const lru_hashtable_key_t *k2, lru_hashtable_key_type_t key_type) { // TODO: merge access_types and access_modes switch (key_type) { case LRU_HASHTABLE_KEY_TYPE_PROCFS: return k1->procfs_key.access_type == k2->procfs_key.access_type && k1->procfs_key.caller_pid_version == k2->procfs_key.caller_pid_version && k1->procfs_key.target_pid_version == k2->procfs_key.target_pid_version; case LRU_HASHTABLE_KEY_TYPE_PTRACE: return k1->ptrace_key.access_mode == k2->ptrace_key.access_mode && k1->ptrace_key.caller_pid_version == k2->ptrace_key.caller_pid_version && k1->ptrace_key.target_pid_version == k2->ptrace_key.target_pid_version; default: return false; } } static int key_hash(const lru_hashtable_key_t *key, lru_hashtable_key_type_t key_type) { switch (key_type) { case LRU_HASHTABLE_KEY_TYPE_PROCFS: return murmur_hash(&key->procfs_key.caller_pid_version, sizeof(key->procfs_key)) >> (64 - LRU_TABLE_SIZE_BITS); case LRU_HASHTABLE_KEY_TYPE_PTRACE: return murmur_hash(&key->ptrace_key.caller_pid_version, sizeof(key->ptrace_key)) >> (64 - LRU_TABLE_SIZE_BITS); default: return -1; } } static lru_hashtable_node_t *find_ref_rcu(struct lru_hashtable_manager *manager, int hash, const lru_hashtable_key_t *key, lru_hashtable_key_type_t key_type) { lru_hashtable_node_t *search_node; hlist_for_each_entry_rcu(search_node, &manager->seen_entries_hashtable[hash], hash_node) { if (!key_equal(&search_node->key, key, key_type)) continue; if (atomic_inc_not_zero(&search_node->refcount)) return search_node; else return NULL; } return NULL; } static lru_hashtable_node_t *find(struct lru_hashtable_manager *manager, int hash, const lru_hashtable_key_t *key, lru_hashtable_key_type_t key_type) { lru_hashtable_node_t *search_node; hlist_for_each_entry(search_node, &manager->seen_entries_hashtable[hash], hash_node) { if (key_equal(&search_node->key, key, key_type)) return search_node; } return NULL; } static void erase_impl(struct lru_hashtable_manager *manager, lru_hashtable_node_t *node) { hash_del_rcu(&node->hash_node); list_del(&node->lru_list_node); node->lru_list_inserted = false; manager->entries_count--; node_put(node); } static void refresh_impl(struct lru_hashtable_manager *manager, lru_hashtable_node_t *node) { if (node->lru_list_inserted) { node->lru_deadline = jiffies + TTL; list_del(&node->lru_list_node); list_add_tail(&node->lru_list_node, &manager->seen_entries_lru_list); } } // MARK: lru hashtable manager int lru_hashtable_manager_init(struct lru_hashtable_manager **out_manager) { *out_manager = vmem_alloc(sizeof(lru_hashtable_manager_t)); if (!*out_manager) return -ENOMEM; mutex_init(&(*out_manager)->table_writer_lock); (*out_manager)->active = false; (*out_manager)->entries_count = 0; hash_init((*out_manager)->seen_entries_hashtable); INIT_LIST_HEAD(&(*out_manager)->seen_entries_lru_list); return 0; } void lru_hashtable_manager_deinit(struct lru_hashtable_manager *manager) { if (!manager) return; vmem_free(manager); } void lru_hashtable_manager_activate(struct lru_hashtable_manager *manager) { mutex_lock(&manager->table_writer_lock); manager->active = true; mutex_unlock(&manager->table_writer_lock); } void lru_hashtable_manager_deactivate(struct lru_hashtable_manager *manager) { mutex_lock(&manager->table_writer_lock); if (manager->active) { while (1) { lru_hashtable_node_t *node = list_first_entry_or_null(&manager->seen_entries_lru_list, lru_hashtable_node_t, lru_list_node); if (!node) break; erase_impl(manager, node); } manager->active = false; } mutex_unlock(&manager->table_writer_lock); } static void sweep_impl(struct lru_hashtable_manager *manager) { while (1) { lru_hashtable_node_t *node = list_first_entry_or_null(&manager->seen_entries_lru_list, lru_hashtable_node_t, lru_list_node); if (!node) break; if (time_after(jiffies, node->lru_deadline)) erase_impl(manager, node); else break; } while (manager->entries_count >= LRU_TABLE_SIZE - LRU_TABLE_CLEAN_SIZE) { lru_hashtable_node_t *node = list_first_entry_or_null(&manager->seen_entries_lru_list, lru_hashtable_node_t, lru_list_node); if (!node) break; erase_impl(manager, node); } } bool lru_hashtable_manager_key_exist(struct lru_hashtable_manager *manager, const lru_hashtable_key_t *key, lru_hashtable_key_type_t key_type) { int hash; lru_hashtable_node_t *node; if (!manager || !manager->active) { return false; } hash = key_hash(key, key_type); if(hash == -1) { return false; } rcu_read_lock(); node = find_ref_rcu(manager, hash, key, key_type); rcu_read_unlock(); if (node) { mutex_lock(&manager->table_writer_lock); refresh_impl(manager, node); mutex_unlock(&manager->table_writer_lock); node_put(node); return true; } mutex_lock(&manager->table_writer_lock); if (!READ_ONCE(manager->active)) { mutex_unlock(&manager->table_writer_lock); return false; } node = find(manager, hash, key, key_type); if (node) { refresh_impl(manager, node); mutex_unlock(&manager->table_writer_lock); return true; } sweep_impl(manager); node = node_alloc(key, key_type); if (!node) { mutex_unlock(&manager->table_writer_lock); return false; } hlist_add_head_rcu(&node->hash_node, &manager->seen_entries_hashtable[hash]); node->lru_deadline = jiffies + TTL; list_add_tail(&node->lru_list_node, &manager->seen_entries_lru_list); node->lru_list_inserted = true; manager->entries_count++; mutex_unlock(&manager->table_writer_lock); return false; }
© 2026 UnknownSec