From 7bdb88581658b7550dc61ee1f574612f891fd886 Mon Sep 17 00:00:00 2001 From: weishu Date: Wed, 9 Aug 2023 18:37:30 +0800 Subject: [PATCH] kernel: fix probe_kernel_read failed to read user addr --- kernel/kernel_compat.c | 40 ++++++++++++++++++++++++++++++++++++++++ kernel/kernel_compat.h | 19 +++++++++---------- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/kernel/kernel_compat.c b/kernel/kernel_compat.c index c4413a56..3c2f1d3d 100644 --- a/kernel/kernel_compat.c +++ b/kernel/kernel_compat.c @@ -131,3 +131,43 @@ ssize_t ksu_kernel_write_compat(struct file *p, const void *buf, size_t count, return result; #endif } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) +long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr, + long count) +{ + return strncpy_from_user_nofault(dst, unsafe_addr, count); +} +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) +long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr, + long count) +{ + return strncpy_from_unsafe_user(dst, unsafe_addr, count); +} +#else +// Copied from: https://elixir.bootlin.com/linux/v4.9.337/source/mm/maccess.c#L201 +long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr, + long count) +{ + mm_segment_t old_fs = get_fs(); + long ret; + + if (unlikely(count <= 0)) + return 0; + + set_fs(USER_DS); + pagefault_disable(); + ret = strncpy_from_user(dst, unsafe_addr, count); + pagefault_enable(); + set_fs(old_fs); + + if (ret >= count) { + ret = count; + dst[ret - 1] = '\0'; + } else if (ret > 0) { + ret++; + } + + return ret; +} +#endif \ No newline at end of file diff --git a/kernel/kernel_compat.h b/kernel/kernel_compat.h index f47f43a5..c0b81a47 100644 --- a/kernel/kernel_compat.h +++ b/kernel/kernel_compat.h @@ -6,21 +6,20 @@ #include "linux/version.h" #include "linux/uaccess.h" -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) -#define ksu_strncpy_from_user_nofault strncpy_from_user_nofault -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) -#define ksu_strncpy_from_user_nofault strncpy_from_unsafe_user -#else -#define ksu_strncpy_from_user_nofault probe_kernel_read -#endif +extern long ksu_strncpy_from_user_nofault(char *dst, + const void __user *unsafe_addr, + long count); #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) extern struct key *init_session_keyring; #endif extern void ksu_android_ns_fs_check(); -extern struct file *ksu_filp_open_compat(const char *filename, int flags, umode_t mode); -extern ssize_t ksu_kernel_read_compat(struct file *p, void *buf, size_t count, loff_t *pos); -extern ssize_t ksu_kernel_write_compat(struct file *p, const void *buf, size_t count, loff_t *pos); +extern struct file *ksu_filp_open_compat(const char *filename, int flags, + umode_t mode); +extern ssize_t ksu_kernel_read_compat(struct file *p, void *buf, size_t count, + loff_t *pos); +extern ssize_t ksu_kernel_write_compat(struct file *p, const void *buf, + size_t count, loff_t *pos); #endif