You've already forked KernelSU-Next
mirror of
https://github.com/KernelSU-Next/KernelSU-Next.git
synced 2025-08-27 23:46:34 +00:00
kernel: implement SuSFS v1.5.2
This commit is contained in:
+308
-6
@@ -33,6 +33,10 @@
|
||||
#include <linux/vmalloc.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS
|
||||
#include <linux/susfs.h>
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS
|
||||
|
||||
#include "allowlist.h"
|
||||
#include "arch.h"
|
||||
#include "core_hook.h"
|
||||
@@ -45,6 +49,20 @@
|
||||
#include "throne_tracker.h"
|
||||
#include "kernel_compat.h"
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS
|
||||
bool susfs_is_allow_su(void)
|
||||
{
|
||||
if (is_manager()) {
|
||||
// we are manager, allow!
|
||||
return true;
|
||||
}
|
||||
return ksu_is_allow_uid(current_uid().val);
|
||||
}
|
||||
|
||||
extern u32 susfs_zygote_sid;
|
||||
extern void susfs_run_try_umount_for_current_mnt_ns(void);
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS
|
||||
|
||||
static bool ksu_module_mounted = false;
|
||||
|
||||
extern int handle_sepolicy(unsigned long arg3, void __user *arg4);
|
||||
@@ -99,7 +117,11 @@ static void setup_groups(struct root_profile *profile, struct cred *cred)
|
||||
put_group_info(group_info);
|
||||
return;
|
||||
}
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
|
||||
group_info->gid[i] = kgid;
|
||||
#else
|
||||
GROUP_AT(group_info, i) = kgid;
|
||||
#endif
|
||||
}
|
||||
|
||||
groups_sort(group_info);
|
||||
@@ -372,6 +394,205 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS
|
||||
if (current_uid_val == 0) {
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
if (arg2 == CMD_SUSFS_ADD_SUS_PATH) {
|
||||
int error = 0;
|
||||
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_path))) {
|
||||
pr_err("susfs: CMD_SUSFS_ADD_SUS_PATH -> arg3 is not accessible\n");
|
||||
return 0;
|
||||
}
|
||||
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
|
||||
pr_err("susfs: CMD_SUSFS_ADD_SUS_PATH -> arg5 is not accessible\n");
|
||||
return 0;
|
||||
}
|
||||
error = susfs_add_sus_path((struct st_susfs_sus_path __user*)arg3);
|
||||
pr_info("susfs: CMD_SUSFS_ADD_SUS_PATH -> ret: %d\n", error);
|
||||
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
|
||||
pr_info("susfs: copy_to_user() failed\n");
|
||||
return 0;
|
||||
}
|
||||
#endif //#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
if (arg2 == CMD_SUSFS_ADD_SUS_MOUNT) {
|
||||
int error = 0;
|
||||
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_mount))) {
|
||||
pr_err("susfs: CMD_SUSFS_ADD_SUS_MOUNT -> arg3 is not accessible\n");
|
||||
return 0;
|
||||
}
|
||||
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
|
||||
pr_err("susfs: CMD_SUSFS_ADD_SUS_MOUNT -> arg5 is not accessible\n");
|
||||
return 0;
|
||||
}
|
||||
error = susfs_add_sus_mount((struct st_susfs_sus_mount __user*)arg3);
|
||||
pr_info("susfs: CMD_SUSFS_ADD_SUS_MOUNT -> ret: %d\n", error);
|
||||
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
|
||||
pr_info("susfs: copy_to_user() failed\n");
|
||||
return 0;
|
||||
}
|
||||
#endif //#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||
if (arg2 == CMD_SUSFS_ADD_SUS_KSTAT) {
|
||||
int error = 0;
|
||||
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_kstat))) {
|
||||
pr_err("susfs: CMD_SUSFS_ADD_SUS_KSTAT -> arg3 is not accessible\n");
|
||||
return 0;
|
||||
}
|
||||
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
|
||||
pr_err("susfs: CMD_SUSFS_ADD_SUS_KSTAT -> arg5 is not accessible\n");
|
||||
return 0;
|
||||
}
|
||||
error = susfs_add_sus_kstat((struct st_susfs_sus_kstat __user*)arg3);
|
||||
pr_info("susfs: CMD_SUSFS_ADD_SUS_KSTAT -> ret: %d\n", error);
|
||||
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
|
||||
pr_info("susfs: copy_to_user() failed\n");
|
||||
return 0;
|
||||
}
|
||||
if (arg2 == CMD_SUSFS_UPDATE_SUS_KSTAT) {
|
||||
int error = 0;
|
||||
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_kstat))) {
|
||||
pr_err("susfs: CMD_SUSFS_UPDATE_SUS_KSTAT -> arg3 is not accessible\n");
|
||||
return 0;
|
||||
}
|
||||
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
|
||||
pr_err("susfs: CMD_SUSFS_UPDATE_SUS_KSTAT -> arg5 is not accessible\n");
|
||||
return 0;
|
||||
}
|
||||
error = susfs_update_sus_kstat((struct st_susfs_sus_kstat __user*)arg3);
|
||||
pr_info("susfs: CMD_SUSFS_UPDATE_SUS_KSTAT -> ret: %d\n", error);
|
||||
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
|
||||
pr_info("susfs: copy_to_user() failed\n");
|
||||
return 0;
|
||||
}
|
||||
if (arg2 == CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY) {
|
||||
int error = 0;
|
||||
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_kstat))) {
|
||||
pr_err("susfs: CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY -> arg3 is not accessible\n");
|
||||
return 0;
|
||||
}
|
||||
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
|
||||
pr_err("susfs: CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY -> arg5 is not accessible\n");
|
||||
return 0;
|
||||
}
|
||||
error = susfs_add_sus_kstat((struct st_susfs_sus_kstat __user*)arg3);
|
||||
pr_info("susfs: CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY -> ret: %d\n", error);
|
||||
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
|
||||
pr_info("susfs: copy_to_user() failed\n");
|
||||
return 0;
|
||||
}
|
||||
#endif //#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||
if (arg2 == CMD_SUSFS_ADD_TRY_UMOUNT) {
|
||||
int error = 0;
|
||||
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_try_umount))) {
|
||||
pr_err("susfs: CMD_SUSFS_ADD_TRY_UMOUNT -> arg3 is not accessible\n");
|
||||
return 0;
|
||||
}
|
||||
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
|
||||
pr_err("susfs: CMD_SUSFS_ADD_TRY_UMOUNT -> arg5 is not accessible\n");
|
||||
return 0;
|
||||
}
|
||||
error = susfs_add_try_umount((struct st_susfs_try_umount __user*)arg3);
|
||||
pr_info("susfs: CMD_SUSFS_ADD_TRY_UMOUNT -> ret: %d\n", error);
|
||||
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
|
||||
pr_info("susfs: copy_to_user() failed\n");
|
||||
return 0;
|
||||
}
|
||||
if (arg2 == CMD_SUSFS_RUN_UMOUNT_FOR_CURRENT_MNT_NS) {
|
||||
int error = 0;
|
||||
susfs_run_try_umount_for_current_mnt_ns();
|
||||
pr_info("susfs: CMD_SUSFS_RUN_UMOUNT_FOR_CURRENT_MNT_NS -> ret: %d\n", error);
|
||||
}
|
||||
#endif //#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||
#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
|
||||
if (arg2 == CMD_SUSFS_SET_UNAME) {
|
||||
int error = 0;
|
||||
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_uname))) {
|
||||
pr_err("susfs: CMD_SUSFS_SET_UNAME -> arg3 is not accessible\n");
|
||||
return 0;
|
||||
}
|
||||
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
|
||||
pr_err("susfs: CMD_SUSFS_SET_UNAME -> arg5 is not accessible\n");
|
||||
return 0;
|
||||
}
|
||||
error = susfs_set_uname((struct st_susfs_uname __user*)arg3);
|
||||
pr_info("susfs: CMD_SUSFS_SET_UNAME -> ret: %d\n", error);
|
||||
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
|
||||
pr_info("susfs: copy_to_user() failed\n");
|
||||
return 0;
|
||||
}
|
||||
#endif //#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
|
||||
#ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
|
||||
if (arg2 == CMD_SUSFS_ENABLE_LOG) {
|
||||
int error = 0;
|
||||
if (arg3 != 0 && arg3 != 1) {
|
||||
pr_err("susfs: CMD_SUSFS_ENABLE_LOG -> arg3 can only be 0 or 1\n");
|
||||
return 0;
|
||||
}
|
||||
susfs_set_log(arg3);
|
||||
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
|
||||
pr_info("susfs: copy_to_user() failed\n");
|
||||
return 0;
|
||||
}
|
||||
#endif //#ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
|
||||
#ifdef CONFIG_KSU_SUSFS_SPOOF_BOOTCONFIG
|
||||
if (arg2 == CMD_SUSFS_SET_BOOTCONFIG) {
|
||||
int error = 0;
|
||||
if (!ksu_access_ok((void __user*)arg3, SUSFS_FAKE_BOOT_CONFIG_SIZE)) {
|
||||
pr_err("susfs: CMD_SUSFS_SET_BOOTCONFIG -> arg3 is not accessible\n");
|
||||
return 0;
|
||||
}
|
||||
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
|
||||
pr_err("susfs: CMD_SUSFS_SET_BOOTCONFIG -> arg5 is not accessible\n");
|
||||
return 0;
|
||||
}
|
||||
error = susfs_set_bootconfig((char __user*)arg3);
|
||||
pr_info("susfs: CMD_SUSFS_SET_BOOTCONFIG -> ret: %d\n", error);
|
||||
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
|
||||
pr_info("susfs: copy_to_user() failed\n");
|
||||
return 0;
|
||||
}
|
||||
#endif //#ifdef CONFIG_KSU_SUSFS_SPOOF_BOOTCONFIG
|
||||
#ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT
|
||||
if (arg2 == CMD_SUSFS_ADD_OPEN_REDIRECT) {
|
||||
int error = 0;
|
||||
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_open_redirect))) {
|
||||
pr_err("susfs: CMD_SUSFS_ADD_OPEN_REDIRECT -> arg3 is not accessible\n");
|
||||
return 0;
|
||||
}
|
||||
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
|
||||
pr_err("susfs: CMD_SUSFS_ADD_OPEN_REDIRECT -> arg5 is not accessible\n");
|
||||
return 0;
|
||||
}
|
||||
error = susfs_add_open_redirect((struct st_susfs_open_redirect __user*)arg3);
|
||||
pr_info("susfs: CMD_SUSFS_ADD_OPEN_REDIRECT -> ret: %d\n", error);
|
||||
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
|
||||
pr_info("susfs: copy_to_user() failed\n");
|
||||
return 0;
|
||||
}
|
||||
#endif //#ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_SU
|
||||
if (arg2 == CMD_SUSFS_SUS_SU) {
|
||||
int error = 0;
|
||||
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_sus_su))) {
|
||||
pr_err("susfs: CMD_SUSFS_SUS_SU -> arg3 is not accessible\n");
|
||||
return 0;
|
||||
}
|
||||
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
|
||||
pr_err("susfs: CMD_SUSFS_SUS_SU -> arg5 is not accessible\n");
|
||||
return 0;
|
||||
}
|
||||
error = susfs_sus_su((struct st_sus_su __user*)arg3);
|
||||
pr_info("susfs: CMD_SUSFS_SUS_SU -> ret: %d\n", error);
|
||||
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
|
||||
pr_info("susfs: copy_to_user() failed\n");
|
||||
return 0;
|
||||
}
|
||||
#endif //#ifdef CONFIG_KSU_SUSFS_SUS_SU
|
||||
}
|
||||
#endif //#ifdef CONFIG_KSU_SUSFS
|
||||
|
||||
// all other cmds are for 'root manager'
|
||||
if (!from_manager) {
|
||||
return 0;
|
||||
@@ -446,15 +667,21 @@ static bool should_umount(struct path *path)
|
||||
return false;
|
||||
}
|
||||
|
||||
static void ksu_umount_mnt(struct path *path, int flags)
|
||||
static int ksu_umount_mnt(struct path *path, int flags)
|
||||
{
|
||||
int err = path_umount(path, flags);
|
||||
if (err) {
|
||||
pr_info("umount %s failed: %d\n", path->dentry->d_iname, err);
|
||||
}
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) || defined(KSU_UMOUNT)
|
||||
return path_umount(path, flags);
|
||||
#else
|
||||
// TODO: umount for non GKI kernel
|
||||
return -ENOSYS;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS
|
||||
void try_umount(const char *mnt, bool check_mnt, int flags)
|
||||
#else
|
||||
static void try_umount(const char *mnt, bool check_mnt, int flags)
|
||||
#endif
|
||||
{
|
||||
struct path path;
|
||||
int err = kern_path(mnt, 0, &path);
|
||||
@@ -472,9 +699,24 @@ static void try_umount(const char *mnt, bool check_mnt, int flags)
|
||||
return;
|
||||
}
|
||||
|
||||
ksu_umount_mnt(&path, flags);
|
||||
err = ksu_umount_mnt(&path, flags);
|
||||
if (err) {
|
||||
pr_warn("umount %s failed: %d\n", mnt, err);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||
void susfs_try_umount_all(uid_t uid) {
|
||||
susfs_try_umount(uid);
|
||||
try_umount("/system", true, 0);
|
||||
try_umount("/system_ext", true, 0);
|
||||
try_umount("/vendor", true, 0);
|
||||
try_umount("/product", true, 0);
|
||||
try_umount("/data/adb/modules", false, MNT_DETACH);
|
||||
try_umount("/debug_ramdisk", false, MNT_DETACH);
|
||||
}
|
||||
#endif
|
||||
|
||||
int ksu_handle_setuid(struct cred *new, const struct cred *old)
|
||||
{
|
||||
// this hook is used for umounting overlayfs for some uid, if there isn't any module mounted, just ignore it!
|
||||
@@ -494,6 +736,17 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
// check if current process is zygote
|
||||
bool is_zygote_child = susfs_is_sid_equal(old->security, susfs_zygote_sid);
|
||||
if (likely(is_zygote_child)) {
|
||||
// if spawned process is non user app process, run try_umount()
|
||||
if (unlikely(new_uid.val < 10000 && new_uid.val >= 1000)) {
|
||||
goto out_try_umount;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!is_appuid(new_uid) || is_unsupported_uid(new_uid.val)) {
|
||||
// pr_info("handle setuid ignore non application or isolated uid: %d\n", new_uid.val);
|
||||
return 0;
|
||||
@@ -503,6 +756,12 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
|
||||
// pr_info("handle setuid ignore allowed application: %d\n", new_uid.val);
|
||||
return 0;
|
||||
}
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
else {
|
||||
// if new uid is not root granted, then drop a payload to inidicate that sus_path will be effective on this uid
|
||||
new->user->android_kabi_reserved2 |= USER_STRUCT_KABI2_NON_ROOT_USER_APP_PROFILE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!ksu_uid_should_umount(new_uid.val)) {
|
||||
return 0;
|
||||
@@ -512,21 +771,31 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
// check old process's selinux context, if it is not zygote, ignore it!
|
||||
// because some su apps may setuid to untrusted_app but they are in global mount namespace
|
||||
// when we umount for such process, that is a disaster!
|
||||
bool is_zygote_child = is_zygote(old->security);
|
||||
#endif
|
||||
if (!is_zygote_child) {
|
||||
pr_info("handle umount ignore non zygote child: %d\n",
|
||||
current->pid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KSU_DEBUG
|
||||
// umount the target mnt
|
||||
pr_info("handle umount for uid: %d, pid: %d\n", new_uid.val,
|
||||
current->pid);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
out_try_umount:
|
||||
#endif
|
||||
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||
// susfs come first, and lastly umount by ksu, make sure umount in reversed order
|
||||
susfs_try_umount_all(new_uid.val);
|
||||
#else
|
||||
// fixme: use `collect_mounts` and `iterate_mount` to iterate all mountpoint and
|
||||
// filter the mountpoint whose target is `/data/adb`
|
||||
try_umount("/system", true, 0);
|
||||
@@ -537,6 +806,7 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
|
||||
// try umount ksu temp path
|
||||
try_umount("/debug_ramdisk", false, MNT_DETACH);
|
||||
try_umount("/sbin", false, MNT_DETACH);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -549,8 +819,14 @@ static int handler_pre(struct kprobe *p, struct pt_regs *regs)
|
||||
int option = (int)PT_REGS_PARM1(real_regs);
|
||||
unsigned long arg2 = (unsigned long)PT_REGS_PARM2(real_regs);
|
||||
unsigned long arg3 = (unsigned long)PT_REGS_PARM3(real_regs);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
|
||||
// PRCTL_SYMBOL is the arch-specificed one, which receive raw pt_regs from syscall
|
||||
unsigned long arg4 = (unsigned long)PT_REGS_SYSCALL_PARM4(real_regs);
|
||||
#else
|
||||
// PRCTL_SYMBOL is the common one, called by C convention in do_syscall_64
|
||||
// https://elixir.bootlin.com/linux/v4.15.18/source/arch/x86/entry/common.c#L287
|
||||
unsigned long arg4 = (unsigned long)PT_REGS_CCALL_PARM4(real_regs);
|
||||
#endif
|
||||
unsigned long arg5 = (unsigned long)PT_REGS_PARM5(real_regs);
|
||||
|
||||
return ksu_handle_prctl(option, arg2, arg3, arg4, arg5);
|
||||
@@ -611,6 +887,24 @@ static int ksu_task_prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
// kernel 4.4 and 4.9
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI)
|
||||
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_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
|
||||
struct inode *new_inode, struct dentry *new_dentry)
|
||||
{
|
||||
@@ -628,11 +922,19 @@ static struct security_hook_list ksu_hooks[] = {
|
||||
LSM_HOOK_INIT(task_prctl, ksu_task_prctl),
|
||||
LSM_HOOK_INIT(inode_rename, ksu_inode_rename),
|
||||
LSM_HOOK_INIT(task_fix_setuid, ksu_task_fix_setuid),
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI)
|
||||
LSM_HOOK_INIT(key_permission, ksu_key_permission)
|
||||
#endif
|
||||
};
|
||||
|
||||
void __init ksu_lsm_hook_init(void)
|
||||
{
|
||||
#if 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
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
Reference in New Issue
Block a user