diff --git a/kernel/ksud.c b/kernel/ksud.c index dc94ad11..09f465f3 100644 --- a/kernel/ksud.c +++ b/kernel/ksud.c @@ -68,6 +68,10 @@ u32 ksu_devpts_sid; // Detect whether it is on or not static bool is_boot_phase = true; +#ifdef CONFIG_COMPAT +bool ksu_is_compat __read_mostly = false; +#endif + void ksu_on_post_fs_data(void) { static bool done = false; @@ -111,6 +115,7 @@ static const char __user *get_user_arg_ptr(struct user_arg_ptr argv, int nr) if (get_user(compat, argv.ptr.compat + nr)) return ERR_PTR(-EFAULT); + ksu_is_compat = true; return compat_ptr(compat); } #endif diff --git a/kernel/selinux/rules.c b/kernel/selinux/rules.c index 0532996b..f658a049 100644 --- a/kernel/selinux/rules.c +++ b/kernel/selinux/rules.c @@ -157,17 +157,45 @@ void ksu_apply_kernelsu_rules() #define CMD_TYPE_CHANGE 8 #define CMD_GENFSCON 9 +#ifdef CONFIG_64BIT struct sepol_data { u32 cmd; u32 subcmd; - char __user *sepol1; - char __user *sepol2; - char __user *sepol3; - char __user *sepol4; - char __user *sepol5; - char __user *sepol6; - char __user *sepol7; + u64 field_sepol1; + u64 field_sepol2; + u64 field_sepol3; + u64 field_sepol4; + u64 field_sepol5; + u64 field_sepol6; + u64 field_sepol7; }; +#ifdef CONFIG_COMPAT +extern bool ksu_is_compat __read_mostly; +struct sepol_compat_data { + u32 cmd; + u32 subcmd; + u32 field_sepol1; + u32 field_sepol2; + u32 field_sepol3; + u32 field_sepol4; + u32 field_sepol5; + u32 field_sepol6; + u32 field_sepol7; +}; +#endif // CONFIG_COMPAT +#else +struct sepol_data { + u32 cmd; + u32 subcmd; + u32 field_sepol1; + u32 field_sepol2; + u32 field_sepol3; + u32 field_sepol4; + u32 field_sepol5; + u32 field_sepol6; + u32 field_sepol7; +}; +#endif // CONFIG_64BIT static int get_object(char *buf, char __user *user_object, size_t buf_sz, char **object) @@ -212,14 +240,61 @@ int ksu_handle_sepolicy(unsigned long arg3, void __user *arg4) pr_info("SELinux permissive or disabled when handle policy!\n"); } + u32 cmd, subcmd; + char __user *sepol1, *sepol2, *sepol3, *sepol4, *sepol5, *sepol6, *sepol7; + +#if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT) + if (unlikely(ksu_is_compat)) { + struct sepol_compat_data compat_data; + if (copy_from_user(&compat_data, arg4, sizeof(struct sepol_compat_data))) { + pr_err("sepol: copy sepol_data failed.\n"); + return -1; + } + sepol1 = compat_ptr(compat_data.field_sepol1); + sepol2 = compat_ptr(compat_data.field_sepol2); + sepol3 = compat_ptr(compat_data.field_sepol3); + sepol4 = compat_ptr(compat_data.field_sepol4); + sepol5 = compat_ptr(compat_data.field_sepol5); + sepol6 = compat_ptr(compat_data.field_sepol6); + sepol7 = compat_ptr(compat_data.field_sepol7); + cmd = compat_data.cmd; + subcmd = compat_data.subcmd; + } else { + struct sepol_data data; + if (copy_from_user(&data, arg4, sizeof(struct sepol_data))) { + pr_err("sepol: copy sepol_data failed.\n"); + return -1; + } + sepol1 = data.field_sepol1; + sepol2 = data.field_sepol2; + sepol3 = data.field_sepol3; + sepol4 = data.field_sepol4; + sepol5 = data.field_sepol5; + sepol6 = data.field_sepol6; + sepol7 = data.field_sepol7; + cmd = data.cmd; + subcmd = data.subcmd; + } +#else + // basically for full native, say (64BIT=y COMPAT=n) || (64BIT=n) + struct sepol_data data; if (copy_from_user(&data, arg4, sizeof(struct sepol_data))) { pr_err("sepol: copy sepol_data failed.\n"); return -1; } - u32 cmd = data.cmd; - u32 subcmd = data.subcmd; + + sepol1 = data.field_sepol1; + sepol2 = data.field_sepol2; + sepol3 = data.field_sepol3; + sepol4 = data.field_sepol4; + sepol5 = data.field_sepol5; + sepol6 = data.field_sepol6; + sepol7 = data.field_sepol7; + cmd = data.cmd; + subcmd = data.subcmd; +#endif rcu_read_lock(); @@ -233,22 +308,22 @@ int ksu_handle_sepolicy(unsigned long arg3, void __user *arg4) char perm_buf[MAX_SEPOL_LEN]; char *s, *t, *c, *p; - if (get_object(src_buf, data.sepol1, sizeof(src_buf), &s) < 0) { + if (get_object(src_buf, sepol1, sizeof(src_buf), &s) < 0) { pr_err("sepol: copy src failed.\n"); goto exit; } - if (get_object(tgt_buf, data.sepol2, sizeof(tgt_buf), &t) < 0) { + if (get_object(tgt_buf, sepol2, sizeof(tgt_buf), &t) < 0) { pr_err("sepol: copy tgt failed.\n"); goto exit; } - if (get_object(cls_buf, data.sepol3, sizeof(cls_buf), &c) < 0) { + if (get_object(cls_buf, sepol3, sizeof(cls_buf), &c) < 0) { pr_err("sepol: copy cls failed.\n"); goto exit; } - if (get_object(perm_buf, data.sepol4, sizeof(perm_buf), &p) < + if (get_object(perm_buf, sepol4, sizeof(perm_buf), &p) < 0) { pr_err("sepol: copy perm failed.\n"); goto exit; @@ -278,24 +353,24 @@ int ksu_handle_sepolicy(unsigned long arg3, void __user *arg4) char perm_set[MAX_SEPOL_LEN]; char *s, *t, *c; - if (get_object(src_buf, data.sepol1, sizeof(src_buf), &s) < 0) { + if (get_object(src_buf, sepol1, sizeof(src_buf), &s) < 0) { pr_err("sepol: copy src failed.\n"); goto exit; } - if (get_object(tgt_buf, data.sepol2, sizeof(tgt_buf), &t) < 0) { + if (get_object(tgt_buf, sepol2, sizeof(tgt_buf), &t) < 0) { pr_err("sepol: copy tgt failed.\n"); goto exit; } - if (get_object(cls_buf, data.sepol3, sizeof(cls_buf), &c) < 0) { + if (get_object(cls_buf, sepol3, sizeof(cls_buf), &c) < 0) { pr_err("sepol: copy cls failed.\n"); goto exit; } - if (strncpy_from_user(operation, data.sepol4, + if (strncpy_from_user(operation, sepol4, sizeof(operation)) < 0) { pr_err("sepol: copy operation failed.\n"); goto exit; } - if (strncpy_from_user(perm_set, data.sepol5, sizeof(perm_set)) < + if (strncpy_from_user(perm_set, sepol5, sizeof(perm_set)) < 0) { pr_err("sepol: copy perm_set failed.\n"); goto exit; @@ -315,7 +390,7 @@ int ksu_handle_sepolicy(unsigned long arg3, void __user *arg4) } else if (cmd == CMD_TYPE_STATE) { char src[MAX_SEPOL_LEN]; - if (strncpy_from_user(src, data.sepol1, sizeof(src)) < 0) { + if (strncpy_from_user(src, sepol1, sizeof(src)) < 0) { pr_err("sepol: copy src failed.\n"); goto exit; } @@ -335,11 +410,11 @@ int ksu_handle_sepolicy(unsigned long arg3, void __user *arg4) char type[MAX_SEPOL_LEN]; char attr[MAX_SEPOL_LEN]; - if (strncpy_from_user(type, data.sepol1, sizeof(type)) < 0) { + if (strncpy_from_user(type, sepol1, sizeof(type)) < 0) { pr_err("sepol: copy type failed.\n"); goto exit; } - if (strncpy_from_user(attr, data.sepol2, sizeof(attr)) < 0) { + if (strncpy_from_user(attr, sepol2, sizeof(attr)) < 0) { pr_err("sepol: copy attr failed.\n"); goto exit; } @@ -359,7 +434,7 @@ int ksu_handle_sepolicy(unsigned long arg3, void __user *arg4) } else if (cmd == CMD_ATTR) { char attr[MAX_SEPOL_LEN]; - if (strncpy_from_user(attr, data.sepol1, sizeof(attr)) < 0) { + if (strncpy_from_user(attr, sepol1, sizeof(attr)) < 0) { pr_err("sepol: copy attr failed.\n"); goto exit; } @@ -376,28 +451,28 @@ int ksu_handle_sepolicy(unsigned long arg3, void __user *arg4) char default_type[MAX_SEPOL_LEN]; char object[MAX_SEPOL_LEN]; - if (strncpy_from_user(src, data.sepol1, sizeof(src)) < 0) { + if (strncpy_from_user(src, sepol1, sizeof(src)) < 0) { pr_err("sepol: copy src failed.\n"); goto exit; } - if (strncpy_from_user(tgt, data.sepol2, sizeof(tgt)) < 0) { + if (strncpy_from_user(tgt, sepol2, sizeof(tgt)) < 0) { pr_err("sepol: copy tgt failed.\n"); goto exit; } - if (strncpy_from_user(cls, data.sepol3, sizeof(cls)) < 0) { + if (strncpy_from_user(cls, sepol3, sizeof(cls)) < 0) { pr_err("sepol: copy cls failed.\n"); goto exit; } - if (strncpy_from_user(default_type, data.sepol4, + if (strncpy_from_user(default_type, sepol4, sizeof(default_type)) < 0) { pr_err("sepol: copy default_type failed.\n"); goto exit; } char *real_object; - if (data.sepol5 == NULL) { + if (sepol5 == NULL) { real_object = NULL; } else { - if (strncpy_from_user(object, data.sepol5, + if (strncpy_from_user(object, sepol5, sizeof(object)) < 0) { pr_err("sepol: copy object failed.\n"); goto exit; @@ -416,19 +491,19 @@ int ksu_handle_sepolicy(unsigned long arg3, void __user *arg4) char cls[MAX_SEPOL_LEN]; char default_type[MAX_SEPOL_LEN]; - if (strncpy_from_user(src, data.sepol1, sizeof(src)) < 0) { + if (strncpy_from_user(src, sepol1, sizeof(src)) < 0) { pr_err("sepol: copy src failed.\n"); goto exit; } - if (strncpy_from_user(tgt, data.sepol2, sizeof(tgt)) < 0) { + if (strncpy_from_user(tgt, sepol2, sizeof(tgt)) < 0) { pr_err("sepol: copy tgt failed.\n"); goto exit; } - if (strncpy_from_user(cls, data.sepol3, sizeof(cls)) < 0) { + if (strncpy_from_user(cls, sepol3, sizeof(cls)) < 0) { pr_err("sepol: copy cls failed.\n"); goto exit; } - if (strncpy_from_user(default_type, data.sepol4, + if (strncpy_from_user(default_type, sepol4, sizeof(default_type)) < 0) { pr_err("sepol: copy default_type failed.\n"); goto exit; @@ -449,15 +524,15 @@ int ksu_handle_sepolicy(unsigned long arg3, void __user *arg4) char name[MAX_SEPOL_LEN]; char path[MAX_SEPOL_LEN]; char context[MAX_SEPOL_LEN]; - if (strncpy_from_user(name, data.sepol1, sizeof(name)) < 0) { + if (strncpy_from_user(name, sepol1, sizeof(name)) < 0) { pr_err("sepol: copy name failed.\n"); goto exit; } - if (strncpy_from_user(path, data.sepol2, sizeof(path)) < 0) { + if (strncpy_from_user(path, sepol2, sizeof(path)) < 0) { pr_err("sepol: copy path failed.\n"); goto exit; } - if (strncpy_from_user(context, data.sepol3, sizeof(context)) < + if (strncpy_from_user(context, sepol3, sizeof(context)) < 0) { pr_err("sepol: copy context failed.\n"); goto exit; diff --git a/kernel/sucompat.c b/kernel/sucompat.c index f32be66d..a4e914e7 100644 --- a/kernel/sucompat.c +++ b/kernel/sucompat.c @@ -37,6 +37,10 @@ bool ksu_devpts_hook __read_mostly = true; extern void ksu_escape_to_root(); +#ifndef CONFIG_KSU_HOOK_KPROBES +static bool ksu_sucompat_non_kp __read_mostly = true; +#endif + static void __user *userspace_stack_buffer(const void *d, size_t len) { /* To avoid having to mmap a page in userspace, just write below the stack @@ -63,6 +67,12 @@ int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, { const char su[] = SU_PATH; +#ifndef CONFIG_KSU_HOOK_KPROBES + if (!ksu_sucompat_non_kp) { + return 0; + } +#endif + #ifndef CONFIG_KSU_HOOK_KPROBES if (!ksu_faccessat_hook) { return 0; @@ -114,6 +124,12 @@ int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags) // const char sh[] = SH_PATH; const char su[] = SU_PATH; +#ifndef CONFIG_KSU_HOOK_KPROBES + if (!ksu_sucompat_non_kp) { + return 0; + } +#endif + #ifndef CONFIG_KSU_HOOK_KPROBES if (!ksu_stat_hook){ return 0; @@ -160,6 +176,13 @@ int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr, void * struct filename *filename; const char su[] = SU_PATH; const char ksud[] = KSUD_PATH; + +#ifndef CONFIG_KSU_HOOK_KPROBES + if (!ksu_sucompat_non_kp) { + return 0; + } +#endif + #ifndef CONFIG_KSU_HOOK_KPROBES if (!ksu_execveat_sucompat_hook) { return 0; @@ -195,6 +218,13 @@ int ksu_handle_execve_sucompat(int *fd, const char __user **filename_user, void const char su[] = SU_PATH; char path[sizeof(su) + 1]; + +#ifndef CONFIG_KSU_HOOK_KPROBES + if (!ksu_sucompat_non_kp){ + return 0; + } +#endif + #ifndef CONFIG_KSU_HOOK_KPROBES if (!ksu_execve_sucompat_hook) { return 0; @@ -350,6 +380,7 @@ void ksu_sucompat_init() ksu_execve_sucompat_hook = true; ksu_execveat_sucompat_hook = true; ksu_devpts_hook = true; + ksu_sucompat_non_kp = true; pr_info("ksu_sucompat_init: hooks enabled: execve/execveat_su, faccessat, stat, devpts\n"); #endif } @@ -367,6 +398,7 @@ void ksu_sucompat_exit() ksu_execve_sucompat_hook = false; ksu_execveat_sucompat_hook = false; ksu_devpts_hook = false; + ksu_sucompat_non_kp = false; pr_info("ksu_sucompat_exit: hooks disabled: execve/execveat_su, faccessat, stat, devpts\n"); #endif } diff --git a/kernel/throne_tracker.c b/kernel/throne_tracker.c index ef611e9e..f47b13b3 100644 --- a/kernel/throne_tracker.c +++ b/kernel/throne_tracker.c @@ -361,12 +361,14 @@ void ksu_track_throne() if (ksu_is_manager_uid_valid()) { pr_info("manager is uninstalled, invalidate it!\n"); ksu_invalidate_manager_uid(); + goto prune; } pr_info("Searching manager...\n"); search_manager("/data/app", 2, &uid_list); pr_info("Search manager finished\n"); } - + +prune: // then prune the allowlist ksu_prune_allowlist(is_uid_exist, &uid_list); out: