lkrg/src/p_lkrg_main.h

449 lines
13 KiB
C
Raw Permalink Normal View History

2017-10-27 07:29:49 +02:00
/*
* pi3's Linux kernel Runtime Guard
*
* Component:
* - Main module
*
* Notes:
* - None
*
* Timeline:
* - Created: 24.XI.2015
*
* Author:
* - Adam 'pi3' Zabrocki (http://pi3.com.pl)
*
*/
#ifndef P_LKRG_MAIN_H
#define P_LKRG_MAIN_H
#define P_LKRG_UNHIDE
#define P_BOOT_DISABLE_LKRG "nolkrg"
2017-10-27 07:29:49 +02:00
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kallsyms.h>
#include <linux/slab.h>
#include <linux/cpu.h>
#include <linux/random.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/version.h>
#include <linux/cpufreq.h>
#include <linux/cpu_pm.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)
#include <linux/cpuhotplug.h>
#endif
#include <linux/netdevice.h>
#include <net/netevent.h>
#include <net/addrconf.h>
#include <linux/inetdevice.h>
#include <linux/usb.h>
#include <linux/acpi.h>
#include <linux/profile.h>
2017-10-27 07:29:49 +02:00
#include <linux/kprobes.h>
#include <linux/namei.h>
#include <linux/dcache.h>
#include <linux/limits.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/rbtree.h>
#include <linux/major.h>
#include <linux/crypto.h>
#include <crypto/hash.h>
#include <linux/scatterlist.h>
#include <linux/signal.h>
2017-12-12 21:34:31 +01:00
#include <linux/timex.h>
#include <linux/vmalloc.h>
#include <linux/ftrace.h>
#include <linux/preempt.h>
#ifndef RHEL_RELEASE_VERSION
#define RHEL_RELEASE_VERSION(a, b) (((a) << 8) + (b))
#endif
#if ( (LINUX_VERSION_CODE < KERNEL_VERSION(4,4,72)) && \
(!(defined(RHEL_RELEASE_CODE)) || \
RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7, 4)))
static inline unsigned long get_random_long(void) {
unsigned long p_ret;
get_random_bytes(&p_ret, sizeof(p_ret));
return p_ret;
}
#endif
2017-10-27 07:29:49 +02:00
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0)
#define p_kzfree kzfree
#else
#define p_kzfree kfree_sensitive
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,15,0) && \
(!defined(RHEL_RELEASE_CODE) || RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(9, 0))
#define p_read_cpu_lock get_online_cpus
#define p_read_cpu_unlock put_online_cpus
#else
#define p_read_cpu_lock cpus_read_lock
#define p_read_cpu_unlock cpus_read_unlock
#endif
#include <linux/stacktrace.h>
#include <asm/stacktrace.h>
#include <asm/tlbflush.h>
#if defined(CONFIG_X86) && defined(CONFIG_UNWINDER_ORC)
#include <asm/unwind.h>
#endif
Fix implicit declaration of function 'task_stack_page' on arm Due to kernel commit f3ac60671954c ("sched/headers: Move task-stack related APIs from <linux/sched.h> to <linux/sched/task_stack.h>") (Linux v4.11) `linux/sched/task_stack.h' should be included to access `task_stack_page'. Compilation failure is appearing on armv8l arch: In file included from ./include/linux/prefetch.h:15, from ./arch/arm/include/asm/atomic.h:12, from ./include/linux/atomic.h:7, from ./include/asm-generic/bitops/lock.h:5, from ./arch/arm/include/asm/bitops.h:243, from ./include/linux/bitops.h:26, from ./include/linux/kernel.h:12, from /usr/src/RPM/BUILD/lkrg-0.8.1/src/modules/exploit_detection/../../p_lkrg_main.h:23, from /usr/src/RPM/BUILD/lkrg-0.8.1/src/modules/exploit_detection/p_exploit_detection.c:18: /usr/src/RPM/BUILD/lkrg-0.8.1/src/modules/exploit_detection/p_exploit_detection.c: In function 'p_iterate_processes': ./arch/arm/include/asm/processor.h:99:40: error: implicit declaration of function 'task_stack_page'; did you mean 'walk_stackframe'? [-Werror=implicit-function-declaration] 99 | ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1) | ^~~~~~~~~~~~~~~ /usr/src/RPM/BUILD/lkrg-0.8.1/src/modules/exploit_detection/p_exploit_detection.c:779:30: note: in expansion of macro 'task_pt_regs' 779 | p_regs_set_ip(task_pt_regs(p_tmp), -1); | ^~~~~~~~~~~~ cc1: some warnings being treated as errors make[1]: *** [scripts/Makefile.build:265: /usr/src/RPM/BUILD/lkrg-0.8.1/src/modules/exploit_detection/p_exploit_detection.o] Error 1 Signed-off-by: Vitaly Chikunov <vt@altlinux.org>
2020-08-18 21:26:54 +02:00
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,11,0)
#include <linux/sched/task_stack.h>
#endif
/*
* Define kmem_cache_create() flags:
* - LKRG has used to leverage SLAB_HWCACHE_ALIGN but memory overhead
* may be too significant for LKRG's use cases
* - Since the kernel 4.5+ we can use SLAB_ACCOUNT to make sure
* that LKRG's caches are standalone
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0)
#define P_LKRG_CACHE_FLAGS 0
#else
#define P_LKRG_CACHE_FLAGS SLAB_ACCOUNT
#endif
/*
* Some custom compilation of the kernel might aggresively inline
* critical functions (from LKRG perspective). That's problematic
* for the project. However, some of the problems *might* be solved
* by uncommenting following definition. However, not all of them
* so you need to experiment.
*/
//#define P_KERNEL_AGGRESSIVE_INLINING 1
//#define p_lkrg_read_only __attribute__((__section__(".data..p_lkrg_read_only"),aligned(PAGE_SIZE)))
#define __p_lkrg_read_only __attribute__((__section__(".p_lkrg_read_only")))
#if defined(CONFIG_X86_64) || defined(CONFIG_ARM64)
#define P_LKRG_MARKER1 0x3369705f6d616441
#define P_LKRG_MARKER2 0xdeadbabedeadbabe
#else
#define P_LKRG_MARKER1 0x3369705f
#define P_LKRG_MARKER2 0xdeadbabe
#endif
#if defined(CONFIG_SECURITY_SELINUX_DEVELOP) && !defined(CONFIG_GCC_PLUGIN_RANDSTRUCT)
#define P_SELINUX_VERIFY
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,9,0) || \
(LINUX_VERSION_CODE >= KERNEL_VERSION(5,4,118) && LINUX_VERSION_CODE < KERNEL_VERSION(5,5,0)) || \
(LINUX_VERSION_CODE >= KERNEL_VERSION(4,19,191) && LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0)) || \
(LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,233) && LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0))
#define P_LKRG_UNEXPORTED_MODULE_ADDRESS
#endif
#define nitems(val) (sizeof(val) / sizeof(val[0]))
typedef struct _p_lkrg_global_conf_structure {
#if defined(CONFIG_X86)
unsigned int p_smep_validate;
unsigned int p_smap_validate;
#endif
unsigned int p_pcfi_validate;
This is a huge change. We completely rewrote communication channel and added a lot of new configuration options. Summary: 1) Introduce 'kint_validate' to control kernel/system integrity logic: 0 - disabled 1 - validation is performed only when manually triggered 3 - validation is performed periodically by timer interrupt and on random events 2) Introduce 'kint_enforce' to control how LKRG reacts when kernel/system integrity fails: 0 - log & accept corruption 1 - log only (for SELinux and CR0.WP violation log & restore original values) 2 - panic() - kill the kernel 3) Introduce 'pint_validate' to control tasks validation logic: 0 - disabled 1 - validate only currently running tasks 2 - validate only currently running tasks + task which changes state to RUNNING 3 - validate all tasks in the system (paranoid mode) 4) Introduce 'pint_enforce' to control how LKRG reacts when task validation fails: 0 - log & accept corruption 1 - kill corrupted task 2 - panic() - kill the kernel 5) Introduce 'smep_validate' to control if SMEP validation will be performed 0 - disable SMEP validation 1 - enable SMEP validation 6) Introduce 'smep_enforce' to control how LKRG reacts when SMEP validation fails: 0 - log & accept 1 - log & restore 2 - panic() - kill the kernel 7) Introduce 'umh_validate' to control if UMH validation will be performed 0 - disable UMH validation 1 - allow only whitelited binaries to execute via UMH 2 - completely block UMH 8) Introduce 'smep_enforce' to control how LKRG reacts when UMH validation fails: 0 - log only 1 - prevent execution 2 - panic() - kill the kernel 9) Introduce 'pcfi_validate' to control if pCFI validation will be performed 0 - disabled 1 - no stackwalk (weak pCFI) 2 - fully enabled 10) Introduce 'pcfi_enforce' to control how LKRG reacts when pCFI validation fails: 0 - log only 1 - kill corrupted task 2 - panic() - kill the kernel 11) Rename 'timestamp' to 'interval' 12) Rename 'force_run' to 'trigger' 13) Rename 'clean_message' to 'heartbeat' 14) Rename 'msr_enforce' to 'msr_validate' 15) Option 'hide' stays the same 16) Option 'log_level' stays the same 17) Option 'block_modules' stays the same
2020-04-25 19:41:52 +02:00
unsigned int p_pint_validate;
unsigned int p_kint_validate;
unsigned int p_log_level;
unsigned int p_block_modules;
unsigned int p_msr_validate;
This is a huge change. We completely rewrote communication channel and added a lot of new configuration options. Summary: 1) Introduce 'kint_validate' to control kernel/system integrity logic: 0 - disabled 1 - validation is performed only when manually triggered 3 - validation is performed periodically by timer interrupt and on random events 2) Introduce 'kint_enforce' to control how LKRG reacts when kernel/system integrity fails: 0 - log & accept corruption 1 - log only (for SELinux and CR0.WP violation log & restore original values) 2 - panic() - kill the kernel 3) Introduce 'pint_validate' to control tasks validation logic: 0 - disabled 1 - validate only currently running tasks 2 - validate only currently running tasks + task which changes state to RUNNING 3 - validate all tasks in the system (paranoid mode) 4) Introduce 'pint_enforce' to control how LKRG reacts when task validation fails: 0 - log & accept corruption 1 - kill corrupted task 2 - panic() - kill the kernel 5) Introduce 'smep_validate' to control if SMEP validation will be performed 0 - disable SMEP validation 1 - enable SMEP validation 6) Introduce 'smep_enforce' to control how LKRG reacts when SMEP validation fails: 0 - log & accept 1 - log & restore 2 - panic() - kill the kernel 7) Introduce 'umh_validate' to control if UMH validation will be performed 0 - disable UMH validation 1 - allow only whitelited binaries to execute via UMH 2 - completely block UMH 8) Introduce 'smep_enforce' to control how LKRG reacts when UMH validation fails: 0 - log only 1 - prevent execution 2 - panic() - kill the kernel 9) Introduce 'pcfi_validate' to control if pCFI validation will be performed 0 - disabled 1 - no stackwalk (weak pCFI) 2 - fully enabled 10) Introduce 'pcfi_enforce' to control how LKRG reacts when pCFI validation fails: 0 - log only 1 - kill corrupted task 2 - panic() - kill the kernel 11) Rename 'timestamp' to 'interval' 12) Rename 'force_run' to 'trigger' 13) Rename 'clean_message' to 'heartbeat' 14) Rename 'msr_enforce' to 'msr_validate' 15) Option 'hide' stays the same 16) Option 'log_level' stays the same 17) Option 'block_modules' stays the same
2020-04-25 19:41:52 +02:00
unsigned int p_heartbeat;
unsigned int p_interval;
unsigned int p_umh_validate;
#if defined(CONFIG_X86)
This is a huge change. We completely rewrote communication channel and added a lot of new configuration options. Summary: 1) Introduce 'kint_validate' to control kernel/system integrity logic: 0 - disabled 1 - validation is performed only when manually triggered 3 - validation is performed periodically by timer interrupt and on random events 2) Introduce 'kint_enforce' to control how LKRG reacts when kernel/system integrity fails: 0 - log & accept corruption 1 - log only (for SELinux and CR0.WP violation log & restore original values) 2 - panic() - kill the kernel 3) Introduce 'pint_validate' to control tasks validation logic: 0 - disabled 1 - validate only currently running tasks 2 - validate only currently running tasks + task which changes state to RUNNING 3 - validate all tasks in the system (paranoid mode) 4) Introduce 'pint_enforce' to control how LKRG reacts when task validation fails: 0 - log & accept corruption 1 - kill corrupted task 2 - panic() - kill the kernel 5) Introduce 'smep_validate' to control if SMEP validation will be performed 0 - disable SMEP validation 1 - enable SMEP validation 6) Introduce 'smep_enforce' to control how LKRG reacts when SMEP validation fails: 0 - log & accept 1 - log & restore 2 - panic() - kill the kernel 7) Introduce 'umh_validate' to control if UMH validation will be performed 0 - disable UMH validation 1 - allow only whitelited binaries to execute via UMH 2 - completely block UMH 8) Introduce 'smep_enforce' to control how LKRG reacts when UMH validation fails: 0 - log only 1 - prevent execution 2 - panic() - kill the kernel 9) Introduce 'pcfi_validate' to control if pCFI validation will be performed 0 - disabled 1 - no stackwalk (weak pCFI) 2 - fully enabled 10) Introduce 'pcfi_enforce' to control how LKRG reacts when pCFI validation fails: 0 - log only 1 - kill corrupted task 2 - panic() - kill the kernel 11) Rename 'timestamp' to 'interval' 12) Rename 'force_run' to 'trigger' 13) Rename 'clean_message' to 'heartbeat' 14) Rename 'msr_enforce' to 'msr_validate' 15) Option 'hide' stays the same 16) Option 'log_level' stays the same 17) Option 'block_modules' stays the same
2020-04-25 19:41:52 +02:00
unsigned int p_smep_enforce;
unsigned int p_smap_enforce;
#endif
This is a huge change. We completely rewrote communication channel and added a lot of new configuration options. Summary: 1) Introduce 'kint_validate' to control kernel/system integrity logic: 0 - disabled 1 - validation is performed only when manually triggered 3 - validation is performed periodically by timer interrupt and on random events 2) Introduce 'kint_enforce' to control how LKRG reacts when kernel/system integrity fails: 0 - log & accept corruption 1 - log only (for SELinux and CR0.WP violation log & restore original values) 2 - panic() - kill the kernel 3) Introduce 'pint_validate' to control tasks validation logic: 0 - disabled 1 - validate only currently running tasks 2 - validate only currently running tasks + task which changes state to RUNNING 3 - validate all tasks in the system (paranoid mode) 4) Introduce 'pint_enforce' to control how LKRG reacts when task validation fails: 0 - log & accept corruption 1 - kill corrupted task 2 - panic() - kill the kernel 5) Introduce 'smep_validate' to control if SMEP validation will be performed 0 - disable SMEP validation 1 - enable SMEP validation 6) Introduce 'smep_enforce' to control how LKRG reacts when SMEP validation fails: 0 - log & accept 1 - log & restore 2 - panic() - kill the kernel 7) Introduce 'umh_validate' to control if UMH validation will be performed 0 - disable UMH validation 1 - allow only whitelited binaries to execute via UMH 2 - completely block UMH 8) Introduce 'smep_enforce' to control how LKRG reacts when UMH validation fails: 0 - log only 1 - prevent execution 2 - panic() - kill the kernel 9) Introduce 'pcfi_validate' to control if pCFI validation will be performed 0 - disabled 1 - no stackwalk (weak pCFI) 2 - fully enabled 10) Introduce 'pcfi_enforce' to control how LKRG reacts when pCFI validation fails: 0 - log only 1 - kill corrupted task 2 - panic() - kill the kernel 11) Rename 'timestamp' to 'interval' 12) Rename 'force_run' to 'trigger' 13) Rename 'clean_message' to 'heartbeat' 14) Rename 'msr_enforce' to 'msr_validate' 15) Option 'hide' stays the same 16) Option 'log_level' stays the same 17) Option 'block_modules' stays the same
2020-04-25 19:41:52 +02:00
unsigned int p_pcfi_enforce;
unsigned int p_pint_enforce;
unsigned int p_kint_enforce;
unsigned int p_trigger;
unsigned int p_hide_lkrg;
unsigned int p_umh_enforce;
Introduce 'profiles' configurable from the sysctl interfact: 1) profile_validate: a) 0 (Disabled): -> kint_validate = 0 (Disabled) -> pint_validate = 0 (Disabled) -> pcfi_validate = 0 (Disabled) -> umh_validate = 0 (Disabled) -> msr_validate = 0 (Disabled) -> smep_validate = 0 (Disabled) -> smap_validate = 0 (Disabled) b) 1 (Light): -> kint_validate = 1 (Manual trigger only) -> pint_validate = 1 (Current task only) -> pcfi_validate = 1 (Weak pCFI) -> umh_validate = 1 (Whitelist) -> msr_validate = 0 (Disabled) -> smep_validate = 1 (Enabled) -> smap_validate = 1 (Enabled) c) 2 (Balanced): -> kint_validate = 2 (Triggered by timer) -> pint_validate = 2 (Current + weaking up task) -> pcfi_validate = 1 (Weak pCFI) -> umh_validate = 1 (Whitelist) -> msr_validate = 0 (Disabled) -> smep_validate = 1 (Enabled) -> smap_validate = 1 (Enabled) d) 3 (Moderate): -> kint_validate = 3 (Triggered by timer + random events) -> pint_validate = 2 (Current + weaking up task) -> pcfi_validate = 2 (Full pCFI) -> umh_validate = 1 (Whitelist) -> msr_validate = 1 (Enabled) -> smep_validate = 1 (Enabled) -> smap_validate = 1 (Enabled) e) 4 (Heavy): -> kint_validate = 3 (Triggered by timer + random events) -> pint_validate = 3 (Paranoid mode - verify all tasks in the system by every hook) -> pcfi_validate = 2 (Full pCFI) -> umh_validate = 2 (Full UMH lock-down) -> msr_validate = 1 (Enabled) -> smep_validate = 1 (Enabled) -> smap_validate = 1 (Enabled) 2) profile_enforce: a) 0 (Log & Accept): -> kint_enforce = 0 (Log & accept) -> pint_enforce = 0 (Log & accept) -> pcfi_enforce = 0 (Log only) -> umh_enforce = 0 (Log only) -> smep_enforce = 0 (Log & accept) -> smap_enforce = 0 (Log & accept) b) 1 (Balanced - selective panic): -> kint_enforce = 1 (Log only) -> pint_enforce = 1 (Kill task) -> pcfi_enforce = 1 (Kill task) -> umh_enforce = 1 (Prevent execution) -> smep_enforce = 2 (Panic) -> smap_enforce = 2 (Panic) c) 2 (Moderate - more panic): -> kint_enforce = 2 (Panic) -> pint_enforce = 1 (Kill task) -> pcfi_enforce = 1 (Kill task) -> umh_enforce = 1 (Prevent execution) -> smep_enforce = 2 (Panic) -> smap_enforce = 2 (Panic) d) 3 (Panic): -> kint_enforce = 2 (Panic) -> pint_enforce = 2 (Panic) -> pcfi_enforce = 2 (Panic) -> umh_enforce = 2 (Panic) -> smep_enforce = 2 (Panic) -> smap_enforce = 2 (Panic)
2020-05-27 18:22:48 +02:00
/* Profiles */
unsigned int p_profile_validate;
unsigned int p_profile_enforce;
} p_lkrg_global_conf_struct;
typedef struct _p_lkrg_global_symbols_structure {
unsigned long (*p_kallsyms_lookup_name)(const char *name);
int (*p_freeze_processes)(void);
void (*p_thaw_processes)(void);
#if !defined(CONFIG_ARM64)
void (*p_flush_tlb_all)(void);
#endif
#if defined(P_KERNEL_AGGRESSIVE_INLINING)
int (*p_set_memory_ro)(unsigned long addr, int numpages);
int (*p_set_memory_rw)(unsigned long addr, int numpages);
#if defined(CONFIG_X86)
;
// int (*p_set_memory_np)(unsigned long addr, int numpages);
#elif defined(CONFIG_ARM64)
int (*p_set_memory_valid)(unsigned long addr, int numpages, int enable);
#endif
#else
#if defined(CONFIG_X86)
int (*p_change_page_attr_set_clr)(unsigned long *addr, int numpages,
pgprot_t mask_set, pgprot_t mask_clr,
int force_split, int in_flag,
struct page **pages);
#elif defined(CONFIG_ARM) || defined(CONFIG_ARM64)
int (*p_change_memory_common)(unsigned long addr, int numpages,
pgprot_t set_mask, pgprot_t clear_mask);
#endif
#endif
int (*p___kernel_text_address)(unsigned long p_addr);
#if defined(CONFIG_SECCOMP)
void (*p_get_seccomp_filter)(struct task_struct *p_task);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,9,0)
void (*p_put_seccomp_filter)(struct seccomp_filter *p_filter);
#else
void (*p_put_seccomp_filter)(struct task_struct *p_task);
#endif
#endif
#ifdef CONFIG_SECURITY_SELINUX
2020-04-17 02:50:59 +02:00
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0)
int *p_selinux_enabled;
2020-04-17 02:50:59 +02:00
#endif
#ifdef P_SELINUX_VERIFY
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0)
struct p_selinux_state *p_selinux_state;
#else
int *p_selinux_enforcing;
#endif
#endif
#endif
int (*p_core_kernel_text)(unsigned long p_addr);
pmd_t *(*p_mm_find_pmd)(struct mm_struct *mm, unsigned long address);
struct mutex *p_jump_label_mutex;
struct mutex *p_text_mutex;
struct mutex *p_tracepoints_mutex;
struct text_poke_loc **p_tp_vec;
int *p_tp_vec_nr;
#if defined(CONFIG_DYNAMIC_DEBUG)
struct list_head *p_ddebug_tables;
struct mutex *p_ddebug_lock;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0)
int (*p_ddebug_remove_module)(const char *p_name);
#endif
#endif
struct list_head *p_modules;
struct kset **p_module_kset;
#if defined(CONFIG_X86)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,8,0)
void (*p_native_write_cr4)(unsigned long p_val);
#endif
#endif
#ifdef P_LKRG_UNEXPORTED_MODULE_ADDRESS
struct module* (*p___module_address)(unsigned long p_val);
struct module* (*p___module_text_address)(unsigned long p_val);
#endif
struct module* (*p_find_module)(const char *name);
struct mutex *p_module_mutex;
int (*p_kallsyms_on_each_symbol)(int (*)(void *, const char *, struct module *, unsigned long), void *);
#if defined(CONFIG_FUNCTION_TRACER)
struct ftrace_rec_iter *(*p_ftrace_rec_iter_start)(void);
struct ftrace_rec_iter *(*p_ftrace_rec_iter_next)(struct ftrace_rec_iter *iter);
struct dyn_ftrace *(*p_ftrace_rec_iter_record)(struct ftrace_rec_iter *iter);
struct mutex *p_ftrace_lock;
#endif
#if defined(CONFIG_OPTPROBES)
void (*p_wait_for_kprobe_optimizer)(void);
#endif
struct module *p_find_me;
unsigned int p_state_init;
} p_lkrg_global_syms;
#ifdef P_LKRG_UNEXPORTED_MODULE_ADDRESS
#define LKRG_P_MODULE_ADDRESS(p_addr) P_SYM(p___module_address)(p_addr)
#define LKRG_P_MODULE_TEXT_ADDRESS(p_addr) P_SYM(p___module_text_address)(p_addr)
#else
#define LKRG_P_MODULE_ADDRESS(p_addr) __module_address(p_addr)
#define LKRG_P_MODULE_TEXT_ADDRESS(p_addr) __module_text_address(p_addr)
#endif
This is a huge change. We completely rewrote communication channel and added a lot of new configuration options. Summary: 1) Introduce 'kint_validate' to control kernel/system integrity logic: 0 - disabled 1 - validation is performed only when manually triggered 3 - validation is performed periodically by timer interrupt and on random events 2) Introduce 'kint_enforce' to control how LKRG reacts when kernel/system integrity fails: 0 - log & accept corruption 1 - log only (for SELinux and CR0.WP violation log & restore original values) 2 - panic() - kill the kernel 3) Introduce 'pint_validate' to control tasks validation logic: 0 - disabled 1 - validate only currently running tasks 2 - validate only currently running tasks + task which changes state to RUNNING 3 - validate all tasks in the system (paranoid mode) 4) Introduce 'pint_enforce' to control how LKRG reacts when task validation fails: 0 - log & accept corruption 1 - kill corrupted task 2 - panic() - kill the kernel 5) Introduce 'smep_validate' to control if SMEP validation will be performed 0 - disable SMEP validation 1 - enable SMEP validation 6) Introduce 'smep_enforce' to control how LKRG reacts when SMEP validation fails: 0 - log & accept 1 - log & restore 2 - panic() - kill the kernel 7) Introduce 'umh_validate' to control if UMH validation will be performed 0 - disable UMH validation 1 - allow only whitelited binaries to execute via UMH 2 - completely block UMH 8) Introduce 'smep_enforce' to control how LKRG reacts when UMH validation fails: 0 - log only 1 - prevent execution 2 - panic() - kill the kernel 9) Introduce 'pcfi_validate' to control if pCFI validation will be performed 0 - disabled 1 - no stackwalk (weak pCFI) 2 - fully enabled 10) Introduce 'pcfi_enforce' to control how LKRG reacts when pCFI validation fails: 0 - log only 1 - kill corrupted task 2 - panic() - kill the kernel 11) Rename 'timestamp' to 'interval' 12) Rename 'force_run' to 'trigger' 13) Rename 'clean_message' to 'heartbeat' 14) Rename 'msr_enforce' to 'msr_validate' 15) Option 'hide' stays the same 16) Option 'log_level' stays the same 17) Option 'block_modules' stays the same
2020-04-25 19:41:52 +02:00
typedef struct _p_lkrg_critical_variables {
unsigned long p_dummy1;
This is a huge change. We completely rewrote communication channel and added a lot of new configuration options. Summary: 1) Introduce 'kint_validate' to control kernel/system integrity logic: 0 - disabled 1 - validation is performed only when manually triggered 3 - validation is performed periodically by timer interrupt and on random events 2) Introduce 'kint_enforce' to control how LKRG reacts when kernel/system integrity fails: 0 - log & accept corruption 1 - log only (for SELinux and CR0.WP violation log & restore original values) 2 - panic() - kill the kernel 3) Introduce 'pint_validate' to control tasks validation logic: 0 - disabled 1 - validate only currently running tasks 2 - validate only currently running tasks + task which changes state to RUNNING 3 - validate all tasks in the system (paranoid mode) 4) Introduce 'pint_enforce' to control how LKRG reacts when task validation fails: 0 - log & accept corruption 1 - kill corrupted task 2 - panic() - kill the kernel 5) Introduce 'smep_validate' to control if SMEP validation will be performed 0 - disable SMEP validation 1 - enable SMEP validation 6) Introduce 'smep_enforce' to control how LKRG reacts when SMEP validation fails: 0 - log & accept 1 - log & restore 2 - panic() - kill the kernel 7) Introduce 'umh_validate' to control if UMH validation will be performed 0 - disable UMH validation 1 - allow only whitelited binaries to execute via UMH 2 - completely block UMH 8) Introduce 'smep_enforce' to control how LKRG reacts when UMH validation fails: 0 - log only 1 - prevent execution 2 - panic() - kill the kernel 9) Introduce 'pcfi_validate' to control if pCFI validation will be performed 0 - disabled 1 - no stackwalk (weak pCFI) 2 - fully enabled 10) Introduce 'pcfi_enforce' to control how LKRG reacts when pCFI validation fails: 0 - log only 1 - kill corrupted task 2 - panic() - kill the kernel 11) Rename 'timestamp' to 'interval' 12) Rename 'force_run' to 'trigger' 13) Rename 'clean_message' to 'heartbeat' 14) Rename 'msr_enforce' to 'msr_validate' 15) Option 'hide' stays the same 16) Option 'log_level' stays the same 17) Option 'block_modules' stays the same
2020-04-25 19:41:52 +02:00
} p_lkrg_critical_var;
typedef struct _p2_lkrg_global_ctrl_structure {
p_lkrg_global_conf_struct ctrl;
p_lkrg_global_syms syms;
This is a huge change. We completely rewrote communication channel and added a lot of new configuration options. Summary: 1) Introduce 'kint_validate' to control kernel/system integrity logic: 0 - disabled 1 - validation is performed only when manually triggered 3 - validation is performed periodically by timer interrupt and on random events 2) Introduce 'kint_enforce' to control how LKRG reacts when kernel/system integrity fails: 0 - log & accept corruption 1 - log only (for SELinux and CR0.WP violation log & restore original values) 2 - panic() - kill the kernel 3) Introduce 'pint_validate' to control tasks validation logic: 0 - disabled 1 - validate only currently running tasks 2 - validate only currently running tasks + task which changes state to RUNNING 3 - validate all tasks in the system (paranoid mode) 4) Introduce 'pint_enforce' to control how LKRG reacts when task validation fails: 0 - log & accept corruption 1 - kill corrupted task 2 - panic() - kill the kernel 5) Introduce 'smep_validate' to control if SMEP validation will be performed 0 - disable SMEP validation 1 - enable SMEP validation 6) Introduce 'smep_enforce' to control how LKRG reacts when SMEP validation fails: 0 - log & accept 1 - log & restore 2 - panic() - kill the kernel 7) Introduce 'umh_validate' to control if UMH validation will be performed 0 - disable UMH validation 1 - allow only whitelited binaries to execute via UMH 2 - completely block UMH 8) Introduce 'smep_enforce' to control how LKRG reacts when UMH validation fails: 0 - log only 1 - prevent execution 2 - panic() - kill the kernel 9) Introduce 'pcfi_validate' to control if pCFI validation will be performed 0 - disabled 1 - no stackwalk (weak pCFI) 2 - fully enabled 10) Introduce 'pcfi_enforce' to control how LKRG reacts when pCFI validation fails: 0 - log only 1 - kill corrupted task 2 - panic() - kill the kernel 11) Rename 'timestamp' to 'interval' 12) Rename 'force_run' to 'trigger' 13) Rename 'clean_message' to 'heartbeat' 14) Rename 'msr_enforce' to 'msr_validate' 15) Option 'hide' stays the same 16) Option 'log_level' stays the same 17) Option 'block_modules' stays the same
2020-04-25 19:41:52 +02:00
p_lkrg_critical_var var;
} p_lkrg_global_ctrl_struct __attribute__((aligned(PAGE_SIZE)));
typedef struct _p_lkrg_ro_page {
#if !defined(CONFIG_ARM) && (!defined(P_KERNEL_AGGRESSIVE_INLINING) && defined(CONFIG_X86))
unsigned long p_marker_np1 __attribute__((aligned(PAGE_SIZE)));
#endif
p_lkrg_global_ctrl_struct p_lkrg_global_ctrl;
#if !defined(CONFIG_ARM) && (!defined(P_KERNEL_AGGRESSIVE_INLINING) && defined(CONFIG_X86))
unsigned long p_marker_np2 __attribute__((aligned(PAGE_SIZE)));
unsigned long p_marker_np3 __attribute__((aligned(PAGE_SIZE)));
#endif
} p_ro_page;
extern p_ro_page p_ro;
This is a huge change. We completely rewrote communication channel and added a lot of new configuration options. Summary: 1) Introduce 'kint_validate' to control kernel/system integrity logic: 0 - disabled 1 - validation is performed only when manually triggered 3 - validation is performed periodically by timer interrupt and on random events 2) Introduce 'kint_enforce' to control how LKRG reacts when kernel/system integrity fails: 0 - log & accept corruption 1 - log only (for SELinux and CR0.WP violation log & restore original values) 2 - panic() - kill the kernel 3) Introduce 'pint_validate' to control tasks validation logic: 0 - disabled 1 - validate only currently running tasks 2 - validate only currently running tasks + task which changes state to RUNNING 3 - validate all tasks in the system (paranoid mode) 4) Introduce 'pint_enforce' to control how LKRG reacts when task validation fails: 0 - log & accept corruption 1 - kill corrupted task 2 - panic() - kill the kernel 5) Introduce 'smep_validate' to control if SMEP validation will be performed 0 - disable SMEP validation 1 - enable SMEP validation 6) Introduce 'smep_enforce' to control how LKRG reacts when SMEP validation fails: 0 - log & accept 1 - log & restore 2 - panic() - kill the kernel 7) Introduce 'umh_validate' to control if UMH validation will be performed 0 - disable UMH validation 1 - allow only whitelited binaries to execute via UMH 2 - completely block UMH 8) Introduce 'smep_enforce' to control how LKRG reacts when UMH validation fails: 0 - log only 1 - prevent execution 2 - panic() - kill the kernel 9) Introduce 'pcfi_validate' to control if pCFI validation will be performed 0 - disabled 1 - no stackwalk (weak pCFI) 2 - fully enabled 10) Introduce 'pcfi_enforce' to control how LKRG reacts when pCFI validation fails: 0 - log only 1 - kill corrupted task 2 - panic() - kill the kernel 11) Rename 'timestamp' to 'interval' 12) Rename 'force_run' to 'trigger' 13) Rename 'clean_message' to 'heartbeat' 14) Rename 'msr_enforce' to 'msr_validate' 15) Option 'hide' stays the same 16) Option 'log_level' stays the same 17) Option 'block_modules' stays the same
2020-04-25 19:41:52 +02:00
#define P_VAR(p_field) p_ro.p_lkrg_global_ctrl.var.p_field
#define P_SYM(p_field) p_ro.p_lkrg_global_ctrl.syms.p_field
#define P_CTRL(p_field) p_ro.p_lkrg_global_ctrl.ctrl.p_field
#define P_CTRL_ADDR &p_ro.p_lkrg_global_ctrl
2023-05-18 10:19:01 +02:00
#define P_SYM_INIT(sym) \
if (!(P_SYM(p_ ## sym) = (typeof(P_SYM(p_ ## sym)))P_SYM(p_kallsyms_lookup_name)(#sym))) { \
p_print_log(P_LOG_FATAL, "Can't find '" #sym "'"); \
goto p_sym_error; \
}
/*
* LKRG counter lock
*/
typedef struct p_lkrg_counter_lock {
atomic_t p_counter;
spinlock_t p_lock;
} p_lkrg_counter_lock;
/* Counter lock API */
static inline void p_lkrg_counter_lock_init(p_lkrg_counter_lock *p_arg) {
spin_lock_init(&p_arg->p_lock);
smp_mb();
atomic_set(&p_arg->p_counter, 0);
smp_mb();
}
static inline unsigned long p_lkrg_counter_lock_trylock(p_lkrg_counter_lock *p_arg, unsigned long *p_flags) {
local_irq_save(*p_flags);
if (!spin_trylock(&p_arg->p_lock)) {
local_irq_restore(*p_flags);
return 0;
}
return 1;
}
static inline void p_lkrg_counter_lock_lock(p_lkrg_counter_lock *p_arg, unsigned long *p_flags) {
spin_lock_irqsave(&p_arg->p_lock, *p_flags);
}
static inline void p_lkrg_counter_lock_unlock(p_lkrg_counter_lock *p_arg, unsigned long *p_flags) {
spin_unlock_irqrestore(&p_arg->p_lock, *p_flags);
}
static inline void p_lkrg_counter_lock_val_inc(p_lkrg_counter_lock *p_arg) {
smp_mb();
atomic_inc(&p_arg->p_counter);
smp_mb();
}
static inline void p_lkrg_counter_lock_val_dec(p_lkrg_counter_lock *p_arg) {
smp_mb();
atomic_dec(&p_arg->p_counter);
smp_mb();
}
static inline int p_lkrg_counter_lock_val_read(p_lkrg_counter_lock *p_arg) {
register int p_ret;
smp_mb();
p_ret = atomic_read(&p_arg->p_counter);
smp_mb();
return p_ret;
}
/* End */
2017-10-27 07:29:49 +02:00
/*
2022-07-18 20:54:33 +02:00
* LKRG modules
2017-10-27 07:29:49 +02:00
*/
#include "modules/print_log/p_lkrg_print_log.h" // printing, error and debug module
#include "modules/hashing/p_lkrg_fast_hash.h" // Hashing module
2017-10-27 07:29:49 +02:00
#include "modules/ksyms/p_resolve_ksym.h" // Resolver module
#include "modules/database/p_database.h" // Database module
#include "modules/integrity_timer/p_integrity_timer.h" // Integrity timer module
#include "modules/kmod/p_kmod.h" // Kernel's modules module
#include "modules/notifiers/p_notifiers.h" // Notifiers module
#include "modules/self-defense/hiding/p_hiding.h" // Hiding module
#include "modules/exploit_detection/p_exploit_detection.h" // Exploit Detection
2017-10-27 07:29:49 +02:00
#include "modules/wrap/p_struct_wrap.h" // Wrapping module
#include "modules/comm_channel/p_comm_channel.h" // Communication channel (sysctl) module
2017-11-13 00:43:10 +01:00
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
#define __GFP_REPEAT ((__force gfp_t)___GFP_RETRY_MAYFAIL)
#endif
2017-10-27 07:29:49 +02:00
#if !defined(CONFIG_KPROBES)
#error "LKRG requires CONFIG_KPROBES"
#elif !defined(CONFIG_HAVE_KRETPROBES)
2020-06-19 19:20:39 +02:00
#error "CONFIG_KPROBES is enabled, however CONFIG_HAVE_KRETPROBES is not found. LKRG requires both."
#endif
#if !defined(CONFIG_MODULE_UNLOAD)
#error "LKRG requires CONFIG_MODULE_UNLOAD"
#endif
#if !defined(CONFIG_KALLSYMS_ALL)
#error "LKRG requires CONFIG_KALLSYMS_ALL"
#endif
#if !defined(CONFIG_JUMP_LABEL)
#error "LKRG requires CONFIG_JUMP_LABEL"
#endif
#if !defined(CONFIG_STACKTRACE)
2020-06-19 19:20:39 +02:00
/*
* A #warning in this header file would be printed too many times during build,
* so let's only do that for something truly important, which the below is not.
*/
// #warning "LKRG does NOT require CONFIG_STACKTRACE. However, in case of pCFI violation, LKRG won't be able to dump full stack-trace."
#endif
2017-10-27 07:29:49 +02:00
#if defined(CONFIG_PREEMPT_RT)
#error "LKRG does not support RT kernels (PREEMPT_RT is enabled)"
#endif
#if defined(CONFIG_TRIM_UNUSED_KSYMS) && !defined(CONFIG_SECURITY_LKRG)
#error "LKRG requires CONFIG_TRIM_UNUSED_KSYMS to be disabled if it should be built as an out-of-tree kernel module"
#endif
2017-10-27 07:29:49 +02:00
#endif