diff --git a/kernel/Makefile b/kernel/Makefile index b635d1ec..23a14d6e 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -16,8 +16,10 @@ endif kernelsu-objs += selinux/selinux.o kernelsu-objs += selinux/sepolicy.o kernelsu-objs += selinux/rules.o + ccflags-y += -I$(srctree)/security/selinux -I$(srctree)/security/selinux/include ccflags-y += -I$(objtree)/security/selinux -include $(srctree)/include/uapi/asm-generic/errno.h +ccflags-y += -include $(srctree)/$(src)/include/ksu_creds.h obj-$(CONFIG_KSU) += kernelsu.o obj-$(CONFIG_KSU_TRACEPOINT_HOOK) += ksu_trace_export.o @@ -123,7 +125,6 @@ ifdef KSU_EXPECTED_SIZE ccflags-y += -DEXPECTED_SIZE=$(KSU_EXPECTED_SIZE) $(info -- Custom KernelSU Manager signature size: $(KSU_EXPECTED_SIZE)) endif - ifdef KSU_EXPECTED_HASH ccflags-y += -DEXPECTED_HASH=\"$(KSU_EXPECTED_HASH)\" $(info -- Custom KernelSU Manager signature hash: $(KSU_EXPECTED_HASH)) diff --git a/kernel/apk_sign.c b/kernel/apk_sign.c index f58b1133..1875a908 100644 --- a/kernel/apk_sign.c +++ b/kernel/apk_sign.c @@ -216,7 +216,9 @@ static int parse_apk_signature(char *path, bool check_multi_manager, int *signat unsigned char buffer[0x11] = { 0 }; u32 size4; u64 size8, size_of_block; + loff_t pos; + bool v2_signing_valid = false; int v2_signing_blocks = 0; bool v3_signing_exist = false; @@ -391,4 +393,4 @@ module_param_cb(ksu_debug_manager_uid, &expected_size_ops, bool is_manager_apk(char *path) { return check_v2_signature(path); -} \ No newline at end of file +} diff --git a/kernel/apk_sign.h b/kernel/apk_sign.h index a7147639..e8997752 100644 --- a/kernel/apk_sign.h +++ b/kernel/apk_sign.h @@ -6,4 +6,4 @@ bool is_manager_apk(char *path); -#endif \ No newline at end of file +#endif diff --git a/kernel/core_hook.c b/kernel/core_hook.c index d5970ad1..2d6103b6 100644 --- a/kernel/core_hook.c +++ b/kernel/core_hook.c @@ -51,8 +51,10 @@ static bool ksu_module_mounted = false; +// selinux/rules.c extern int handle_sepolicy(unsigned long arg3, void __user *arg4); +// sucompat.c static bool ksu_su_compat_enabled = true; extern void ksu_sucompat_init(); extern void ksu_sucompat_exit(); @@ -63,10 +65,10 @@ static inline bool is_allow_su() // we are manager, allow! return true; } - return ksu_is_allow_uid(current_uid().val); + return ksu_is_allow_uid(ksu_current_uid()); } -static inline bool is_unsupported_app_uid(uid_t uid) +static inline bool is_unsupported_uid(uid_t uid) { #define LAST_APPLICATION_UID 19999 uid_t appid = uid % 100000; @@ -121,7 +123,12 @@ static void setup_groups(struct root_profile *profile, struct cred *cred) static void disable_seccomp(void) { - assert_spin_locked(¤t->sighand->siglock); + struct task_struct *tsk = get_current(); + + pr_info("%s++\n", __func__); + spin_lock_irq(&tsk->sighand->siglock); + assert_spin_locked(&tsk->sighand->siglock); + // disable seccomp #if defined(CONFIG_GENERIC_ENTRY) && \ LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) @@ -131,40 +138,56 @@ static void disable_seccomp(void) #endif #ifdef CONFIG_SECCOMP - current->seccomp.mode = 0; - current->seccomp.filter = NULL; + tsk->seccomp.mode = 0; + if (tsk->seccomp.filter == NULL) { + pr_warn("tsk->seccomp.filter is NULL already!\n"); + goto out; + } + + // 5.9+ have filter_count and use seccomp_filter_release +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) + seccomp_filter_release(tsk); + atomic_set(&tsk->seccomp.filter_count, 0); #else + put_seccomp_filter(tsk); + tsk->seccomp.filter = NULL; #endif +#endif + +out: + spin_unlock_irq(&tsk->sighand->siglock); + pr_info("%s--\n", __func__); } void escape_to_root(void) { - struct cred *cred; - - cred = prepare_creds(); - if (!cred) { + struct cred *newcreds = prepare_creds(); + if (newcreds == NULL) { pr_err("%s: failed to allocate new cred.\n", __func__); return; } - if (cred->euid.val == 0) { + if (ksu_cred_euid(newcreds) == 0) { pr_warn("Already root, don't escape!\n"); - abort_creds(cred); + abort_creds(newcreds); return; } - struct root_profile *profile = ksu_get_root_profile(cred->uid.val); + struct root_profile *profile = + ksu_get_root_profile(ksu_cred_uid(newcreds)); - cred->uid.val = profile->uid; - cred->suid.val = profile->uid; - cred->euid.val = profile->uid; - cred->fsuid.val = profile->uid; + ksu_cred_uid(newcreds) = profile->uid; + ksu_cred_suid(newcreds) = profile->uid; + ksu_cred_euid(newcreds) = profile->uid; + ksu_cred_fsuid(newcreds) = profile->uid; - cred->gid.val = profile->gid; - cred->fsgid.val = profile->gid; - cred->sgid.val = profile->gid; - cred->egid.val = profile->gid; - cred->securebits = 0; + ksu_cred_gid(newcreds) = profile->gid; + ksu_cred_fsgid(newcreds) = profile->gid; + ksu_cred_sgid(newcreds) = profile->gid; + ksu_cred_egid(newcreds) = profile->gid; + + // no wrapper, ignore it. + newcreds->securebits = 0; BUILD_BUG_ON(sizeof(profile->capabilities.effective) != sizeof(kernel_cap_t)); @@ -174,23 +197,17 @@ void escape_to_root(void) // we add it here but don't add it to cap_inhertiable, it would be dropped automaticly after exec! u64 cap_for_ksud = profile->capabilities.effective | CAP_DAC_READ_SEARCH; - memcpy(&cred->cap_effective, &cap_for_ksud, - sizeof(cred->cap_effective)); - memcpy(&cred->cap_permitted, &profile->capabilities.effective, - sizeof(cred->cap_permitted)); - memcpy(&cred->cap_bset, &profile->capabilities.effective, - sizeof(cred->cap_bset)); + memcpy(&newcreds->cap_effective, &cap_for_ksud, + sizeof(newcreds->cap_effective)); + memcpy(&newcreds->cap_permitted, &profile->capabilities.effective, + sizeof(newcreds->cap_permitted)); + memcpy(&newcreds->cap_bset, &profile->capabilities.effective, + sizeof(newcreds->cap_bset)); - setup_groups(profile, cred); - - commit_creds(cred); - - // Refer to kernel/seccomp.c: seccomp_set_mode_strict - // When disabling Seccomp, ensure that current->sighand->siglock is held during the operation. - spin_lock_irq(¤t->sighand->siglock); + setup_groups(profile, newcreds); + commit_creds(newcreds); + disable_seccomp(); - spin_unlock_irq(¤t->sighand->siglock); - setup_selinux(profile->selinux_domain); } @@ -201,7 +218,7 @@ int ksu_handle_rename(struct dentry *old_dentry, struct dentry *new_dentry) return 0; } - if (current_uid().val != 1000) { + if (ksu_current_uid() != 1000) { // skip non system uid return 0; } @@ -269,14 +286,14 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3, } // TODO: find it in throne tracker! - uid_t current_uid_val = current_uid().val; + uid_t current_uid_val = ksu_current_uid(); uid_t manager_uid = ksu_get_manager_uid(); if (current_uid_val != manager_uid && current_uid_val % 100000 == manager_uid) { ksu_set_manager_uid(current_uid_val); } - bool from_root = 0 == current_uid().val; + bool from_root = 0 == ksu_current_uid(); bool from_manager = is_manager(); if (!from_root && !from_manager) { @@ -300,7 +317,7 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3, if (arg2 == CMD_GRANT_ROOT) { if (is_allow_su()) { - pr_info("allow root for: %d\n", current_uid().val); + pr_info("allow root for: %d\n", ksu_current_uid()); escape_to_root(); if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) { pr_err("grant_root: prctl reply error\n"); @@ -499,8 +516,6 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3, const char *hook_type; #if defined(CONFIG_KSU_KPROBES_HOOK) - - hook_type = "Kprobes"; #elif defined(CONFIG_KSU_TRACEPOINT_HOOK) hook_type = "Tracepoint"; @@ -598,7 +613,7 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3, bool enabled = (arg3 != 0); if (enabled == ksu_su_compat_enabled) { pr_info("cmd enable su but no need to change.\n"); - if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {// return the reply_ok directly + if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) { pr_err("prctl reply error, cmd: %lu\n", arg2); } return 0; @@ -617,13 +632,14 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3, return 0; } -static bool is_non_appuid(kuid_t uid) +static bool is_appuid(kuid_t uid) { #define PER_USER_RANGE 100000 #define FIRST_APPLICATION_UID 10000 +#define LAST_APPLICATION_UID 19999 uid_t appid = uid.val % PER_USER_RANGE; - return appid < FIRST_APPLICATION_UID; + return appid >= FIRST_APPLICATION_UID && appid <= LAST_APPLICATION_UID; } static bool should_umount(struct path *path) @@ -634,7 +650,7 @@ static bool should_umount(struct path *path) if (current->nsproxy->mnt_ns == init_nsproxy.mnt_ns) { pr_info("ignore global mnt namespace process: %d\n", - current_uid().val); + ksu_current_uid()); return false; } @@ -651,8 +667,8 @@ static void ksu_path_umount(const char *mnt, struct path *path, int flags) int ret = path_umount(path, flags); pr_info("%s: path: %s ret: %d\n", __func__, mnt, ret); } +#define ksu_umount_mnt(mnt, path, flags) (ksu_path_umount(mnt, path, flags)) #else -// TODO: Search a way to make this works without set_fs functions static void ksu_sys_umount(const char *mnt, int flags) { char __user *usermnt = (char __user *)mnt; @@ -669,7 +685,14 @@ static void ksu_sys_umount(const char *mnt, int flags) set_fs(old_fs); pr_info("%s: path: %s ret: %d\n", __func__, usermnt, ret); } -#endif + +#define ksu_umount_mnt(mnt, __unused, flags) \ + ({ \ + path_put(__unused); \ + ksu_sys_umount(mnt, flags); \ + }) + +#endif static void try_umount(const char *mnt, bool check_mnt, int flags) { @@ -691,11 +714,7 @@ static void try_umount(const char *mnt, bool check_mnt, int flags) return; } -#ifdef KSU_HAS_PATH_UMOUNT - ksu_path_umount(mnt, &path, flags); -#else - ksu_sys_umount(mnt, flags); -#endif + ksu_umount_mnt(mnt, &path, flags); } int ksu_handle_setuid(struct cred *new, const struct cred *old) @@ -717,33 +736,29 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old) return 0; } - if (is_non_appuid(new_uid)) { -#ifdef CONFIG_KSU_DEBUG - pr_info("handle setuid ignore non application uid: %d\n", new_uid.val); -#endif + if (!is_appuid(new_uid) || is_unsupported_uid(new_uid.val)) { + // pr_info("handle setuid ignore non application or isolated uid: %d\n", new_uid.val); return 0; } - // isolated process may be directly forked from zygote, always unmount - if (is_unsupported_app_uid(new_uid.val)) { -#ifdef CONFIG_KSU_DEBUG - pr_info("handle umount for unsupported application uid: %d\n", new_uid.val); -#endif - goto do_umount; - } - if (ksu_is_allow_uid(new_uid.val)) { -#ifdef CONFIG_KSU_DEBUG - pr_info("handle setuid ignore allowed application: %d\n", new_uid.val); -#endif + // pr_info("handle setuid ignore allowed application: %d\n", new_uid.val); return 0; } -do_umount: + if (!ksu_uid_should_umount(new_uid.val)) { + return 0; + } else { +#ifdef CONFIG_KSU_DEBUG + pr_info("uid: %d should not umount!\n", current_uid().val); +#endif + } + // check old process's selinux context, if it is not zygote, ignore it! // because some su apps may setuid to untrusted_app but they are in global mount namespace // when we umount for such process, that is a disaster! - if (!is_zygote(old->security)) { + bool is_zygote_child = is_zygote(old->security); + if (!is_zygote_child) { pr_info("handle umount ignore non zygote child: %d\n", current->pid); return 0; diff --git a/kernel/include/ksu_creds.h b/kernel/include/ksu_creds.h new file mode 100644 index 00000000..bdcba952 --- /dev/null +++ b/kernel/include/ksu_creds.h @@ -0,0 +1,39 @@ +/* + * KernelSU creds wrapper + * + * Provide a wrapper for a few credentials use (e.g current_uid().val), + * so it would be easier to maintain + * some older linux versions. + */ + +#ifndef __KSU_H_CREDS +#define __KSU_H_CREDS + +#include +#include + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) && \ + defined(CONFIG_UIDGID_STRICT_TYPE_CHECKS)) || \ + LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) +#define ksu_cred_uid(x) ((x)->uid.val) +#define ksu_cred_suid(x) ((x)->suid.val) +#define ksu_cred_euid(x) ((x)->euid.val) +#define ksu_cred_fsuid(x) ((x)->fsuid.val) +#define ksu_cred_gid(x) ((x)->gid.val) +#define ksu_cred_fsgid(x) ((x)->fsgid.val) +#define ksu_cred_sgid(x) ((x)->sgid.val) +#define ksu_cred_egid(x) ((x)->egid.val) +#define ksu_current_uid() (current_uid().val) +#else +#define ksu_cred_uid(x) ((x)->uid) +#define ksu_cred_suid(x) ((x)->suid) +#define ksu_cred_euid(x) ((x)->euid) +#define ksu_cred_fsuid(x) ((x)->fsuid) +#define ksu_cred_gid(x) ((x)->gid) +#define ksu_cred_fsgid(x) ((x)->fsgid) +#define ksu_cred_sgid(x) ((x)->sgid) +#define ksu_cred_egid(x) ((x)->egid) +#define ksu_current_uid() (current_uid()) +#endif + +#endif diff --git a/kernel/kernel_compat.c b/kernel/kernel_compat.c index 0875ca10..fb10951a 100644 --- a/kernel/kernel_compat.c +++ b/kernel/kernel_compat.c @@ -178,3 +178,33 @@ long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr, return ret; } #endif + +long ksu_strncpy_from_user_retry(char *dst, const void __user *unsafe_addr, + long count) +{ + long ret; + + 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))) { +#ifdef CONFIG_KSU_DEBUG + pr_err("%s: faulted!\n", __func__); +#endif + return -EFAULT; + } + + // why we don't do like how strncpy_from_user_nofault? + ret = strncpy_from_user(dst, unsafe_addr, count); + + if (ret >= count) { + ret = count; + dst[ret - 1] = '\0'; + } else if (likely(ret >= 0)) { + ret++; + } + + return ret; +} diff --git a/kernel/kernel_compat.h b/kernel/kernel_compat.h index 19227a36..cf262d42 100644 --- a/kernel/kernel_compat.h +++ b/kernel/kernel_compat.h @@ -31,6 +31,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) || \ @@ -47,9 +50,9 @@ extern ssize_t ksu_kernel_write_compat(struct file *p, const void *buf, size_t count, loff_t *pos); #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) -#define ksu_access_ok(addr, size) (access_ok(addr, size)) +#define ksu_access_ok(addr, size) access_ok(addr, size) #else -#define ksu_access_ok(addr, size) (access_ok(VERIFY_READ, addr, size)) +#define ksu_access_ok(addr, size) access_ok(VERIFY_READ, addr, size) #endif #endif diff --git a/kernel/ksud.c b/kernel/ksud.c index 37dbc2cb..da8a43a0 100644 --- a/kernel/ksud.c +++ b/kernel/ksud.c @@ -200,7 +200,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("/system/bin/init first arg: %s\n", first_arg); @@ -225,7 +225,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")) { @@ -250,7 +250,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 diff --git a/kernel/manager.h b/kernel/manager.h index 37bafbe8..c7304e83 100644 --- a/kernel/manager.h +++ b/kernel/manager.h @@ -20,7 +20,7 @@ static inline bool ksu_is_manager_uid_valid() static inline bool is_manager() { - return unlikely(ksu_is_any_manager(current_uid().val) || ksu_manager_uid == current_uid().val); + return unlikely(ksu_is_any_manager(ksu_current_uid()) || ksu_manager_uid == ksu_current_uid()); } static inline uid_t ksu_get_manager_uid() diff --git a/kernel/setup.sh b/kernel/setup.sh index d013bfe2..fe53fcd8 100755 --- a/kernel/setup.sh +++ b/kernel/setup.sh @@ -41,8 +41,7 @@ setup_kernelsu() { echo "[+] Setting up KernelSU..." # Clone the repository and rename it to KernelSU if [ ! -d "$GKI_ROOT/KernelSU" ]; then - git clone https://github.com/SukiSU-Ultra/SukiSU-Ultra SukiSU-Ultra - mv SukiSU-Ultra KernelSU + git clone https://github.com/SukiSU-Ultra/SukiSU-Ultra KernelSU echo "[+] Repository cloned and renamed to KernelSU." fi cd "$GKI_ROOT/KernelSU" diff --git a/kernel/sucompat.c b/kernel/sucompat.c index 828f6af3..8b20b1a4 100644 --- a/kernel/sucompat.c +++ b/kernel/sucompat.c @@ -26,7 +26,7 @@ #define SH_PATH "/system/bin/sh" static const char su[] = SU_PATH; -const char ksud_path[] = KSUD_PATH; +static const char ksud_path[] = KSUD_PATH; extern void escape_to_root(); @@ -52,127 +52,91 @@ static inline char __user *ksud_user_path(void) return userspace_stack_buffer(ksud_path, sizeof(ksud_path)); } -int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, - int *__unused_flags) +static inline bool __is_su_allowed(const void *ptr_to_check) { #ifndef CONFIG_KSU_KPROBES_HOOK - if (!ksu_sucompat_hook_state) { - return 0; - } + if (!ksu_sucompat_hook_state) + return false; #endif + if (likely(!ksu_is_allow_uid(ksu_current_uid()))) + return false; - if (!ksu_is_allow_uid(current_uid().val)) { - return 0; - } + if (unlikely(!ptr_to_check)) + return false; - char path[sizeof(su) + 1]; + return true; +} +#define is_su_allowed(ptr) __is_su_allowed((const void *)ptr) + +static int ksu_sucompat_user_common(const char __user **filename_user, + const char *syscall_name, + const bool escalate) +{ + char path[sizeof(su)]; // sizeof includes nullterm already! memset(path, 0, sizeof(path)); - ksu_strncpy_from_user_nofault(path, *filename_user, sizeof(path)); - if (unlikely(!memcmp(path, su, sizeof(su)))) { - pr_info("faccessat su->sh!\n"); + ksu_strncpy_from_user_retry(path, *filename_user, sizeof(path)); + + if (memcmp(path, su, sizeof(su))) + return 0; + + if (escalate) { + pr_info("%s su found\n", syscall_name); + *filename_user = ksud_user_path(); + escape_to_root(); // escalate !! + } else { + pr_info("%s su->sh!\n", syscall_name); *filename_user = sh_user_path(); } return 0; } +int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *__unused_flags) +{ + if (!is_su_allowed(filename_user)) + return 0; + + return ksu_sucompat_user_common(filename_user, "faccessat", false); +} + int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags) { -#ifndef CONFIG_KSU_KPROBES_HOOK - if (!ksu_sucompat_hook_state) { - return 0; - } -#endif - - if (!ksu_is_allow_uid(current_uid().val)) { - return 0; - } - - if (unlikely(!filename_user)) { - return 0; - } - - char path[sizeof(su) + 1]; - memset(path, 0, sizeof(path)); - - ksu_strncpy_from_user_nofault(path, *filename_user, sizeof(path)); - - if (unlikely(!memcmp(path, su, sizeof(su)))) { - pr_info("newfstatat su->sh!\n"); - *filename_user = sh_user_path(); - } - - return 0; -} - -// the call from execve_handler_pre won't provided correct value for __never_use_argument, use them after fix execve_handler_pre, keeping them for consistence for manually patched code -int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr, - void *__never_use_argv, void *__never_use_envp, - int *__never_use_flags) -{ - struct filename *filename; -#ifndef CONFIG_KSU_KPROBES_HOOK - if (!ksu_sucompat_hook_state) { - return 0; - } -#endif - - if (unlikely(!filename_ptr)) + if (!is_su_allowed(filename_user)) return 0; - filename = *filename_ptr; - if (IS_ERR(filename)) { - return 0; - } - - if (likely(memcmp(filename->name, su, sizeof(su)))) - return 0; - - if (!ksu_is_allow_uid(current_uid().val)) - return 0; - - pr_info("do_execveat_common su found\n"); - memcpy((void *)filename->name, ksud_path, sizeof(ksud_path)); - - escape_to_root(); - - return 0; + return ksu_sucompat_user_common(filename_user, "newfstatat", false); } int ksu_handle_execve_sucompat(int *fd, const char __user **filename_user, void *__never_use_argv, void *__never_use_envp, int *__never_use_flags) { - char path[sizeof(su) + 1]; - - if (unlikely(!filename_user)) + if (!is_su_allowed(filename_user)) return 0; - /* - * 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 (!ksu_access_ok(*filename_user, sizeof(path))) + return ksu_sucompat_user_common(filename_user, "sys_execve", true); +} + +int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr, + void *__never_use_argv, void *__never_use_envp, + int *__never_use_flags) +{ + struct filename *filename; + + if (!is_su_allowed(filename_ptr)) return 0; - // success = returns number of bytes and should be less than path - long len = strncpy_from_user(path, *filename_user, sizeof(path)); - if (len <= 0) + filename = *filename_ptr; + if (IS_ERR(filename)) return 0; - // strncpy_from_user_nofault does this too - path[sizeof(path) - 1] = '\0'; - - if (likely(memcmp(path, su, sizeof(su)))) + if (likely(memcmp(filename->name, su, sizeof(su)))) return 0; - if (!ksu_is_allow_uid(current_uid().val)) - return 0; - - pr_info("sys_execve su found\n"); - *filename_user = ksud_user_path(); + pr_info("do_execveat_common su found\n"); + memcpy((void *)filename->name, ksud_path, sizeof(ksud_path)); escape_to_root(); @@ -185,7 +149,7 @@ static int ksu_inline_handle_devpts(struct inode *inode) return 0; } - uid_t uid = current_uid().val; + uid_t uid = ksu_current_uid(); if (uid % 100000 < 10000) { // not untrusted_app, ignore it return 0; @@ -212,9 +176,8 @@ static int ksu_inline_handle_devpts(struct inode *inode) int __ksu_handle_devpts(struct inode *inode) { #ifndef CONFIG_KSU_KPROBES_HOOK - if (!ksu_sucompat_hook_state) { + if (!ksu_sucompat_hook_state) return 0; - } #endif return ksu_inline_handle_devpts(inode); }