10 Commits

Author SHA1 Message Date
YC酱luyancib
4301d1dc5d kernel(lsm_hooks):fix misding __init (#641) 2025-11-30 10:21:58 +08:00
AlexLiuDev233
36d803a92a kernel: fix build (#633) 2025-11-28 18:02:24 +08:00
AlexLiuDev233
3a12bdead1 kernel: Add nuke_ext4_sysfs interface (#632)
Co-authored-by: weishu <twsxtd@gmail.com>
2025-11-27 18:44:01 +05:30
F640
57e3c095be include objsec.h unconditonally (#618) 2025-11-26 20:33:30 +08:00
backslashxx
3510203fa6 kernel: expose umount list to ioctl interface (#2950)
This idea is borrowed from simonpunk's susfs4ksu.
What we see here is that, yeah well, lets just have userspace send us
what it
wants unmounted, this is better than hardcoding everything.

This also solves that issue where MNT_DETACH fails, as long as we send
unmountables in proper order.

A small anti-duplicate mechanism is also added.

While in-kernel umount is a bit worse than zygisk-provider-based ones,
this can still
serve as a healthy alternative.

---------

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
Co-authored-by: weishu <twsxtd@gmail.com>
Signed-off-by: fc5b87cf <rissu.ntk@gmail.com>
2025-11-18 23:13:27 +08:00
F640
2aa0034695 fix compile on nongki branch (#602)
* fix compile

* revert some edits
2025-11-18 23:07:00 +08:00
fc5b87cf
7782c00275 kernel: handle seccomp_filter_release compat (#203)
* It's actually very excessive that we provide this thing
- Stale: https://github.com/rsuntk/KernelSU/pull/199

Signed-off-by: TwinbornPlate75 <3342733415@qq.com>
Signed-off-by: fc5b87cf <rissu.ntk@gmail.com>
Co-authored-by: TwinbornPlate75 <3342733415@qq.com>
2025-11-18 15:21:50 +08:00
fc5b87cf
dc3de58aa6 kernel: fix compatibility with 5.10
Signed-off-by: fc5b87cf <rissu.ntk@gmail.com>
2025-11-18 15:20:43 +08:00
fc5b87cf
83db28b262 kernel: add close_fd helper, debloat dmesg log
Signed-off-by: fc5b87cf <rissu.ntk@gmail.com>
2025-11-18 15:20:35 +08:00
backslashxx
6e44090e57 RELAND: kernel: throne_tracker: always cleanup
sometimes crowning fails especially when you replace managers.
it is likely due to using different manager hashes. this will
initialize this dynamically and then clear out unconditionally,
manager or not, to try avoid stale data.

while that is a good thing, this will cause a lot of repetetive
work, especially when nothing is crowned.

but ehh, I'd take the reliability and simplicity.

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
Signed-off-by: fc5b87cf <rissu.ntk@gmail.com>
2025-11-18 15:19:13 +08:00
14 changed files with 289 additions and 106 deletions

View File

@@ -145,7 +145,14 @@ endif
ifeq ($(shell grep -q "task_security_struct\s\+\*selinux_cred" $(srctree)/security/selinux/include/objsec.h; echo $$?),0)
ccflags-y += -DKSU_OPTIONAL_SELINUX_CRED
endif
# seccomp_types.h were added on 6.7
ifeq ($(shell grep -q "atomic_t\s\+filter_count" $(srctree)/include/linux/seccomp.h $(srctree)/include/linux/seccomp_types.h; echo $$?),0)
ccflags-y += -DKSU_OPTIONAL_SECCOMP_FILTER_CNT
endif
# some old kernel backport this, let's check if put_seccomp_filter still exist
ifneq ($(shell grep -wq "put_seccomp_filter" $(srctree)/kernel/seccomp.c $(srctree)/include/linux/seccomp.h; echo $$?),0)
ccflags-y += -DKSU_OPTIONAL_SECCOMP_FILTER_RELEASE
endif
ifeq ($(shell grep -q "anon_inode_getfd_secure" $(srctree)/fs/anon_inodes.c; echo $$?),0)
ccflags-y += -DKSU_HAS_GETFD_SECURE
endif

View File

@@ -436,7 +436,7 @@ void persistent_allow_list(void)
goto put_task;
}
cb->func = do_persistent_allow_list;
ksu_task_work_add(tsk, cb, TWA_RESUME);
task_work_add(tsk, cb, TWA_RESUME);
put_task:
put_task_struct(tsk);

View File

@@ -81,6 +81,7 @@ static long ksu_sys_setns(int fd, int flags)
PT_REGS_PARM1(&regs) = fd;
PT_REGS_PARM2(&regs) = flags;
// TODO: arm support
#if (defined(__aarch64__) || defined(__x86_64__))
return SYS_SETNS_SYMBOL(&regs);
#else
@@ -180,13 +181,7 @@ static void setup_mount_namespace(int32_t ns_mode)
if (ret) {
pr_warn("sys_setns failed: %ld\n", ret);
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
close_fd(fd);
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)
ksys_close(fd);
#else
sys_close(fd);
#endif
do_close_fd(fd);
}
if (ns_mode == 2) {
@@ -227,16 +222,25 @@ void disable_seccomp(struct task_struct *tsk)
#ifdef CONFIG_SECCOMP
tsk->seccomp.mode = 0;
if (tsk->seccomp.filter) {
// 5.9+ have filter_count and use seccomp_filter_release
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
seccomp_filter_release(tsk);
// 5.9+ have filter_count, but optional.
#ifdef KSU_OPTIONAL_SECCOMP_FILTER_CNT
atomic_set(&tsk->seccomp.filter_count, 0);
#endif
// some old kernel backport seccomp_filter_release..
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0) && \
defined(KSU_OPTIONAL_SECCOMP_FILTER_RELEASE)
seccomp_filter_release(tsk);
#else
// never, ever call seccomp_filter_release on 6.10+ (no effect)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) && \
LINUX_VERSION_CODE < KERNEL_VERSION(6, 10, 0))
seccomp_filter_release(tsk);
#else
// for 6.11+ kernel support?
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0)
put_seccomp_filter(tsk);
#endif
tsk->seccomp.filter = NULL;
#endif
#endif
}
#endif

View File

@@ -123,3 +123,27 @@ long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
return ret;
}
#endif
long ksu_copy_from_user_nofault(void *dst, const void __user *src, size_t size)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
return copy_from_user_nofault(dst, src, size);
#else
// https://elixir.bootlin.com/linux/v5.8/source/mm/maccess.c#L205
long ret = -EFAULT;
mm_segment_t old_fs = get_fs();
set_fs(USER_DS);
// tweaked to use ksu_access_ok
if (ksu_access_ok(src, size)) {
pagefault_disable();
ret = __copy_from_user_inatomic(dst, src, size);
pagefault_enable();
}
set_fs(old_fs);
if (ret)
return -EFAULT;
return 0;
#endif
}

View File

@@ -4,6 +4,7 @@
#include <linux/fs.h>
#include <linux/version.h>
#include <linux/task_work.h>
#include <linux/fdtable.h>
#include "ss/policydb.h"
#include "linux/key.h"
@@ -69,16 +70,21 @@ extern struct key *init_session_keyring;
// Linux >= 5.7
// task_work_add (struct, struct, enum)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)
#define ksu_task_work_add(tsk, cb, notify) task_work_add(tsk, cb, notify)
#else
// Linux pre-5.7
// task_work_add (struct, struct, bool)
#define ksu_task_work_add(tsk, cb, notify) task_work_add(tsk, cb, notify)
// Decoy, so it wouldn't complain.
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 7, 0)
#ifndef TWA_RESUME
#define TWA_RESUME true
#endif
#endif
static inline int do_close_fd(unsigned int fd)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
return close_fd(fd);
#else
return __close_fd(current->files, fd);
#endif
}
#endif

