diff --git a/kernel/Makefile b/kernel/Makefile index f8dff4d6..fcc58a5b 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -62,6 +62,13 @@ $(info -- KernelSU Manager signature hash: $(KSU_EXPECTED_HASH)) ccflags-y += -DEXPECTED_SIZE=$(KSU_EXPECTED_SIZE) ccflags-y += -DEXPECTED_HASH=\"$(KSU_EXPECTED_HASH)\" +ifeq ($(shell grep -q "int path_umount" $(srctree)/fs/namespace.c; echo $$?),0) +ccflags-y += -DKSU_UMOUNT +else +$(info -- Did you know you can backport path_umount to fs/namespace.c from 5.9?) +$(info -- Read: https://kernelsu.org/guide/how-to-integrate-for-non-gki.html#path_umount) +endif + ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat ccflags-y += -Wno-declaration-after-statement -Wno-unused-function diff --git a/kernel/core_hook.c b/kernel/core_hook.c index dfb4d3f6..06fc75cf 100644 --- a/kernel/core_hook.c +++ b/kernel/core_hook.c @@ -513,7 +513,7 @@ static bool should_umount(struct path *path) static void ksu_umount_mnt(struct path *path, int flags) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) || KSU_UMOUNT int err = path_umount(path, flags); if (err) { pr_info("umount %s failed: %d\n", path->dentry->d_iname, err); diff --git a/website/docs/guide/how-to-integrate-for-non-gki.md b/website/docs/guide/how-to-integrate-for-non-gki.md index 131bd581..00abe526 100644 --- a/website/docs/guide/how-to-integrate-for-non-gki.md +++ b/website/docs/guide/how-to-integrate-for-non-gki.md @@ -40,6 +40,11 @@ But if you encounter a boot loop when integrated KernelSU, it is maybe *kprobe i comment out `ksu_enable_sucompat()` and `ksu_enable_ksud()` in `KernelSU/kernel/ksu.c`, if the device boots normally, then kprobe may be broken. ::: +:::info How to get module umount feature working on pre-GKI? + +If your kernel is older than 5.9, you should backport ```path_umount``` to ```fs/namespace.c```. This is required to get module umount feature working. If you don't backport ```path_umount```, module umount feature won't work. You can get more info on how to achieve this at the end of this page. +::: + ## Manually modify the kernel source If kprobe does not work in your kernel (may be an upstream or kernel bug below 4.8), then you can try this way: @@ -292,6 +297,55 @@ index 45306f9ef247..815091ebfca4 100755 add_input_randomness(type, code, value); ``` +## path_umount + +You can get module umount feature working on pre-GKI kernels by manually backporting ```path_umount``` from 5.9. You can use this patch as reference: + +```diff +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -1739,6 +1739,39 @@ static inline bool may_mandlock(void) + } + #endif + ++static int can_umount(const struct path *path, int flags) ++{ ++ struct mount *mnt = real_mount(path->mnt); ++ ++ if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW)) ++ return -EINVAL; ++ if (!may_mount()) ++ return -EPERM; ++ if (path->dentry != path->mnt->mnt_root) ++ return -EINVAL; ++ if (!check_mnt(mnt)) ++ return -EINVAL; ++ if (mnt->mnt.mnt_flags & MNT_LOCKED) /* Check optimistically */ ++ return -EINVAL; ++ if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ return 0; ++} ++ ++int path_umount(struct path *path, int flags) ++{ ++ struct mount *mnt = real_mount(path->mnt); ++ int ret; ++ ++ ret = can_umount(path, flags); ++ if (!ret) ++ ret = do_umount(mnt, flags); ++ ++ /* we mustn't call path_put() as that would clear mnt_expiry_mark */ ++ dput(path->dentry); ++ mntput_no_expire(mnt); ++ return ret; ++} + /* + * Now umount can handle mount points as well as block devices. + * This is important for filesystems which use unnamed block devices. +``` + Finally, build your kernel again, KernelSU should work well. :::info Entering safe mode accidiently?