* Cherry-picked range: (kernel)
ebea31daa8..6915b62b9a
* Also merged unmerged pr:
https://github.com/tiann/KernelSU/pull/ 2909
Co-authored-by: Ylarod <me@ylarod.cn>
Co-authored-by: 5ec1cff <56485584+5ec1cff@users.noreply.github.com>
Co-authored-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
Co-authored-by: u9521 <63995396+u9521@users.noreply.github.com>
Co-authored-by: Wang Han <416810799@qq.com>
123 lines
3.1 KiB
C
123 lines
3.1 KiB
C
#include <linux/lsm_hooks.h>
|
|
#include <linux/uidgid.h>
|
|
#include <linux/version.h>
|
|
#include <linux/binfmts.h>
|
|
#include <linux/err.h>
|
|
|
|
#include "klog.h" // IWYU pragma: keep
|
|
#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 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
|