View File

@@ -44,28 +44,11 @@ static const struct ksu_feature_handler kernel_umount_handler = {
.set_handler = kernel_umount_feature_set,
};
static bool should_umount(struct path *path)
{
if (!path) {
return false;
}
if (current->nsproxy->mnt_ns == init_nsproxy.mnt_ns) {
pr_info("ignore global mnt namespace process: %d\n",
current_uid().val);
return false;
}
if (path->mnt && path->mnt->mnt_sb && path->mnt->mnt_sb->s_type) {
const char *fstype = path->mnt->mnt_sb->s_type->name;
return strcmp(fstype, "overlay") == 0;
}
return false;
}
#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)
extern int path_umount(struct path *path, int flags);
static void ksu_umount_mnt(const char *__never_use_mnt, struct path *path, int flags)
static void ksu_umount_mnt(const char *__never_use_mnt, struct path *path,
int flags)
{
int err = path_umount(path, flags);
if (err) {
@@ -91,12 +74,12 @@ static void ksu_sys_umount(const char *mnt, int flags)
#define ksu_umount_mnt(mnt, __unused, flags) \
({ \
path_put(__unused); \
ksu_sys_umount(mnt, flags); \
ksu_sys_umount(mnt, flags); \
})
#endif
static void try_umount(const char *mnt, bool check_mnt, int flags)
static void try_umount(const char *mnt, int flags)
{
struct path path;
int err = kern_path(mnt, 0, &path);
@@ -110,25 +93,17 @@ static void try_umount(const char *mnt, bool check_mnt, int flags)
return;
}
// we are only interest in some specific mounts
if (check_mnt && !should_umount(&path)) {
path_put(&path);
return;
}
ksu_umount_mnt(mnt, &path, flags);
}
static inline void do_ksu_umount_lists(void)
static inline void do_umount_work(void)
{
// fixme: use `collect_mounts` and `iterate_mount` to iterate all mountpoint and
// filter the mountpoint whose target is `/data/adb`
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);
struct mount_entry *entry;
list_for_each_entry (entry, &mount_list, list) {
pr_info("%s: unmounting: %s flags 0x%x\n", __func__,
entry->umountable, entry->flags);
try_umount(entry->umountable, entry->flags);
}
}
#ifdef KSU_SHOULD_USE_NEW_TP
@@ -145,7 +120,9 @@ static void umount_tw_func(struct callback_head *cb)
saved = override_creds(tw->old_cred);
}
do_ksu_umount_lists();
down_read(&mount_list_lock);
do_umount_work();
up_read(&mount_list_lock);
if (saved)
revert_creds(saved);
@@ -198,7 +175,7 @@ int ksu_handle_umount(uid_t old_uid, uid_t new_uid)
tw->old_cred = get_current_cred();
tw->cb.func = umount_tw_func;
int err = ksu_task_work_add(current, &tw->cb, TWA_RESUME);
int err = task_work_add(current, &tw->cb, TWA_RESUME);
if (err) {
if (tw->old_cred) {
put_cred(tw->old_cred);
@@ -208,7 +185,9 @@ int ksu_handle_umount(uid_t old_uid, uid_t new_uid)
}
#else
// Using task work for non-kp context is expansive?
do_ksu_umount_lists();
down_read(&mount_list_lock);
do_umount_work();
up_read(&mount_list_lock);
#endif
return 0;

View File

@@ -2,6 +2,8 @@
#define __KSU_H_KERNEL_UMOUNT
#include <linux/types.h>
#include <linux/list.h>
#include <linux/rwsem.h>
void ksu_kernel_umount_init(void);
void ksu_kernel_umount_exit(void);
@@ -9,4 +11,13 @@ void ksu_kernel_umount_exit(void);
// Handler function to be called from setresuid hook
int ksu_handle_umount(uid_t old_uid, uid_t new_uid);
// for the umount list
struct mount_entry {
char *umountable;
unsigned int flags;
struct list_head list;
};
extern struct list_head mount_list;
extern struct rw_semaphore mount_list_lock;
#endif

View File

@@ -105,13 +105,13 @@ void on_post_fs_data(void)
}
extern void ext4_unregister_sysfs(struct super_block *sb);
static void nuke_ext4_sysfs(void)
int nuke_ext4_sysfs(const char* mnt)
{
struct path path;
int err = kern_path("/data/adb/modules", 0, &path);
int err = kern_path(mnt, 0, &path);
if (err) {
pr_err("nuke path err: %d\n", err);
return;
return err;
}
struct super_block *sb = path.dentry->d_inode->i_sb;
@@ -119,18 +119,18 @@ static void nuke_ext4_sysfs(void)
if (strcmp(name, "ext4") != 0) {
pr_info("nuke but module aren't mounted\n");
path_put(&path);
return;
return -EINVAL;
}
ext4_unregister_sysfs(sb);
path_put(&path);
return 0;
}
void on_module_mounted(void)
{
pr_info("on_module_mounted!\n");
ksu_module_mounted = true;
nuke_ext4_sysfs();
}
void on_boot_completed(void)
@@ -254,7 +254,7 @@ first_app_process:
rcu_read_lock();
init_task = rcu_dereference(current->real_parent);
if (init_task) {
ksu_task_work_add(init_task, &on_post_fs_data_cb,
task_work_add(init_task, &on_post_fs_data_cb,
TWA_RESUME);
}
rcu_read_unlock();

View File

@@ -14,6 +14,8 @@ void on_boot_completed(void);
bool ksu_is_safe_mode(void);
int nuke_ext4_sysfs(const char* mnt);
extern u32 ksu_file_sid;
extern bool ksu_module_mounted;
extern bool ksu_boot_completed;

View File

@@ -5,6 +5,7 @@
#include <linux/err.h>
#include "klog.h" // IWYU pragma: keep
#include "ksud.h"
#include "kernel_compat.h"
#include "setuid_hook.h"
@@ -102,7 +103,7 @@ static const struct lsm_id ksu_lsmid = {
};
#endif
void ksu_lsm_hook_init(void)
void __init ksu_lsm_hook_init(void)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 8, 0)
security_add_hooks(ksu_hooks, ARRAY_SIZE(ksu_hooks), &ksu_lsmid);

