44#include <linux/err.h>
55#include <linux/init.h>
66#include <linux/init_task.h>
7- #include <linux/kallsyms.h>
87#include <linux/kernel.h>
9- #include <linux/kprobes.h>
108#include <linux/lsm_hooks.h>
11- #include <linux/mm.h>
129#include <linux/nsproxy.h>
1310#include <linux/path.h>
1411#include <linux/printk.h>
15- #include <linux/sched.h>
16- #include <linux/security.h>
17- #include <linux/stddef.h>
1812#include <linux/string.h>
19- #include <linux/types.h>
2013#include <linux/uaccess.h>
2114#include <linux/uidgid.h>
2215#include <linux/version.h>
2316#include <linux/mount.h>
24-
2517#include <linux/fs.h>
2618#include <linux/namei.h>
2719
28- #ifdef MODULE
29- #include <linux/list.h>
30- #include <linux/irqflags.h>
31- #include <linux/mm_types.h>
32- #include <linux/rcupdate.h>
33- #include <linux/vmalloc.h>
34- #endif
35-
3620#include "allowlist.h"
37- #include "arch.h"
21+
3822#include "core_hook.h"
3923#include "klog.h" // IWYU pragma: keep
4024#include "ksu.h"
@@ -305,9 +289,6 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
305289 pr_err ("prctl reply error, cmd: %lu\n" , arg2 );
306290 }
307291 u32 version_flags = 0 ;
308- #ifdef MODULE
309- version_flags |= 0x1 ;
310- #endif
311292 if (arg4 &&
312293 copy_to_user (arg4 , & version_flags , sizeof (version_flags ))) {
313294 pr_err ("prctl reply error, cmd: %lu\n" , arg2 );
@@ -644,69 +625,6 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
644625 return 0 ;
645626}
646627
647- // Init functons
648-
649- static int handler_pre (struct kprobe * p , struct pt_regs * regs )
650- {
651- struct pt_regs * real_regs = PT_REAL_REGS (regs );
652- int option = (int )PT_REGS_PARM1 (real_regs );
653- unsigned long arg2 = (unsigned long )PT_REGS_PARM2 (real_regs );
654- unsigned long arg3 = (unsigned long )PT_REGS_PARM3 (real_regs );
655- // PRCTL_SYMBOL is the arch-specificed one, which receive raw pt_regs from syscall
656- unsigned long arg4 = (unsigned long )PT_REGS_SYSCALL_PARM4 (real_regs );
657- unsigned long arg5 = (unsigned long )PT_REGS_PARM5 (real_regs );
658-
659- return ksu_handle_prctl (option , arg2 , arg3 , arg4 , arg5 );
660- }
661-
662- static struct kprobe prctl_kp = {
663- .symbol_name = PRCTL_SYMBOL ,
664- .pre_handler = handler_pre ,
665- };
666-
667- static int renameat_handler_pre (struct kprobe * p , struct pt_regs * regs )
668- {
669- #if LINUX_VERSION_CODE >= KERNEL_VERSION (5 , 12 , 0 )
670- // https://elixir.bootlin.com/linux/v5.12-rc1/source/include/linux/fs.h
671- struct renamedata * rd = PT_REGS_PARM1 (regs );
672- struct dentry * old_entry = rd -> old_dentry ;
673- struct dentry * new_entry = rd -> new_dentry ;
674- #else
675- struct dentry * old_entry = (struct dentry * )PT_REGS_PARM2 (regs );
676- struct dentry * new_entry = (struct dentry * )PT_REGS_CCALL_PARM4 (regs );
677- #endif
678-
679- return ksu_handle_rename (old_entry , new_entry );
680- }
681-
682- static struct kprobe renameat_kp = {
683- .symbol_name = "vfs_rename" ,
684- .pre_handler = renameat_handler_pre ,
685- };
686-
687- __maybe_unused int ksu_kprobe_init (void )
688- {
689- int rc = 0 ;
690- rc = register_kprobe (& prctl_kp );
691-
692- if (rc ) {
693- pr_info ("prctl kprobe failed: %d.\n" , rc );
694- return rc ;
695- }
696-
697- rc = register_kprobe (& renameat_kp );
698- pr_info ("renameat kp: %d\n" , rc );
699-
700- return rc ;
701- }
702-
703- __maybe_unused int ksu_kprobe_exit (void )
704- {
705- unregister_kprobe (& prctl_kp );
706- unregister_kprobe (& renameat_kp );
707- return 0 ;
708- }
709-
710628static int ksu_task_prctl (int option , unsigned long arg2 , unsigned long arg3 ,
711629 unsigned long arg4 , unsigned long arg5 )
712630{
@@ -726,7 +644,6 @@ static int ksu_task_fix_setuid(struct cred *new, const struct cred *old,
726644 return ksu_handle_setuid (new , old );
727645}
728646
729- #ifndef MODULE
730647static struct security_hook_list ksu_hooks [] = {
731648 LSM_HOOK_INIT (task_prctl , ksu_task_prctl ),
732649 LSM_HOOK_INIT (inode_rename , ksu_inode_rename ),
@@ -738,184 +655,7 @@ void __init ksu_lsm_hook_init(void)
738655 security_add_hooks (ksu_hooks , ARRAY_SIZE (ksu_hooks ), "ksu" );
739656}
740657
741- #else
742- static int override_security_head (void * head , const void * new_head , size_t len )
743- {
744- unsigned long base = (unsigned long )head & PAGE_MASK ;
745- unsigned long offset = offset_in_page (head );
746-
747- // this is impossible for our case because the page alignment
748- // but be careful for other cases!
749- BUG_ON (offset + len > PAGE_SIZE );
750- struct page * page = phys_to_page (__pa (base ));
751- if (!page ) {
752- return - EFAULT ;
753- }
754-
755- void * addr = vmap (& page , 1 , VM_MAP , PAGE_KERNEL );
756- if (!addr ) {
757- return - ENOMEM ;
758- }
759- local_irq_disable ();
760- memcpy (addr + offset , new_head , len );
761- local_irq_enable ();
762- vunmap (addr );
763- return 0 ;
764- }
765-
766- static void free_security_hook_list (struct hlist_head * head )
767- {
768- struct hlist_node * temp ;
769- struct security_hook_list * entry ;
770-
771- if (!head )
772- return ;
773-
774- hlist_for_each_entry_safe (entry , temp , head , list ) {
775- hlist_del (& entry -> list );
776- kfree (entry );
777- }
778-
779- kfree (head );
780- }
781-
782- struct hlist_head * copy_security_hlist (struct hlist_head * orig )
783- {
784- struct hlist_head * new_head = kmalloc (sizeof (* new_head ), GFP_KERNEL );
785- if (!new_head )
786- return NULL ;
787-
788- INIT_HLIST_HEAD (new_head );
789-
790- struct security_hook_list * entry ;
791- struct security_hook_list * new_entry ;
792-
793- hlist_for_each_entry (entry , orig , list ) {
794- new_entry = kmalloc (sizeof (* new_entry ), GFP_KERNEL );
795- if (!new_entry ) {
796- free_security_hook_list (new_head );
797- return NULL ;
798- }
799-
800- * new_entry = * entry ;
801-
802- hlist_add_tail_rcu (& new_entry -> list , new_head );
803- }
804-
805- return new_head ;
806- }
807-
808- #define LSM_SEARCH_MAX 180 // This should be enough to iterate
809- static void * find_head_addr (void * security_ptr , int * index )
810- {
811- if (!security_ptr ) {
812- return NULL ;
813- }
814- struct hlist_head * head_start =
815- (struct hlist_head * )& security_hook_heads ;
816-
817- for (int i = 0 ; i < LSM_SEARCH_MAX ; i ++ ) {
818- struct hlist_head * head = head_start + i ;
819- struct security_hook_list * pos ;
820- hlist_for_each_entry (pos , head , list ) {
821- if (pos -> hook .capget == security_ptr ) {
822- if (index ) {
823- * index = i ;
824- }
825- return head ;
826- }
827- }
828- }
829-
830- return NULL ;
831- }
832-
833- #define GET_SYMBOL_ADDR (sym ) \
834- ({ \
835- void *addr = kallsyms_lookup_name(#sym ".cfi_jt"); \
836- if (!addr) { \
837- addr = kallsyms_lookup_name(#sym); \
838- } \
839- addr; \
840- })
841-
842- #define KSU_LSM_HOOK_HACK_INIT (head_ptr , name , func ) \
843- do { \
844- static struct security_hook_list hook = { \
845- .hook = { .name = func } \
846- }; \
847- hook.head = head_ptr; \
848- hook.lsm = "ksu"; \
849- struct hlist_head *new_head = copy_security_hlist(hook.head); \
850- if (!new_head) { \
851- pr_err("Failed to copy security list: %s\n", #name); \
852- break; \
853- } \
854- hlist_add_tail_rcu(&hook.list, new_head); \
855- if (override_security_head(hook.head, new_head, \
856- sizeof(*new_head))) { \
857- free_security_hook_list(new_head); \
858- pr_err("Failed to hack lsm for: %s\n", #name); \
859- } \
860- } while (0)
861-
862- void __init ksu_lsm_hook_init (void )
863- {
864- void * cap_prctl = GET_SYMBOL_ADDR (cap_task_prctl );
865- void * prctl_head = find_head_addr (cap_prctl , NULL );
866- if (prctl_head ) {
867- if (prctl_head != & security_hook_heads .task_prctl ) {
868- pr_warn ("prctl's address has shifted!\n" );
869- }
870- KSU_LSM_HOOK_HACK_INIT (prctl_head , task_prctl , ksu_task_prctl );
871- } else {
872- pr_warn ("Failed to find task_prctl!\n" );
873- }
874-
875- int inode_killpriv_index = -1 ;
876- void * cap_killpriv = GET_SYMBOL_ADDR (cap_inode_killpriv );
877- find_head_addr (cap_killpriv , & inode_killpriv_index );
878- if (inode_killpriv_index < 0 ) {
879- pr_warn ("Failed to find inode_rename, use kprobe instead!\n" );
880- register_kprobe (& renameat_kp );
881- } else {
882- int inode_rename_index = inode_killpriv_index +
883- & security_hook_heads .inode_rename -
884- & security_hook_heads .inode_killpriv ;
885- struct hlist_head * head_start =
886- (struct hlist_head * )& security_hook_heads ;
887- void * inode_rename_head = head_start + inode_rename_index ;
888- if (inode_rename_head != & security_hook_heads .inode_rename ) {
889- pr_warn ("inode_rename's address has shifted!\n" );
890- }
891- KSU_LSM_HOOK_HACK_INIT (inode_rename_head , inode_rename ,
892- ksu_inode_rename );
893- }
894- void * cap_setuid = GET_SYMBOL_ADDR (cap_task_fix_setuid );
895- void * setuid_head = find_head_addr (cap_setuid , NULL );
896- if (setuid_head ) {
897- if (setuid_head != & security_hook_heads .task_fix_setuid ) {
898- pr_warn ("setuid's address has shifted!\n" );
899- }
900- KSU_LSM_HOOK_HACK_INIT (setuid_head , task_fix_setuid ,
901- ksu_task_fix_setuid );
902- } else {
903- pr_warn ("Failed to find task_fix_setuid!\n" );
904- }
905- smp_mb ();
906- }
907- #endif
908-
909658void __init ksu_core_init (void )
910659{
911660 ksu_lsm_hook_init ();
912661}
913-
914- void ksu_core_exit (void )
915- {
916- #ifdef CONFIG_KPROBES
917- pr_info ("ksu_core_kprobe_exit\n" );
918- // we dont use this now
919- // ksu_kprobe_exit();
920- #endif
921- }
0 commit comments