kernel: sucompat: increase reliability of execve_sucompat
On plain ARMv8.0 devices (A53,A57,A73), strncpy_from_user_nofault() sometimes fails to copy `filename_user` string correctly. This breaks su ofc, breaking some apps like Termux (Play Store ver), ZArchiver and Root Explorer. This does NOT seem to affect newer ARMv8.2+ CPUs (A75/A76 and newer) My speculation? ARMv8.0 has weak speculation :) here we replace `strncpy_from_user_nofault()` with another routine: - access_ok() to validate the pointer - strncpy_from_user() to copy and validate string - manual null-termination just in case, as strncpy_from_user_nofault also does it - remove that memset, seems useless as it is an strncpy, not strncat Kind of mimicking _nofault, but yes with this one we allow pagefaults. Tested on: - ARMv8.0 A73.a53, A57.a53, A53.a53 - ARMv8.2 A76.a55 Tested-by: iDead XD <rafifirdaus12bb@gmail.com> Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
This commit is contained in:
@@ -161,8 +161,25 @@ int ksu_handle_execve_sucompat(int *fd, const char __user **filename_user,
|
||||
if (unlikely(!filename_user))
|
||||
return 0;
|
||||
|
||||
memset(path, 0, sizeof(path));
|
||||
ksu_strncpy_from_user_nofault(path, *filename_user, sizeof(path));
|
||||
/*
|
||||
* nofault variant fails silently due to pagefault_disable
|
||||
* some cpus dont really have that good speculative execution
|
||||
* access_ok to substitute set_fs, we check if pointer is accessible
|
||||
*/
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0)
|
||||
if (!access_ok(VERIFY_READ, *filename_user, sizeof(path)))
|
||||
return 0;
|
||||
#else
|
||||
if (!access_ok(*filename_user, sizeof(path)))
|
||||
return 0;
|
||||
#endif
|
||||
// success = returns number of bytes and should be less than path
|
||||
long len = strncpy_from_user(path, *filename_user, sizeof(path));
|
||||
if (len <= 0)
|
||||
return 0;
|
||||
|
||||
// strncpy_from_user_nofault does this too
|
||||
path[sizeof(path) - 1] = '\0';
|
||||
|
||||
if (likely(memcmp(path, su, sizeof(su))))
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user