kernel: add wrapper for creds, refine disable_seccomp, revert some changes (#131)
1. Wrapper for creds:
* Some older kernel does not have {.val}, so, for nicer compatibility support and clean code,
make some wrapper for credential use.
* After this change, do not use current_uid().val, instead, use ksu_current_uid(). For more
info, check kernel/include/ksu_creds.h.
2. Refine disable_seccomp (need to add k6.11+ support)
https://github.com/tiann/KernelSU/pull/2708
https://github.com/tiann/KernelSU/issues/2706
3. Revert "Handle unmount for isolated process correctly"
Reason: https://github.com/tiann/KernelSU/pull/2696#issuecomment-3181866301
Co-authored-by: Wang Han <416810799@qq.com>
Co-authored-by: rsuntk <rsuntk@yukiprjkt.my.id>
This commit is contained in:
@@ -19,6 +19,7 @@ kernelsu-objs += selinux/rules.o
|
|||||||
|
|
||||||
ccflags-y += -I$(srctree)/security/selinux -I$(srctree)/security/selinux/include
|
ccflags-y += -I$(srctree)/security/selinux -I$(srctree)/security/selinux/include
|
||||||
ccflags-y += -I$(objtree)/security/selinux -include $(srctree)/include/uapi/asm-generic/errno.h
|
ccflags-y += -I$(objtree)/security/selinux -include $(srctree)/include/uapi/asm-generic/errno.h
|
||||||
|
ccflags-y += -include $(srctree)/$(src)/include/ksu_creds.h
|
||||||
|
|
||||||
obj-$(CONFIG_KSU) += kernelsu.o
|
obj-$(CONFIG_KSU) += kernelsu.o
|
||||||
obj-$(CONFIG_KSU_TRACEPOINT_HOOK) += ksu_trace_export.o
|
obj-$(CONFIG_KSU_TRACEPOINT_HOOK) += ksu_trace_export.o
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/namei.h>
|
#include <linux/namei.h>
|
||||||
#ifndef KSU_HAS_PATH_UMOUNT
|
#ifndef KSU_HAS_PATH_UMOUNT
|
||||||
#include <linux/syscalls.h> // sys_umount
|
#include <linux/syscalls.h> // sys_umount (<4.17) & ksys_umount (4.17+)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MODULE
|
#ifdef MODULE
|
||||||
@@ -49,6 +49,7 @@
|
|||||||
#include "selinux/selinux.h"
|
#include "selinux/selinux.h"
|
||||||
#include "throne_tracker.h"
|
#include "throne_tracker.h"
|
||||||
#include "kernel_compat.h"
|
#include "kernel_compat.h"
|
||||||
|
#include "include/ksu_creds.h"
|
||||||
|
|
||||||
#ifdef CONFIG_KPM
|
#ifdef CONFIG_KPM
|
||||||
#include "kpm/kpm.h"
|
#include "kpm/kpm.h"
|
||||||
@@ -61,7 +62,7 @@ bool susfs_is_allow_su(void)
|
|||||||
// we are manager, allow!
|
// we are manager, allow!
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return ksu_is_allow_uid(current_uid().val);
|
return ksu_is_allow_uid(ksu_current_uid());
|
||||||
}
|
}
|
||||||
|
|
||||||
extern u32 susfs_zygote_sid;
|
extern u32 susfs_zygote_sid;
|
||||||
@@ -143,7 +144,7 @@ static inline bool is_allow_su()
|
|||||||
// we are manager, allow!
|
// we are manager, allow!
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return ksu_is_allow_uid(current_uid().val);
|
return ksu_is_allow_uid(ksu_current_uid());
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool is_unsupported_uid(uid_t uid)
|
static inline bool is_unsupported_uid(uid_t uid)
|
||||||
@@ -196,11 +197,17 @@ static void setup_groups(struct root_profile *profile, struct cred *cred)
|
|||||||
|
|
||||||
groups_sort(group_info);
|
groups_sort(group_info);
|
||||||
set_groups(cred, group_info);
|
set_groups(cred, group_info);
|
||||||
|
put_group_info(group_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void disable_seccomp()
|
static void disable_seccomp(void)
|
||||||
{
|
{
|
||||||
assert_spin_locked(¤t->sighand->siglock);
|
struct task_struct *tsk = get_current();
|
||||||
|
|
||||||
|
pr_info("%s++\n", __func__);
|
||||||
|
spin_lock_irq(&tsk->sighand->siglock);
|
||||||
|
assert_spin_locked(&tsk->sighand->siglock);
|
||||||
|
|
||||||
// disable seccomp
|
// disable seccomp
|
||||||
#if defined(CONFIG_GENERIC_ENTRY) && \
|
#if defined(CONFIG_GENERIC_ENTRY) && \
|
||||||
LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
|
LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
|
||||||
@@ -210,46 +217,56 @@ static void disable_seccomp()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SECCOMP
|
#ifdef CONFIG_SECCOMP
|
||||||
current->seccomp.mode = 0;
|
tsk->seccomp.mode = 0;
|
||||||
current->seccomp.filter = NULL;
|
if (tsk->seccomp.filter == NULL) {
|
||||||
|
pr_warn("tsk->seccomp.filter is NULL already!\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5.9+ have filter_count and use seccomp_filter_release
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
|
||||||
|
seccomp_filter_release(tsk);
|
||||||
|
atomic_set(&tsk->seccomp.filter_count, 0);
|
||||||
#else
|
#else
|
||||||
|
put_seccomp_filter(tsk);
|
||||||
|
tsk->seccomp.filter = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
out:
|
||||||
|
spin_unlock_irq(&tsk->sighand->siglock);
|
||||||
|
pr_info("%s--\n", __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ksu_escape_to_root(void)
|
void ksu_escape_to_root(void)
|
||||||
{
|
{
|
||||||
struct cred *cred;
|
struct cred *newcreds = prepare_creds();
|
||||||
|
if (newcreds == NULL) {
|
||||||
if (current_euid().val == 0) {
|
pr_err("%s: failed to allocate new cred.\n", __func__);
|
||||||
pr_warn("Already root, don't escape!\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rcu_read_lock();
|
if (ksu_cred_euid(newcreds) == 0) {
|
||||||
|
pr_warn("Already root, don't escape!\n");
|
||||||
|
abort_creds(newcreds);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
struct root_profile *profile =
|
||||||
cred = (struct cred *)__task_cred((current));
|
ksu_get_root_profile(ksu_cred_uid(newcreds));
|
||||||
if (!cred) {
|
|
||||||
pr_err("%s: cred is NULL! bailing out..\n", __func__);
|
|
||||||
rcu_read_unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} while (!get_cred_rcu(cred));
|
|
||||||
|
|
||||||
rcu_read_unlock();
|
ksu_cred_uid(newcreds) = profile->uid;
|
||||||
|
ksu_cred_suid(newcreds) = profile->uid;
|
||||||
|
ksu_cred_euid(newcreds) = profile->uid;
|
||||||
|
ksu_cred_fsuid(newcreds) = profile->uid;
|
||||||
|
|
||||||
struct root_profile *profile = ksu_get_root_profile(cred->uid.val);
|
ksu_cred_gid(newcreds) = profile->gid;
|
||||||
|
ksu_cred_fsgid(newcreds) = profile->gid;
|
||||||
|
ksu_cred_sgid(newcreds) = profile->gid;
|
||||||
|
ksu_cred_egid(newcreds) = profile->gid;
|
||||||
|
|
||||||
cred->uid.val = profile->uid;
|
// no wrapper, ignore it.
|
||||||
cred->suid.val = profile->uid;
|
newcreds->securebits = 0;
|
||||||
cred->euid.val = profile->uid;
|
|
||||||
cred->fsuid.val = profile->uid;
|
|
||||||
|
|
||||||
cred->gid.val = profile->gid;
|
|
||||||
cred->fsgid.val = profile->gid;
|
|
||||||
cred->sgid.val = profile->gid;
|
|
||||||
cred->egid.val = profile->gid;
|
|
||||||
cred->securebits = 0;
|
|
||||||
|
|
||||||
BUILD_BUG_ON(sizeof(profile->capabilities.effective) !=
|
BUILD_BUG_ON(sizeof(profile->capabilities.effective) !=
|
||||||
sizeof(kernel_cap_t));
|
sizeof(kernel_cap_t));
|
||||||
@@ -259,23 +276,17 @@ void ksu_escape_to_root(void)
|
|||||||
// we add it here but don't add it to cap_inhertiable, it would be dropped automaticly after exec!
|
// we add it here but don't add it to cap_inhertiable, it would be dropped automaticly after exec!
|
||||||
u64 cap_for_ksud =
|
u64 cap_for_ksud =
|
||||||
profile->capabilities.effective | CAP_DAC_READ_SEARCH;
|
profile->capabilities.effective | CAP_DAC_READ_SEARCH;
|
||||||
memcpy(&cred->cap_effective, &cap_for_ksud,
|
memcpy(&newcreds->cap_effective, &cap_for_ksud,
|
||||||
sizeof(cred->cap_effective));
|
sizeof(newcreds->cap_effective));
|
||||||
memcpy(&cred->cap_permitted, &profile->capabilities.effective,
|
memcpy(&newcreds->cap_permitted, &profile->capabilities.effective,
|
||||||
sizeof(cred->cap_permitted));
|
sizeof(newcreds->cap_permitted));
|
||||||
memcpy(&cred->cap_bset, &profile->capabilities.effective,
|
memcpy(&newcreds->cap_bset, &profile->capabilities.effective,
|
||||||
sizeof(cred->cap_bset));
|
sizeof(newcreds->cap_bset));
|
||||||
|
|
||||||
setup_groups(profile, cred);
|
setup_groups(profile, newcreds);
|
||||||
|
commit_creds(newcreds);
|
||||||
put_cred(cred); // - release here - include/linux/cred.h
|
|
||||||
|
|
||||||
// Refer to kernel/seccomp.c: seccomp_set_mode_strict
|
|
||||||
// When disabling Seccomp, ensure that current->sighand->siglock is held during the operation.
|
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
|
||||||
disable_seccomp();
|
disable_seccomp();
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
ksu_setup_selinux(profile->selinux_domain);
|
ksu_setup_selinux(profile->selinux_domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,7 +297,7 @@ int ksu_handle_rename(struct dentry *old_dentry, struct dentry *new_dentry)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_uid().val != 1000) {
|
if (ksu_current_uid() != 1000) {
|
||||||
// skip non system uid
|
// skip non system uid
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -354,14 +365,14 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: find it in throne tracker!
|
// TODO: find it in throne tracker!
|
||||||
uid_t current_uid_val = current_uid().val;
|
uid_t current_uid_val = ksu_current_uid();
|
||||||
uid_t manager_uid = ksu_get_manager_uid();
|
uid_t manager_uid = ksu_get_manager_uid();
|
||||||
if (current_uid_val != manager_uid &&
|
if (current_uid_val != manager_uid &&
|
||||||
current_uid_val % 100000 == manager_uid) {
|
current_uid_val % 100000 == manager_uid) {
|
||||||
ksu_set_manager_uid(current_uid_val);
|
ksu_set_manager_uid(current_uid_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool from_root = 0 == current_uid().val;
|
bool from_root = 0 == ksu_current_uid();
|
||||||
bool from_manager = ksu_is_manager();
|
bool from_manager = ksu_is_manager();
|
||||||
|
|
||||||
if (!from_root && !from_manager) {
|
if (!from_root && !from_manager) {
|
||||||
@@ -385,7 +396,7 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
|||||||
|
|
||||||
if (arg2 == CMD_GRANT_ROOT) {
|
if (arg2 == CMD_GRANT_ROOT) {
|
||||||
if (is_allow_su()) {
|
if (is_allow_su()) {
|
||||||
pr_info("allow root for: %d\n", current_uid().val);
|
pr_info("allow root for: %d\n", ksu_current_uid());
|
||||||
ksu_escape_to_root();
|
ksu_escape_to_root();
|
||||||
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
|
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
|
||||||
pr_err("grant_root: prctl reply error\n");
|
pr_err("grant_root: prctl reply error\n");
|
||||||
@@ -1131,7 +1142,7 @@ static bool should_umount(struct path *path)
|
|||||||
|
|
||||||
if (current->nsproxy->mnt_ns == init_nsproxy.mnt_ns) {
|
if (current->nsproxy->mnt_ns == init_nsproxy.mnt_ns) {
|
||||||
pr_info("ignore global mnt namespace process: %d\n",
|
pr_info("ignore global mnt namespace process: %d\n",
|
||||||
current_uid().val);
|
ksu_current_uid());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1146,12 +1157,13 @@ static bool should_umount(struct path *path)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef KSU_HAS_PATH_UMOUNT
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) || defined(KSU_HAS_PATH_UMOUNT)
|
||||||
static void ksu_path_umount(const char *mnt, struct path *path, int flags)
|
static void ksu_path_umount(const char *mnt, struct path *path, int flags)
|
||||||
{
|
{
|
||||||
int err = path_umount(path, flags);
|
int ret = path_umount(path, flags);
|
||||||
pr_info("%s: path: %s ret: %d\n", __func__, mnt, err);
|
pr_info("%s: path: %s ret: %d\n", __func__, mnt, ret);
|
||||||
}
|
}
|
||||||
|
#define ksu_umount_mnt(mnt, path, flags) (ksu_path_umount(mnt, path, flags))
|
||||||
#else
|
#else
|
||||||
// TODO: Search a way to make this works without set_fs functions
|
// TODO: Search a way to make this works without set_fs functions
|
||||||
static void ksu_sys_umount(const char *mnt, int flags)
|
static void ksu_sys_umount(const char *mnt, int flags)
|
||||||
@@ -1168,9 +1180,16 @@ static void ksu_sys_umount(const char *mnt, int flags)
|
|||||||
ret = sys_umount(usermnt, flags); // cuz asmlinkage long sys##name
|
ret = sys_umount(usermnt, flags); // cuz asmlinkage long sys##name
|
||||||
#endif
|
#endif
|
||||||
set_fs(old_fs);
|
set_fs(old_fs);
|
||||||
pr_info("%s: path: %s ret: %d \n", __func__, usermnt, ret);
|
pr_info("%s: path: %s ret: %d\n", __func__, usermnt, ret);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
#define ksu_umount_mnt(mnt, __unused, flags) \
|
||||||
|
({ \
|
||||||
|
path_put(__unused); \
|
||||||
|
ksu_sys_umount(mnt, flags); \
|
||||||
|
})
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||||
void ksu_try_umount(const char *mnt, bool check_mnt, int flags, uid_t uid)
|
void ksu_try_umount(const char *mnt, bool check_mnt, int flags, uid_t uid)
|
||||||
@@ -1202,11 +1221,7 @@ static void try_umount(const char *mnt, bool check_mnt, int flags)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef KSU_HAS_PATH_UMOUNT
|
ksu_umount_mnt(mnt, &path, flags);
|
||||||
ksu_path_umount(mnt, &path, flags);
|
|
||||||
#else
|
|
||||||
ksu_sys_umount(mnt, flags);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||||
@@ -1333,7 +1348,7 @@ out_ksu_try_umount:
|
|||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
#ifdef CONFIG_KSU_DEBUG
|
#ifdef CONFIG_KSU_DEBUG
|
||||||
pr_info("uid: %d should not umount!\n", current_uid().val);
|
pr_info("uid: %d should not umount!\n", ksu_current_uid());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#ifndef CONFIG_KSU_SUSFS
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
@@ -1383,75 +1398,6 @@ out_susfs_try_umount_all:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init functons
|
|
||||||
|
|
||||||
static int handler_pre(struct kprobe *p, struct pt_regs *regs)
|
|
||||||
{
|
|
||||||
struct pt_regs *real_regs = PT_REAL_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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct kprobe prctl_kp = {
|
|
||||||
.symbol_name = PRCTL_SYMBOL,
|
|
||||||
.pre_handler = handler_pre,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int renameat_handler_pre(struct kprobe *p, struct pt_regs *regs)
|
|
||||||
{
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)
|
|
||||||
// https://elixir.bootlin.com/linux/v5.12-rc1/source/include/linux/fs.h
|
|
||||||
struct renamedata *rd = PT_REGS_PARM1(regs);
|
|
||||||
struct dentry *old_entry = rd->old_dentry;
|
|
||||||
struct dentry *new_entry = rd->new_dentry;
|
|
||||||
#else
|
|
||||||
struct dentry *old_entry = (struct dentry *)PT_REGS_PARM2(regs);
|
|
||||||
struct dentry *new_entry = (struct dentry *)PT_REGS_CCALL_PARM4(regs);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return ksu_handle_rename(old_entry, new_entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct kprobe renameat_kp = {
|
|
||||||
.symbol_name = "vfs_rename",
|
|
||||||
.pre_handler = renameat_handler_pre,
|
|
||||||
};
|
|
||||||
|
|
||||||
__maybe_unused int ksu_kprobe_init(void)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
rc = register_kprobe(&prctl_kp);
|
|
||||||
|
|
||||||
if (rc) {
|
|
||||||
pr_info("prctl kprobe failed: %d.\n", rc);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = register_kprobe(&renameat_kp);
|
|
||||||
pr_info("renameat kp: %d\n", rc);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
__maybe_unused int ksu_kprobe_exit(void)
|
|
||||||
{
|
|
||||||
unregister_kprobe(&prctl_kp);
|
|
||||||
unregister_kprobe(&renameat_kp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ksu_task_prctl(int option, unsigned long arg2, unsigned long arg3,
|
static int ksu_task_prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||||
unsigned long arg4, unsigned long arg5)
|
unsigned long arg4, unsigned long arg5)
|
||||||
{
|
{
|
||||||
@@ -1459,7 +1405,9 @@ static int ksu_task_prctl(int option, unsigned long arg2, unsigned long arg3,
|
|||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
// kernel 4.4 and 4.9
|
// kernel 4.4 and 4.9
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
|
#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,
|
static int ksu_key_permission(key_ref_t key_ref, const struct cred *cred,
|
||||||
unsigned perm)
|
unsigned perm)
|
||||||
{
|
{
|
||||||
@@ -1523,6 +1471,27 @@ void __init ksu_lsm_hook_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
// keep renameat_handler for LKM support
|
||||||
|
static int renameat_handler_pre(struct kprobe *p, struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)
|
||||||
|
// https://elixir.bootlin.com/linux/v5.12-rc1/source/include/linux/fs.h
|
||||||
|
struct renamedata *rd = PT_REGS_PARM1(regs);
|
||||||
|
struct dentry *old_entry = rd->old_dentry;
|
||||||
|
struct dentry *new_entry = rd->new_dentry;
|
||||||
|
#else
|
||||||
|
struct dentry *old_entry = (struct dentry *)PT_REGS_PARM2(regs);
|
||||||
|
struct dentry *new_entry = (struct dentry *)PT_REGS_CCALL_PARM4(regs);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ksu_handle_rename(old_entry, new_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kprobe renameat_kp = {
|
||||||
|
.symbol_name = "vfs_rename",
|
||||||
|
.pre_handler = renameat_handler_pre,
|
||||||
|
};
|
||||||
|
|
||||||
static int override_security_head(void *head, const void *new_head, size_t len)
|
static int override_security_head(void *head, const void *new_head, size_t len)
|
||||||
{
|
{
|
||||||
unsigned long base = (unsigned long)head & PAGE_MASK;
|
unsigned long base = (unsigned long)head & PAGE_MASK;
|
||||||
@@ -1702,4 +1671,4 @@ void ksu_core_exit(void)
|
|||||||
// we dont use this now
|
// we dont use this now
|
||||||
// ksu_kprobe_exit();
|
// ksu_kprobe_exit();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
39
kernel/include/ksu_creds.h
Normal file
39
kernel/include/ksu_creds.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* KernelSU creds wrapper
|
||||||
|
*
|
||||||
|
* Provide a wrapper for a few credentials use (e.g current_uid().val),
|
||||||
|
* so it would be easier to maintain
|
||||||
|
* some older linux versions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __KSU_H_CREDS
|
||||||
|
#define __KSU_H_CREDS
|
||||||
|
|
||||||
|
#include <linux/cred.h>
|
||||||
|
#include <linux/version.h>
|
||||||
|
|
||||||
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) && \
|
||||||
|
defined(CONFIG_UIDGID_STRICT_TYPE_CHECKS)) || \
|
||||||
|
LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
|
||||||
|
#define ksu_cred_uid(x) ((x)->uid.val)
|
||||||
|
#define ksu_cred_suid(x) ((x)->suid.val)
|
||||||
|
#define ksu_cred_euid(x) ((x)->euid.val)
|
||||||
|
#define ksu_cred_fsuid(x) ((x)->fsuid.val)
|
||||||
|
#define ksu_cred_gid(x) ((x)->gid.val)
|
||||||
|
#define ksu_cred_fsgid(x) ((x)->fsgid.val)
|
||||||
|
#define ksu_cred_sgid(x) ((x)->sgid.val)
|
||||||
|
#define ksu_cred_egid(x) ((x)->egid.val)
|
||||||
|
#define ksu_current_uid() (current_uid().val)
|
||||||
|
#else
|
||||||
|
#define ksu_cred_uid(x) ((x)->uid)
|
||||||
|
#define ksu_cred_suid(x) ((x)->suid)
|
||||||
|
#define ksu_cred_euid(x) ((x)->euid)
|
||||||
|
#define ksu_cred_fsuid(x) ((x)->fsuid)
|
||||||
|
#define ksu_cred_gid(x) ((x)->gid)
|
||||||
|
#define ksu_cred_fsgid(x) ((x)->fsgid)
|
||||||
|
#define ksu_cred_sgid(x) ((x)->sgid)
|
||||||
|
#define ksu_cred_egid(x) ((x)->egid)
|
||||||
|
#define ksu_current_uid() (current_uid())
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <linux/cred.h>
|
#include <linux/cred.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
#include "include/ksu_creds.h"
|
||||||
|
|
||||||
#define KSU_INVALID_UID -1
|
#define KSU_INVALID_UID -1
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@ static inline bool ksu_is_manager_uid_valid()
|
|||||||
|
|
||||||
static inline bool ksu_is_manager()
|
static inline bool ksu_is_manager()
|
||||||
{
|
{
|
||||||
return unlikely(ksu_is_any_manager(current_uid().val) || ksu_manager_uid == current_uid().val);
|
return unlikely(ksu_is_any_manager(ksu_current_uid()) || ksu_manager_uid == ksu_current_uid());
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uid_t ksu_get_manager_uid()
|
static inline uid_t ksu_get_manager_uid()
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "klog.h" // IWYU pragma: keep
|
#include "klog.h" // IWYU pragma: keep
|
||||||
#include "ksud.h"
|
#include "ksud.h"
|
||||||
#include "kernel_compat.h"
|
#include "kernel_compat.h"
|
||||||
|
#include "include/ksu_creds.h"
|
||||||
|
|
||||||
#define SU_PATH "/system/bin/su"
|
#define SU_PATH "/system/bin/su"
|
||||||
#define SH_PATH "/system/bin/sh"
|
#define SH_PATH "/system/bin/sh"
|
||||||
@@ -66,7 +67,7 @@ int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_KSU_SUSFS_SUS_SU
|
#ifndef CONFIG_KSU_SUSFS_SUS_SU
|
||||||
if (!ksu_is_allow_uid(current_uid().val)) {
|
if (!ksu_is_allow_uid(ksu_current_uid())) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -116,7 +117,7 @@ int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_KSU_SUSFS_SUS_SU
|
#ifndef CONFIG_KSU_SUSFS_SUS_SU
|
||||||
if (!ksu_is_allow_uid(current_uid().val)) {
|
if (!ksu_is_allow_uid(ksu_current_uid())) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -181,7 +182,7 @@ int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#ifndef CONFIG_KSU_SUSFS_SUS_SU
|
#ifndef CONFIG_KSU_SUSFS_SUS_SU
|
||||||
if (!ksu_is_allow_uid(current_uid().val))
|
if (!ksu_is_allow_uid(ksu_current_uid()))
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -231,7 +232,7 @@ int ksu_handle_execve_sucompat(int *fd, const char __user **filename_user,
|
|||||||
if (likely(memcmp(path, su, sizeof(su))))
|
if (likely(memcmp(path, su, sizeof(su))))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!ksu_is_allow_uid(current_uid().val))
|
if (!ksu_is_allow_uid(ksu_current_uid()))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
pr_info("sys_execve su found\n");
|
pr_info("sys_execve su found\n");
|
||||||
@@ -248,7 +249,7 @@ static int ksu_inline_handle_devpts(struct inode *inode)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uid_t uid = current_uid().val;
|
uid_t uid = ksu_current_uid();
|
||||||
if (uid % 100000 < 10000) {
|
if (uid % 100000 < 10000) {
|
||||||
// not untrusted_app, ignore it
|
// not untrusted_app, ignore it
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user