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 );
@@ -633,69 +614,6 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
633614 return 0 ;
634615}
635616
636- // Init functons
637-
638- static int handler_pre (struct kprobe * p , struct pt_regs * regs )
639- {
640- struct pt_regs * real_regs = PT_REAL_REGS (regs );
641- int option = (int )PT_REGS_PARM1 (real_regs );
642- unsigned long arg2 = (unsigned long )PT_REGS_PARM2 (real_regs );
643- unsigned long arg3 = (unsigned long )PT_REGS_PARM3 (real_regs );
644- // PRCTL_SYMBOL is the arch-specificed one, which receive raw pt_regs from syscall
645- unsigned long arg4 = (unsigned long )PT_REGS_SYSCALL_PARM4 (real_regs );
646- unsigned long arg5 = (unsigned long )PT_REGS_PARM5 (real_regs );
647-
648- return ksu_handle_prctl (option , arg2 , arg3 , arg4 , arg5 );
649- }
650-
651- static struct kprobe prctl_kp = {
652- .symbol_name = PRCTL_SYMBOL ,
653- .pre_handler = handler_pre ,
654- };
655-
656- static int renameat_handler_pre (struct kprobe * p , struct pt_regs * regs )
657- {
658- #if LINUX_VERSION_CODE >= KERNEL_VERSION (5 , 12 , 0 )
659- // https://elixir.bootlin.com/linux/v5.12-rc1/source/include/linux/fs.h
660- struct renamedata * rd = PT_REGS_PARM1 (regs );
661- struct dentry * old_entry = rd -> old_dentry ;
662- struct dentry * new_entry = rd -> new_dentry ;
663- #else
664- struct dentry * old_entry = (struct dentry * )PT_REGS_PARM2 (regs );
665- struct dentry * new_entry = (struct dentry * )PT_REGS_CCALL_PARM4 (regs );
666- #endif
667-
668- return ksu_handle_rename (old_entry , new_entry );
669- }
670-
671- static struct kprobe renameat_kp = {
672- .symbol_name = "vfs_rename" ,
673- .pre_handler = renameat_handler_pre ,
674- };
675-
676- __maybe_unused int ksu_kprobe_init (void )
677- {
678- int rc = 0 ;
679- rc = register_kprobe (& prctl_kp );
680-
681- if (rc ) {
682- pr_info ("prctl kprobe failed: %d.\n" , rc );
683- return rc ;
684- }
685-
686- rc = register_kprobe (& renameat_kp );
687- pr_info ("renameat kp: %d\n" , rc );
688-
689- return rc ;
690- }
691-
692- __maybe_unused int ksu_kprobe_exit (void )
693- {
694- unregister_kprobe (& prctl_kp );
695- unregister_kprobe (& renameat_kp );
696- return 0 ;
697- }
698-
699617static int ksu_task_prctl (int option , unsigned long arg2 , unsigned long arg3 ,
700618 unsigned long arg4 , unsigned long arg5 )
701619{
@@ -715,7 +633,6 @@ static int ksu_task_fix_setuid(struct cred *new, const struct cred *old,
715633 return ksu_handle_setuid (new , old );
716634}
717635
718- #ifndef MODULE
719636static struct security_hook_list ksu_hooks [] = {
720637 LSM_HOOK_INIT (task_prctl , ksu_task_prctl ),
721638 LSM_HOOK_INIT (inode_rename , ksu_inode_rename ),
@@ -727,184 +644,7 @@ void __init ksu_lsm_hook_init(void)
727644 security_add_hooks (ksu_hooks , ARRAY_SIZE (ksu_hooks ), "ksu" );
728645}
729646
730- #else
731- static int override_security_head (void * head , const void * new_head , size_t len )
732- {
733- unsigned long base = (unsigned long )head & PAGE_MASK ;
734- unsigned long offset = offset_in_page (head );
735-
736- // this is impossible for our case because the page alignment
737- // but be careful for other cases!
738- BUG_ON (offset + len > PAGE_SIZE );
739- struct page * page = phys_to_page (__pa (base ));
740- if (!page ) {
741- return - EFAULT ;
742- }
743-
744- void * addr = vmap (& page , 1 , VM_MAP , PAGE_KERNEL );
745- if (!addr ) {
746- return - ENOMEM ;
747- }
748- local_irq_disable ();
749- memcpy (addr + offset , new_head , len );
750- local_irq_enable ();
751- vunmap (addr );
752- return 0 ;
753- }
754-
755- static void free_security_hook_list (struct hlist_head * head )
756- {
757- struct hlist_node * temp ;
758- struct security_hook_list * entry ;
759-
760- if (!head )
761- return ;
762-
763- hlist_for_each_entry_safe (entry , temp , head , list ) {
764- hlist_del (& entry -> list );
765- kfree (entry );
766- }
767-
768- kfree (head );
769- }
770-
771- struct hlist_head * copy_security_hlist (struct hlist_head * orig )
772- {
773- struct hlist_head * new_head = kmalloc (sizeof (* new_head ), GFP_KERNEL );
774- if (!new_head )
775- return NULL ;
776-
777- INIT_HLIST_HEAD (new_head );
778-
779- struct security_hook_list * entry ;
780- struct security_hook_list * new_entry ;
781-
782- hlist_for_each_entry (entry , orig , list ) {
783- new_entry = kmalloc (sizeof (* new_entry ), GFP_KERNEL );
784- if (!new_entry ) {
785- free_security_hook_list (new_head );
786- return NULL ;
787- }
788-
789- * new_entry = * entry ;
790-
791- hlist_add_tail_rcu (& new_entry -> list , new_head );
792- }
793-
794- return new_head ;
795- }
796-
797- #define LSM_SEARCH_MAX 180 // This should be enough to iterate
798- static void * find_head_addr (void * security_ptr , int * index )
799- {
800- if (!security_ptr ) {
801- return NULL ;
802- }
803- struct hlist_head * head_start =
804- (struct hlist_head * )& security_hook_heads ;
805-
806- for (int i = 0 ; i < LSM_SEARCH_MAX ; i ++ ) {
807- struct hlist_head * head = head_start + i ;
808- struct security_hook_list * pos ;
809- hlist_for_each_entry (pos , head , list ) {
810- if (pos -> hook .capget == security_ptr ) {
811- if (index ) {
812- * index = i ;
813- }
814- return head ;
815- }
816- }
817- }
818-
819- return NULL ;
820- }
821-
822- #define GET_SYMBOL_ADDR (sym ) \
823- ({ \
824- void *addr = kallsyms_lookup_name(#sym ".cfi_jt"); \
825- if (!addr) { \
826- addr = kallsyms_lookup_name(#sym); \
827- } \
828- addr; \
829- })
830-
831- #define KSU_LSM_HOOK_HACK_INIT (head_ptr , name , func ) \
832- do { \
833- static struct security_hook_list hook = { \
834- .hook = { .name = func } \
835- }; \
836- hook.head = head_ptr; \
837- hook.lsm = "ksu"; \
838- struct hlist_head *new_head = copy_security_hlist(hook.head); \
839- if (!new_head) { \
840- pr_err("Failed to copy security list: %s\n", #name); \
841- break; \
842- } \
843- hlist_add_tail_rcu(&hook.list, new_head); \
844- if (override_security_head(hook.head, new_head, \
845- sizeof(*new_head))) { \
846- free_security_hook_list(new_head); \
847- pr_err("Failed to hack lsm for: %s\n", #name); \
848- } \
849- } while (0)
850-
851- void __init ksu_lsm_hook_init (void )
852- {
853- void * cap_prctl = GET_SYMBOL_ADDR (cap_task_prctl );
854- void * prctl_head = find_head_addr (cap_prctl , NULL );
855- if (prctl_head ) {
856- if (prctl_head != & security_hook_heads .task_prctl ) {
857- pr_warn ("prctl's address has shifted!\n" );
858- }
859- KSU_LSM_HOOK_HACK_INIT (prctl_head , task_prctl , ksu_task_prctl );
860- } else {
861- pr_warn ("Failed to find task_prctl!\n" );
862- }
863-
864- int inode_killpriv_index = -1 ;
865- void * cap_killpriv = GET_SYMBOL_ADDR (cap_inode_killpriv );
866- find_head_addr (cap_killpriv , & inode_killpriv_index );
867- if (inode_killpriv_index < 0 ) {
868- pr_warn ("Failed to find inode_rename, use kprobe instead!\n" );
869- register_kprobe (& renameat_kp );
870- } else {
871- int inode_rename_index = inode_killpriv_index +
872- & security_hook_heads .inode_rename -
873- & security_hook_heads .inode_killpriv ;
874- struct hlist_head * head_start =
875- (struct hlist_head * )& security_hook_heads ;
876- void * inode_rename_head = head_start + inode_rename_index ;
877- if (inode_rename_head != & security_hook_heads .inode_rename ) {
878- pr_warn ("inode_rename's address has shifted!\n" );
879- }
880- KSU_LSM_HOOK_HACK_INIT (inode_rename_head , inode_rename ,
881- ksu_inode_rename );
882- }
883- void * cap_setuid = GET_SYMBOL_ADDR (cap_task_fix_setuid );
884- void * setuid_head = find_head_addr (cap_setuid , NULL );
885- if (setuid_head ) {
886- if (setuid_head != & security_hook_heads .task_fix_setuid ) {
887- pr_warn ("setuid's address has shifted!\n" );
888- }
889- KSU_LSM_HOOK_HACK_INIT (setuid_head , task_fix_setuid ,
890- ksu_task_fix_setuid );
891- } else {
892- pr_warn ("Failed to find task_fix_setuid!\n" );
893- }
894- smp_mb ();
895- }
896- #endif
897-
898647void __init ksu_core_init (void )
899648{
900649 ksu_lsm_hook_init ();
901650}
902-
903- void ksu_core_exit (void )
904- {
905- #ifdef CONFIG_KPROBES
906- pr_info ("ksu_core_kprobe_exit\n" );
907- // we dont use this now
908- // ksu_kprobe_exit();
909- #endif
910- }
0 commit comments