/
usr
/
src
/
file_protector-1.1-1507
/
File Upload :
llllll
Current File: //usr/src/file_protector-1.1-1507/compat.c
/** @file @brief Support for legacy Linux kernel versions @details Copyright (c) 2018-2021 Acronis International GmbH @author Mikhail Krivtsov (mikhail.krivtsov@acronis.com) @since $Id: $ */ #include "compat.h" #include "debug.h" /* * 'get_task_exe_file()' appeared in 'stable/v4.8', * it was backported in RedHat/CentOS 7 (kernel v3.10) */ #ifndef HAVE_GET_TASK_EXE #include <linux/sched.h> // task_lock() // 'get_mm_exe_file' is not 'exported' static struct file *get_mm_exe_file_impl(struct mm_struct *mm) { struct file *exe_file; /* * We need mmap_sem to protect against races with removal of * VM_EXECUTABLE vmas */ down_read(&mm->mmap_sem); exe_file = mm->exe_file; if (exe_file) get_file(exe_file); up_read(&mm->mmap_sem); return exe_file; } struct file *get_task_exe_file_impl(struct task_struct *task) { struct file *exe_file = NULL; struct mm_struct *mm; mm = get_task_mm(task); if (mm) { exe_file = get_mm_exe_file_impl(mm); mmput(mm); } return exe_file; } #elif defined(GET_TASK_EXE_NOT_EXPORTED) //copy from 5.15.0 struct file *get_mm_exe_file_impl(struct mm_struct *mm) { struct file *exe_file; rcu_read_lock(); exe_file = rcu_dereference(mm->exe_file); if (exe_file && !get_file_rcu(exe_file)) exe_file = NULL; rcu_read_unlock(); return exe_file; } struct file *get_task_exe_file_impl(struct task_struct *task) { struct file *exe_file = NULL; struct mm_struct *mm; task_lock(task); mm = task->mm; if (mm) { if (!(task->flags & PF_KTHREAD)) exe_file = get_mm_exe_file_impl(mm); } task_unlock(task); return exe_file; } #endif #ifndef HAVE_KALLSYMS_LOOKUP_NAME // { #include <linux/kallsyms.h> // kallsyms_on_each_symbol() typedef struct { const char *name; unsigned long kallsyms_address; } kallsyms_lookup_name_ctx_t; static int kallsyms_lookup_name_on_each_symbol_cb(void *data, const char *namebuf, struct module *module, unsigned long kallsyms_address) { kallsyms_lookup_name_ctx_t *ctx = data; if (0 == strcmp(namebuf, ctx->name)) { ctx->kallsyms_address = kallsyms_address; return 1; } return 0; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0) #include <linux/kprobes.h> typedef typeof(&kallsyms_on_each_symbol) kallsyms_on_each_symbol_t; static kallsyms_on_each_symbol_t kallsyms_on_each_symbol_ptr = NULL; static const char kallsyms_on_each_symbol_name[] = "kallsyms_on_each_symbol"; static char symbol_name_buffer[128]; int get_kallsyms_on_each_symbol(void) { struct kprobe kp = { .symbol_name = kallsyms_on_each_symbol_name, .addr = 0, }; IPRINTF("searching for kallsyms_on_each_symbol by kprobe"); register_kprobe(&kp); kallsyms_on_each_symbol_ptr = (kallsyms_on_each_symbol_t)kp.addr; unregister_kprobe(&kp); IPRINTF("kallsyms_on_each_symbol [0x%px] [%pS]", kallsyms_on_each_symbol_ptr, kallsyms_on_each_symbol_ptr); memset(symbol_name_buffer, 0, 128); snprintf(symbol_name_buffer, 128, "%ps", kallsyms_on_each_symbol_ptr); if (strncmp(symbol_name_buffer, kallsyms_on_each_symbol_name, strlen(kallsyms_on_each_symbol_name)) != 0) { EPRINTF("kallsyms_on_each_symbol address [%px] is wrong", (void *)kallsyms_on_each_symbol_ptr); kallsyms_on_each_symbol_ptr = (kallsyms_on_each_symbol_t)0; return -1; } return 0; } #endif static inline int kallsyms_on_each_symbol_compat(int (*fn)(void *, const char *, struct module *, unsigned long), void *data) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0) if (kallsyms_on_each_symbol_ptr == NULL) { return 0; } return kallsyms_on_each_symbol_ptr(fn, data); #else return kallsyms_on_each_symbol(fn, data); #endif } unsigned long compat_kallsyms_lookup_name(const char *name) { kallsyms_lookup_name_ctx_t ctx = { .name = name, .kallsyms_address = 0, }; if (kallsyms_on_each_symbol_compat(kallsyms_lookup_name_on_each_symbol_cb, &ctx)) { DPRINTF("name='%s' address=0x%lx", name, ctx.kallsyms_address); return ctx.kallsyms_address; } else { DPRINTF("name='%s' not found", name); return 0; } return 0; } // } #endif // tracepoint registration interface was modified in 'stable/v3.15' #ifdef HAVE_TRACEPOINT_PROBE_REGISTER_STRUCT // { #include <linux/tracepoint.h> // for_each_kernel_tracepoint(), // tracepoint_probe_register(), // tracepoint_probe_unregister() typedef struct { const char *name; struct tracepoint *tracepoint; } lookup_tracepoint_ctx_t; static void lookup_tracepoint_on_each_tracepoint_cb(struct tracepoint *tp, void *data) { lookup_tracepoint_ctx_t *ctx = data; //DPRINTF("%p %s", tp, tp->name); if (0 == strcmp(tp->name, ctx->name)) { ctx->tracepoint = tp; } } static struct tracepoint *lookup_tracepoint(const char *name) { lookup_tracepoint_ctx_t ctx = { .name = name, .tracepoint = 0, }; for_each_kernel_tracepoint(lookup_tracepoint_on_each_tracepoint_cb, &ctx); return ctx.tracepoint; } int tracepoint_probe_register_compat(const char *name, void *probe, void *data) { struct tracepoint *tp = lookup_tracepoint(name); return (!tp) ? -ENOSYS : tracepoint_probe_register(tp, probe, data); } int tracepoint_probe_unregister_compat(const char *name, void *probe, void *data) { struct tracepoint *tp = lookup_tracepoint(name); return (!tp) ? -ENOSYS : tracepoint_probe_unregister(tp, probe, data); } // } #endif // rbtree postorder iteration functions appeared in 'stable/v3.12' #if !defined(HAVE_RB_FIRST_POSTORDER) || !defined(HAVE_RB_NEXT_POSTORDER) static struct rb_node *rb_left_deepest_node(const struct rb_node *node) { for (;;) { if (node->rb_left) node = node->rb_left; else if (node->rb_right) node = node->rb_right; else return (struct rb_node *)node; } } #endif #ifndef HAVE_RB_NEXT_POSTORDER struct rb_node *rb_next_postorder(const struct rb_node *node) { const struct rb_node *parent; if (!node) return NULL; parent = rb_parent(node); /* If we're sitting on node, we've already seen our children */ if (parent && node == parent->rb_left && parent->rb_right) { /* If we are the parent's left node, go to the parent's right * node then all the way down to the left */ return rb_left_deepest_node(parent->rb_right); } else /* Otherwise we are the parent's right node, and the parent * should be next */ return (struct rb_node *)parent; } #endif #ifndef HAVE_RB_FIRST_POSTORDER struct rb_node *rb_first_postorder(const struct rb_root *root) { if (!root->rb_node) return NULL; return rb_left_deepest_node(root->rb_node); } #endif
Copyright ©2k19 -
Hexid
|
Tex7ure