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 bf06b92850
commit a3a847a885

View File

@@ -25,6 +25,9 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/namei.h> #include <linux/namei.h>
#ifndef KSU_HAS_PATH_UMOUNT
#include <linux/syscalls.h> // sys_umount
#endif
#ifdef MODULE #ifdef MODULE
#include <linux/list.h> #include <linux/list.h>
@@ -538,6 +541,7 @@ static bool should_umount(struct path *path)
return false; return false;
} }
#ifdef KSU_HAS_PATH_UMOUNT
static void ksu_umount_mnt(struct path *path, int flags) static void ksu_umount_mnt(struct path *path, int flags)
{ {
int err = path_umount(path, flags); int err = path_umount(path, flags);
@@ -549,6 +553,18 @@ static void ksu_umount_mnt(struct path *path, int flags)
path->dentry->d_iname); path->dentry->d_iname);
} }
} }
#else
static void 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
static void try_umount(const char *mnt, bool check_mnt, int flags) static void try_umount(const char *mnt, bool check_mnt, int flags)
{ {
@@ -568,7 +584,11 @@ static void try_umount(const char *mnt, bool check_mnt, int flags)
return; return;
} }
#ifdef KSU_HAS_PATH_UMOUNT
ksu_umount_mnt(&path, flags); ksu_umount_mnt(&path, flags);
#else
ksu_sys_umount(mnt, flags);
#endif
} }
int ksu_handle_setuid(struct cred *new, const struct cred *old) int ksu_handle_setuid(struct cred *new, const struct cred *old)