kernel: core_hook: screw path_umount backport, call sys_umount directly

I am repasting here what I posted on the source code originally:

/*
 * turns out path_umount backport is completely unneeded
 * we copy the trick used on strncpy_from_unsafe_user / strncpy_from_user_nofault
 * https://elixir.bootlin.com/linux/v4.4.302/source/mm/maccess.c#L184
 * basically
 *
 *     mm_segment_t old_fs = get_fs();     // remember original fs segment
 *     set_fs(USER_DS);                    // or KERNEL_DS *
 *     do_whatever_in_userspace();
 *     set_fs(old_fs);                     // restore fs segment
 *
 *  * kernel -> user, KERNEL_DS, user -> kernel, USER_DS
 *
 * so yes, we can try to straight up call a syscall from kernel space
 *
 * NOTE: on newer kernels you can use force_uaccess_begin + force_uaccess_end
 * ref: https://elixir.bootlin.com/linux/v5.10.237/source/mm/maccess.c#L250
 *
 */

path_umount backport now optional — neat trick, werks, what can I say.

Backports? Nah, we’re good.

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
This commit is contained in:
backslashxx
2025-05-22 23:32:58 +08:00
committed by ShirkNeko
parent 5aed2c2d2d
commit cd32ee21be

View File

@@ -23,6 +23,9 @@
#include <linux/fs.h>
#include <linux/namei.h>
#ifndef KSU_HAS_PATH_UMOUNT
#include <linux/syscalls.h> // sys_umount
#endif
#ifdef MODULE
#include <linux/list.h>
@@ -984,6 +987,7 @@ static bool should_umount(struct path *path)
#endif
}
#ifdef KSU_HAS_PATH_UMOUNT
static int ksu_umount_mnt(struct path *path, int flags)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) || defined(KSU_UMOUNT)
@@ -993,6 +997,18 @@ static int ksu_umount_mnt(struct path *path, int flags)
return -ENOSYS;
#endif
}
#else
static int ksu_sys_umount(const char *mnt, int flags)
{
char __user *usermnt = (char __user *)mnt;
mm_segment_t old_fs = get_fs();
set_fs(KERNEL_DS);
long ret = sys_umount(usermnt, flags); // cuz asmlinkage long sys##name
set_fs(old_fs);
pr_info("%s: path: %s code: %d \n", __func__, usermnt, ret);
}
#endif
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
void ksu_try_umount(const char *mnt, bool check_mnt, int flags, uid_t uid)
@@ -1022,7 +1038,11 @@ static void ksu_try_umount(const char *mnt, bool check_mnt, int flags)
}
#endif
#ifdef KSU_HAS_PATH_UMOUNT
err = ksu_umount_mnt(&path, flags);
#else
err = ksu_sys_umount(mnt, flags);
#endif
if (err) {
pr_warn("umount %s failed: %d\n", mnt, err);
}