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;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#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,
|
extern long ksu_strncpy_from_user_nofault(char *dst,
|
||||||
const void __user *unsafe_addr,
|
const void __user *unsafe_addr,
|
||||||
long count);
|
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)
|
#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;
|
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);
|
const char __user *p = get_user_arg_ptr(*argv, 1);
|
||||||
if (p && !IS_ERR(p)) {
|
if (p && !IS_ERR(p)) {
|
||||||
char first_arg[16];
|
char first_arg[16];
|
||||||
ksu_strncpy_from_user_nofault(
|
ksu_strncpy_from_user_retry(
|
||||||
first_arg, p, sizeof(first_arg));
|
first_arg, p, sizeof(first_arg));
|
||||||
pr_info("/system/bin/init first arg: %s\n",
|
pr_info("/system/bin/init first arg: %s\n",
|
||||||
first_arg);
|
first_arg);
|
||||||
if (!strcmp(first_arg, "second_stage") ||
|
if (!strcmp(first_arg, "second_stage")) {
|
||||||
(argc == 2 && !strcmp(first_arg, ""))) {
|
|
||||||
pr_info("/system/bin/init second_stage executed\n");
|
pr_info("/system/bin/init second_stage executed\n");
|
||||||
apply_kernelsu_rules();
|
apply_kernelsu_rules();
|
||||||
init_second_stage_executed = true;
|
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);
|
const char __user *p = get_user_arg_ptr(*argv, 1);
|
||||||
if (p && !IS_ERR(p)) {
|
if (p && !IS_ERR(p)) {
|
||||||
char first_arg[16];
|
char first_arg[16];
|
||||||
ksu_strncpy_from_user_nofault(
|
ksu_strncpy_from_user_retry(
|
||||||
first_arg, p, sizeof(first_arg));
|
first_arg, p, sizeof(first_arg));
|
||||||
pr_info("/init first arg: %s\n", first_arg);
|
pr_info("/init first arg: %s\n", first_arg);
|
||||||
if (!strcmp(first_arg, "--second-stage")) {
|
if (!strcmp(first_arg, "--second-stage")) {
|
||||||
@@ -248,7 +247,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
|
|||||||
}
|
}
|
||||||
char env[256];
|
char env[256];
|
||||||
// Reading environment variable strings from user space
|
// Reading environment variable strings from user space
|
||||||
if (ksu_strncpy_from_user_nofault(
|
if (ksu_strncpy_from_user_retry(
|
||||||
env, p, sizeof(env)) < 0)
|
env, p, sizeof(env)) < 0)
|
||||||
continue;
|
continue;
|
||||||
// Parsing environment variable names and values
|
// Parsing environment variable names and values
|
||||||
|
|||||||
Reference in New Issue
Block a user