mirror of
https://github.com/openwall/lkrg.git
synced 2023-12-13 21:30:29 +01:00
Add a kprobe verification functionality
Add a new logic to the integrity verification routine verifying if the kprobes are enabled and correctly run. This commit makes kprobe verification functionality as an independent module invoked by integrity verification routine as well as during initialization to make sure kprobes are enabled and run as intended (otherwise, initialization fails).
This commit is contained in:
parent
7db7483880
commit
26f36ed495
7 changed files with 188 additions and 40 deletions
1
Makefile
1
Makefile
|
@ -31,6 +31,7 @@ $(TARGET)-objs += src/modules/ksyms/p_resolve_ksym.o \
|
|||
src/modules/hashing/p_lkrg_fast_hash.o \
|
||||
src/modules/comm_channel/p_comm_channel.o \
|
||||
src/modules/integrity_timer/p_integrity_timer.o \
|
||||
src/modules/integrity_timer/verify_kprobes/p_verify_kprobes.o \
|
||||
src/modules/kmod/p_kmod.o \
|
||||
src/modules/database/CPU.o \
|
||||
src/modules/database/arch/x86/p_x86_metadata.o \
|
||||
|
|
|
@ -211,6 +211,12 @@ void p_check_integrity(struct work_struct *p_work) {
|
|||
p_tmp_hash = hash_from_CPU_data(p_tmp_cpus);
|
||||
p_read_cpu_unlock();
|
||||
|
||||
/* Verify kprobes now */
|
||||
if (lkrg_verify_kprobes()) {
|
||||
/* I'm hacked! ;( */
|
||||
p_hack_check++;
|
||||
}
|
||||
|
||||
p_text_section_lock();
|
||||
|
||||
/*
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
#ifndef P_LKRG_INTEGRITY_TIMER_H
|
||||
#define P_LKRG_INTEGRITY_TIMER_H
|
||||
|
||||
/* Submodule for verifying kprobes */
|
||||
#include "verify_kprobes/p_verify_kprobes.h"
|
||||
|
||||
#define p_alloc_offload() kmem_cache_alloc(p_offload_cache, GFP_ATOMIC)
|
||||
#define p_free_offload(name) kmem_cache_free(p_offload_cache, (void *)(name))
|
||||
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* pi3's Linux kernel Runtime Guard
|
||||
*
|
||||
* Component:
|
||||
* - Integrity verification kprobe verification submodule
|
||||
*
|
||||
* Notes:
|
||||
* - Verify if kprobes are enabled and correctly run
|
||||
*
|
||||
* Timeline:
|
||||
* - Created: 30.XI.2022
|
||||
*
|
||||
* Author:
|
||||
* - Adam 'pi3' Zabrocki (http://pi3.com.pl)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../../../p_lkrg_main.h"
|
||||
|
||||
static int p_lkrg_dummy_entry(struct kretprobe_instance *p_ri, struct pt_regs *p_regs);
|
||||
static int p_lkrg_dummy_ret(struct kretprobe_instance *ri, struct pt_regs *p_regs);
|
||||
|
||||
static char p_lkrg_dummy_kretprobe_state = 0;
|
||||
|
||||
static struct kretprobe p_lkrg_dummy_kretprobe = {
|
||||
.kp.symbol_name = "lkrg_dummy",
|
||||
.handler = p_lkrg_dummy_ret,
|
||||
.entry_handler = p_lkrg_dummy_entry,
|
||||
};
|
||||
|
||||
__attribute__((optimize(0)))
|
||||
noinline int lkrg_dummy(int arg) {
|
||||
|
||||
p_debug_log(P_LOG_DEBUG,
|
||||
"[lkrg_dummy] Argument value: [%d]\n",arg);
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* We can verify integrity of the internal kprobe structures here
|
||||
*/
|
||||
|
||||
return arg+1;
|
||||
}
|
||||
|
||||
|
||||
int lkrg_verify_kprobes(void) {
|
||||
|
||||
int p_ret = 0, ret = -1;
|
||||
|
||||
/* Verify kprobes now */
|
||||
if ( (ret = lkrg_dummy(0)) != 3) {
|
||||
/* I'm hacked! ;( */
|
||||
p_print_log(P_LOG_ALERT, "DETECT: Kprobes: Don't work as intended (disabled?)");
|
||||
p_ret = -1;
|
||||
}
|
||||
p_print_log(P_LOG_WATCH, "lkrg_dummy returned %d vs. expected 3",ret);
|
||||
|
||||
return p_ret;
|
||||
}
|
||||
|
||||
static int p_lkrg_dummy_entry(struct kretprobe_instance *p_ri, struct pt_regs *p_regs) {
|
||||
|
||||
p_regs_set_arg1(p_regs, p_regs_get_arg1(p_regs) + 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int p_lkrg_dummy_ret(struct kretprobe_instance *ri, struct pt_regs *p_regs) {
|
||||
|
||||
p_regs_set_ret(p_regs, p_regs_get_ret(p_regs) + 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
GENERATE_INSTALL_FUNC(lkrg_dummy)
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* pi3's Linux kernel Runtime Guard
|
||||
*
|
||||
* Component:
|
||||
* - Integrity verification kprobe verification submodule
|
||||
*
|
||||
* Notes:
|
||||
* - Verify if kprobes are enabled and correctly run
|
||||
*
|
||||
* Timeline:
|
||||
* - Created: 2.XII.2022
|
||||
*
|
||||
* Author:
|
||||
* - Adam 'pi3' Zabrocki (http://pi3.com.pl)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef P_LKRG_INTEGRITY_VERIFY_KPROBES_H
|
||||
#define P_LKRG_INTEGRITY_VERIFY_KPROBES_H
|
||||
|
||||
int lkrg_verify_kprobes(void);
|
||||
|
||||
int p_install_lkrg_dummy_hook(int p_isra);
|
||||
void p_uninstall_lkrg_dummy_hook(void);
|
||||
|
||||
#endif
|
|
@ -199,10 +199,11 @@ static inline int p_ddebug_remove_module(const char *p_name) {
|
|||
|
||||
#ifdef CONFIG_X86
|
||||
|
||||
#if defined(CONFIG_X86_64)
|
||||
|
||||
/*
|
||||
* Get
|
||||
*/
|
||||
#if defined(CONFIG_X86_64)
|
||||
static inline unsigned long p_regs_get_arg1(struct pt_regs *p_regs) {
|
||||
return p_regs->di;
|
||||
}
|
||||
|
@ -248,10 +249,51 @@ static inline unsigned long p_syscall_get_arg2(struct pt_regs *p_regs) {
|
|||
#else
|
||||
return p_regs_get_arg2(p_regs);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Set
|
||||
*/
|
||||
static inline void p_regs_set_arg1(struct pt_regs *p_regs, unsigned long p_val) {
|
||||
p_regs->di = p_val;
|
||||
}
|
||||
|
||||
static inline void p_regs_set_arg2(struct pt_regs *p_regs, unsigned long p_val) {
|
||||
p_regs->si = p_val;
|
||||
}
|
||||
|
||||
static inline void p_regs_set_ip(struct pt_regs *p_regs, unsigned long p_val) {
|
||||
p_regs->ip = p_val;
|
||||
}
|
||||
|
||||
static inline void p_regs_set_ret(struct pt_regs *p_regs, unsigned long p_val) {
|
||||
p_regs->ax = p_val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Syscalls
|
||||
*/
|
||||
static inline void p_syscall_set_arg1(struct pt_regs *p_regs, unsigned long p_val) {
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0) && defined(CONFIG_ARCH_HAS_SYSCALL_WRAPPER)
|
||||
p_regs_set_arg1((struct pt_regs *)p_regs_get_arg1(p_regs), p_val);
|
||||
#else
|
||||
p_regs_set_arg1(p_regs, p_val);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void p_syscall_set_arg2(struct pt_regs *p_regs, unsigned long p_val) {
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0) && defined(CONFIG_ARCH_HAS_SYSCALL_WRAPPER)
|
||||
p_regs_set_arg2((struct pt_regs *)p_regs_get_arg1(p_regs), p_val);
|
||||
#else
|
||||
p_regs_set_arg2(p_regs, p_val);
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Get
|
||||
*/
|
||||
static inline unsigned long p_regs_get_arg1(struct pt_regs *p_regs) {
|
||||
return p_regs->ax;
|
||||
}
|
||||
|
@ -303,47 +345,9 @@ static inline unsigned long p_syscall_get_arg2(struct pt_regs *p_regs) {
|
|||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Set
|
||||
*/
|
||||
#if defined(CONFIG_X86_64)
|
||||
|
||||
static inline void p_regs_set_arg1(struct pt_regs *p_regs, unsigned long p_val) {
|
||||
p_regs->di = p_val;
|
||||
}
|
||||
|
||||
static inline void p_regs_set_arg2(struct pt_regs *p_regs, unsigned long p_val) {
|
||||
p_regs->si = p_val;
|
||||
}
|
||||
|
||||
static inline void p_regs_set_ip(struct pt_regs *p_regs, unsigned long p_val) {
|
||||
p_regs->ip = p_val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Syscalls
|
||||
*/
|
||||
static inline void p_syscall_set_arg1(struct pt_regs *p_regs, unsigned long p_val) {
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0) && defined(CONFIG_ARCH_HAS_SYSCALL_WRAPPER)
|
||||
p_regs_set_arg1((struct pt_regs *)p_regs_get_arg1(p_regs), p_val);
|
||||
#else
|
||||
p_regs_set_arg1(p_regs, p_val);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void p_syscall_set_arg2(struct pt_regs *p_regs, unsigned long p_val) {
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0) && defined(CONFIG_ARCH_HAS_SYSCALL_WRAPPER)
|
||||
p_regs_set_arg2((struct pt_regs *)p_regs_get_arg1(p_regs), p_val);
|
||||
#else
|
||||
p_regs_set_arg2(p_regs, p_val);
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline void p_regs_set_arg1(struct pt_regs *p_regs, unsigned long p_val) {
|
||||
p_regs->ax = p_val;
|
||||
}
|
||||
|
@ -360,6 +364,10 @@ static inline void p_regs_set_ip(struct pt_regs *p_regs, unsigned long p_val) {
|
|||
p_regs->ip = p_val;
|
||||
}
|
||||
|
||||
static inline void p_regs_set_ret(struct pt_regs *p_regs, unsigned long p_val) {
|
||||
p_regs->ax = p_val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Syscalls
|
||||
*/
|
||||
|
@ -548,6 +556,10 @@ static inline void p_regs_set_ip(struct pt_regs *p_regs, unsigned long p_val) {
|
|||
p_regs->ARM_pc = p_val;
|
||||
}
|
||||
|
||||
static inline void p_regs_set_ret(struct pt_regs *p_regs, unsigned long p_val) {
|
||||
p_regs->ARM_r0 = p_val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Syscalls
|
||||
*/
|
||||
|
@ -684,6 +696,10 @@ static inline void p_regs_set_ip(struct pt_regs *p_regs, unsigned long p_val) {
|
|||
p_regs->pc = p_val;
|
||||
}
|
||||
|
||||
static inline void p_regs_set_ret(struct pt_regs *p_regs, unsigned long p_val) {
|
||||
p_regs->regs[0] = p_val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Syscalls
|
||||
*/
|
||||
|
|
|
@ -409,6 +409,27 @@ static int __init p_lkrg_register(void) {
|
|||
p_parse_module_params();
|
||||
P_SYM(p_find_me) = THIS_MODULE;
|
||||
|
||||
/*
|
||||
* Verify if kprobes run as intended
|
||||
*/
|
||||
|
||||
/* Register kprobes hooks necessary to verify kprobes itself */
|
||||
if (p_install_lkrg_dummy_hook(0)) {
|
||||
p_print_log(P_LOG_FATAL, "Can't hook 'lkrg_dummy'");
|
||||
return P_LKRG_GENERAL_ERROR;
|
||||
}
|
||||
|
||||
/* Verify kprobes now */
|
||||
if (lkrg_verify_kprobes()) {
|
||||
/*
|
||||
* Kprobes does not work as intended.
|
||||
* LKRG can't function without it, stop initialization!
|
||||
*/
|
||||
p_print_log(P_LOG_FATAL, "Can't continue initialization without working kprobes");
|
||||
p_uninstall_lkrg_dummy_hook();
|
||||
return P_LKRG_GENERAL_ERROR;
|
||||
}
|
||||
|
||||
P_SYM_INIT(freeze_processes, int (*)(void))
|
||||
P_SYM_INIT(thaw_processes, void (*)(void))
|
||||
#if defined(CONFIG_X86) && LINUX_VERSION_CODE >= KERNEL_VERSION(5,8,0)
|
||||
|
@ -548,6 +569,7 @@ p_main_error:
|
|||
p_unregister_arch_metadata();
|
||||
p_offload_cache_delete();
|
||||
p_deregister_module_notifier();
|
||||
p_uninstall_lkrg_dummy_hook();
|
||||
if (p_db.p_CPU_metadata_array) {
|
||||
p_kzfree(p_db.p_CPU_metadata_array);
|
||||
p_db.p_CPU_metadata_array = NULL;
|
||||
|
@ -610,7 +632,7 @@ static void __exit p_lkrg_deregister(void) {
|
|||
p_unregister_arch_metadata();
|
||||
p_offload_cache_delete();
|
||||
p_deregister_module_notifier();
|
||||
|
||||
p_uninstall_lkrg_dummy_hook();
|
||||
|
||||
if (p_db.p_CPU_metadata_array)
|
||||
p_kzfree(p_db.p_CPU_metadata_array);
|
||||
|
|
Loading…
Reference in a new issue