View File

@@ -15,6 +15,8 @@
#include <linux/sched.h>
#endif
#include "objsec.h"
#include "allowlist.h"
#include "feature.h"
#include "klog.h" // IWYU pragma: keep

View File

@@ -1,5 +1,3 @@
#include "supercalls.h"
#include <linux/anon_inodes.h>
#include <linux/capability.h>
#include <linux/cred.h>
@@ -14,11 +12,14 @@
#include <linux/uaccess.h>
#include <linux/version.h>
#include "supercalls.h"
#include "arch.h"
#include "allowlist.h"
#include "feature.h"
#include "klog.h" // IWYU pragma: keep
#include "ksud.h"
#include "kernel_compat.h"
#include "kernel_umount.h"
#include "manager.h"
#include "selinux/selinux.h"
#include "objsec.h"
@@ -371,10 +372,15 @@ static int do_get_wrapper_fd(void __user *arg) {
goto put_orig_file;
}
// kcompat for older kernel
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
#define getfd_secure anon_inode_create_getfd
#else
#elif defined(KSU_HAS_GETFD_SECURE)
#define getfd_secure anon_inode_getfd_secure
#else
// technically not a secure inode, but, this is the only way so.
#define getfd_secure(name, ops, data, flags, __unused) \
anon_inode_getfd(name, ops, data, flags)
#endif
ret = getfd_secure("[ksu_fdwrapper]", &data->ops, data, f->f_flags, NULL);
if (ret < 0) {
@@ -386,7 +392,11 @@ static int do_get_wrapper_fd(void __user *arg) {
struct inode* wrapper_inode = file_inode(pf);
// copy original inode mode
wrapper_inode->i_mode = file_inode(f)->i_mode;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) || defined(KSU_OPTIONAL_SELINUX_INODE)
struct inode_security_struct *sec = selinux_inode(wrapper_inode);
#else
struct inode_security_struct *sec = (struct inode_security_struct *)wrapper_inode->i_security;
#endif
if (sec) {
sec->sid = ksu_file_sid;
}
@@ -466,6 +476,146 @@ static int do_manage_mark(void __user *arg)
return 0;
}
struct list_head mount_list = LIST_HEAD_INIT(mount_list);
DECLARE_RWSEM(mount_list_lock);
static int add_try_umount(void __user *arg)
{
struct mount_entry *new_entry, *entry, *tmp;
struct ksu_add_try_umount_cmd cmd;
char buf[256] = { 0 };
if (copy_from_user(&cmd, arg, sizeof cmd))
return -EFAULT;
switch (cmd.mode) {
case KSU_UMOUNT_WIPE: {
struct mount_entry *entry, *tmp;
down_write(&mount_list_lock);
list_for_each_entry_safe (entry, tmp, &mount_list, list) {
pr_info("wipe_umount_list: removing entry: %s\n",
entry->umountable);
list_del(&entry->list);
kfree(entry->umountable);
kfree(entry);
}
up_write(&mount_list_lock);
return 0;
}
case KSU_UMOUNT_ADD: {
long len = strncpy_from_user(buf, (const char __user *)cmd.arg,
256);
if (len <= 0)
return -EFAULT;
buf[sizeof(buf) - 1] = '\0';
new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL);
if (!new_entry)
return -ENOMEM;
new_entry->umountable = kstrdup(buf, GFP_KERNEL);
if (!new_entry->umountable) {
kfree(new_entry);
return -1;
}
down_write(&mount_list_lock);
// disallow dupes
// if this gets too many, we can consider moving this whole task to a kthread
list_for_each_entry (entry, &mount_list, list) {
if (!strcmp(entry->umountable, buf)) {
pr_info("cmd_add_try_umount: %s is already here!\n",
buf);
up_write(&mount_list_lock);
kfree(new_entry->umountable);
kfree(new_entry);
return -1;
}
}
// now check flags and add
// this also serves as a null check
if (cmd.flags)
new_entry->flags = cmd.flags;
else
new_entry->flags = 0;
// debug
list_add(&new_entry->list, &mount_list);
up_write(&mount_list_lock);
pr_info("cmd_add_try_umount: %s added!\n", buf);
return 0;
}
// this is just strcmp'd wipe anyway
case KSU_UMOUNT_DEL: {
long len = strncpy_from_user(buf, (const char __user *)cmd.arg,
sizeof(buf) - 1);
if (len <= 0)
return -EFAULT;
buf[sizeof(buf) - 1] = '\0';
down_write(&mount_list_lock);
list_for_each_entry_safe (entry, tmp, &mount_list, list) {
if (!strcmp(entry->umountable, buf)) {
pr_info("cmd_add_try_umount: entry removed: %s\n",
entry->umountable);
list_del(&entry->list);
kfree(entry->umountable);
kfree(entry);
}
}
up_write(&mount_list_lock);
return 0;
}
default: {
pr_err("cmd_add_try_umount: invalid operation %u\n", cmd.mode);
return -EINVAL;
}
} // switch(cmd.mode)
return 0;
}
static int do_nuke_ext4_sysfs(void __user *arg)
{
struct ksu_nuke_ext4_sysfs_cmd cmd;
char mnt[256];
long ret;
if (copy_from_user(&cmd, arg, sizeof(cmd)))
return -EFAULT;
if (!cmd.arg)
return -EINVAL;
memset(mnt, 0, sizeof(mnt));
ret = strncpy_from_user(mnt, cmd.arg, sizeof(mnt));
if (ret < 0) {
pr_err("nuke ext4 copy mnt failed: %ld\\n", ret);
return -EFAULT; // 或者 return ret;
}
if (ret == sizeof(mnt)) {
pr_err("nuke ext4 mnt path too long\\n");
return -ENAMETOOLONG;
}
pr_info("do_nuke_ext4_sysfs: %s\n", mnt);
return nuke_ext4_sysfs(mnt);
}
// 100. GET_FULL_VERSION - Get full version string
static int do_get_full_version(void __user *arg)
{
@@ -642,6 +792,8 @@ static const struct ksu_ioctl_cmd_map ksu_ioctl_handlers[] = {
{ .cmd = KSU_IOCTL_SET_FEATURE, .name = "SET_FEATURE", .handler = do_set_feature, .perm_check = manager_or_root },
{ .cmd = KSU_IOCTL_GET_WRAPPER_FD, .name = "GET_WRAPPER_FD", .handler = do_get_wrapper_fd, .perm_check = manager_or_root },
{ .cmd = KSU_IOCTL_MANAGE_MARK, .name = "MANAGE_MARK", .handler = do_manage_mark, .perm_check = manager_or_root },
{ .cmd = KSU_IOCTL_NUKE_EXT4_SYSFS, .name = "NUKE_EXT4_SYSFS", .handler = do_nuke_ext4_sysfs, .perm_check = manager_or_root },
{ .cmd = KSU_IOCTL_ADD_TRY_UMOUNT, .name = "ADD_TRY_UMOUNT", .handler = add_try_umount, .perm_check = manager_or_root },
{ .cmd = KSU_IOCTL_GET_FULL_VERSION,.name = "GET_FULL_VERSION", .handler = do_get_full_version, .perm_check = always_allow},
{ .cmd = KSU_IOCTL_HOOK_TYPE,.name = "GET_HOOK_TYPE", .handler = do_get_hook_type, .perm_check = manager_or_root},
{ .cmd = KSU_IOCTL_ENABLE_KPM, .name = "GET_ENABLE_KPM", .handler = do_enable_kpm, .perm_check = manager_or_root},
@@ -669,11 +821,7 @@ static void ksu_install_fd_tw_func(struct callback_head *cb)
if (copy_to_user(tw->outp, &fd, sizeof(fd))) {
pr_err("install ksu fd reply err\n");
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
close_fd(fd);
#else
ksys_close(fd);
#endif
do_close_fd(fd);
}
kfree(tw);
@@ -699,7 +847,7 @@ static int reboot_handler_pre(struct kprobe *p, struct pt_regs *regs)
tw->outp = (int __user *)arg4;
tw->cb.func = ksu_install_fd_tw_func;
if (ksu_task_work_add(current, &tw->cb, TWA_RESUME)) {
if (task_work_add(current, &tw->cb, TWA_RESUME)) {
kfree(tw);
pr_warn("install fd add task_work failed\n");
}
@@ -730,13 +878,7 @@ int ksu_handle_sys_reboot(int magic1, int magic2, unsigned int cmd,
// downstream: dereference all arg usage!
if (copy_to_user((void __user *)*arg, &fd, sizeof(fd))) {
pr_err("install ksu fd reply err\n");
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
close_fd(fd);
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)
ksys_close(fd);
#else
sys_close(fd);
#endif
do_close_fd(fd);
}
return 0;
}
@@ -842,8 +984,10 @@ int ksu_install_fd(void)
// Install fd
fd_install(fd, filp);
#ifdef CONFIG_KSU_DEBUG
pr_info("ksu fd[%d] installed for %s/%d\n", fd, current->comm,
current->pid);
#endif
return fd;
}

View File

@@ -8,6 +8,7 @@
#ifdef CONFIG_KPM
#include "kpm/kpm.h"
#endif
#include "ksu.h"
// Magic numbers for reboot hook to install fd
#define KSU_INSTALL_MAGIC1 0xDEADBEEF
@@ -77,6 +78,10 @@ struct ksu_set_feature_cmd {
__u64 value; // Input: feature value/state to set
};
struct ksu_nuke_ext4_sysfs_cmd {
__aligned_u64 arg; // Input: mnt pointer
};
// Other command structures
struct ksu_get_full_version_cmd {
char version_full[KSU_FULL_VERSION_STRING]; // Output: full version string
@@ -120,6 +125,16 @@ struct ksu_manage_mark_cmd {
#define KSU_MARK_UNMARK 3
#define KSU_MARK_REFRESH 4
struct ksu_add_try_umount_cmd {
__aligned_u64 arg; // char ptr, this is the mountpoint
__u32 flags; // this is the flag we use for it
__u8 mode; // denotes what to do with it 0:wipe_list 1:add_to_list 2:delete_entry
};
#define KSU_UMOUNT_WIPE 0 // ignore everything and wipe list
#define KSU_UMOUNT_ADD 1 // add entry (path + flags)
#define KSU_UMOUNT_DEL 2 // delete entry, strcmp
// IOCTL command definitions
#define KSU_IOCTL_GRANT_ROOT _IOC(_IOC_NONE, 'K', 1, 0)
#define KSU_IOCTL_GET_INFO _IOC(_IOC_READ, 'K', 2, 0)
@@ -137,6 +152,8 @@ struct ksu_manage_mark_cmd {
#define KSU_IOCTL_SET_FEATURE _IOC(_IOC_WRITE, 'K', 14, 0)
#define KSU_IOCTL_GET_WRAPPER_FD _IOC(_IOC_WRITE, 'K', 15, 0)
#define KSU_IOCTL_MANAGE_MARK _IOC(_IOC_READ | _IOC_WRITE, 'K', 16, 0)
#define KSU_IOCTL_NUKE_EXT4_SYSFS _IOC(_IOC_WRITE, 'K', 17, 0)
#define KSU_IOCTL_ADD_TRY_UMOUNT _IOC(_IOC_WRITE, 'K', 18, 0)
// Other IOCTL command definitions
#define KSU_IOCTL_GET_FULL_VERSION _IOC(_IOC_READ, 'K', 100, 0)
#define KSU_IOCTL_HOOK_TYPE _IOC(_IOC_READ, 'K', 101, 0)

View File

@@ -212,7 +212,7 @@ struct apk_path_hash {
struct list_head list;
};
static struct list_head apk_path_hash_list = LIST_HEAD_INIT(apk_path_hash_list);
static struct list_head apk_path_hash_list;
struct my_dir_context {
struct dir_context ctx;
@@ -279,8 +279,9 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
data->depth = my_ctx->depth - 1;
list_add_tail(&data->list, my_ctx->data_path_list);
} else {
if ((namelen == 8) && (strncmp(name, "base.apk", namelen) == 0)) {
struct apk_path_hash *pos, *n;
if ((namelen == 8) &&
(strncmp(name, "base.apk", namelen) == 0)) {
struct apk_path_hash *pos;
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0)
unsigned int hash = full_name_hash(dirpath, strlen(dirpath));
#else
@@ -307,32 +308,18 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
crown_manager(dirpath, my_ctx->private_data, 0);
*my_ctx->stop = 1;
}
struct apk_path_hash *apk_data = kzalloc(sizeof(*apk_data), GFP_ATOMIC);
if (apk_data) {
apk_data->hash = hash;
apk_data->exists = true;
list_add_tail(&apk_data->list, &apk_path_hash_list);
}
if (is_manager_apk(dirpath)) {
// Manager found, clear APK cache list
list_for_each_entry_safe(pos, n, &apk_path_hash_list, list) {
list_del(&pos->list);
kfree(pos);
}
}
}
}
return FILLDIR_ACTOR_CONTINUE;
}
void search_manager(const char *path, int depth, struct list_head *uid_data)
static void search_manager(const char *path, int depth, struct list_head *uid_data)
{
int i, stop = 0;
struct list_head data_path_list;
INIT_LIST_HEAD(&data_path_list);
INIT_LIST_HEAD(&apk_path_hash_list);
unsigned long data_app_magic = 0;
// Initialize APK cache list
@@ -397,12 +384,11 @@ void search_manager(const char *path, int depth, struct list_head *uid_data)
}
}
// Remove stale cached APK entries
// clear apk_path_hash_list unconditionally
pr_info("search manager: cleanup!\n");
list_for_each_entry_safe (pos, n, &apk_path_hash_list, list) {
if (!pos->exists) {
list_del(&pos->list);
kfree(pos);
}
list_del(&pos->list);
kfree(pos);
}
}