You've already forked KernelSU-Next
mirror of
https://github.com/KernelSU-Next/KernelSU-Next.git
synced 2025-08-27 23:46:34 +00:00
ksud: Address pagefault in ksu_handle_execveat_ksud (#662)
* ksud: Address pagefault in ksu_handle_execveat_ksud As pointed out by @backslashxx, when strncpy pagefaults, it causes the first_arg to be completely NULL in some systems. This causes second_stage initialization to fail hence causing SU to be non-functional. This patch copies ksu_strncpy_from_user_retry from @backslashxx's commit:e2fe25e485This adds a fallback to perform a normal strncpy_from_user when nofault fails which allows us to get the first_arg in such cases. Co-authored-by: backslashxx <118538522+backslashxx@users.noreply.github.com> Signed-off-by: Edrick Sinsuan <evcsinsuan@gmail.com> * Revert "ksud: Add second_stage init variant (#653)" This reverts commitc6b60a24e8. --------- Signed-off-by: Edrick Sinsuan <evcsinsuan@gmail.com> Co-authored-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
This commit is contained in:
@@ -173,3 +173,26 @@ long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int ksu_access_ok(const void *addr, unsigned long size)
|
||||
{
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)
|
||||
return access_ok(addr, size);
|
||||
#else
|
||||
return access_ok(VERIFY_READ, addr, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
long ksu_strncpy_from_user_retry(char *dst, const void __user *unsafe_addr,
|
||||
long count)
|
||||
{
|
||||
long ret = ksu_strncpy_from_user_nofault(dst, unsafe_addr, count);
|
||||
if (likely(ret >= 0))
|
||||
return ret;
|
||||
|
||||
// we faulted! fallback to slow path
|
||||
if (unlikely(!ksu_access_ok(unsafe_addr, count)))
|
||||
return -EFAULT;
|
||||
|
||||
return strncpy_from_user(dst, unsafe_addr, count);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
extern long ksu_strncpy_from_user_nofault(char *dst,
|
||||
const void __user *unsafe_addr,
|
||||
long count);
|
||||
extern long ksu_strncpy_from_user_retry(char *dst,
|
||||
const void __user *unsafe_addr,
|
||||
long count);
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
|
||||
extern struct key *init_session_keyring;
|
||||
|
||||
@@ -197,12 +197,11 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
|
||||
const char __user *p = get_user_arg_ptr(*argv, 1);
|
||||
if (p && !IS_ERR(p)) {
|
||||
char first_arg[16];
|
||||
ksu_strncpy_from_user_nofault(
|
||||
ksu_strncpy_from_user_retry(
|
||||
first_arg, p, sizeof(first_arg));
|
||||
pr_info("/system/bin/init first arg: %s\n",
|
||||
first_arg);
|
||||
if (!strcmp(first_arg, "second_stage") ||
|
||||
(argc == 2 && !strcmp(first_arg, ""))) {
|
||||
if (!strcmp(first_arg, "second_stage")) {
|
||||
pr_info("/system/bin/init second_stage executed\n");
|
||||
apply_kernelsu_rules();
|
||||
init_second_stage_executed = true;
|
||||
@@ -223,7 +222,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
|
||||
const char __user *p = get_user_arg_ptr(*argv, 1);
|
||||
if (p && !IS_ERR(p)) {
|
||||
char first_arg[16];
|
||||
ksu_strncpy_from_user_nofault(
|
||||
ksu_strncpy_from_user_retry(
|
||||
first_arg, p, sizeof(first_arg));
|
||||
pr_info("/init first arg: %s\n", first_arg);
|
||||
if (!strcmp(first_arg, "--second-stage")) {
|
||||
@@ -248,7 +247,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
|
||||
}
|
||||
char env[256];
|
||||
// Reading environment variable strings from user space
|
||||
if (ksu_strncpy_from_user_nofault(
|
||||
if (ksu_strncpy_from_user_retry(
|
||||
env, p, sizeof(env)) < 0)
|
||||
continue;
|
||||
// Parsing environment variable names and values
|
||||
|
||||
Reference in New Issue
Block a user