ksud: migrate ksud execution to security_bprm_check (tiann#2653)
This migrates ksud execution decision-making to bprm_check_security. This requires passing proper argv and envp to a modified _ksud handler aptly named 'ksu_handle_bprm_ksud'. Introduces: int ksu_handle_bprm_ksud(const char *filename, const char *argv1, const char *envp, size_t envp_len) which is adapted from: int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr, struct user_arg_ptr *argv, struct user_arg_ptr *envp, int *flags) ksu_handle_bprm_ksud handles all the decision making, it decides when it is time to apply_kernelsu_rules depending if it sees "second_stage". For LSM hook, turns out we can pull out argv and envp from mm_struct. The code in here explains itself on how to do it. whole blob exists on arg_start to arg_end, so we just pull it out and grab next array after the first null terminator. as for envp, we pass the pointer then hunt for it when needed My reasoning on adding a fallback on usercopy is that on some devices a fault happens, and it copies garbled data. On my creation of this, I actually had to lock that _nofault copy on a spinlock as a way to mimic preempt_disable/enable without actually doing it. As per user reports, no failed _nofault copies anyway but we have-to-have a fallback for resilience. References: - old version16efcd8193e- old version237d5938e66- bad usercopy #21 This now provides a small helper function, ksu_copy_from_user_retry, which explains itself. First we attempt a _nofault copy, if that fails, we try plain. With that, It also provides an inlined copy_from_user_nofault for < 5.8. While using strncpy_from_user_nofault was considered, this wont do, this will only copy up to the first \0. devlog:16e5dce9e7...16c1f5f52128642e60d7...728de0c571References: https://elixir.bootlin.com/linux/v4.14.1/source/include/linux/mm_types.h#L429 https://elixir.bootlin.com/linux/v4.14.1/source/include/linux/lsm_hooks.h Stale: https://github.com/tiann/KernelSU/pull/2653 Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
This commit is contained in:
@@ -70,8 +70,10 @@ void ksu_android_ns_fs_check(void)
|
||||
if (current->nsproxy && current->fs &&
|
||||
current->nsproxy->mnt_ns != init_task.nsproxy->mnt_ns) {
|
||||
android_context_saved_enabled = true;
|
||||
#ifdef CONFIG_KSU_DEBUG
|
||||
pr_info("android context saved enabled due to init mnt_ns(%p) != android mnt_ns(%p)\n",
|
||||
current->nsproxy->mnt_ns, init_task.nsproxy->mnt_ns);
|
||||
#endif
|
||||
ksu_save_ns_fs(&android_context_saved);
|
||||
} else {
|
||||
pr_info("android context saved disabled\n");
|
||||
@@ -93,7 +95,9 @@ struct file *ksu_filp_open_compat(const char *filename, int flags, umode_t mode)
|
||||
// switch mnt_ns even if current is not wq_worker, to ensure what we open is the correct file in android mnt_ns, rather than user created mnt_ns
|
||||
struct ksu_ns_fs_saved saved;
|
||||
if (android_context_saved_enabled) {
|
||||
#ifdef CONFIG_KSU_DEBUG
|
||||
pr_info("start switch current nsproxy and fs to android context\n");
|
||||
#endif
|
||||
task_lock(current);
|
||||
ksu_save_ns_fs(&saved);
|
||||
ksu_load_ns_fs(&android_context_saved);
|
||||
@@ -104,7 +108,9 @@ struct file *ksu_filp_open_compat(const char *filename, int flags, umode_t mode)
|
||||
task_lock(current);
|
||||
ksu_load_ns_fs(&saved);
|
||||
task_unlock(current);
|
||||
#ifdef CONFIG_KSU_DEBUG
|
||||
pr_info("switch current nsproxy and fs back to saved successfully\n");
|
||||
#endif
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
@@ -208,3 +214,27 @@ long ksu_strncpy_from_user_retry(char *dst, const void __user *unsafe_addr,
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
long ksu_copy_from_user_nofault(void *dst, const void __user *src, size_t size)
|
||||
{
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
|
||||
return copy_from_user_nofault(dst, src, size);
|
||||
#else
|
||||
// https://elixir.bootlin.com/linux/v5.8/source/mm/maccess.c#L205
|
||||
long ret = -EFAULT;
|
||||
mm_segment_t old_fs = get_fs();
|
||||
|
||||
set_fs(USER_DS);
|
||||
// tweaked to use ksu_access_ok
|
||||
if (ksu_access_ok(src, size)) {
|
||||
pagefault_disable();
|
||||
ret = __copy_from_user_inatomic(dst, src, size);
|
||||
pagefault_enable();
|
||||
}
|
||||
set_fs(old_fs);
|
||||
|
||||
if (ret)
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user