kernel: Apply the susfs patch
Co-authored-by: simonpunk <simonpunk2016@gmail.com> Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
This commit is contained in:
127
kernel/Kconfig
127
kernel/Kconfig
@@ -48,4 +48,131 @@ config KSU_MANUAL_HOOK
|
|||||||
help
|
help
|
||||||
If enabled, Hook required KernelSU syscalls with manually-patched function.
|
If enabled, Hook required KernelSU syscalls with manually-patched function.
|
||||||
|
|
||||||
|
menu "KernelSU - SUSFS"
|
||||||
|
|
||||||
|
config KSU_SUSFS
|
||||||
|
bool "KernelSU addon - SUSFS"
|
||||||
|
depends on KSU
|
||||||
|
depends on THREAD_INFO_IN_TASK
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Patch and Enable SUSFS to kernel with KernelSU.
|
||||||
|
|
||||||
|
config KSU_SUSFS_SUS_PATH
|
||||||
|
bool "Enable to hide suspicious path (NOT recommended)"
|
||||||
|
depends on KSU_SUSFS
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
- Allow hiding the user-defined path and all its sub-paths from various system calls.
|
||||||
|
- Includes temp fix for the leaks of app path in /sdcard/Android/data directory.
|
||||||
|
- Effective only on zygote spawned user app process.
|
||||||
|
- Use with cautious as it may cause performance loss and will be vulnerable to side channel attacks,
|
||||||
|
just disable this feature if it doesn't work for you or you don't need it at all.
|
||||||
|
|
||||||
|
config KSU_SUSFS_SUS_MOUNT
|
||||||
|
bool "Enable to hide suspicious mounts"
|
||||||
|
depends on KSU_SUSFS
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
- Allow hiding the user-defined mount paths from /proc/self/[mounts|mountinfo|mountstat].
|
||||||
|
- Effective on all processes for hiding mount entries.
|
||||||
|
- Mounts mounted by process with ksu domain will be forced to be assigned the dev name "KSU".
|
||||||
|
- mnt_id and mnt_group_id of the sus mount will be assigned to a much bigger number to solve the issue of id not being contiguous.
|
||||||
|
|
||||||
|
config KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
|
||||||
|
bool "Enable to hide KSU's default mounts automatically (experimental)"
|
||||||
|
depends on KSU_SUSFS_SUS_MOUNT
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
- Automatically add KSU's default mounts to sus_mount.
|
||||||
|
- No susfs command is needed in userspace.
|
||||||
|
- Only mount operation from process with ksu domain will be checked.
|
||||||
|
|
||||||
|
config KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
|
||||||
|
bool "Enable to hide suspicious bind mounts automatically (experimental)"
|
||||||
|
depends on KSU_SUSFS_SUS_MOUNT
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
- Automatically add binded mounts to sus_mount.
|
||||||
|
- No susfs command is needed in userspace.
|
||||||
|
- Only mount operation from process with ksu domain will be checked.
|
||||||
|
|
||||||
|
config KSU_SUSFS_SUS_KSTAT
|
||||||
|
bool "Enable to spoof suspicious kstat"
|
||||||
|
depends on KSU_SUSFS
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
- Allow spoofing the kstat of user-defined file/directory.
|
||||||
|
- Effective only on zygote spawned user app process.
|
||||||
|
|
||||||
|
config KSU_SUSFS_TRY_UMOUNT
|
||||||
|
bool "Enable to use ksu's try_umount"
|
||||||
|
depends on KSU_SUSFS
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
- Allow using try_umount to umount other user-defined mount paths prior to ksu's default umount paths.
|
||||||
|
- Effective on all NO-root-access-granted processes.
|
||||||
|
|
||||||
|
config KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
|
||||||
|
bool "Enable to add bind mounts to ksu's try_umount automatically (experimental)"
|
||||||
|
depends on KSU_SUSFS_TRY_UMOUNT
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
- Automatically add binded mounts to ksu's try_umount.
|
||||||
|
- No susfs command is needed in userspace.
|
||||||
|
- Only mount operation from process with ksu domain will be checked.
|
||||||
|
|
||||||
|
config KSU_SUSFS_SPOOF_UNAME
|
||||||
|
bool "Enable to spoof uname"
|
||||||
|
depends on KSU_SUSFS
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
- Allow spoofing the string returned by uname syscall to user-defined string.
|
||||||
|
- Effective on all processes.
|
||||||
|
|
||||||
|
config KSU_SUSFS_ENABLE_LOG
|
||||||
|
bool "Enable logging susfs log to kernel"
|
||||||
|
depends on KSU_SUSFS
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
- Allow logging susfs log to kernel, uncheck it to completely disable all susfs log.
|
||||||
|
|
||||||
|
config KSU_SUSFS_HIDE_KSU_SUSFS_SYMBOLS
|
||||||
|
bool "Enable to automatically hide ksu and susfs symbols from /proc/kallsyms"
|
||||||
|
depends on KSU_SUSFS
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
- Automatically hide ksu and susfs symbols from '/proc/kallsyms'.
|
||||||
|
- Effective on all processes.
|
||||||
|
|
||||||
|
config KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG
|
||||||
|
bool "Enable to spoof /proc/bootconfig (gki) or /proc/cmdline (non-gki)"
|
||||||
|
depends on KSU_SUSFS
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
- Spoof the output of /proc/bootconfig (gki) or /proc/cmdline (non-gki) with a user-defined file.
|
||||||
|
- Effective on all processes.
|
||||||
|
|
||||||
|
config KSU_SUSFS_OPEN_REDIRECT
|
||||||
|
bool "Enable to redirect a path to be opened with another path (experimental)"
|
||||||
|
depends on KSU_SUSFS
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
- Allow redirecting a target path to be opened with another user-defined path.
|
||||||
|
- Effective only on processes with uid < 2000.
|
||||||
|
- Please be reminded that process with open access to the target and redirected path can be detected.
|
||||||
|
|
||||||
|
config KSU_SUSFS_SUS_MAP
|
||||||
|
bool "Enable to hide some mmapped real file from different proc maps interfaces"
|
||||||
|
depends on KSU_SUSFS
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
- Allow hiding mmapped real file from /proc/<pid>/[maps|smaps|smaps_rollup|map_files|mem|pagemap]
|
||||||
|
- It does NOT support hiding for anon memory.
|
||||||
|
- It does NOT hide any inline hooks or plt hooks cause by the injected library itself.
|
||||||
|
- It may not be able to evade detections by apps that implement a good injection detection.
|
||||||
|
- Effective only on zygote spawned umounted user app process.
|
||||||
|
|
||||||
|
endmenu
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ kernelsu-objs += seccomp_cache.o
|
|||||||
kernelsu-objs += file_wrapper.o
|
kernelsu-objs += file_wrapper.o
|
||||||
kernelsu-objs += throne_comm.o
|
kernelsu-objs += throne_comm.o
|
||||||
kernelsu-objs += sulog.o
|
kernelsu-objs += sulog.o
|
||||||
|
kernelsu-objs += lsm_hook.o
|
||||||
|
|
||||||
ifeq ($(CONFIG_KSU_MANUAL_SU), y)
|
ifeq ($(CONFIG_KSU_MANUAL_SU), y)
|
||||||
ccflags-y += -DCONFIG_KSU_MANUAL_SU
|
ccflags-y += -DCONFIG_KSU_MANUAL_SU
|
||||||
@@ -183,4 +184,14 @@ $(info -- Supported Unofficial Manager: 5ec1cff (GKI) rsuntk (Non-GKI) ShirkNeko
|
|||||||
ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat
|
ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat
|
||||||
ccflags-y += -Wno-declaration-after-statement -Wno-unused-function -Wno-unused-variable
|
ccflags-y += -Wno-declaration-after-statement -Wno-unused-function -Wno-unused-variable
|
||||||
|
|
||||||
# Keep a new line here!! Because someone may append config
|
## For susfs stuff ##
|
||||||
|
ifeq ($(shell test -e $(srctree)/fs/susfs.c; echo $$?),0)
|
||||||
|
$(eval SUSFS_VERSION=$(shell cat $(srctree)/include/linux/susfs.h | grep -E '^#define SUSFS_VERSION' | cut -d' ' -f3 | sed 's/"//g'))
|
||||||
|
$(info )
|
||||||
|
$(info -- SUSFS_VERSION: $(SUSFS_VERSION))
|
||||||
|
else
|
||||||
|
$(info -- You have not integrated susfs in your kernel yet.)
|
||||||
|
$(info -- Read: https://gitlab.com/simonpunk/susfs4ksu)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Keep a new line here!! Because someone may append config
|
||||||
@@ -21,7 +21,9 @@
|
|||||||
#include "selinux/selinux.h"
|
#include "selinux/selinux.h"
|
||||||
#include "allowlist.h"
|
#include "allowlist.h"
|
||||||
#include "manager.h"
|
#include "manager.h"
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
#include "syscall_hook_manager.h"
|
#include "syscall_hook_manager.h"
|
||||||
|
#endif // #ifndef CONFIG_KSU_SUSFS
|
||||||
|
|
||||||
#define FILE_MAGIC 0x7f4b5355 // ' KSU', u32
|
#define FILE_MAGIC 0x7f4b5355 // ' KSU', u32
|
||||||
#define FILE_FORMAT_VERSION 3 // u32
|
#define FILE_FORMAT_VERSION 3 // u32
|
||||||
@@ -262,8 +264,10 @@ out:
|
|||||||
|
|
||||||
if (persist) {
|
if (persist) {
|
||||||
persistent_allow_list();
|
persistent_allow_list();
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
// FIXME: use a new flag
|
// FIXME: use a new flag
|
||||||
ksu_mark_running_process();
|
ksu_mark_running_process();
|
||||||
|
#endif // #ifndef CONFIG_KSU_SUSFS
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -12,7 +12,9 @@
|
|||||||
#include "app_profile.h"
|
#include "app_profile.h"
|
||||||
#include "klog.h" // IWYU pragma: keep
|
#include "klog.h" // IWYU pragma: keep
|
||||||
#include "selinux/selinux.h"
|
#include "selinux/selinux.h"
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
#include "syscall_hook_manager.h"
|
#include "syscall_hook_manager.h"
|
||||||
|
#endif
|
||||||
#include "sucompat.h"
|
#include "sucompat.h"
|
||||||
#include "sulog.h"
|
#include "sulog.h"
|
||||||
|
|
||||||
@@ -88,8 +90,10 @@ void disable_seccomp(void)
|
|||||||
void escape_with_root_profile(void)
|
void escape_with_root_profile(void)
|
||||||
{
|
{
|
||||||
struct cred *cred;
|
struct cred *cred;
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
struct task_struct *p = current;
|
struct task_struct *p = current;
|
||||||
struct task_struct *t;
|
struct task_struct *t;
|
||||||
|
#endif
|
||||||
|
|
||||||
cred = prepare_creds();
|
cred = prepare_creds();
|
||||||
if (!cred) {
|
if (!cred) {
|
||||||
@@ -149,9 +153,11 @@ void escape_with_root_profile(void)
|
|||||||
ksu_sulog_report_su_grant(current_euid().val, NULL, "escape_to_root");
|
ksu_sulog_report_su_grant(current_euid().val, NULL, "escape_to_root");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
for_each_thread (p, t) {
|
for_each_thread (p, t) {
|
||||||
ksu_set_task_tracepoint_flag(t);
|
ksu_set_task_tracepoint_flag(t);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_KSU_MANUAL_SU
|
#ifdef CONFIG_KSU_MANUAL_SU
|
||||||
@@ -214,9 +220,10 @@ void escape_to_root_for_cmd_su(uid_t target_uid, pid_t target_pid)
|
|||||||
{
|
{
|
||||||
struct cred *newcreds;
|
struct cred *newcreds;
|
||||||
struct task_struct *target_task;
|
struct task_struct *target_task;
|
||||||
unsigned long flags;
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
struct task_struct *p = current;
|
struct task_struct *p = current;
|
||||||
struct task_struct *t;
|
struct task_struct *t;
|
||||||
|
#endif
|
||||||
|
|
||||||
pr_info("cmd_su: escape_to_root_for_cmd_su called for UID: %d, PID: %d\n", target_uid, target_pid);
|
pr_info("cmd_su: escape_to_root_for_cmd_su called for UID: %d, PID: %d\n", target_uid, target_pid);
|
||||||
|
|
||||||
@@ -298,9 +305,11 @@ void escape_to_root_for_cmd_su(uid_t target_uid, pid_t target_pid)
|
|||||||
#if __SULOG_GATE
|
#if __SULOG_GATE
|
||||||
ksu_sulog_report_su_grant(target_uid, "cmd_su", "manual_escalation");
|
ksu_sulog_report_su_grant(target_uid, "cmd_su", "manual_escalation");
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
for_each_thread (p, t) {
|
for_each_thread (p, t) {
|
||||||
ksu_set_task_tracepoint_flag(t);
|
ksu_set_task_tracepoint_flag(t);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
pr_info("cmd_su: privilege escalation completed for UID: %d, PID: %d\n", target_uid, target_pid);
|
pr_info("cmd_su: privilege escalation completed for UID: %d, PID: %d\n", target_uid, target_pid);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -21,7 +21,11 @@
|
|||||||
|
|
||||||
#include "sulog.h"
|
#include "sulog.h"
|
||||||
|
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
static bool ksu_kernel_umount_enabled = true;
|
static bool ksu_kernel_umount_enabled = true;
|
||||||
|
#else
|
||||||
|
bool ksu_kernel_umount_enabled = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
static int kernel_umount_feature_get(u64 *value)
|
static int kernel_umount_feature_get(u64 *value)
|
||||||
{
|
{
|
||||||
@@ -44,11 +48,25 @@ static const struct ksu_feature_handler kernel_umount_handler = {
|
|||||||
.set_handler = kernel_umount_feature_set,
|
.set_handler = kernel_umount_feature_set,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS
|
||||||
|
extern bool susfs_is_mnt_devname_ksu(struct path *path);
|
||||||
|
|
||||||
|
#if defined(CONFIG_KSU_SUSFS_TRY_UMOUNT) && defined(CONFIG_KSU_SUSFS_ENABLE_LOG)
|
||||||
|
extern bool susfs_is_log_enabled;
|
||||||
|
#endif // #if defined(CONFIG_KSU_SUSFS_TRY_UMOUNT) && defined(CONFIG_KSU_SUSFS_ENABLE_LOG)
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||||
|
extern void susfs_try_umount(void);
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS
|
||||||
|
|
||||||
static bool should_umount(struct path *path)
|
static bool should_umount(struct path *path)
|
||||||
{
|
{
|
||||||
if (!path) {
|
if (!path) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_KSU_SUSFS
|
||||||
|
return susfs_is_mnt_devname_ksu(path);
|
||||||
|
#else
|
||||||
|
|
||||||
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", current_uid().val);
|
pr_info("ignore global mnt namespace process: %d\n", current_uid().val);
|
||||||
@@ -60,6 +78,7 @@ static bool should_umount(struct path *path)
|
|||||||
return strcmp(fstype, "overlay") == 0;
|
return strcmp(fstype, "overlay") == 0;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) || defined(KSU_HAS_PATH_UMOUNT)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) || defined(KSU_HAS_PATH_UMOUNT)
|
||||||
@@ -97,7 +116,11 @@ static int ksu_sys_umount(const char *mnt, int flags)
|
|||||||
})
|
})
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||||
void try_umount(const char *mnt, bool check_mnt, int flags)
|
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 // #ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||||
{
|
{
|
||||||
struct path path;
|
struct path path;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -118,6 +141,12 @@ void try_umount(const char *mnt, bool check_mnt, int flags)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_KSU_SUSFS_TRY_UMOUNT) && defined(CONFIG_KSU_SUSFS_ENABLE_LOG)
|
||||||
|
if (susfs_is_log_enabled) {
|
||||||
|
pr_info("susfs: umounting '%s'\n", mnt);
|
||||||
|
}
|
||||||
|
#endif // #if defined(CONFIG_KSU_SUSFS_TRY_UMOUNT) && defined(CONFIG_KSU_SUSFS_ENABLE_LOG)
|
||||||
|
|
||||||
ret = ksu_umount_mnt(mnt, &path, flags);
|
ret = ksu_umount_mnt(mnt, &path, flags);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
#ifdef CONFIG_KSU_DEBUG
|
#ifdef CONFIG_KSU_DEBUG
|
||||||
@@ -126,6 +155,20 @@ void try_umount(const char *mnt, bool check_mnt, int flags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||||
|
void susfs_try_umount_all(void) {
|
||||||
|
susfs_try_umount();
|
||||||
|
try_umount("/odm", true, 0);
|
||||||
|
try_umount("/system", true, 0);
|
||||||
|
try_umount("/vendor", true, 0);
|
||||||
|
try_umount("/product", true, 0);
|
||||||
|
try_umount("/system_ext", true, 0);
|
||||||
|
try_umount("/data/adb/modules", false, MNT_DETACH);
|
||||||
|
try_umount("/debug_ramdisk", true, MNT_DETACH);
|
||||||
|
}
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||||
|
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
struct umount_tw {
|
struct umount_tw {
|
||||||
struct callback_head cb;
|
struct callback_head cb;
|
||||||
const struct cred *old_cred;
|
const struct cred *old_cred;
|
||||||
@@ -147,15 +190,8 @@ static void umount_tw_func(struct callback_head *cb)
|
|||||||
try_umount("/product", true, 0);
|
try_umount("/product", true, 0);
|
||||||
try_umount("/system_ext", true, 0);
|
try_umount("/system_ext", true, 0);
|
||||||
try_umount("/data/adb/modules", false, MNT_DETACH);
|
try_umount("/data/adb/modules", false, MNT_DETACH);
|
||||||
try_umount("/data/adb/kpm", false, MNT_DETACH);
|
|
||||||
// try umount ksu temp path
|
// try umount ksu temp path
|
||||||
try_umount("/debug_ramdisk", false, MNT_DETACH);
|
try_umount("/debug_ramdisk", false, MNT_DETACH);
|
||||||
try_umount("/sbin", false, MNT_DETACH);
|
|
||||||
|
|
||||||
try_umount("/system/etc/hosts", false, MNT_DETACH);
|
|
||||||
// try umount lsposed dex2oat bins
|
|
||||||
try_umount("/apex/com.android.art/bin/dex2oat64", false, MNT_DETACH);
|
|
||||||
try_umount("/apex/com.android.art/bin/dex2oat32", false, MNT_DETACH);
|
|
||||||
|
|
||||||
if (saved)
|
if (saved)
|
||||||
revert_creds(saved);
|
revert_creds(saved);
|
||||||
@@ -224,6 +260,7 @@ int ksu_handle_umount(uid_t old_uid, uid_t new_uid)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif // #ifndef CONFIG_KSU_SUSFS
|
||||||
|
|
||||||
void ksu_kernel_umount_init(void)
|
void ksu_kernel_umount_init(void)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,9 @@
|
|||||||
void ksu_kernel_umount_init(void);
|
void ksu_kernel_umount_init(void);
|
||||||
void ksu_kernel_umount_exit(void);
|
void ksu_kernel_umount_exit(void);
|
||||||
|
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
// Handler function to be called from setresuid hook
|
// Handler function to be called from setresuid hook
|
||||||
int ksu_handle_umount(uid_t old_uid, uid_t new_uid);
|
int ksu_handle_umount(uid_t old_uid, uid_t new_uid);
|
||||||
|
#endif // #ifndef CONFIG_KSU_SUSFS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
19
kernel/ksu.c
19
kernel/ksu.c
@@ -7,11 +7,18 @@
|
|||||||
#include <generated/compile.h>
|
#include <generated/compile.h>
|
||||||
#include <linux/version.h> /* LINUX_VERSION_CODE, KERNEL_VERSION macros */
|
#include <linux/version.h> /* LINUX_VERSION_CODE, KERNEL_VERSION macros */
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS
|
||||||
|
#include <linux/susfs.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "allowlist.h"
|
#include "allowlist.h"
|
||||||
|
#include "ksu.h"
|
||||||
#include "feature.h"
|
#include "feature.h"
|
||||||
#include "klog.h" // IWYU pragma: keep
|
#include "klog.h" // IWYU pragma: keep
|
||||||
#include "throne_tracker.h"
|
#include "throne_tracker.h"
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
#include "syscall_hook_manager.h"
|
#include "syscall_hook_manager.h"
|
||||||
|
#endif
|
||||||
#include "ksud.h"
|
#include "ksud.h"
|
||||||
#include "supercalls.h"
|
#include "supercalls.h"
|
||||||
|
|
||||||
@@ -57,11 +64,15 @@ int __init kernelsu_init(void)
|
|||||||
|
|
||||||
ksu_feature_init();
|
ksu_feature_init();
|
||||||
|
|
||||||
|
ksu_lsm_hook_init();
|
||||||
|
|
||||||
ksu_supercalls_init();
|
ksu_supercalls_init();
|
||||||
|
|
||||||
sukisu_custom_config_init();
|
sukisu_custom_config_init();
|
||||||
|
|
||||||
|
#if defined(CONFIG_KPROBES) && !defined(CONFIG_KSU_SUSFS)
|
||||||
ksu_syscall_hook_manager_init();
|
ksu_syscall_hook_manager_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
ksu_workqueue = alloc_ordered_workqueue("kernelsu_work_queue", 0);
|
ksu_workqueue = alloc_ordered_workqueue("kernelsu_work_queue", 0);
|
||||||
|
|
||||||
@@ -69,7 +80,13 @@ int __init kernelsu_init(void)
|
|||||||
|
|
||||||
ksu_throne_tracker_init();
|
ksu_throne_tracker_init();
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS
|
||||||
|
susfs_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_KPROBES) && !defined(CONFIG_KSU_SUSFS)
|
||||||
ksu_ksud_init();
|
ksu_ksud_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MODULE
|
#ifdef MODULE
|
||||||
#ifndef CONFIG_KSU_DEBUG
|
#ifndef CONFIG_KSU_DEBUG
|
||||||
@@ -90,9 +107,11 @@ void kernelsu_exit(void)
|
|||||||
|
|
||||||
destroy_workqueue(ksu_workqueue);
|
destroy_workqueue(ksu_workqueue);
|
||||||
|
|
||||||
|
#if defined(CONFIG_KPROBES) && !defined(CONFIG_KSU_SUSFS)
|
||||||
ksu_ksud_exit();
|
ksu_ksud_exit();
|
||||||
|
|
||||||
ksu_syscall_hook_manager_exit();
|
ksu_syscall_hook_manager_exit();
|
||||||
|
#endif
|
||||||
|
|
||||||
sukisu_custom_config_exit();
|
sukisu_custom_config_exit();
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ struct manager_list_info {
|
|||||||
|
|
||||||
bool ksu_queue_work(struct work_struct *work);
|
bool ksu_queue_work(struct work_struct *work);
|
||||||
|
|
||||||
|
void ksu_lsm_hook_init(void);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static inline int startswith(char *s, char *prefix)
|
static inline int startswith(char *s, char *prefix)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -33,7 +33,9 @@
|
|||||||
#include "klog.h" // IWYU pragma: keep
|
#include "klog.h" // IWYU pragma: keep
|
||||||
#include "ksud.h"
|
#include "ksud.h"
|
||||||
#include "selinux/selinux.h"
|
#include "selinux/selinux.h"
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
#include "syscall_hook_manager.h"
|
#include "syscall_hook_manager.h"
|
||||||
|
#endif // #ifndef CONFIG_KSU_SUSFS
|
||||||
|
|
||||||
bool ksu_module_mounted __read_mostly = false;
|
bool ksu_module_mounted __read_mostly = false;
|
||||||
bool ksu_boot_completed __read_mostly = false;
|
bool ksu_boot_completed __read_mostly = false;
|
||||||
@@ -65,7 +67,7 @@ static void stop_vfs_read_hook(void);
|
|||||||
static void stop_execve_hook(void);
|
static void stop_execve_hook(void);
|
||||||
static void stop_input_hook(void);
|
static void stop_input_hook(void);
|
||||||
|
|
||||||
#ifdef KSU_KPROBES_HOOK
|
#if defined(KSU_KPROBES_HOOK) && !defined(CONFIG_KSU_SUSFS)
|
||||||
static struct work_struct stop_vfs_read_work;
|
static struct work_struct stop_vfs_read_work;
|
||||||
static struct work_struct stop_execve_hook_work;
|
static struct work_struct stop_execve_hook_work;
|
||||||
static struct work_struct stop_input_hook_work;
|
static struct work_struct stop_input_hook_work;
|
||||||
@@ -90,8 +92,10 @@ void on_post_fs_data(void)
|
|||||||
done = true;
|
done = true;
|
||||||
pr_info("on_post_fs_data!\n");
|
pr_info("on_post_fs_data!\n");
|
||||||
ksu_load_allow_list();
|
ksu_load_allow_list();
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
pr_info("mark tif for running process\n");
|
pr_info("mark tif for running process\n");
|
||||||
ksu_mark_running_process();
|
ksu_mark_running_process();
|
||||||
|
#endif // #ifndef CONFIG_KSU_SUSFS
|
||||||
ksu_observer_init();
|
ksu_observer_init();
|
||||||
// sanity check, this may influence the performance
|
// sanity check, this may influence the performance
|
||||||
stop_input_hook();
|
stop_input_hook();
|
||||||
@@ -136,11 +140,15 @@ void on_module_mounted(void){
|
|||||||
void on_boot_completed(void){
|
void on_boot_completed(void){
|
||||||
ksu_boot_completed = true;
|
ksu_boot_completed = true;
|
||||||
pr_info("on_boot_completed!\n");
|
pr_info("on_boot_completed!\n");
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
// remark process, we don't want to mark other init
|
// remark process, we don't want to mark other init
|
||||||
// forked process excepte zygote and adbd
|
// forked process excepte zygote and adbd
|
||||||
|
ksu_unmark_all_process();
|
||||||
ksu_mark_running_process();
|
ksu_mark_running_process();
|
||||||
|
#endif // #ifndef CONFIG_KSU_SUSFS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
#define MAX_ARG_STRINGS 0x7FFFFFFF
|
#define MAX_ARG_STRINGS 0x7FFFFFFF
|
||||||
struct user_arg_ptr {
|
struct user_arg_ptr {
|
||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
@@ -153,6 +161,7 @@ struct user_arg_ptr {
|
|||||||
#endif
|
#endif
|
||||||
} ptr;
|
} ptr;
|
||||||
};
|
};
|
||||||
|
#endif // #ifndef CONFIG_KSU_SUSFS
|
||||||
|
|
||||||
static const char __user *get_user_arg_ptr(struct user_arg_ptr argv, int nr)
|
static const char __user *get_user_arg_ptr(struct user_arg_ptr argv, int nr)
|
||||||
{
|
{
|
||||||
@@ -335,7 +344,9 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
|
|||||||
task_work_add(init_task, &on_post_fs_data_cb, TWA_RESUME);
|
task_work_add(init_task, &on_post_fs_data_cb, TWA_RESUME);
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
ksu_set_task_tracepoint_flag(current); // we are zygote!
|
ksu_set_task_tracepoint_flag(current); // we are zygote!
|
||||||
|
#endif
|
||||||
|
|
||||||
stop_execve_hook();
|
stop_execve_hook();
|
||||||
}
|
}
|
||||||
@@ -529,7 +540,7 @@ bool ksu_is_safe_mode()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef KSU_KPROBES_HOOK
|
#if defined(KSU_KPROBES_HOOK) && !defined(CONFIG_KSU_SUSFS)
|
||||||
|
|
||||||
static int sys_execve_handler_pre(struct kprobe *p, struct pt_regs *regs)
|
static int sys_execve_handler_pre(struct kprobe *p, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
@@ -605,7 +616,7 @@ static void do_stop_input_hook(struct work_struct *work)
|
|||||||
|
|
||||||
static void stop_vfs_read_hook(void)
|
static void stop_vfs_read_hook(void)
|
||||||
{
|
{
|
||||||
#ifdef KSU_KPROBES_HOOK
|
#if defined(KSU_KPROBES_HOOK) && !defined(CONFIG_KSU_SUSFS)
|
||||||
bool ret = schedule_work(&stop_vfs_read_work);
|
bool ret = schedule_work(&stop_vfs_read_work);
|
||||||
pr_info("unregister vfs_read kprobe: %d!\n", ret);
|
pr_info("unregister vfs_read kprobe: %d!\n", ret);
|
||||||
#else
|
#else
|
||||||
@@ -616,7 +627,7 @@ static void stop_vfs_read_hook(void)
|
|||||||
|
|
||||||
static void stop_execve_hook(void)
|
static void stop_execve_hook(void)
|
||||||
{
|
{
|
||||||
#ifdef KSU_KPROBES_HOOK
|
#if defined(KSU_KPROBES_HOOK) && !defined(CONFIG_KSU_SUSFS)
|
||||||
bool ret = schedule_work(&stop_execve_hook_work);
|
bool ret = schedule_work(&stop_execve_hook_work);
|
||||||
pr_info("unregister execve kprobe: %d!\n", ret);
|
pr_info("unregister execve kprobe: %d!\n", ret);
|
||||||
#else
|
#else
|
||||||
@@ -632,7 +643,7 @@ static void stop_input_hook(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
input_hook_stopped = true;
|
input_hook_stopped = true;
|
||||||
#ifdef KSU_KPROBES_HOOK
|
#if defined(KSU_KPROBES_HOOK) && !defined(CONFIG_KSU_SUSFS)
|
||||||
bool ret = schedule_work(&stop_input_hook_work);
|
bool ret = schedule_work(&stop_input_hook_work);
|
||||||
pr_info("unregister input kprobe: %d!\n", ret);
|
pr_info("unregister input kprobe: %d!\n", ret);
|
||||||
#else
|
#else
|
||||||
@@ -644,7 +655,7 @@ static void stop_input_hook(void)
|
|||||||
// ksud: module support
|
// ksud: module support
|
||||||
void ksu_ksud_init(void)
|
void ksu_ksud_init(void)
|
||||||
{
|
{
|
||||||
#ifdef KSU_KPROBES_HOOK
|
#if defined(KSU_KPROBES_HOOK) && !defined(CONFIG_KSU_SUSFS)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = register_kprobe(&execve_kp);
|
ret = register_kprobe(&execve_kp);
|
||||||
@@ -664,7 +675,7 @@ void ksu_ksud_init(void)
|
|||||||
|
|
||||||
void ksu_ksud_exit(void)
|
void ksu_ksud_exit(void)
|
||||||
{
|
{
|
||||||
#ifdef KSU_KPROBES_HOOK
|
#if defined(KSU_KPROBES_HOOK) && !defined(CONFIG_KSU_SUSFS)
|
||||||
unregister_kprobe(&execve_kp);
|
unregister_kprobe(&execve_kp);
|
||||||
// this should be done before unregister vfs_read_kp
|
// this should be done before unregister vfs_read_kp
|
||||||
// unregister_kprobe(&vfs_read_kp);
|
// unregister_kprobe(&vfs_read_kp);
|
||||||
|
|||||||
@@ -18,4 +18,23 @@ extern u32 ksu_file_sid;
|
|||||||
extern bool ksu_module_mounted;
|
extern bool ksu_module_mounted;
|
||||||
extern bool ksu_boot_completed;
|
extern bool ksu_boot_completed;
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS
|
||||||
|
#define MAX_ARG_STRINGS 0x7FFFFFFF
|
||||||
|
struct user_arg_ptr {
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
bool is_compat;
|
||||||
|
#endif
|
||||||
|
union {
|
||||||
|
const char __user *const __user *native;
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
const compat_uptr_t __user *compat;
|
||||||
|
#endif
|
||||||
|
} ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
|
||||||
|
struct user_arg_ptr *argv,
|
||||||
|
struct user_arg_ptr *envp, int *flags);
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
74
kernel/lsm_hook.c
Normal file
74
kernel/lsm_hook.c
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
#include <linux/version.h>
|
||||||
|
#include <linux/security.h>
|
||||||
|
#include <linux/lsm_hooks.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/cred.h>
|
||||||
|
#include <linux/key.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/uidgid.h>
|
||||||
|
|
||||||
|
#include "kernel_compat.h"
|
||||||
|
#include "ksu.h"
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 10, 0) && defined(CONFIG_KSU_MANUAL_SU)
|
||||||
|
#include "manual_su.h"
|
||||||
|
|
||||||
|
static int ksu_task_alloc(struct task_struct *task,
|
||||||
|
unsigned long clone_flags)
|
||||||
|
{
|
||||||
|
ksu_try_escalate_for_uid(task_uid(task).val);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
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 struct security_hook_list ksu_hooks[] = {
|
||||||
|
#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 10, 0) && defined(CONFIG_KSU_MANUAL_SU)
|
||||||
|
LSM_HOOK_INIT(task_alloc, ksu_task_alloc),
|
||||||
|
#endif
|
||||||
|
#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
|
||||||
|
};
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 8, 0)
|
||||||
|
const struct lsm_id ksu_lsmid = {
|
||||||
|
.name = "ksu",
|
||||||
|
.id = 912,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void __init ksu_lsm_hook_init(void)
|
||||||
|
{
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 8, 0)
|
||||||
|
// https://elixir.bootlin.com/linux/v6.8/source/include/linux/lsm_hooks.h#L120
|
||||||
|
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
|
||||||
|
}
|
||||||
@@ -18,21 +18,36 @@ static inline bool ksu_is_manager_uid_valid(void)
|
|||||||
return ksu_manager_uid != KSU_INVALID_UID;
|
return ksu_manager_uid != KSU_INVALID_UID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
static inline bool is_manager(void)
|
static inline bool is_manager(void)
|
||||||
{
|
{
|
||||||
return unlikely(ksu_is_any_manager(current_uid().val) ||
|
return unlikely(ksu_is_any_manager(current_uid().val) ||
|
||||||
(ksu_manager_uid != KSU_INVALID_UID && ksu_manager_uid == current_uid().val));
|
(ksu_manager_uid != KSU_INVALID_UID && ksu_manager_uid == current_uid().val));
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
static inline bool is_manager()
|
||||||
|
{
|
||||||
|
return unlikely((ksu_manager_uid == current_uid().val % 100000) ||
|
||||||
|
(ksu_manager_uid != KSU_INVALID_UID && ksu_manager_uid == current_uid().val % 100000));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline uid_t ksu_get_manager_uid(void)
|
static inline uid_t ksu_get_manager_uid(void)
|
||||||
{
|
{
|
||||||
return ksu_manager_uid;
|
return ksu_manager_uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
static inline void ksu_set_manager_uid(uid_t uid)
|
static inline void ksu_set_manager_uid(uid_t uid)
|
||||||
{
|
{
|
||||||
ksu_manager_uid = uid;
|
ksu_manager_uid = uid;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
static inline void ksu_set_manager_uid(uid_t uid)
|
||||||
|
{
|
||||||
|
ksu_manager_uid = uid % 100000;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline void ksu_invalidate_manager_uid(void)
|
static inline void ksu_invalidate_manager_uid(void)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -142,6 +142,15 @@ void apply_kernelsu_rules(void)
|
|||||||
// https://android-review.googlesource.com/c/platform/system/logging/+/3725346
|
// https://android-review.googlesource.com/c/platform/system/logging/+/3725346
|
||||||
ksu_dontaudit(db, "untrusted_app", KERNEL_SU_DOMAIN, "dir", "getattr");
|
ksu_dontaudit(db, "untrusted_app", KERNEL_SU_DOMAIN, "dir", "getattr");
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS
|
||||||
|
// Allow umount in zygote process without installing zygisk
|
||||||
|
ksu_allow(db, "zygote", "labeledfs", "filesystem", "unmount");
|
||||||
|
susfs_set_kernel_sid();
|
||||||
|
susfs_set_init_sid();
|
||||||
|
susfs_set_ksu_sid();
|
||||||
|
susfs_set_zygote_sid();
|
||||||
|
#endif
|
||||||
|
|
||||||
mutex_unlock(&ksu_rules);
|
mutex_unlock(&ksu_rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -166,3 +166,96 @@ u32 ksu_get_ksu_file_sid()
|
|||||||
}
|
}
|
||||||
return ksu_file_sid;
|
return ksu_file_sid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS
|
||||||
|
#define KERNEL_INIT_DOMAIN "u:r:init:s0"
|
||||||
|
#define KERNEL_ZYGOTE_DOMAIN "u:r:zygote:s0"
|
||||||
|
#define KERNEL_KERNEL_DOMAIN "u:r:kernel:s0"
|
||||||
|
#ifndef KERNEL_SU_DOMAIN
|
||||||
|
#define KERNEL_SU_DOMAIN "u:r:su:s0"
|
||||||
|
#endif // #ifndef KERNEL_SU_DOMAIN
|
||||||
|
u32 susfs_ksu_sid = 0;
|
||||||
|
u32 susfs_init_sid = 0;
|
||||||
|
u32 susfs_zygote_sid = 0;
|
||||||
|
u32 susfs_kernel_sid = 0;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void susfs_set_kernel_sid(void)
|
||||||
|
{
|
||||||
|
susfs_set_sid(KERNEL_KERNEL_DOMAIN, &susfs_kernel_sid);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -29,4 +29,17 @@ u32 ksu_get_ksu_file_sid(void);
|
|||||||
|
|
||||||
int handle_sepolicy(unsigned long arg3, void __user *arg4);
|
int handle_sepolicy(unsigned long arg3, void __user *arg4);
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS
|
||||||
|
bool susfs_is_sid_equal(void *sec, u32 sid2);
|
||||||
|
u32 susfs_get_sid_from_name(const char *secctx_name);
|
||||||
|
u32 susfs_get_current_sid(void);
|
||||||
|
void susfs_set_zygote_sid(void);
|
||||||
|
bool susfs_is_current_zygote_domain(void);
|
||||||
|
void susfs_set_ksu_sid(void);
|
||||||
|
bool susfs_is_current_ksu_domain(void);
|
||||||
|
void susfs_set_init_sid(void);
|
||||||
|
bool susfs_is_current_init_domain(void);
|
||||||
|
void susfs_set_kernel_sid(void);
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -29,10 +29,13 @@
|
|||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/uidgid.h>
|
#include <linux/uidgid.h>
|
||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
#include <linux/lsm_hooks.h>
|
|
||||||
#include <linux/binfmts.h>
|
#include <linux/binfmts.h>
|
||||||
#include <linux/tty.h>
|
#include <linux/tty.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS
|
||||||
|
#include <linux/susfs.h>
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS
|
||||||
|
|
||||||
#ifndef KSU_HAS_PATH_UMOUNT
|
#ifndef KSU_HAS_PATH_UMOUNT
|
||||||
#include <linux/syscalls.h> // sys_umount (<4.17) & ksys_umount (4.17+)
|
#include <linux/syscalls.h> // sys_umount (<4.17) & ksys_umount (4.17+)
|
||||||
#endif
|
#endif
|
||||||
@@ -54,12 +57,48 @@
|
|||||||
#include "selinux/selinux.h"
|
#include "selinux/selinux.h"
|
||||||
#include "seccomp_cache.h"
|
#include "seccomp_cache.h"
|
||||||
#include "supercalls.h"
|
#include "supercalls.h"
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
#include "syscall_hook_manager.h"
|
#include "syscall_hook_manager.h"
|
||||||
|
#endif
|
||||||
#include "kernel_umount.h"
|
#include "kernel_umount.h"
|
||||||
#include "app_profile.h"
|
#include "app_profile.h"
|
||||||
|
|
||||||
#include "sulog.h"
|
#include "sulog.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS
|
||||||
|
static inline bool is_some_system_uid(uid_t uid)
|
||||||
|
{
|
||||||
|
uid %= 100000;
|
||||||
|
return (uid >= 1000 && uid < 10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool is_zygote_isolated_service_uid(uid_t uid)
|
||||||
|
{
|
||||||
|
uid %= 100000;
|
||||||
|
return (uid >= 90000 && uid < 100000);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool is_zygote_normal_app_uid(uid_t uid)
|
||||||
|
{
|
||||||
|
uid %= 100000;
|
||||||
|
return (uid >= 10000 && uid < 19999);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool susfs_is_umount_for_zygote_system_process_enabled = false;
|
||||||
|
|
||||||
|
extern bool susfs_is_umount_for_zygote_iso_service_enabled;
|
||||||
|
extern u32 susfs_zygote_sid;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
extern void susfs_run_sus_path_loop(uid_t uid);
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
extern void susfs_reorder_mnt_id(void);
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||||
|
extern void susfs_try_umount_all(void);
|
||||||
|
#endif
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS
|
||||||
|
|
||||||
static bool ksu_enhanced_security_enabled = false;
|
static bool ksu_enhanced_security_enabled = false;
|
||||||
|
|
||||||
static int enhanced_security_feature_get(u64 *value)
|
static int enhanced_security_feature_get(u64 *value)
|
||||||
@@ -92,6 +131,7 @@ static inline bool is_allow_su(void)
|
|||||||
return ksu_is_allow_uid_for_current(current_uid().val);
|
return ksu_is_allow_uid_for_current(current_uid().val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid)
|
int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid)
|
||||||
{
|
{
|
||||||
uid_t new_uid = ruid;
|
uid_t new_uid = ruid;
|
||||||
@@ -171,59 +211,114 @@ int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
extern bool ksu_kernel_umount_enabled;
|
||||||
|
extern bool ksu_module_mounted;
|
||||||
|
int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid){
|
||||||
|
// we rely on the fact that zygote always call setresuid(3) with same uids
|
||||||
|
uid_t new_uid = ruid;
|
||||||
|
uid_t old_uid = current_uid().val;
|
||||||
|
|
||||||
// kernel 4.4 and 4.9
|
// if old process is root, ignore it.
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || \
|
if (old_uid != 0 && ksu_enhanced_security_enabled) {
|
||||||
defined(CONFIG_IS_HW_HISI) || \
|
// disallow any non-ksu domain escalation from non-root to root!
|
||||||
defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
|
// euid is what we care about here as it controls permission
|
||||||
static int ksu_key_permission(key_ref_t key_ref, const struct cred *cred,
|
if (unlikely(euid == 0)) {
|
||||||
unsigned perm)
|
if (!is_ksu_domain()) {
|
||||||
{
|
pr_warn("find suspicious EoP: %d %s, from %d to %d\n",
|
||||||
if (init_session_keyring != NULL) {
|
current->pid, current->comm, old_uid, new_uid);
|
||||||
|
force_sig(SIGKILL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// disallow appuid decrease to any other uid if it is not allowed to su
|
||||||
|
if (is_appuid(old_uid)) {
|
||||||
|
if (euid < current_euid().val && !ksu_is_allow_uid_for_current(old_uid)) {
|
||||||
|
pr_warn("find suspicious EoP: %d %s, from %d to %d\n",
|
||||||
|
current->pid, current->comm, old_uid, new_uid);
|
||||||
|
force_sig(SIGKILL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (strcmp(current->comm, "init")) {
|
|
||||||
// we are only interested in `init` process
|
// We only interest in process spwaned by zygote
|
||||||
|
if (!susfs_is_sid_equal(current_cred()->security, susfs_zygote_sid)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
init_session_keyring = cred->session_keyring;
|
|
||||||
pr_info("kernel_compat: got init_session_keyring\n");
|
// Check if spawned process is isolated service first, and force to do umount if so
|
||||||
|
if (is_zygote_isolated_service_uid(new_uid) && susfs_is_umount_for_zygote_iso_service_enabled) {
|
||||||
|
goto do_umount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - Since ksu maanger app uid is excluded in allow_list_arr, so ksu_uid_should_umount(manager_uid)
|
||||||
|
// will always return true, that's why we need to explicitly check if new_uid belongs to
|
||||||
|
// ksu manager
|
||||||
|
if (ksu_get_manager_uid() == new_uid % 100000) {
|
||||||
|
pr_info("install fd for manager: %d\n", new_uid);
|
||||||
|
ksu_install_fd();
|
||||||
|
spin_lock_irq(¤t->sighand->siglock);
|
||||||
|
ksu_seccomp_allow_cache(current->seccomp.filter, __NR_reboot);
|
||||||
|
spin_unlock_irq(¤t->sighand->siglock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if spawned process is normal user app and needs to be umounted
|
||||||
|
if (likely(is_zygote_normal_app_uid(new_uid) && ksu_uid_should_umount(new_uid))) {
|
||||||
|
goto do_umount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lastly, Check if spawned process is some system process and needs to be umounted
|
||||||
|
if (unlikely(is_some_system_uid(new_uid) && susfs_is_umount_for_zygote_system_process_enabled)) {
|
||||||
|
goto do_umount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ksu_is_allow_uid_for_current(new_uid)) {
|
||||||
|
if (current->seccomp.mode == SECCOMP_MODE_FILTER &&
|
||||||
|
current->seccomp.filter) {
|
||||||
|
spin_lock_irq(¤t->sighand->siglock);
|
||||||
|
ksu_seccomp_allow_cache(current->seccomp.filter, __NR_reboot);
|
||||||
|
spin_unlock_irq(¤t->sighand->siglock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
do_umount:
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||||
|
if (!ksu_kernel_umount_enabled || !ksu_module_mounted) {
|
||||||
|
goto skip_try_umount;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_info("susfs: running susfs_try_umount_all() for uid: %u\n", new_uid);
|
||||||
|
susfs_try_umount_all();
|
||||||
|
|
||||||
|
skip_try_umount:
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||||
|
|
||||||
|
get_task_struct(current);
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
// We can reorder the mnt_id now after all sus mounts are umounted
|
||||||
|
susfs_reorder_mnt_id();
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
|
||||||
|
susfs_set_current_proc_umounted();
|
||||||
|
|
||||||
|
put_task_struct(current);
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
susfs_run_sus_path_loop(new_uid);
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif // #ifndef CONFIG_KSU_SUSFS
|
||||||
|
|
||||||
#ifndef MODULE
|
|
||||||
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
|
|
||||||
};
|
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 8, 0)
|
|
||||||
const struct lsm_id ksu_lsmid = {
|
|
||||||
.name = "ksu",
|
|
||||||
.id = 912,
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void __init ksu_lsm_hook_init(void)
|
|
||||||
{
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 8, 0)
|
|
||||||
// https://elixir.bootlin.com/linux/v6.8/source/include/linux/lsm_hooks.h#L120
|
|
||||||
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
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void ksu_setuid_hook_init(void)
|
void ksu_setuid_hook_init(void)
|
||||||
{
|
{
|
||||||
ksu_lsm_hook_init();
|
|
||||||
ksu_kernel_umount_init();
|
ksu_kernel_umount_init();
|
||||||
if (ksu_register_feature_handler(&enhanced_security_handler)) {
|
if (ksu_register_feature_handler(&enhanced_security_handler)) {
|
||||||
pr_err("Failed to register enhanced security feature handler\n");
|
pr_err("Failed to register enhanced security feature handler\n");
|
||||||
|
|||||||
@@ -13,13 +13,20 @@
|
|||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS
|
||||||
|
#include <linux/namei.h>
|
||||||
|
#include "objsec.h"
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS
|
||||||
|
|
||||||
#include "allowlist.h"
|
#include "allowlist.h"
|
||||||
#include "feature.h"
|
#include "feature.h"
|
||||||
#include "klog.h" // IWYU pragma: keep
|
#include "klog.h" // IWYU pragma: keep
|
||||||
#include "ksud.h"
|
#include "ksud.h"
|
||||||
#include "sucompat.h"
|
#include "sucompat.h"
|
||||||
#include "app_profile.h"
|
#include "app_profile.h"
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
#include "syscall_hook_manager.h"
|
#include "syscall_hook_manager.h"
|
||||||
|
#endif // #ifndef CONFIG_KSU_SUSFS
|
||||||
|
|
||||||
#include "sulog.h"
|
#include "sulog.h"
|
||||||
|
|
||||||
@@ -72,6 +79,7 @@ static char __user *ksud_user_path(void)
|
|||||||
return userspace_stack_buffer(ksud_path, sizeof(ksud_path));
|
return userspace_stack_buffer(ksud_path, sizeof(ksud_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
|
int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
|
||||||
int *__unused_flags)
|
int *__unused_flags)
|
||||||
{
|
{
|
||||||
@@ -192,6 +200,142 @@ int ksu_handle_execve_sucompat(const char __user **filename_user,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
static const char sh_path[] = SH_PATH;
|
||||||
|
static const char su_path[] = SU_PATH;
|
||||||
|
static const char ksud_path[] = KSUD_PATH;
|
||||||
|
|
||||||
|
extern bool ksu_kernel_umount_enabled;
|
||||||
|
|
||||||
|
// the call from execve_handler_pre won't provided correct value for __never_use_argument, use them after fix execve_handler_pre, keeping them for consistence for manually patched code
|
||||||
|
int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
|
||||||
|
void *__never_use_argv, void *__never_use_envp,
|
||||||
|
int *__never_use_flags)
|
||||||
|
{
|
||||||
|
struct filename *filename;
|
||||||
|
|
||||||
|
if (unlikely(!filename_ptr))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
filename = *filename_ptr;
|
||||||
|
if (IS_ERR(filename)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (likely(memcmp(filename->name, su_path, sizeof(su_path))))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
pr_info("do_execveat_common su found\n");
|
||||||
|
memcpy((void *)filename->name, ksud_path, sizeof(ksud_path));
|
||||||
|
|
||||||
|
escape_with_root_profile();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv,
|
||||||
|
void *envp, int *flags)
|
||||||
|
{
|
||||||
|
if (ksu_handle_execveat_ksud(fd, filename_ptr, argv, envp, flags)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ksu_handle_execveat_sucompat(fd, filename_ptr, argv, envp,
|
||||||
|
flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
|
||||||
|
int *__unused_flags)
|
||||||
|
{
|
||||||
|
char path[sizeof(su_path) + 1] = {0};
|
||||||
|
|
||||||
|
strncpy_from_user_nofault(path, *filename_user, sizeof(path));
|
||||||
|
|
||||||
|
if (unlikely(!memcmp(path, su_path, sizeof(su_path)))) {
|
||||||
|
pr_info("faccessat su->sh!\n");
|
||||||
|
*filename_user = sh_user_path();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
|
||||||
|
int ksu_handle_stat(int *dfd, struct filename **filename, int *flags) {
|
||||||
|
if (unlikely(IS_ERR(*filename) || (*filename)->name == NULL)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (likely(memcmp((*filename)->name, su_path, sizeof(su_path)))) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_info("ksu_handle_stat: su->sh!\n");
|
||||||
|
memcpy((void *)((*filename)->name), sh_path, sizeof(sh_path));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags)
|
||||||
|
{
|
||||||
|
if (unlikely(!filename_user)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char path[sizeof(su_path) + 1] = {0};
|
||||||
|
|
||||||
|
// Remove this later!! we use syscall hook, so this will never happen!!!!!
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) && 0
|
||||||
|
// it becomes a `struct filename *` after 5.18
|
||||||
|
// https://elixir.bootlin.com/linux/v5.18/source/fs/stat.c#L216
|
||||||
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)
|
||||||
|
struct filename *filename = *((struct filename **)filename_user);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (IS_ERR(filename)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (likely(memcmp(filename->name, su_path, sizeof(su_path))))
|
||||||
|
return 0;
|
||||||
|
pr_info("ksu_handle_stat: su->sh!\n");
|
||||||
|
memcpy((void *)filename->name, sh_path, sizeof(sh_path));
|
||||||
|
#else
|
||||||
|
strncpy_from_user_nofault(path, *filename_user, sizeof(path));
|
||||||
|
|
||||||
|
if (unlikely(!memcmp(path, su_path, sizeof(su_path)))) {
|
||||||
|
pr_info("ksu_handle_stat: su->sh!\n");
|
||||||
|
*filename_user = sh_user_path();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif // #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
|
||||||
|
|
||||||
|
int ksu_handle_devpts(struct inode *inode)
|
||||||
|
{
|
||||||
|
if (!current->mm) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uid_t uid = current_uid().val;
|
||||||
|
if (uid % 100000 < 10000) {
|
||||||
|
// not untrusted_app, ignore it
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!__ksu_is_allow_uid_for_current(uid))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (ksu_file_sid) {
|
||||||
|
struct inode_security_struct *sec = selinux_inode(inode);
|
||||||
|
if (sec) {
|
||||||
|
sec->sid = ksu_file_sid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif // #ifndef CONFIG_KSU_SUSFS
|
||||||
|
|
||||||
// sucompat: permitted process can execute 'su' to gain root access.
|
// sucompat: permitted process can execute 'su' to gain root access.
|
||||||
void ksu_sucompat_init()
|
void ksu_sucompat_init()
|
||||||
|
|||||||
@@ -10,7 +10,11 @@ void ksu_sucompat_exit(void);
|
|||||||
// Handler functions exported for hook_manager
|
// Handler functions exported for hook_manager
|
||||||
int ksu_handle_faccessat(int *dfd, const char __user **filename_user,
|
int ksu_handle_faccessat(int *dfd, const char __user **filename_user,
|
||||||
int *mode, int *__unused_flags);
|
int *mode, int *__unused_flags);
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) && defined(CONFIG_KSU_SUSFS)
|
||||||
|
int ksu_handle_stat(int *dfd, struct filename **filename, int *flags);
|
||||||
|
#else
|
||||||
int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags);
|
int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags);
|
||||||
|
#endif // #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) && defined(CONFIG_KSU_SUSFS)
|
||||||
int ksu_handle_execve_sucompat(const char __user **filename_user,
|
int ksu_handle_execve_sucompat(const char __user **filename_user,
|
||||||
void *__never_use_argv, void *__never_use_envp,
|
void *__never_use_argv, void *__never_use_envp,
|
||||||
int *__never_use_flags);
|
int *__never_use_flags);
|
||||||
|
|||||||
@@ -24,7 +24,9 @@
|
|||||||
#include "selinux/selinux.h"
|
#include "selinux/selinux.h"
|
||||||
#include "objsec.h"
|
#include "objsec.h"
|
||||||
#include "file_wrapper.h"
|
#include "file_wrapper.h"
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
#include "syscall_hook_manager.h"
|
#include "syscall_hook_manager.h"
|
||||||
|
#endif
|
||||||
#include "throne_comm.h"
|
#include "throne_comm.h"
|
||||||
#include "dynamic_manager.h"
|
#include "dynamic_manager.h"
|
||||||
|
|
||||||
@@ -32,6 +34,56 @@
|
|||||||
#include "manual_su.h"
|
#include "manual_su.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS
|
||||||
|
#include <linux/namei.h>
|
||||||
|
#include <linux/susfs.h>
|
||||||
|
|
||||||
|
bool susfs_is_boot_completed_triggered = false;
|
||||||
|
|
||||||
|
extern bool susfs_is_umount_for_zygote_system_process_enabled;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
|
||||||
|
extern bool susfs_is_auto_add_sus_bind_mount_enabled;
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
|
||||||
|
extern bool susfs_is_auto_add_sus_ksu_default_mount_enabled;
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
|
||||||
|
extern bool susfs_is_auto_add_try_umount_for_bind_mount_enabled;
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
|
||||||
|
|
||||||
|
static void susfs_on_post_fs_data(void) {
|
||||||
|
struct path path;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
if (!kern_path(DATA_ADB_UMOUNT_FOR_ZYGOTE_SYSTEM_PROCESS, 0, &path)) {
|
||||||
|
susfs_is_umount_for_zygote_system_process_enabled = true;
|
||||||
|
path_put(&path);
|
||||||
|
}
|
||||||
|
pr_info("susfs_is_umount_for_zygote_system_process_enabled: %d\n", susfs_is_umount_for_zygote_system_process_enabled);
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
|
||||||
|
if (!kern_path(DATA_ADB_NO_AUTO_ADD_SUS_BIND_MOUNT, 0, &path)) {
|
||||||
|
susfs_is_auto_add_sus_bind_mount_enabled = false;
|
||||||
|
path_put(&path);
|
||||||
|
}
|
||||||
|
pr_info("susfs_is_auto_add_sus_bind_mount_enabled: %d\n", susfs_is_auto_add_sus_bind_mount_enabled);
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
|
||||||
|
if (!kern_path(DATA_ADB_NO_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT, 0, &path)) {
|
||||||
|
susfs_is_auto_add_sus_ksu_default_mount_enabled = false;
|
||||||
|
path_put(&path);
|
||||||
|
}
|
||||||
|
pr_info("susfs_is_auto_add_sus_ksu_default_mount_enabled: %d\n", susfs_is_auto_add_sus_ksu_default_mount_enabled);
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
|
||||||
|
if (!kern_path(DATA_ADB_NO_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT, 0, &path)) {
|
||||||
|
susfs_is_auto_add_try_umount_for_bind_mount_enabled = false;
|
||||||
|
path_put(&path);
|
||||||
|
}
|
||||||
|
pr_info("susfs_is_auto_add_try_umount_for_bind_mount_enabled: %d\n", susfs_is_auto_add_try_umount_for_bind_mount_enabled);
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
|
||||||
|
}
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS
|
||||||
|
|
||||||
bool ksu_uid_scanner_enabled = false;
|
bool ksu_uid_scanner_enabled = false;
|
||||||
|
|
||||||
// Permission check functions
|
// Permission check functions
|
||||||
@@ -121,6 +173,10 @@ static int do_report_event(void __user *arg)
|
|||||||
if (!post_fs_data_lock) {
|
if (!post_fs_data_lock) {
|
||||||
post_fs_data_lock = true;
|
post_fs_data_lock = true;
|
||||||
pr_info("post-fs-data triggered\n");
|
pr_info("post-fs-data triggered\n");
|
||||||
|
#ifdef CONFIG_KSU_SUSFS
|
||||||
|
susfs_on_post_fs_data();
|
||||||
|
pr_info("susfs_on_post_fs_data triggered\n");
|
||||||
|
#endif
|
||||||
on_post_fs_data();
|
on_post_fs_data();
|
||||||
init_uid_scanner();
|
init_uid_scanner();
|
||||||
#if __SULOG_GATE
|
#if __SULOG_GATE
|
||||||
@@ -136,6 +192,9 @@ static int do_report_event(void __user *arg)
|
|||||||
boot_complete_lock = true;
|
boot_complete_lock = true;
|
||||||
pr_info("boot_complete triggered\n");
|
pr_info("boot_complete triggered\n");
|
||||||
on_boot_completed();
|
on_boot_completed();
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
susfs_is_boot_completed_triggered = true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -422,7 +481,9 @@ put_orig_file:
|
|||||||
static int do_manage_mark(void __user *arg)
|
static int do_manage_mark(void __user *arg)
|
||||||
{
|
{
|
||||||
struct ksu_manage_mark_cmd cmd;
|
struct ksu_manage_mark_cmd cmd;
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (copy_from_user(&cmd, arg, sizeof(cmd))) {
|
if (copy_from_user(&cmd, arg, sizeof(cmd))) {
|
||||||
pr_err("manage_mark: copy_from_user failed\n");
|
pr_err("manage_mark: copy_from_user failed\n");
|
||||||
@@ -431,6 +492,7 @@ static int do_manage_mark(void __user *arg)
|
|||||||
|
|
||||||
switch (cmd.operation) {
|
switch (cmd.operation) {
|
||||||
case KSU_MARK_GET: {
|
case KSU_MARK_GET: {
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
// Get task mark status
|
// Get task mark status
|
||||||
ret = ksu_get_task_mark(cmd.pid);
|
ret = ksu_get_task_mark(cmd.pid);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@@ -439,8 +501,12 @@ static int do_manage_mark(void __user *arg)
|
|||||||
}
|
}
|
||||||
cmd.result = (u32)ret;
|
cmd.result = (u32)ret;
|
||||||
break;
|
break;
|
||||||
|
#else
|
||||||
|
return -EINVAL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
case KSU_MARK_MARK: {
|
case KSU_MARK_MARK: {
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
if (cmd.pid == 0) {
|
if (cmd.pid == 0) {
|
||||||
ksu_mark_all_process();
|
ksu_mark_all_process();
|
||||||
} else {
|
} else {
|
||||||
@@ -451,9 +517,13 @@ static int do_manage_mark(void __user *arg)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
pr_info("susfs: cmd: KSU_MARK_MARK => do nothing\n");
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case KSU_MARK_UNMARK: {
|
case KSU_MARK_UNMARK: {
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
if (cmd.pid == 0) {
|
if (cmd.pid == 0) {
|
||||||
ksu_unmark_all_process();
|
ksu_unmark_all_process();
|
||||||
} else {
|
} else {
|
||||||
@@ -464,11 +534,18 @@ static int do_manage_mark(void __user *arg)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
pr_info("susfs: cmd: KSU_MARK_UNMARK => do nothing\n");
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case KSU_MARK_REFRESH: {
|
case KSU_MARK_REFRESH: {
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
ksu_mark_running_process();
|
ksu_mark_running_process();
|
||||||
pr_info("manage_mark: refreshed running processes\n");
|
pr_info("manage_mark: refreshed running processes\n");
|
||||||
|
#else
|
||||||
|
pr_info("susfs: cmd: KSU_MARK_REFRESH: do nothing\n");
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
@@ -508,9 +585,11 @@ static int do_get_hook_type(void __user *arg)
|
|||||||
{
|
{
|
||||||
struct ksu_hook_type_cmd cmd = {0};
|
struct ksu_hook_type_cmd cmd = {0};
|
||||||
const char *type = "Tracepoint";
|
const char *type = "Tracepoint";
|
||||||
|
|
||||||
#if defined(KSU_MANUAL_HOOK)
|
#if defined(KSU_MANUAL_HOOK)
|
||||||
type = "Manual";
|
type = "Manual";
|
||||||
|
#elif defined(CONFIG_KSU_SUSFS)
|
||||||
|
type = "Inline";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
|
||||||
@@ -717,6 +796,7 @@ static const struct ksu_ioctl_cmd_map ksu_ioctl_handlers[] = {
|
|||||||
{ .cmd = 0, .name = NULL, .handler = NULL, .perm_check = NULL} // Sentine
|
{ .cmd = 0, .name = NULL, .handler = NULL, .perm_check = NULL} // Sentine
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
struct ksu_install_fd_tw {
|
struct ksu_install_fd_tw {
|
||||||
struct callback_head cb;
|
struct callback_head cb;
|
||||||
int __user *outp;
|
int __user *outp;
|
||||||
@@ -792,6 +872,142 @@ static struct kprobe reboot_kp = {
|
|||||||
.pre_handler = reboot_handler_pre,
|
.pre_handler = reboot_handler_pre,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
int ksu_handle_sys_reboot(int magic1, int magic2, unsigned int cmd, void __user **arg)
|
||||||
|
{
|
||||||
|
if (magic1 != KSU_INSTALL_MAGIC1) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If magic2 is susfs and current process is root
|
||||||
|
if (magic2 == SUSFS_MAGIC && current_uid().val == 0) {
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
if (cmd == CMD_SUSFS_ADD_SUS_PATH) {
|
||||||
|
susfs_add_sus_path(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (cmd == CMD_SUSFS_ADD_SUS_PATH_LOOP) {
|
||||||
|
susfs_add_sus_path_loop(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (cmd == CMD_SUSFS_SET_ANDROID_DATA_ROOT_PATH) {
|
||||||
|
susfs_set_i_state_on_external_dir(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (cmd == CMD_SUSFS_SET_SDCARD_ROOT_PATH) {
|
||||||
|
susfs_set_i_state_on_external_dir(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif //#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
if (cmd == CMD_SUSFS_ADD_SUS_MOUNT) {
|
||||||
|
susfs_add_sus_mount(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (cmd == CMD_SUSFS_HIDE_SUS_MNTS_FOR_ALL_PROCS) {
|
||||||
|
susfs_set_hide_sus_mnts_for_all_procs(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (cmd == CMD_SUSFS_UMOUNT_FOR_ZYGOTE_ISO_SERVICE) {
|
||||||
|
susfs_set_umount_for_zygote_iso_service(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif //#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||||
|
if (cmd == CMD_SUSFS_ADD_SUS_KSTAT) {
|
||||||
|
susfs_add_sus_kstat(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (cmd == CMD_SUSFS_UPDATE_SUS_KSTAT) {
|
||||||
|
susfs_update_sus_kstat(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (cmd == CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY) {
|
||||||
|
susfs_add_sus_kstat(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif //#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||||
|
if (cmd == CMD_SUSFS_ADD_TRY_UMOUNT) {
|
||||||
|
susfs_add_try_umount(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif //#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
|
||||||
|
if (cmd == CMD_SUSFS_SET_UNAME) {
|
||||||
|
susfs_set_uname(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif //#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
|
||||||
|
if (cmd == CMD_SUSFS_ENABLE_LOG) {
|
||||||
|
susfs_enable_log(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif //#ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG
|
||||||
|
if (cmd == CMD_SUSFS_SET_CMDLINE_OR_BOOTCONFIG) {
|
||||||
|
susfs_set_cmdline_or_bootconfig(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif //#ifdef CONFIG_KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT
|
||||||
|
if (cmd == CMD_SUSFS_ADD_OPEN_REDIRECT) {
|
||||||
|
susfs_add_open_redirect(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif //#ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_SU
|
||||||
|
if (cmd == CMD_SUSFS_SHOW_SUS_SU_WORKING_MODE) {
|
||||||
|
susfs_get_sus_su_working_mode(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (cmd == CMD_SUSFS_IS_SUS_SU_READY) {
|
||||||
|
susfs_is_sus_su_ready(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (cmd == CMD_SUSFS_SUS_SU) {
|
||||||
|
susfs_sus_su(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif //#ifdef CONFIG_KSU_SUSFS_SUS_SU
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MAP
|
||||||
|
if (cmd == CMD_SUSFS_ADD_SUS_MAP) {
|
||||||
|
susfs_add_sus_map(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_MAP
|
||||||
|
if (cmd == CMD_SUSFS_ENABLE_AVC_LOG_SPOOFING) {
|
||||||
|
susfs_set_avc_log_spoofing(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (cmd == CMD_SUSFS_SHOW_ENABLED_FEATURES) {
|
||||||
|
susfs_get_enabled_features(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (cmd == CMD_SUSFS_SHOW_VARIANT) {
|
||||||
|
susfs_show_variant(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (cmd == CMD_SUSFS_SHOW_VERSION) {
|
||||||
|
susfs_show_version(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this is a request to install KSU fd
|
||||||
|
if (magic2 == KSU_INSTALL_MAGIC2) {
|
||||||
|
int fd = ksu_install_fd();
|
||||||
|
pr_info("[%d] install ksu fd: %d\n", current->pid, fd);
|
||||||
|
if (copy_to_user((int *)*arg, &fd, sizeof(fd))) {
|
||||||
|
pr_err("install ksu fd reply err\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif // #ifndef CONFIG_KSU_SUSFS
|
||||||
|
|
||||||
void ksu_supercalls_init(void)
|
void ksu_supercalls_init(void)
|
||||||
{
|
{
|
||||||
@@ -801,6 +1017,7 @@ void ksu_supercalls_init(void)
|
|||||||
for (i = 0; ksu_ioctl_handlers[i].handler; i++) {
|
for (i = 0; ksu_ioctl_handlers[i].handler; i++) {
|
||||||
pr_info(" %-18s = 0x%08x\n", ksu_ioctl_handlers[i].name, ksu_ioctl_handlers[i].cmd);
|
pr_info(" %-18s = 0x%08x\n", ksu_ioctl_handlers[i].name, ksu_ioctl_handlers[i].cmd);
|
||||||
}
|
}
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
#ifdef KSU_KPROBES_HOOK
|
#ifdef KSU_KPROBES_HOOK
|
||||||
int rc = register_kprobe(&reboot_kp);
|
int rc = register_kprobe(&reboot_kp);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
@@ -809,13 +1026,18 @@ void ksu_supercalls_init(void)
|
|||||||
pr_info("reboot kprobe registered successfully\n");
|
pr_info("reboot kprobe registered successfully\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ksu_supercalls_exit(void)
|
void ksu_supercalls_exit(void)
|
||||||
{
|
{
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
#ifdef KSU_KPROBES_HOOK
|
#ifdef KSU_KPROBES_HOOK
|
||||||
unregister_kprobe(&reboot_kp);
|
unregister_kprobe(&reboot_kp);
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
pr_info("susfs: do nothing\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ksu_ioctl_audit(unsigned int cmd, const char *cmd_name, uid_t uid, int ret)
|
static inline void ksu_ioctl_audit(unsigned int cmd, const char *cmd_name, uid_t uid, int ret)
|
||||||
@@ -906,4 +1128,4 @@ int ksu_install_fd(void)
|
|||||||
pr_info("ksu fd installed: %d for pid %d\n", fd, current->pid);
|
pr_info("ksu fd installed: %d for pid %d\n", fd, current->pid);
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -259,28 +259,28 @@ int ksu_handle_init_mark_tracker(const char __user **filename_user)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_KSU_MANUAL_SU
|
|
||||||
#include "manual_su.h"
|
|
||||||
static inline void ksu_handle_task_alloc(struct pt_regs *regs)
|
|
||||||
{
|
|
||||||
ksu_try_escalate_for_uid(current_uid().val);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
|
#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
|
||||||
// Generic sys_enter handler that dispatches to specific handlers
|
// Generic sys_enter handler that dispatches to specific handlers
|
||||||
static void ksu_sys_enter_handler(void *data, struct pt_regs *regs, long id)
|
static void ksu_sys_enter_handler(void *data, struct pt_regs *regs, long id)
|
||||||
{
|
{
|
||||||
if (unlikely(check_syscall_fastpath(id))) {
|
if (unlikely(check_syscall_fastpath(id))) {
|
||||||
|
#ifndef CONFIG_KSU_SUSFS
|
||||||
#ifdef KSU_TP_HOOK
|
#ifdef KSU_TP_HOOK
|
||||||
if (ksu_su_compat_enabled) {
|
if (ksu_su_compat_enabled) {
|
||||||
// Handle newfstatat
|
// Handle newfstatat
|
||||||
if (id == __NR_newfstatat) {
|
if (id == __NR_newfstatat) {
|
||||||
int *dfd = (int *)&PT_REGS_PARM1(regs);
|
int *dfd = (int *)&PT_REGS_PARM1(regs);
|
||||||
const char __user **filename_user =
|
|
||||||
(const char __user **)&PT_REGS_PARM2(regs);
|
|
||||||
int *flags = (int *)&PT_REGS_SYSCALL_PARM4(regs);
|
int *flags = (int *)&PT_REGS_SYSCALL_PARM4(regs);
|
||||||
ksu_handle_stat(dfd, filename_user, flags);
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) && defined(CONFIG_KSU_SUSFS)
|
||||||
|
// Kernel 6.1+ with SUSFS uses struct filename **
|
||||||
|
struct filename **filename_ptr = (struct filename **)&PT_REGS_PARM2(regs);
|
||||||
|
ksu_handle_stat(dfd, filename_ptr, flags);
|
||||||
|
#else
|
||||||
|
// Older kernel or no SUSFS: use const char __user **
|
||||||
|
const char __user **filename_user = (const char __user **)&PT_REGS_PARM2(regs);
|
||||||
|
ksu_handle_stat(dfd, filename_user, flags);
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,11 +316,6 @@ static void ksu_sys_enter_handler(void *data, struct pt_regs *regs, long id)
|
|||||||
ksu_handle_setresuid(ruid, euid, suid);
|
ksu_handle_setresuid(ruid, euid, suid);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_KSU_MANUAL_SU
|
|
||||||
// Handle task_alloc via clone/fork
|
|
||||||
if (id == __NR_clone || id == __NR_clone3)
|
|
||||||
return ksu_handle_task_alloc(regs);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user