kernel, manager: Track upstream changes (#195)
* These commits are carefully picked from upstream (tiann/KernelSU)
- Picked range:
8c5f485f27..e5f43a3427
Signed-off-by: Faris <rissu.ntk@gmail.com>
Co-authored-by: Wang Han <416810799@qq.com>
Co-authored-by: TwinbornPlate75 <3342733415@qq.com>
Co-authored-by: KOWX712 <leecc0503@gmail.com>
Co-authored-by: Ylarod <me@ylarod.cn>
Co-authored-by: YuKongA <70465933+YuKongA@users.noreply.github.com>
Co-authored-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
Co-authored-by: 5ec1cff <56485584+5ec1cff@users.noreply.github.com>
Co-authored-by: weishu <twsxtd@gmail.com>
This commit is contained in:
@@ -1,3 +1,10 @@
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/version.h>
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
|
||||
#include <linux/sched/task_stack.h>
|
||||
#else
|
||||
#include <linux/sched.h>
|
||||
#endif
|
||||
#include <linux/slab.h>
|
||||
#include <linux/task_work.h>
|
||||
#include <linux/thread_info.h>
|
||||
@@ -22,7 +29,6 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/uidgid.h>
|
||||
#include <linux/version.h>
|
||||
#ifndef KSU_HAS_PATH_UMOUNT
|
||||
#include <linux/syscalls.h> // sys_umount (<4.17) & ksys_umount (4.17+)
|
||||
#endif
|
||||
@@ -42,6 +48,7 @@
|
||||
#include "throne_comm.h"
|
||||
#include "kernel_compat.h"
|
||||
#include "supercalls.h"
|
||||
#include "sucompat.h"
|
||||
|
||||
bool ksu_module_mounted __read_mostly = false;
|
||||
|
||||
@@ -56,6 +63,7 @@ bool ksu_is_compat __read_mostly = false;
|
||||
#endif
|
||||
|
||||
static bool ksu_kernel_umount_enabled = true;
|
||||
static bool ksu_enhanced_security_enabled = false;
|
||||
|
||||
static int kernel_umount_feature_get(u64 *value)
|
||||
{
|
||||
@@ -78,13 +86,34 @@ static const struct ksu_feature_handler kernel_umount_handler = {
|
||||
.set_handler = kernel_umount_feature_set,
|
||||
};
|
||||
|
||||
static int enhanced_security_feature_get(u64 *value)
|
||||
{
|
||||
*value = ksu_enhanced_security_enabled ? 1 : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int enhanced_security_feature_set(u64 value)
|
||||
{
|
||||
bool enable = value != 0;
|
||||
ksu_enhanced_security_enabled = enable;
|
||||
pr_info("enhanced_security: set to %d\n", enable);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ksu_feature_handler enhanced_security_handler = {
|
||||
.feature_id = KSU_FEATURE_ENHANCED_SECURITY,
|
||||
.name = "enhanced_security",
|
||||
.get_handler = enhanced_security_feature_get,
|
||||
.set_handler = enhanced_security_feature_set,
|
||||
};
|
||||
|
||||
static inline bool is_allow_su(void)
|
||||
{
|
||||
if (is_manager()) {
|
||||
// we are manager, allow!
|
||||
return true;
|
||||
}
|
||||
return ksu_is_allow_uid(current_uid().val);
|
||||
return ksu_is_allow_uid_for_current(current_uid().val);
|
||||
}
|
||||
|
||||
static inline bool is_unsupported_uid(uid_t uid)
|
||||
@@ -179,6 +208,10 @@ static void disable_seccomp(struct task_struct *tsk)
|
||||
void escape_to_root(void)
|
||||
{
|
||||
struct cred *cred;
|
||||
#ifdef KSU_SHOULD_USE_NEW_TP
|
||||
struct task_struct *p = current;
|
||||
struct task_struct *t;
|
||||
#endif
|
||||
|
||||
cred = prepare_creds();
|
||||
if (!cred) {
|
||||
@@ -229,8 +262,15 @@ void escape_to_root(void)
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
|
||||
setup_selinux(profile->selinux_domain);
|
||||
|
||||
#ifdef KSU_SHOULD_USE_NEW_TP
|
||||
for_each_thread (p, t) {
|
||||
ksu_set_task_tracepoint_flag(t);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
extern void ext4_unregister_sysfs(struct super_block *sb);
|
||||
void nuke_ext4_sysfs(void)
|
||||
{
|
||||
#ifdef CONFIG_EXT4_FS
|
||||
@@ -244,12 +284,13 @@ void nuke_ext4_sysfs(void)
|
||||
struct super_block *sb = path.dentry->d_inode->i_sb;
|
||||
const char *name = sb->s_type->name;
|
||||
if (strcmp(name, "ext4") != 0) {
|
||||
pr_info("skipping s_type: %s\n", name);
|
||||
pr_info("nuke_module: skipping s_type: %s\n", name);
|
||||
path_put(&path);
|
||||
return;
|
||||
}
|
||||
|
||||
ext4_unregister_sysfs(sb);
|
||||
pr_info("nuke_module: ext4 sysfs unregistered.n\n");
|
||||
path_put(&path);
|
||||
#endif
|
||||
}
|
||||
@@ -285,6 +326,7 @@ static bool should_umount(struct path *path)
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) || \
|
||||
defined(KSU_HAS_PATH_UMOUNT)
|
||||
extern int path_umount(struct path *path, int flags);
|
||||
#define ksu_umount_mnt(__unused, path, flags) (path_umount(path, flags))
|
||||
#else
|
||||
static int ksu_sys_umount(const char *mnt, int flags)
|
||||
@@ -384,6 +426,14 @@ static void umount_tw_func(struct callback_head *cb)
|
||||
}
|
||||
#endif
|
||||
|
||||
// force_sig kcompat, TODO: move it out of core_hook.c
|
||||
// https://elixir.bootlin.com/linux/v5.3-rc1/source/kernel/signal.c#L1613
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
|
||||
#define __force_sig(sig) force_sig(sig)
|
||||
#else
|
||||
#define __force_sig(sig) force_sig(sig, current)
|
||||
#endif
|
||||
|
||||
int ksu_handle_setuid(struct cred *new, const struct cred *old)
|
||||
{
|
||||
if (!new || !old) {
|
||||
@@ -396,9 +446,39 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
|
||||
|
||||
if (0 != old_uid.val) {
|
||||
// old process is not root, ignore it.
|
||||
if (ksu_enhanced_security_enabled) {
|
||||
// disallow any non-ksu domain escalation from non-root to root!
|
||||
if (unlikely(new_uid.val) == 0) {
|
||||
if (!is_ksu_domain()) {
|
||||
pr_warn("find suspicious EoP: %d %s, from %d to %d\n",
|
||||
current->pid, current->comm,
|
||||
old_uid.val, new_uid.val);
|
||||
__force_sig(SIGKILL);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// disallow appuid decrease to any other uid if it is allowed to su
|
||||
if (is_appuid(old_uid)) {
|
||||
if (new_uid.val < old_uid.val &&
|
||||
!ksu_is_allow_uid_for_current(
|
||||
old_uid.val)) {
|
||||
pr_warn("find suspicious EoP: %d %s, from %d to %d\n",
|
||||
current->pid, current->comm,
|
||||
old_uid.val, new_uid.val);
|
||||
__force_sig(SIGKILL);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef KSU_SHOULD_USE_NEW_TP
|
||||
if (new_uid.val == 2000 && ksu_su_compat_enabled) {
|
||||
ksu_set_task_tracepoint_flag(current);
|
||||
}
|
||||
#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;
|
||||
@@ -417,10 +497,11 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
ksu_seccomp_allow_cache(current->seccomp.filter, __NR_reboot);
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
ksu_set_task_tracepoint_flag(current);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ksu_is_allow_uid(new_uid.val)) {
|
||||
if (ksu_is_allow_uid_for_current(new_uid.val)) {
|
||||
if (current->seccomp.mode == SECCOMP_MODE_FILTER &&
|
||||
current->seccomp.filter) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
@@ -428,9 +509,17 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
|
||||
__NR_reboot);
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
if (ksu_su_compat_enabled) {
|
||||
ksu_set_task_tracepoint_flag(current);
|
||||
}
|
||||
} else {
|
||||
if (ksu_su_compat_enabled) {
|
||||
// Disable syscall tracepoint sucompat for non-allowed processes
|
||||
ksu_clear_task_tracepoint_flag(current);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (ksu_is_allow_uid(new_uid.val)) {
|
||||
if (ksu_is_allow_uid_for_current(new_uid.val)) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
disable_seccomp(current);
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
@@ -465,7 +554,7 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
|
||||
// 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!
|
||||
if (!is_zygote(old->security)) {
|
||||
if (!is_zygote(old)) {
|
||||
pr_info("handle umount ignore non zygote child: %d\n",
|
||||
current->pid);
|
||||
return 0;
|
||||
@@ -706,6 +795,10 @@ void __init ksu_core_init(void)
|
||||
if (ksu_register_feature_handler(&kernel_umount_handler)) {
|
||||
pr_err("Failed to register umount feature handler\n");
|
||||
}
|
||||
|
||||
if (ksu_register_feature_handler(&enhanced_security_handler)) {
|
||||
pr_err("Failed to register enhanced security feature handler\n");
|
||||
}
|
||||
}
|
||||
|
||||
void ksu_core_exit(void)
|
||||
@@ -723,13 +816,20 @@ void __init ksu_core_init(void)
|
||||
if (ksu_register_feature_handler(&kernel_umount_handler)) {
|
||||
pr_err("Failed to register umount feature handler\n");
|
||||
}
|
||||
|
||||
if (ksu_register_feature_handler(&enhanced_security_handler)) {
|
||||
pr_err("Failed to register enhanced security feature handler\n");
|
||||
}
|
||||
}
|
||||
|
||||
void ksu_core_exit(void)
|
||||
{
|
||||
ksu_unregister_feature_handler(KSU_FEATURE_KERNEL_UMOUNT);
|
||||
|
||||
ksu_uid_exit();
|
||||
ksu_throne_comm_exit();
|
||||
|
||||
ksu_unregister_feature_handler(KSU_FEATURE_ENHANCED_SECURITY);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user