#include #include #include #include #include #include "klog.h" // IWYU pragma: keep #include "ksud.h" #include "kernel_compat.h" #include "setuid_hook.h" #ifndef KSU_SHOULD_USE_NEW_TP #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || \ defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND) static int ksu_key_permission(key_ref_t key_ref, const struct cred *cred, unsigned perm) { if (init_session_keyring != NULL) { return 0; } if (strcmp(current->comm, "init")) { // we are only interested in `init` process return 0; } init_session_keyring = cred->session_keyring; pr_info("kernel_compat: got init_session_keyring\n"); return 0; } #endif static int ksu_task_fix_setuid(struct cred *new, const struct cred *old, int flags) { kuid_t new_uid = new->uid; kuid_t new_euid = new->euid; return ksu_handle_setresuid((uid_t)new_uid.val, (uid_t)new_euid.val, (uid_t)new_uid.val); } #ifndef DEVPTS_SUPER_MAGIC #define DEVPTS_SUPER_MAGIC 0x1cd1 #endif extern int __ksu_handle_devpts(struct inode *inode); // sucompat.c #ifdef CONFIG_COMPAT bool ksu_is_compat __read_mostly = false; #endif int ksu_inode_permission(struct inode *inode, int mask) { if (inode && inode->i_sb && unlikely(inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)) { //pr_info("%s: handling devpts for: %s \n", __func__, current->comm); __ksu_handle_devpts(inode); } return 0; } int ksu_bprm_check(struct linux_binprm *bprm) { char *filename = (char *)bprm->filename; if (likely(!ksu_execveat_hook)) return 0; #ifdef CONFIG_COMPAT static bool compat_check_done __read_mostly = false; if ( unlikely(!compat_check_done) && unlikely(!strcmp(filename, "/data/adb/ksud")) && !memcmp(bprm->buf, "\x7f\x45\x4c\x46", 4) ) { if (bprm->buf[4] == 0x01 ) ksu_is_compat = true; pr_info("%s: %s ELF magic found! ksu_is_compat: %d \n", __func__, filename, ksu_is_compat); compat_check_done = true; } #endif ksu_handle_pre_ksud(filename); return 0; } static struct security_hook_list ksu_hooks[] = { #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || \ defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND) LSM_HOOK_INIT(key_permission, ksu_key_permission), #endif LSM_HOOK_INIT(inode_permission, ksu_inode_permission), #ifndef KSU_SHOULD_USE_NEW_TP LSM_HOOK_INIT(bprm_check_security, ksu_bprm_check), #endif LSM_HOOK_INIT(task_fix_setuid, ksu_task_fix_setuid) }; #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 8, 0) static const struct lsm_id ksu_lsmid = { .name = "ksu", .id = 912, }; #endif void __init ksu_lsm_hook_init(void) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 8, 0) security_add_hooks(ksu_hooks, ARRAY_SIZE(ksu_hooks), &ksu_lsmid); #elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) security_add_hooks(ksu_hooks, ARRAY_SIZE(ksu_hooks), "ksu"); #else // https://elixir.bootlin.com/linux/v4.10.17/source/include/linux/lsm_hooks.h#L1892 security_add_hooks(ksu_hooks, ARRAY_SIZE(ksu_hooks)); #endif pr_info("LSM hooks initialized.\n"); } #else void ksu_lsm_hook_init(void) { return; } #endif