#include "selinux.h" #include "objsec.h" #include "linux/version.h" #include "../klog.h" // IWYU pragma: keep #ifndef KSU_COMPAT_USE_SELINUX_STATE #include "avc.h" #endif #define KERNEL_SU_DOMAIN "u:r:su:s0" #ifdef CONFIG_KSU_SUSFS #define KERNEL_INIT_DOMAIN "u:r:init:s0" #define KERNEL_ZYGOTE_DOMAIN "u:r:zygote:s0" u32 susfs_ksu_sid = 0; u32 susfs_init_sid = 0; u32 susfs_zygote_sid = 0; #endif static int transive_to_domain(const char *domain) { struct cred *cred; struct task_security_struct *tsec; u32 sid; int error; cred = (struct cred *)__task_cred(current); tsec = cred->security; if (!tsec) { pr_err("tsec == NULL!\n"); return -1; } error = security_secctx_to_secid(domain, strlen(domain), &sid); if (error) { pr_info("security_secctx_to_secid %s -> sid: %d, error: %d\n", domain, sid, error); } if (!error) { tsec->sid = sid; tsec->create_sid = 0; tsec->keycreate_sid = 0; tsec->sockcreate_sid = 0; } return error; } void ksu_setup_selinux(const char *domain) { if (transive_to_domain(domain)) { pr_err("transive domain failed.\n"); return; } /* we didn't need this now, we have change selinux rules when boot! if (!is_domain_permissive) { if (set_domain_permissive() == 0) { is_domain_permissive = true; } }*/ } void ksu_setenforce(bool enforce) { #ifdef CONFIG_SECURITY_SELINUX_DEVELOP #ifdef KSU_COMPAT_USE_SELINUX_STATE selinux_state.enforcing = enforce; #else selinux_enforcing = enforce; #endif #endif } bool ksu_getenforce() { #ifdef CONFIG_SECURITY_SELINUX_DISABLE #ifdef KSU_COMPAT_USE_SELINUX_STATE if (selinux_state.disabled) { #else if (selinux_disabled) { #endif return false; } #endif #ifdef CONFIG_SECURITY_SELINUX_DEVELOP #ifdef KSU_COMPAT_USE_SELINUX_STATE return selinux_state.enforcing; #else return selinux_enforcing; #endif #else return true; #endif } #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)) && \ !defined(KSU_COMPAT_HAS_CURRENT_SID) /* * get the subjective security ID of the current task */ static inline u32 current_sid(void) { const struct task_security_struct *tsec = current_security(); return tsec->sid; } #endif bool ksu_is_ksu_domain() { char *domain; u32 seclen; bool result; int err = security_secid_to_secctx(current_sid(), &domain, &seclen); if (err) { return false; } result = strncmp(KERNEL_SU_DOMAIN, domain, seclen) == 0; security_release_secctx(domain, seclen); return result; } bool ksu_is_zygote(void *sec) { struct task_security_struct *tsec = (struct task_security_struct *)sec; if (!tsec) { return false; } char *domain; u32 seclen; bool result; int err = security_secid_to_secctx(tsec->sid, &domain, &seclen); if (err) { return false; } result = strncmp("u:r:zygote:s0", domain, seclen) == 0; security_release_secctx(domain, seclen); return result; } #ifdef CONFIG_KSU_SUSFS static inline void susfs_set_sid(const char *secctx_name, u32 *out_sid) { int err; if (!secctx_name || !out_sid) { pr_err("secctx_name || out_sid is NULL\n"); return; } err = security_secctx_to_secid(secctx_name, strlen(secctx_name), out_sid); if (err) { pr_err("failed setting sid for '%s', err: %d\n", secctx_name, err); return; } pr_info("sid '%u' is set for secctx_name '%s'\n", *out_sid, secctx_name); } bool susfs_is_sid_equal(void *sec, u32 sid2) { struct task_security_struct *tsec = (struct task_security_struct *)sec; if (!tsec) { return false; } return tsec->sid == sid2; } u32 susfs_get_sid_from_name(const char *secctx_name) { u32 out_sid = 0; int err; if (!secctx_name) { pr_err("secctx_name is NULL\n"); return 0; } err = security_secctx_to_secid(secctx_name, strlen(secctx_name), &out_sid); if (err) { pr_err("failed getting sid from secctx_name: %s, err: %d\n", secctx_name, err); return 0; } return out_sid; } u32 susfs_get_current_sid(void) { return current_sid(); } void susfs_set_zygote_sid(void) { susfs_set_sid(KERNEL_ZYGOTE_DOMAIN, &susfs_zygote_sid); } bool susfs_is_current_zygote_domain(void) { return unlikely(current_sid() == susfs_zygote_sid); } void susfs_set_ksu_sid(void) { susfs_set_sid(KERNEL_SU_DOMAIN, &susfs_ksu_sid); } bool susfs_is_current_ksu_domain(void) { return unlikely(current_sid() == susfs_ksu_sid); } void susfs_set_init_sid(void) { susfs_set_sid(KERNEL_INIT_DOMAIN, &susfs_init_sid); } bool susfs_is_current_init_domain(void) { return unlikely(current_sid() == susfs_init_sid); } #endif #define DEVPTS_DOMAIN "u:object_r:ksu_file:s0" u32 ksu_get_devpts_sid() { u32 devpts_sid = 0; int err = security_secctx_to_secid(DEVPTS_DOMAIN, strlen(DEVPTS_DOMAIN), &devpts_sid); if (err) { pr_info("get devpts sid err %d\n", err); } return devpts_sid; }