From b427c86ab30f017f46a6a737ec3a0cf81b00e0a8 Mon Sep 17 00:00:00 2001 From: weishu Date: Tue, 27 Dec 2022 18:21:10 +0700 Subject: [PATCH] misc: code format(use kernel code stype: https://www.kernel.org/doc/html/v6.1/process/coding-style.html --- kernel/allowlist.c | 325 +++++++-------- kernel/allowlist.h | 2 +- kernel/apk_sign.c | 182 +++++---- kernel/arch.h | 4 +- kernel/ksu.c | 114 +++--- kernel/selinux/rules.c | 8 +- kernel/selinux/selinux.c | 55 +-- kernel/selinux/sepolicy.c | 820 +++++++++++++++++++++----------------- kernel/sucompat.c | 157 ++++---- 9 files changed, 903 insertions(+), 764 deletions(-) diff --git a/kernel/allowlist.c b/kernel/allowlist.c index 32681710..f1e59d14 100644 --- a/kernel/allowlist.c +++ b/kernel/allowlist.c @@ -26,9 +26,9 @@ #define FILE_FORMAT_VERSION 1 // u32 struct perm_data { - struct list_head list; - uid_t uid; - bool allow; + struct list_head list; + uid_t uid; + bool allow; }; static struct list_head allow_list; @@ -41,210 +41,221 @@ static struct work_struct ksu_load_work; bool persistent_allow_list(void); -bool ksu_allow_uid(uid_t uid, bool allow) { +bool ksu_allow_uid(uid_t uid, bool allow) +{ + // find the node first! + struct perm_data *p = NULL; + struct list_head *pos = NULL; + bool result = false; + list_for_each (pos, &allow_list) { + p = list_entry(pos, struct perm_data, list); + pr_info("ksu_allow_uid :%d, allow: %d\n", p->uid, p->allow); + if (uid == p->uid) { + p->allow = allow; + result = true; + goto exit; + } + } - // find the node first! - struct perm_data *p = NULL; - struct list_head *pos = NULL; - bool result = false; - list_for_each(pos, &allow_list) { - p = list_entry(pos, struct perm_data, list); - pr_info("ksu_allow_uid :%d, allow: %d\n", p->uid, p->allow); - if (uid == p->uid) { - p->allow = allow; - result = true; - goto exit; - } - } + // not found, alloc a new node! + p = (struct perm_data *)kmalloc(sizeof(struct perm_data), GFP_KERNEL); + if (!p) { + pr_err("alloc allow node failed.\n"); + return false; + } + p->uid = uid; + p->allow = allow; - // not found, alloc a new node! - p = (struct perm_data *)kmalloc(sizeof(struct perm_data), GFP_KERNEL); - if (!p) { - pr_err("alloc allow node failed.\n"); - return false; - } - p->uid = uid; - p->allow = allow; - - list_add_tail(&p->list, &allow_list); - result = true; + list_add_tail(&p->list, &allow_list); + result = true; exit: - persistent_allow_list(); + persistent_allow_list(); - return result; + return result; } -bool ksu_is_allow_uid(uid_t uid) { - struct perm_data *p = NULL; - struct list_head *pos = NULL; +bool ksu_is_allow_uid(uid_t uid) +{ + struct perm_data *p = NULL; + struct list_head *pos = NULL; - if (uid == 0) { - // already root, but only allow our domain. - return is_ksu_domain(); - } + if (uid == 0) { + // already root, but only allow our domain. + return is_ksu_domain(); + } - list_for_each(pos, &allow_list) { - p = list_entry(pos, struct perm_data, list); - // pr_info("is_allow_uid uid :%d, allow: %d\n", p->uid, p->allow); - if (uid == p->uid) { - return p->allow; - } - } + list_for_each (pos, &allow_list) { + p = list_entry(pos, struct perm_data, list); + // pr_info("is_allow_uid uid :%d, allow: %d\n", p->uid, p->allow); + if (uid == p->uid) { + return p->allow; + } + } - return false; + return false; } -bool ksu_get_allow_list(int *array, int *length, bool allow) { - struct perm_data *p = NULL; - struct list_head *pos = NULL; - int i = 0; - list_for_each(pos, &allow_list) { - p = list_entry(pos, struct perm_data, list); - pr_info("get_allow_list uid: %d allow: %d\n", p->uid, p->allow); - if (p->allow == allow) { - array[i++] = p->uid; - } - } - *length = i; +bool ksu_get_allow_list(int *array, int *length, bool allow) +{ + struct perm_data *p = NULL; + struct list_head *pos = NULL; + int i = 0; + list_for_each (pos, &allow_list) { + p = list_entry(pos, struct perm_data, list); + pr_info("get_allow_list uid: %d allow: %d\n", p->uid, p->allow); + if (p->allow == allow) { + array[i++] = p->uid; + } + } + *length = i; - return true; + return true; } -void do_persistent_allow_list(struct work_struct *work) { - u32 magic = FILE_MAGIC; - u32 version = FILE_FORMAT_VERSION; - struct perm_data *p = NULL; - struct list_head *pos = NULL; - loff_t off = 0; +void do_persistent_allow_list(struct work_struct *work) +{ + u32 magic = FILE_MAGIC; + u32 version = FILE_FORMAT_VERSION; + struct perm_data *p = NULL; + struct list_head *pos = NULL; + loff_t off = 0; - struct file *fp = filp_open(KERNEL_SU_ALLOWLIST, O_WRONLY | O_CREAT, 0644); + struct file *fp = + filp_open(KERNEL_SU_ALLOWLIST, O_WRONLY | O_CREAT, 0644); - if (IS_ERR(fp)) { - pr_err("save_allow_list creat file failed: %d\n", PTR_ERR(fp)); - return; - } + if (IS_ERR(fp)) { + pr_err("save_allow_list creat file failed: %d\n", PTR_ERR(fp)); + return; + } - // store magic and version - if (kernel_write(fp, &magic, sizeof(magic), &off) != sizeof(magic)) { - pr_err("save_allow_list write magic failed.\n"); - goto exit; - } + // store magic and version + if (kernel_write(fp, &magic, sizeof(magic), &off) != sizeof(magic)) { + pr_err("save_allow_list write magic failed.\n"); + goto exit; + } - if (kernel_write(fp, &version, sizeof(version), &off) != sizeof(version)) { - pr_err("save_allow_list write version failed.\n"); - goto exit; - } + if (kernel_write(fp, &version, sizeof(version), &off) != + sizeof(version)) { + pr_err("save_allow_list write version failed.\n"); + goto exit; + } - list_for_each(pos, &allow_list) { - p = list_entry(pos, struct perm_data, list); - pr_info("save allow list uid :%d, allow: %d\n", p->uid, p->allow); - kernel_write(fp, &p->uid, sizeof(p->uid), &off); - kernel_write(fp, &p->allow, sizeof(p->allow), &off); - } + list_for_each (pos, &allow_list) { + p = list_entry(pos, struct perm_data, list); + pr_info("save allow list uid :%d, allow: %d\n", p->uid, + p->allow); + kernel_write(fp, &p->uid, sizeof(p->uid), &off); + kernel_write(fp, &p->allow, sizeof(p->allow), &off); + } exit: - filp_close(fp, 0); + filp_close(fp, 0); } -void do_load_allow_list(struct work_struct *work) { +void do_load_allow_list(struct work_struct *work) +{ + loff_t off = 0; + ssize_t ret = 0; + struct file *fp = NULL; + u32 magic; + u32 version; - loff_t off = 0; - ssize_t ret = 0; - struct file *fp = NULL; - u32 magic; - u32 version; + fp = filp_open("/data/adb/", O_RDONLY, 0); + if (IS_ERR(fp)) { + int errno = PTR_ERR(fp); + pr_err("load_allow_list open '/data/adb': %d\n", PTR_ERR(fp)); + if (errno == -ENOENT) { + msleep(2000); + queue_work(ksu_workqueue, &ksu_load_work); + return; + } else { + pr_info("load_allow list dir exist now!"); + } + } else { + filp_close(fp, 0); + } - fp = filp_open("/data/adb/", O_RDONLY, 0); - if (IS_ERR(fp)) { - int errno = PTR_ERR(fp); - pr_err("load_allow_list open '/data/adb': %d\n", PTR_ERR(fp)); - if (errno == -ENOENT) { - msleep(2000); - queue_work(ksu_workqueue, &ksu_load_work); - return; - } else { - pr_info("load_allow list dir exist now!"); - } - } else { - filp_close(fp, 0); - } + // load allowlist now! + fp = filp_open(KERNEL_SU_ALLOWLIST, O_RDONLY, 0); - // load allowlist now! - fp = filp_open(KERNEL_SU_ALLOWLIST, O_RDONLY, 0); + if (IS_ERR(fp)) { + pr_err("load_allow_list open file failed: %d\n", PTR_ERR(fp)); + return; + } - if (IS_ERR(fp)) { - pr_err("load_allow_list open file failed: %d\n", PTR_ERR(fp)); - return; - } + // verify magic + if (kernel_read(fp, &magic, sizeof(magic), &off) != sizeof(magic) || + magic != FILE_MAGIC) { + pr_err("allowlist file invalid: %d!\n", magic); + goto exit; + } - // verify magic - if (kernel_read(fp, &magic, sizeof(magic), &off) != sizeof(magic) || magic != FILE_MAGIC) { - pr_err("allowlist file invalid: %d!\n", magic); - goto exit; - } + if (kernel_read(fp, &version, sizeof(version), &off) != + sizeof(version)) { + pr_err("allowlist read version: %d failed\n", version); + goto exit; + } - if (kernel_read(fp, &version, sizeof(version), &off) != sizeof(version)) { - pr_err("allowlist read version: %d failed\n", version); - goto exit; - } + pr_info("allowlist version: %d\n", version); - pr_info("allowlist version: %d\n", version); + while (true) { + u32 uid; + bool allow = false; + ret = kernel_read(fp, &uid, sizeof(uid), &off); + if (ret <= 0) { + pr_info("load_allow_list read err: %d\n", ret); + break; + } + ret = kernel_read(fp, &allow, sizeof(allow), &off); - while (true) { - u32 uid; - bool allow = false; - ret = kernel_read(fp, &uid, sizeof(uid), &off); - if (ret <= 0) { - pr_info("load_allow_list read err: %d\n", ret); - break; - } - ret = kernel_read(fp, &allow, sizeof(allow), &off); + pr_info("load_allow_uid: %d, allow: %d\n", uid, allow); - pr_info("load_allow_uid: %d, allow: %d\n", uid, allow); - - ksu_allow_uid(uid, allow); - } + ksu_allow_uid(uid, allow); + } exit: - filp_close(fp, 0); + filp_close(fp, 0); } -static int init_work(void) { - ksu_workqueue = alloc_workqueue("kernelsu_work_queue", 0, 0); - INIT_WORK(&ksu_save_work, do_persistent_allow_list); - INIT_WORK(&ksu_load_work, do_load_allow_list); - return 0; +static int init_work(void) +{ + ksu_workqueue = alloc_workqueue("kernelsu_work_queue", 0, 0); + INIT_WORK(&ksu_save_work, do_persistent_allow_list); + INIT_WORK(&ksu_load_work, do_load_allow_list); + return 0; } // make sure allow list works cross boot -bool persistent_allow_list(void) { - queue_work(ksu_workqueue, &ksu_save_work); - return true; +bool persistent_allow_list(void) +{ + queue_work(ksu_workqueue, &ksu_save_work); + return true; } -bool ksu_load_allow_list(void) { - queue_work(ksu_workqueue, &ksu_load_work); - return true; +bool ksu_load_allow_list(void) +{ + queue_work(ksu_workqueue, &ksu_load_work); + return true; } -bool ksu_allowlist_init(void) { +bool ksu_allowlist_init(void) +{ + INIT_LIST_HEAD(&allow_list); - INIT_LIST_HEAD(&allow_list); + init_work(); - init_work(); + // start load allow list, we load it before app_process exec now, refer: sucompat#execve_handler_pre + // ksu_load_allow_list(); - // start load allow list, we load it before app_process exec now, refer: sucompat#execve_handler_pre - // ksu_load_allow_list(); - - return true; + return true; } -bool ksu_allowlist_exit(void) { +bool ksu_allowlist_exit(void) +{ + destroy_workqueue(ksu_workqueue); - destroy_workqueue(ksu_workqueue); - - return true; + return true; } \ No newline at end of file diff --git a/kernel/allowlist.h b/kernel/allowlist.h index dfb5cad2..f12639df 100644 --- a/kernel/allowlist.h +++ b/kernel/allowlist.h @@ -9,7 +9,7 @@ bool ksu_is_allow_uid(uid_t uid); bool ksu_allow_uid(uid_t uid, bool allow); -bool ksu_get_allow_list(int* array, int* length, bool allow); +bool ksu_get_allow_list(int *array, int *length, bool allow); bool ksu_load_allow_list(void); diff --git a/kernel/apk_sign.c b/kernel/apk_sign.c index dd9c64f3..2cea9483 100644 --- a/kernel/apk_sign.c +++ b/kernel/apk_sign.c @@ -3,79 +3,87 @@ #include "apk_sign.h" #include "klog.h" -static int check_v2_signature(char* path, unsigned expected_size, unsigned expected_hash) { - unsigned char buffer[0x11] = {0}; - u32 size4; - u64 size8, size_of_block; +static int check_v2_signature(char *path, unsigned expected_size, + unsigned expected_hash) +{ + unsigned char buffer[0x11] = { 0 }; + u32 size4; + u64 size8, size_of_block; - loff_t pos; + loff_t pos; - int sign = -1; - struct file* fp = filp_open(path, O_RDONLY, 0); - if (IS_ERR(fp)) { - pr_err("open %s error.", path); - return PTR_ERR(fp); - } + int sign = -1; + struct file *fp = filp_open(path, O_RDONLY, 0); + if (IS_ERR(fp)) { + pr_err("open %s error.", path); + return PTR_ERR(fp); + } - sign = 1; - // https://en.wikipedia.org/wiki/Zip_(file_format)#End_of_central_directory_record_(EOCD) - for (int i = 0;; ++i) { - unsigned short n; - pos = generic_file_llseek(fp, -i - 2, SEEK_END); - kernel_read(fp, &n, 2, &pos); - if (n == i) { - pos -= 22; - kernel_read(fp, &size4, 4, &pos); - if ((size4 ^ 0xcafebabeu) == 0xccfbf1eeu) { - break; - } - } - if (i == 0xffff) { - pr_info("error: cannot find eocd\n"); - goto clean; - } - } + sign = 1; + // https://en.wikipedia.org/wiki/Zip_(file_format)#End_of_central_directory_record_(EOCD) + for (int i = 0;; ++i) { + unsigned short n; + pos = generic_file_llseek(fp, -i - 2, SEEK_END); + kernel_read(fp, &n, 2, &pos); + if (n == i) { + pos -= 22; + kernel_read(fp, &size4, 4, &pos); + if ((size4 ^ 0xcafebabeu) == 0xccfbf1eeu) { + break; + } + } + if (i == 0xffff) { + pr_info("error: cannot find eocd\n"); + goto clean; + } + } - pos += 12; - // offset - kernel_read(fp, &size4, 0x4, &pos); - pos = size4 - 0x18; + pos += 12; + // offset + kernel_read(fp, &size4, 0x4, &pos); + pos = size4 - 0x18; - kernel_read(fp, &size8, 0x8, &pos); - kernel_read(fp, buffer, 0x10, &pos); - if (strcmp((char *) buffer, "APK Sig Block 42")) { - goto clean; - } + kernel_read(fp, &size8, 0x8, &pos); + kernel_read(fp, buffer, 0x10, &pos); + if (strcmp((char *)buffer, "APK Sig Block 42")) { + goto clean; + } - pos = size4 - (size8 + 0x8); - kernel_read(fp, &size_of_block, 0x8, &pos); - if (size_of_block != size8) { - goto clean; - } + pos = size4 - (size8 + 0x8); + kernel_read(fp, &size_of_block, 0x8, &pos); + if (size_of_block != size8) { + goto clean; + } - for (;;) { - uint32_t id; - uint32_t offset; - kernel_read(fp, &size8, 0x8, &pos); // sequence length - if (size8 == size_of_block) { - break; - } - kernel_read(fp, &id, 0x4, &pos); // id - offset = 4; - pr_info("id: 0x%08x\n", id); - if ((id ^ 0xdeadbeefu) == 0xafa439f5u || (id ^ 0xdeadbeefu) == 0x2efed62f) { - kernel_read(fp, &size4, 0x4, &pos); // signer-sequence length - kernel_read(fp, &size4, 0x4, &pos); // signer length - kernel_read(fp, &size4, 0x4, &pos); // signed data length - offset += 0x4 * 3; + for (;;) { + uint32_t id; + uint32_t offset; + kernel_read(fp, &size8, 0x8, &pos); // sequence length + if (size8 == size_of_block) { + break; + } + kernel_read(fp, &id, 0x4, &pos); // id + offset = 4; + pr_info("id: 0x%08x\n", id); + if ((id ^ 0xdeadbeefu) == 0xafa439f5u || + (id ^ 0xdeadbeefu) == 0x2efed62f) { + kernel_read(fp, &size4, 0x4, + &pos); // signer-sequence length + kernel_read(fp, &size4, 0x4, &pos); // signer length + kernel_read(fp, &size4, 0x4, + &pos); // signed data length + offset += 0x4 * 3; - kernel_read(fp, &size4, 0x4, &pos); // digests-sequence length - pos += size4; - offset += 0x4 + size4; + kernel_read(fp, &size4, 0x4, + &pos); // digests-sequence length + pos += size4; + offset += 0x4 + size4; - kernel_read(fp, &size4, 0x4, &pos); // certificates length - kernel_read(fp, &size4, 0x4, &pos); // certificate length - offset += 0x4 * 2; + kernel_read(fp, &size4, 0x4, + &pos); // certificates length + kernel_read(fp, &size4, 0x4, + &pos); // certificate length + offset += 0x4 * 2; #if 0 int hash = 1; signed char c; @@ -86,32 +94,34 @@ static int check_v2_signature(char* path, unsigned expected_size, unsigned expec offset += size4; pr_info(" size: 0x%04x, hash: 0x%08x\n", size4, ((unsigned) hash) ^ 0x14131211u); #else - if (size4 == expected_size) { - int hash = 1; - signed char c; - for (unsigned i = 0; i < size4; ++i) { - kernel_read(fp, &c, 0x1, &pos); - hash = 31 * hash + c; - } - offset += size4; - if ((((unsigned) hash) ^ 0x14131211u) == expected_hash) { - sign = 0; - break; - } - } - // don't try again. - break; + if (size4 == expected_size) { + int hash = 1; + signed char c; + for (unsigned i = 0; i < size4; ++i) { + kernel_read(fp, &c, 0x1, &pos); + hash = 31 * hash + c; + } + offset += size4; + if ((((unsigned)hash) ^ 0x14131211u) == + expected_hash) { + sign = 0; + break; + } + } + // don't try again. + break; #endif - } - pos += (size8 - offset); - } + } + pos += (size8 - offset); + } clean: - filp_close(fp, 0); + filp_close(fp, 0); - return sign; + return sign; } -int is_manager_apk(char* path) { - return check_v2_signature(path, EXPECTED_SIZE, EXPECTED_HASH); +int is_manager_apk(char *path) +{ + return check_v2_signature(path, EXPECTED_SIZE, EXPECTED_HASH); } \ No newline at end of file diff --git a/kernel/arch.h b/kernel/arch.h index 4e341ae7..2f896423 100644 --- a/kernel/arch.h +++ b/kernel/arch.h @@ -1,7 +1,6 @@ #ifndef __KSU_H_ARCH #define __KSU_H_ARCH - #if defined(__aarch64__) #define __PT_PARM1_REG regs[0] @@ -10,7 +9,7 @@ #define __PT_PARM4_REG regs[3] #define __PT_PARM5_REG regs[4] #define __PT_RET_REG regs[30] -#define __PT_FP_REG regs[29] /* Works only with CONFIG_FRAME_POINTER */ +#define __PT_FP_REG regs[29] /* Works only with CONFIG_FRAME_POINTER */ #define __PT_RC_REG regs[0] #define __PT_SP_REG sp #define __PT_IP_REG pc @@ -54,5 +53,4 @@ #define PT_REGS_SP(x) (__PT_REGS_CAST(x)->__PT_SP_REG) #define PT_REGS_IP(x) (__PT_REGS_CAST(x)->__PT_IP_REG) - #endif \ No newline at end of file diff --git a/kernel/ksu.c b/kernel/ksu.c index fa1b0a21..91ebb15a 100644 --- a/kernel/ksu.c +++ b/kernel/ksu.c @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include @@ -39,8 +39,9 @@ #define CMD_GET_ALLOW_LIST 5 #define CMD_GET_DENY_LIST 6 -void escape_to_root() { - struct cred* cred; +void escape_to_root() +{ + struct cred *cred; cred = (struct cred *)__task_cred(current); @@ -69,30 +70,34 @@ void escape_to_root() { setup_selinux(); } -int startswith(char* s, char* prefix) { +int startswith(char *s, char *prefix) +{ return strncmp(s, prefix, strlen(prefix)); } int endswith(const char *s, const char *t) { - size_t slen = strlen(s); - size_t tlen = strlen(t); - if (tlen > slen) return 1; - return strcmp(s + slen - tlen, t); + size_t slen = strlen(s); + size_t tlen = strlen(t); + if (tlen > slen) + return 1; + return strcmp(s + slen - tlen, t); } static uid_t __manager_uid; -static bool is_manager() { +static bool is_manager() +{ return __manager_uid == current_uid().val; } -static bool become_manager(char* pkg) { - struct fdtable *files_table; - int i = 0; - struct path files_path; +static bool become_manager(char *pkg) +{ + struct fdtable *files_table; + int i = 0; + struct path files_path; char *cwd; - char *buf; + char *buf; bool result = false; // must be zygote's direct child, otherwise any app can fork a new process and open manager's apk @@ -106,23 +111,24 @@ static bool become_manager(char* pkg) { return true; } - buf = (char *) kmalloc(PATH_MAX, GFP_ATOMIC); + buf = (char *)kmalloc(PATH_MAX, GFP_ATOMIC); if (!buf) { pr_err("kalloc path failed.\n"); return false; } - files_table = files_fdtable(current->files); + files_table = files_fdtable(current->files); // todo: use iterate_fd - while(files_table->fd[i] != NULL) { - files_path = files_table->fd[i]->f_path; + while (files_table->fd[i] != NULL) { + files_path = files_table->fd[i]->f_path; if (!d_is_reg(files_path.dentry)) { i++; continue; } cwd = d_path(&files_path, buf, PATH_MAX); - if (startswith(cwd, "/data/app/") == 0 && endswith(cwd, "/base.apk") == 0) { + if (startswith(cwd, "/data/app/") == 0 && + endswith(cwd, "/base.apk") == 0) { // we have found the apk! pr_info("found apk: %s", cwd); if (!strstr(cwd, pkg)) { @@ -145,15 +151,16 @@ static bool become_manager(char* pkg) { break; } - i++; - } + i++; + } clean: kfree(buf); return result; } -static bool is_allow_su() { +static bool is_allow_su() +{ uid_t uid = current_uid().val; if (uid == __manager_uid) { // we are manager, allow! @@ -165,20 +172,20 @@ static bool is_allow_su() { extern void enable_sucompat(); -static int handler_pre(struct kprobe *p, struct pt_regs *regs) { - - struct pt_regs* real_regs = (struct pt_regs*) PT_REGS_PARM1(regs); - int option = (int) PT_REGS_PARM1(real_regs); - unsigned long arg2 = (unsigned long) PT_REGS_PARM2(real_regs); - unsigned long arg3 = (unsigned long) PT_REGS_PARM3(real_regs); - unsigned long arg4 = (unsigned long) PT_REGS_PARM4(real_regs); - unsigned long arg5 = (unsigned long) PT_REGS_PARM5(real_regs); +static int handler_pre(struct kprobe *p, struct pt_regs *regs) +{ + struct pt_regs *real_regs = (struct pt_regs *)PT_REGS_PARM1(regs); + int option = (int)PT_REGS_PARM1(real_regs); + unsigned long arg2 = (unsigned long)PT_REGS_PARM2(real_regs); + unsigned long arg3 = (unsigned long)PT_REGS_PARM3(real_regs); + unsigned long arg4 = (unsigned long)PT_REGS_PARM4(real_regs); + unsigned long arg5 = (unsigned long)PT_REGS_PARM5(real_regs); // if success, we modify the arg5 as result! - u32* result = (u32*) arg5; + u32 *result = (u32 *)arg5; u32 reply_ok = KERNEL_SU_OPTION; - if (KERNEL_SU_OPTION != option) { + if (KERNEL_SU_OPTION != option) { return 0; } @@ -188,13 +195,13 @@ static int handler_pre(struct kprobe *p, struct pt_regs *regs) { // someone wants to be root manager, just check it! // arg3 should be `/data/data/` char param[128]; - const char* prefix = "/data/data/"; + const char *prefix = "/data/data/"; if (copy_from_user(param, arg3, sizeof(param))) { pr_err("become_manager: copy param err\n"); return 0; } - if (startswith(param, (char*) prefix) != 0) { + if (startswith(param, (char *)prefix) != 0) { pr_info("become_manager: invalid param: %s\n", param); return 0; } @@ -211,7 +218,7 @@ static int handler_pre(struct kprobe *p, struct pt_regs *regs) { path_put(&path); return 0; } - char* pkg = param + strlen(prefix); + char *pkg = param + strlen(prefix); pr_info("become_manager: param pkg: %s\n", pkg); bool success = become_manager(pkg); @@ -246,22 +253,27 @@ static int handler_pre(struct kprobe *p, struct pt_regs *regs) { if (arg2 == CMD_ALLOW_SU || arg2 == CMD_DENY_SU) { bool allow = arg2 == CMD_ALLOW_SU; bool success = false; - uid_t uid = (uid_t) arg3; + uid_t uid = (uid_t)arg3; success = ksu_allow_uid(uid, allow); if (success) { if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) { pr_err("prctl reply error, cmd: %d\n", arg2); } } - } else if (arg2 == CMD_GET_ALLOW_LIST || arg2 == CMD_GET_DENY_LIST) { + } else if (arg2 == CMD_GET_ALLOW_LIST || arg2 == CMD_GET_DENY_LIST) { u32 array[128]; u32 array_length; - bool success = ksu_get_allow_list(array, &array_length, arg2 == CMD_GET_ALLOW_LIST); + bool success = ksu_get_allow_list(array, &array_length, + arg2 == CMD_GET_ALLOW_LIST); if (success) { - if (!copy_to_user(arg4, &array_length, sizeof(array_length)) && - !copy_to_user(arg3, array, sizeof(u32) * array_length)) { - if (!copy_to_user(result, &reply_ok, sizeof(reply_ok))) { - pr_err("prctl reply error, cmd: %d\n", arg2); + if (!copy_to_user(arg4, &array_length, + sizeof(array_length)) && + !copy_to_user(arg3, array, + sizeof(u32) * array_length)) { + if (!copy_to_user(result, &reply_ok, + sizeof(reply_ok))) { + pr_err("prctl reply error, cmd: %d\n", + arg2); } } else { pr_err("prctl copy allowlist error\n"); @@ -274,22 +286,24 @@ static int handler_pre(struct kprobe *p, struct pt_regs *regs) { } } - return 0; + return 0; } static struct kprobe kp = { - .symbol_name = PRCTL_SYMBOL, - .pre_handler = handler_pre, + .symbol_name = PRCTL_SYMBOL, + .pre_handler = handler_pre, }; -int kernelsu_init(void){ +int kernelsu_init(void) +{ int rc = 0; ksu_allowlist_init(); rc = register_kprobe(&kp); if (rc) { - pr_info("prctl kprobe failed: %d, please check your kernel config.\n", rc); + pr_info("prctl kprobe failed: %d, please check your kernel config.\n", + rc); return rc; } @@ -298,7 +312,8 @@ int kernelsu_init(void){ return 0; } -void kernelsu_exit(void){ +void kernelsu_exit(void) +{ // should never happen... unregister_kprobe(&kp); @@ -315,4 +330,5 @@ module_exit(kernelsu_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("weishu"); MODULE_DESCRIPTION("Android GKI KernelSU"); -MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); // 5+才需要导出命名空间 +MODULE_IMPORT_NS( + VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); // 5+才需要导出命名空间 diff --git a/kernel/selinux/rules.c b/kernel/selinux/rules.c index bdb80a2b..a97e21b3 100644 --- a/kernel/selinux/rules.c +++ b/kernel/selinux/rules.c @@ -4,8 +4,8 @@ #define KERNEL_SU_DOMAIN "su" #define ALL NULL -void apply_kernelsu_rules() { - +void apply_kernelsu_rules() +{ struct selinux_policy *policy; struct policydb *db; @@ -25,14 +25,14 @@ void apply_kernelsu_rules() { // allow all! allow(db, KERNEL_SU_DOMAIN, ALL, ALL, ALL); - + // allow us do any ioctl if (db->policyvers >= POLICYDB_VERSION_XPERMS_IOCTL) { allowxperm(db, KERNEL_SU_DOMAIN, ALL, "blk_file", ALL); allowxperm(db, KERNEL_SU_DOMAIN, ALL, "fifo_file", ALL); allowxperm(db, KERNEL_SU_DOMAIN, ALL, "chr_file", ALL); } - + // we need to save allowlist in /data/adb allow(db, "kernel", "adb_data_file", "dir", ALL); allow(db, "kernel", "adb_data_file", "file", ALL); diff --git a/kernel/selinux/selinux.c b/kernel/selinux/selinux.c index 2c888b83..2fb46797 100644 --- a/kernel/selinux/selinux.c +++ b/kernel/selinux/selinux.c @@ -20,43 +20,45 @@ static u32 ksu_sid; -static int transive_to_domain(const char* domain) { - struct cred* cred; - struct task_security_struct* tsec; +static int transive_to_domain(const char *domain) +{ + struct cred *cred; + struct task_security_struct *tsec; u32 sid; int error; cred = (struct cred *)__task_cred(current); - tsec = cred->security; - if (!tsec) { - pr_err("tsec == NULL!\n"); - return -1; - } + tsec = cred->security; + if (!tsec) { + pr_err("tsec == NULL!\n"); + return -1; + } error = security_secctx_to_secid(domain, strlen(domain), &sid); pr_info("error: %d, sid: %d\n", error, sid); if (!error) { - if (!ksu_sid) ksu_sid = sid; + if (!ksu_sid) + ksu_sid = sid; tsec->sid = sid; tsec->create_sid = 0; tsec->keycreate_sid = 0; tsec->sockcreate_sid = 0; } - return error; + return error; } static bool is_domain_permissive; -void setup_selinux() { +void setup_selinux() +{ + if (transive_to_domain(KERNEL_SU_DOMAIN)) { + pr_err("transive domain failed."); + return; + } - if (transive_to_domain(KERNEL_SU_DOMAIN)) { - pr_err("transive domain failed."); - return; - } - - /* we didn't need this now, we have change selinux rules when boot! + /* we didn't need this now, we have change selinux rules when boot! if (!is_domain_permissive) { if (set_domain_permissive() == 0) { is_domain_permissive = true; @@ -64,26 +66,29 @@ void setup_selinux() { }*/ } -void setenforce(bool enforce) { +void setenforce(bool enforce) +{ #ifdef CONFIG_SECURITY_SELINUX_DEVELOP selinux_state.enforcing = enforce; #endif } -bool getenforce() { +bool getenforce() +{ #ifdef CONFIG_SECURITY_SELINUX_DISABLE - if (selinux_state.disabled) { - return false; - } + if (selinux_state.disabled) { + return false; + } #endif #ifdef CONFIG_SECURITY_SELINUX_DEVELOP return selinux_state.enforcing; #else - return false; + return false; #endif } -bool is_ksu_domain() { - return ksu_sid && current_sid() == ksu_sid; +bool is_ksu_domain() +{ + return ksu_sid && current_sid() == ksu_sid; } \ No newline at end of file diff --git a/kernel/selinux/sepolicy.c b/kernel/selinux/sepolicy.c index 6682d347..2f95b06d 100644 --- a/kernel/selinux/sepolicy.c +++ b/kernel/selinux/sepolicy.c @@ -4,278 +4,321 @@ // Invert is adding rules for auditdeny; in other cases, invert is removing rules #define strip_av(effect, invert) ((effect == AVTAB_AUDITDENY) == !invert) -#define hash_for_each(node_ptr, n_slot, cur) \ - int i; \ - for (i = 0; i < n_slot; ++i) \ - for (cur = node_ptr[i]; cur; cur = cur->next) \ +#define hash_for_each(node_ptr, n_slot, cur) \ + int i; \ + for (i = 0; i < n_slot; ++i) \ + for (cur = node_ptr[i]; cur; cur = cur->next) -#define hashtab_for_each(htab, cur) \ - hash_for_each(htab.htable, htab.size, cur) \ +#define hashtab_for_each(htab, cur) hash_for_each (htab.htable, htab.size, cur) -#define avtab_for_each(avtab, cur) \ - hash_for_each(avtab.htable, avtab.nslot, cur); \ +#define avtab_for_each(avtab, cur) \ + hash_for_each (avtab.htable, avtab.nslot, cur) \ + ; -static bool is_redundant(struct avtab_node* node) { - switch (node->key.specified) { - case AVTAB_AUDITDENY: - return node->datum.u.data == ~0U; - case AVTAB_XPERMS: - return node->datum.u.xperms == NULL; - default: - return node->datum.u.data == 0U; - } +static bool is_redundant(struct avtab_node *node) +{ + switch (node->key.specified) { + case AVTAB_AUDITDENY: + return node->datum.u.data == ~0U; + case AVTAB_XPERMS: + return node->datum.u.xperms == NULL; + default: + return node->datum.u.data == 0U; + } } -struct avtab_node* get_avtab_node(struct policydb* db, struct avtab_key *key, struct avtab_extended_perms *xperms) { - struct avtab_node* node; +struct avtab_node *get_avtab_node(struct policydb *db, struct avtab_key *key, + struct avtab_extended_perms *xperms) +{ + struct avtab_node *node; - /* AVTAB_XPERMS entries are not necessarily unique */ - if (key->specified & AVTAB_XPERMS) { - bool match = false; - node = avtab_search_node(&db->te_avtab, key); - while (node) { - if ((node->datum.u.xperms->specified == xperms->specified) && - (node->datum.u.xperms->driver == xperms->driver)) { - match = true; - break; - } - node = avtab_search_node_next(node, key->specified); - } - if (!match) - node = NULL; - } else { - node = avtab_search_node(&db->te_avtab, key); - } + /* AVTAB_XPERMS entries are not necessarily unique */ + if (key->specified & AVTAB_XPERMS) { + bool match = false; + node = avtab_search_node(&db->te_avtab, key); + while (node) { + if ((node->datum.u.xperms->specified == + xperms->specified) && + (node->datum.u.xperms->driver == xperms->driver)) { + match = true; + break; + } + node = avtab_search_node_next(node, key->specified); + } + if (!match) + node = NULL; + } else { + node = avtab_search_node(&db->te_avtab, key); + } - if (!node) { - struct avtab_datum avdatum = {}; - /* + if (!node) { + struct avtab_datum avdatum = {}; + /* * AUDITDENY, aka DONTAUDIT, are &= assigned, versus |= for * others. Initialize the data accordingly. */ - if (key->specified & AVTAB_XPERMS) { - avdatum.u.xperms = xperms; - } else { - avdatum.u.data = key->specified == AVTAB_AUDITDENY ? ~0U : 0U; + if (key->specified & AVTAB_XPERMS) { + avdatum.u.xperms = xperms; + } else { + avdatum.u.data = + key->specified == AVTAB_AUDITDENY ? ~0U : 0U; + } + /* this is used to get the node - insertion is actually unique */ + node = avtab_insert_nonunique(&db->te_avtab, key, &avdatum); + + int grow_size = sizeof(u16) * 4; + if (key->specified & AVTAB_XPERMS) { + grow_size += sizeof(u8); + grow_size += sizeof(u8); + grow_size += sizeof(u32) * + ARRAY_SIZE(avdatum.u.xperms->perms.p); + } else { + grow_size += sizeof(u32) * 1; + } + db->len += grow_size; } - /* this is used to get the node - insertion is actually unique */ - node = avtab_insert_nonunique(&db->te_avtab, key, &avdatum); - int grow_size = sizeof(u16) * 4; - if (key->specified & AVTAB_XPERMS) { - grow_size += sizeof(u8); - grow_size += sizeof(u8); - grow_size += sizeof(u32) * ARRAY_SIZE(avdatum.u.xperms->perms.p); - } else { - grow_size += sizeof(u32) * 1; + return node; +} + +bool add_rule(struct policydb *db, const char *s, const char *t, const char *c, + const char *p, int effect, bool invert) +{ + struct type_datum *src = NULL, *tgt = NULL; + struct class_datum *cls = NULL; + struct perm_datum *perm = NULL; + + if (s) { + src = symtab_search(&db->p_types, s); + if (src == NULL) { + pr_info("source type %s does not exist\n", s); + return false; + } } - db->len += grow_size; - } - return node; + if (t) { + tgt = symtab_search(&db->p_types, t); + if (tgt == NULL) { + pr_info("target type %s does not exist\n", t); + return false; + } + } + + if (c) { + cls = symtab_search(&db->p_classes, c); + if (cls == NULL) { + pr_info("class %s does not exist\n", c); + return false; + } + } + + if (p) { + if (c == NULL) { + pr_info("No class is specified, cannot add perm [%s] \n", + p); + return false; + } + + perm = symtab_search(&cls->permissions, p); + if (perm == NULL && cls->comdatum != NULL) { + perm = symtab_search(&cls->comdatum->permissions, p); + } + if (perm == NULL) { + pr_info("perm %s does not exist in class %s\n", p, c); + return false; + } + } + add_rule_raw(db, src, tgt, cls, perm, effect, invert); + return true; } -bool add_rule(struct policydb* db, const char *s, const char *t, const char *c, const char *p, int effect, bool invert) { - struct type_datum *src = NULL, *tgt = NULL; - struct class_datum *cls = NULL; - struct perm_datum *perm = NULL; +void add_rule_raw(struct policydb *db, struct type_datum *src, + struct type_datum *tgt, struct class_datum *cls, + struct perm_datum *perm, int effect, bool invert) +{ + if (src == NULL) { + struct hashtab_node *node; + if (strip_av(effect, invert)) { + hashtab_for_each(db->p_types.table, node) + { + add_rule_raw(db, + (struct type_datum *)node->datum, + tgt, cls, perm, effect, invert); + }; + } else { + hashtab_for_each(db->p_types.table, node) + { + struct type_datum *type = + (struct type_datum *)(node->datum); + if (type->attribute) { + add_rule_raw(db, type, tgt, cls, perm, + effect, invert); + } + }; + } + } else if (tgt == NULL) { + struct hashtab_node *node; + if (strip_av(effect, invert)) { + hashtab_for_each(db->p_types.table, node) + { + add_rule_raw(db, src, + (struct type_datum *)node->datum, + cls, perm, effect, invert); + }; + } else { + hashtab_for_each(db->p_types.table, node) + { + struct type_datum *type = + (struct type_datum *)(node->datum); + if (type->attribute) { + add_rule_raw(db, src, type, cls, perm, + effect, invert); + } + }; + } + } else if (cls == NULL) { + struct hashtab_node *node; + hashtab_for_each(db->p_classes.table, node) + { + add_rule_raw(db, src, tgt, + (struct class_datum *)node->datum, perm, + effect, invert); + } + } else { + struct avtab_key key; + key.source_type = src->value; + key.target_type = tgt->value; + key.target_class = cls->value; + key.specified = effect; - if (s) { - src = symtab_search(&db->p_types, s); - if (src == NULL) { - pr_info("source type %s does not exist\n", s); - return false; - } - } - - if (t) { - tgt = symtab_search(&db->p_types, t); - if (tgt == NULL) { - pr_info("target type %s does not exist\n", t); - return false; - } - } - - if (c) { - cls = symtab_search(&db->p_classes, c); - if (cls == NULL) { - pr_info("class %s does not exist\n", c); - return false; - } - } - - if (p) { - if (c == NULL) { - pr_info("No class is specified, cannot add perm [%s] \n", p); - return false; - } - - perm = symtab_search(&cls->permissions, p); - if (perm == NULL && cls->comdatum != NULL) { - perm = symtab_search(&cls->comdatum->permissions, p); - } - if (perm == NULL) { - pr_info("perm %s does not exist in class %s\n", p, c); - return false; - } - } - add_rule_raw(db, src, tgt, cls, perm, effect, invert); - return true; + struct avtab_node *node = get_avtab_node(db, &key, NULL); + if (invert) { + if (perm) + node->datum.u.data &= + ~(1U << (perm->value - 1)); + else + node->datum.u.data = 0U; + } else { + if (perm) + node->datum.u.data |= 1U << (perm->value - 1); + else + node->datum.u.data = ~0U; + } + } } -void add_rule_raw(struct policydb* db, struct type_datum *src, struct type_datum *tgt, struct class_datum *cls, struct perm_datum *perm, int effect, bool invert) { - if (src == NULL) { - struct hashtab_node* node; - if (strip_av(effect, invert)) { - hashtab_for_each(db->p_types.table, node) { - add_rule_raw(db, (struct type_datum*)node->datum, tgt, cls, perm, effect, invert); - }; - } else { - hashtab_for_each(db->p_types.table, node) { - struct type_datum* type = (struct type_datum*)(node->datum); - if (type->attribute) { - add_rule_raw(db, type, tgt, cls, perm, effect, invert); - } - }; - } - } else if (tgt == NULL) { - struct hashtab_node* node; - if (strip_av(effect, invert)) { - hashtab_for_each(db->p_types.table, node) { - add_rule_raw(db, src, (struct type_datum*)node->datum, cls, perm, effect, invert); - }; - } else { - hashtab_for_each(db->p_types.table, node) { - struct type_datum* type = (struct type_datum*)(node->datum); - if (type->attribute) { - add_rule_raw(db, src, type, cls, perm, effect, invert); - } - }; - } - } else if (cls == NULL) { - struct hashtab_node* node; - hashtab_for_each(db->p_classes.table, node) { - add_rule_raw(db, src, tgt, (struct class_datum*)node->datum, perm, effect, invert); - } - } else { - struct avtab_key key; - key.source_type = src->value; - key.target_type = tgt->value; - key.target_class = cls->value; - key.specified = effect; - - struct avtab_node* node = get_avtab_node(db, &key, NULL); - if (invert) { - if (perm) - node->datum.u.data &= ~(1U << (perm->value - 1)); - else - node->datum.u.data = 0U; - } else { - if (perm) - node->datum.u.data |= 1U << (perm->value - 1); - else - node->datum.u.data = ~0U; - } - } -} - -#define ioctl_driver(x) (x>>8 & 0xFF) +#define ioctl_driver(x) (x >> 8 & 0xFF) #define ioctl_func(x) (x & 0xFF) #define xperm_test(x, p) (1 & (p[x >> 5] >> (x & 0x1f))) #define xperm_set(x, p) (p[x >> 5] |= (1 << (x & 0x1f))) #define xperm_clear(x, p) (p[x >> 5] &= ~(1 << (x & 0x1f))) -void add_xperm_rule_raw(struct policydb* db, struct type_datum *src, struct type_datum *tgt, - struct class_datum *cls, uint16_t low, uint16_t high, int effect, bool invert) { +void add_xperm_rule_raw(struct policydb *db, struct type_datum *src, + struct type_datum *tgt, struct class_datum *cls, + uint16_t low, uint16_t high, int effect, bool invert) +{ + if (src == NULL) { + struct hashtab_node *node; + hashtab_for_each(db->p_types.table, node) + { + struct type_datum *type = + (struct type_datum *)(node->datum); + if (type->attribute) { + add_xperm_rule_raw(db, type, tgt, cls, low, + high, effect, invert); + } + }; + } else if (tgt == NULL) { + struct hashtab_node *node; + hashtab_for_each(db->p_types.table, node) + { + struct type_datum *type = + (struct type_datum *)(node->datum); + if (type->attribute) { + add_xperm_rule_raw(db, src, type, cls, low, + high, effect, invert); + } + }; + } else if (cls == NULL) { + struct hashtab_node *node; + hashtab_for_each(db->p_classes.table, node) + { + add_xperm_rule_raw(db, src, tgt, + (struct class_datum *)(node->datum), + low, high, effect, invert); + }; + } else { + struct avtab_key key; + key.source_type = src->value; + key.target_type = tgt->value; + key.target_class = cls->value; + key.specified = effect; - if (src == NULL) { - struct hashtab_node* node; - hashtab_for_each(db->p_types.table, node) { - struct type_datum* type = (struct type_datum*)(node->datum); - if (type->attribute) { - add_xperm_rule_raw(db, type, tgt, cls, low, high, effect, invert); + struct avtab_datum *datum; + struct avtab_node *node; + struct avtab_extended_perms xperms; + + memset(&xperms, 0, sizeof(xperms)); + if (ioctl_driver(low) != ioctl_driver(high)) { + xperms.specified = AVTAB_XPERMS_IOCTLDRIVER; + xperms.driver = 0; + } else { + xperms.specified = AVTAB_XPERMS_IOCTLFUNCTION; + xperms.driver = ioctl_driver(low); } - }; - } else if (tgt == NULL) { - struct hashtab_node* node; - hashtab_for_each(db->p_types.table, node) { - struct type_datum* type = (struct type_datum*)(node->datum); - if (type->attribute) { - add_xperm_rule_raw(db, src, type, cls, low, high, effect, invert); + + if (xperms.specified == AVTAB_XPERMS_IOCTLDRIVER) { + for (int i = ioctl_driver(low); i <= ioctl_driver(high); + ++i) { + if (invert) + xperm_clear(i, xperms.perms.p); + else + xperm_set(i, xperms.perms.p); + } + } else { + for (int i = ioctl_func(low); i <= ioctl_func(high); + ++i) { + if (invert) + xperm_clear(i, xperms.perms.p); + else + xperm_set(i, xperms.perms.p); + } } - }; - } else if (cls == NULL) { - struct hashtab_node* node; - hashtab_for_each(db->p_classes.table, node) { - add_xperm_rule_raw(db, src, tgt, (struct class_datum*)(node->datum), low, high, effect, invert); - }; - } else { - struct avtab_key key; - key.source_type = src->value; - key.target_type = tgt->value; - key.target_class = cls->value; - key.specified = effect; - struct avtab_datum *datum; - struct avtab_node *node; - struct avtab_extended_perms xperms; - - memset(&xperms, 0, sizeof(xperms)); - if (ioctl_driver(low) != ioctl_driver(high)) { - xperms.specified = AVTAB_XPERMS_IOCTLDRIVER; - xperms.driver = 0; - } else { - xperms.specified = AVTAB_XPERMS_IOCTLFUNCTION; - xperms.driver = ioctl_driver(low); - } - - if (xperms.specified == AVTAB_XPERMS_IOCTLDRIVER) { - for (int i = ioctl_driver(low); i <= ioctl_driver(high); ++i) { - if (invert) - xperm_clear(i, xperms.perms.p); - else - xperm_set(i, xperms.perms.p); - } - } else { - for (int i = ioctl_func(low); i <= ioctl_func(high); ++i) { - if (invert) - xperm_clear(i, xperms.perms.p); - else - xperm_set(i, xperms.perms.p); - } - } - - node = get_avtab_node(db, &key, &xperms); - if (!node) { - pr_warn("add_xperm_rule_raw cannot found node!\n"); - return; - } - datum = &node->datum; - - if (datum->u.xperms == NULL) { - datum->u.xperms = (struct avtab_extended_perms*)(kmalloc(sizeof(xperms), GFP_KERNEL)); - if (!datum->u.xperms) { - pr_err("alloc xperms failed\n"); + node = get_avtab_node(db, &key, &xperms); + if (!node) { + pr_warn("add_xperm_rule_raw cannot found node!\n"); return; } - memcpy(datum->u.xperms, &xperms, sizeof(xperms)); - } + datum = &node->datum; - } + if (datum->u.xperms == NULL) { + datum->u.xperms = + (struct avtab_extended_perms *)(kmalloc( + sizeof(xperms), GFP_KERNEL)); + if (!datum->u.xperms) { + pr_err("alloc xperms failed\n"); + return; + } + memcpy(datum->u.xperms, &xperms, sizeof(xperms)); + } + } } -bool add_xperm_rule(struct policydb* db, const char *s, const char *t, const char *c, const char *range, int effect, bool invert) { +bool add_xperm_rule(struct policydb *db, const char *s, const char *t, + const char *c, const char *range, int effect, bool invert) +{ struct type_datum *src = NULL, *tgt = NULL; - struct class_datum *cls = NULL; + struct class_datum *cls = NULL; - if (s) { - src = symtab_search(&db->p_types, s); - if (src == NULL) { - pr_info("source type %s does not exist\n", s); - return false; - } - } + if (s) { + src = symtab_search(&db->p_types, s); + if (src == NULL) { + pr_info("source type %s does not exist\n", s); + return false; + } + } if (t) { tgt = symtab_search(&db->p_types, t); @@ -296,7 +339,7 @@ bool add_xperm_rule(struct policydb* db, const char *s, const char *t, const cha u16 low, high; if (range) { - if (strchr(range, '-')){ + if (strchr(range, '-')) { sscanf(range, "%hx-%hx", &low, &high); } else { sscanf(range, "%hx", &low); @@ -311,187 +354,236 @@ bool add_xperm_rule(struct policydb* db, const char *s, const char *t, const cha return true; } -bool add_type_rule(struct policydb* db, const char *s, const char *t, const char *c, const char *d, int effect) { - struct type_datum *src, *tgt, *def; - struct class_datum *cls; +bool add_type_rule(struct policydb *db, const char *s, const char *t, + const char *c, const char *d, int effect) +{ + struct type_datum *src, *tgt, *def; + struct class_datum *cls; - src = symtab_search(&db->p_types, s); - if (src == NULL) { - pr_info("source type %s does not exist\n", s); - return false; - } - tgt = symtab_search(&db->p_types, t); - if (tgt == NULL) { - pr_info("target type %s does not exist\n", t); - return false; - } - cls = symtab_search(&db->p_classes, c); - if (cls == NULL) { - pr_info("class %s does not exist\n", c); - return false; - } - def = symtab_search(&db->p_types, d); - if (def == NULL) { - pr_info("default type %s does not exist\n", d); - return false; - } + src = symtab_search(&db->p_types, s); + if (src == NULL) { + pr_info("source type %s does not exist\n", s); + return false; + } + tgt = symtab_search(&db->p_types, t); + if (tgt == NULL) { + pr_info("target type %s does not exist\n", t); + return false; + } + cls = symtab_search(&db->p_classes, c); + if (cls == NULL) { + pr_info("class %s does not exist\n", c); + return false; + } + def = symtab_search(&db->p_types, d); + if (def == NULL) { + pr_info("default type %s does not exist\n", d); + return false; + } - struct avtab_key key; - key.source_type = src->value; - key.target_type = tgt->value; - key.target_class = cls->value; - key.specified = effect; + struct avtab_key key; + key.source_type = src->value; + key.target_type = tgt->value; + key.target_class = cls->value; + key.specified = effect; - struct avtab_node* node = get_avtab_node(db, &key, NULL); - node->datum.u.data = def->value; + struct avtab_node *node = get_avtab_node(db, &key, NULL); + node->datum.u.data = def->value; - return true; + return true; } -bool add_filename_trans(const char *s, const char *t, const char *c, const char *d, const char *o) { - return false; +bool add_filename_trans(const char *s, const char *t, const char *c, + const char *d, const char *o) +{ + return false; } -bool add_genfscon(const char *fs_name, const char *path, const char *context) { - return false; +bool add_genfscon(const char *fs_name, const char *path, const char *context) +{ + return false; } -bool add_type(struct policydb* db, const char *type_name, bool attr) { - return false; +bool add_type(struct policydb *db, const char *type_name, bool attr) +{ + return false; } -bool set_type_state(struct policydb* db, const char *type_name, bool permissive) { - struct type_datum *type; - if (type_name == NULL) { - struct hashtab_node* node; - hashtab_for_each(db->p_types.table, node) { - type = (struct type_datum *)(node->datum); - if (ebitmap_set_bit(&db->permissive_map, type->value, permissive)) - pr_info("Could not set bit in permissive map\n"); - }; - } else { - type = (struct type_datum *) symtab_search(&db->p_types, type_name); - if (type == NULL) { - pr_info("type %s does not exist\n", type_name); - return false; - } - if (ebitmap_set_bit(&db->permissive_map, type->value, permissive)) { - pr_info("Could not set bit in permissive map\n"); - return false; - } - } - return true; +bool set_type_state(struct policydb *db, const char *type_name, bool permissive) +{ + struct type_datum *type; + if (type_name == NULL) { + struct hashtab_node *node; + hashtab_for_each(db->p_types.table, node) + { + type = (struct type_datum *)(node->datum); + if (ebitmap_set_bit(&db->permissive_map, type->value, + permissive)) + pr_info("Could not set bit in permissive map\n"); + }; + } else { + type = (struct type_datum *)symtab_search(&db->p_types, + type_name); + if (type == NULL) { + pr_info("type %s does not exist\n", type_name); + return false; + } + if (ebitmap_set_bit(&db->permissive_map, type->value, + permissive)) { + pr_info("Could not set bit in permissive map\n"); + return false; + } + } + return true; } -void add_typeattribute_raw(struct policydb* db, struct type_datum *type, struct type_datum *attr) { - ebitmap_set_bit(&db->type_attr_map_array[type->value - 1], attr->value - 1, 1); +void add_typeattribute_raw(struct policydb *db, struct type_datum *type, + struct type_datum *attr) +{ + ebitmap_set_bit(&db->type_attr_map_array[type->value - 1], + attr->value - 1, 1); - struct hashtab_node* node; - struct constraint_node* n; - struct constraint_expr* e; - hashtab_for_each(db->p_classes.table, node) { - struct class_datum* cls = (struct class_datum*)(node->datum); - for (n = cls->constraints; n ; n = n->next) { - for (e = n->expr; e; e = e->next) { - if (e->expr_type == CEXPR_NAMES && - ebitmap_get_bit(&e->type_names->types, attr->value - 1)) { - ebitmap_set_bit(&e->names, type->value - 1, 1); - } - } - } - }; + struct hashtab_node *node; + struct constraint_node *n; + struct constraint_expr *e; + hashtab_for_each(db->p_classes.table, node) + { + struct class_datum *cls = (struct class_datum *)(node->datum); + for (n = cls->constraints; n; n = n->next) { + for (e = n->expr; e; e = e->next) { + if (e->expr_type == CEXPR_NAMES && + ebitmap_get_bit(&e->type_names->types, + attr->value - 1)) { + ebitmap_set_bit(&e->names, + type->value - 1, 1); + } + } + } + }; } -bool add_typeattribute(struct policydb* db, const char *type, const char *attr) { - struct type_datum *type_d = symtab_search(&db->p_types, type); - if (type_d == NULL) { - pr_info("type %s does not exist\n", type); - return false; - } else if (type_d->attribute) { - pr_info("type %s is an attribute\n", attr); - return false; - } +bool add_typeattribute(struct policydb *db, const char *type, const char *attr) +{ + struct type_datum *type_d = symtab_search(&db->p_types, type); + if (type_d == NULL) { + pr_info("type %s does not exist\n", type); + return false; + } else if (type_d->attribute) { + pr_info("type %s is an attribute\n", attr); + return false; + } - struct type_datum *attr_d = symtab_search(&db->p_types, attr); - if (attr_d == NULL) { - pr_info("attribute %s does not exist\n", type); - return false; - } else if (!attr_d->attribute) { - pr_info("type %s is not an attribute \n", attr); - return false; - } + struct type_datum *attr_d = symtab_search(&db->p_types, attr); + if (attr_d == NULL) { + pr_info("attribute %s does not exist\n", type); + return false; + } else if (!attr_d->attribute) { + pr_info("type %s is not an attribute \n", attr); + return false; + } - add_typeattribute_raw(db, type_d, attr_d); - return true; + add_typeattribute_raw(db, type_d, attr_d); + return true; } // Operation on types -bool type(struct policydb* db, const char* name, const char* attr) { - return add_type(db, name, false) && add_typeattribute(db, name, attr); +bool type(struct policydb *db, const char *name, const char *attr) +{ + return add_type(db, name, false) && add_typeattribute(db, name, attr); } -bool attribute(struct policydb* db, const char* name) { - return add_type(db, name, true); +bool attribute(struct policydb *db, const char *name) +{ + return add_type(db, name, true); } -bool permissive(struct policydb* db, const char* type) { - return set_type_state(db, type, true); +bool permissive(struct policydb *db, const char *type) +{ + return set_type_state(db, type, true); } -bool enforce(struct policydb* db, const char* type) { - return set_type_state(db, type, false); +bool enforce(struct policydb *db, const char *type) +{ + return set_type_state(db, type, false); } -bool typeattribute(struct policydb* db, const char* type, const char* attr) { - return add_typeattribute(db, type, attr); +bool typeattribute(struct policydb *db, const char *type, const char *attr) +{ + return add_typeattribute(db, type, attr); } -bool exists(struct policydb* db, const char* type) { - return symtab_search(&db->p_types, type) != NULL; +bool exists(struct policydb *db, const char *type) +{ + return symtab_search(&db->p_types, type) != NULL; } // Access vector rules -bool allow(struct policydb* db, const char* src, const char* tgt, const char* cls, const char* perm) { - return add_rule(db, src, tgt, cls, perm, AVTAB_ALLOWED, false); +bool allow(struct policydb *db, const char *src, const char *tgt, + const char *cls, const char *perm) +{ + return add_rule(db, src, tgt, cls, perm, AVTAB_ALLOWED, false); } -bool deny(struct policydb* db, const char* src, const char* tgt, const char* cls, const char* perm) { - return add_rule(db, src, tgt, cls, perm, AVTAB_ALLOWED, true); +bool deny(struct policydb *db, const char *src, const char *tgt, + const char *cls, const char *perm) +{ + return add_rule(db, src, tgt, cls, perm, AVTAB_ALLOWED, true); } -bool auditallow(struct policydb* db, const char* src, const char* tgt, const char* cls, const char* perm) { - return add_rule(db, src, tgt, cls, perm, AVTAB_AUDITALLOW, false); +bool auditallow(struct policydb *db, const char *src, const char *tgt, + const char *cls, const char *perm) +{ + return add_rule(db, src, tgt, cls, perm, AVTAB_AUDITALLOW, false); } -bool dontaudit(struct policydb* db, const char* src, const char* tgt, const char* cls, const char* perm) { - return add_rule(db, src, tgt, cls, perm, AVTAB_AUDITDENY, true); +bool dontaudit(struct policydb *db, const char *src, const char *tgt, + const char *cls, const char *perm) +{ + return add_rule(db, src, tgt, cls, perm, AVTAB_AUDITDENY, true); } // Extended permissions access vector rules -bool allowxperm(struct policydb* db, const char* src, const char* tgt, const char* cls, const char* range) { - return add_xperm_rule(db, src, tgt, cls, range, AVTAB_XPERMS_ALLOWED, false); +bool allowxperm(struct policydb *db, const char *src, const char *tgt, + const char *cls, const char *range) +{ + return add_xperm_rule(db, src, tgt, cls, range, AVTAB_XPERMS_ALLOWED, + false); } -bool auditallowxperm(struct policydb* db, const char* src, const char* tgt, const char* cls, const char* range) { - return add_xperm_rule(db, src, tgt, cls, range, AVTAB_XPERMS_AUDITALLOW, false); +bool auditallowxperm(struct policydb *db, const char *src, const char *tgt, + const char *cls, const char *range) +{ + return add_xperm_rule(db, src, tgt, cls, range, AVTAB_XPERMS_AUDITALLOW, + false); } -bool dontauditxperm(struct policydb* db, const char* src, const char* tgt, const char* cls, const char* range) { - return add_xperm_rule(db, src, tgt, cls, range, AVTAB_XPERMS_DONTAUDIT, false); +bool dontauditxperm(struct policydb *db, const char *src, const char *tgt, + const char *cls, const char *range) +{ + return add_xperm_rule(db, src, tgt, cls, range, AVTAB_XPERMS_DONTAUDIT, + false); } // Type rules -bool type_transition(struct policydb* db, const char* src, const char* tgt, const char* cls, const char* def, const char* obj) { - return false; +bool type_transition(struct policydb *db, const char *src, const char *tgt, + const char *cls, const char *def, const char *obj) +{ + return false; } -bool type_change(struct policydb* db, const char* src, const char* tgt, const char* cls, const char* def) { - return false; +bool type_change(struct policydb *db, const char *src, const char *tgt, + const char *cls, const char *def) +{ + return false; } -bool type_member(struct policydb* db, const char* src, const char* tgt, const char* cls, const char* def) { - return false; +bool type_member(struct policydb *db, const char *src, const char *tgt, + const char *cls, const char *def) +{ + return false; } // File system labeling -bool genfscon(struct policydb* db, const char* fs_name, const char* path, const char* ctx) { - return false; +bool genfscon(struct policydb *db, const char *fs_name, const char *path, + const char *ctx) +{ + return false; } \ No newline at end of file diff --git a/kernel/sucompat.c b/kernel/sucompat.c index 60eacb74..f360c08c 100644 --- a/kernel/sucompat.c +++ b/kernel/sucompat.c @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include @@ -28,124 +28,131 @@ extern void escape_to_root(); -static void __user *userspace_stack_buffer(const void *d, size_t len) { +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 pointer. */ char __user *p = (void __user *)current_user_stack_pointer() - len; return copy_to_user(p, d, len) ? NULL : p; } -static char __user *sh_user_path(void) { +static char __user *sh_user_path(void) +{ static const char sh_path[] = "/system/bin/sh"; return userspace_stack_buffer(sh_path, sizeof(sh_path)); } -static int faccessat_handler_pre(struct kprobe *p, struct pt_regs *regs) { - struct filename* filename; - const char su[] = SU_PATH; +static int faccessat_handler_pre(struct kprobe *p, struct pt_regs *regs) +{ + struct filename *filename; + const char su[] = SU_PATH; - if (!ksu_is_allow_uid(current_uid().val)) { - return 0; - } + if (!ksu_is_allow_uid(current_uid().val)) { + return 0; + } - filename = getname(PT_REGS_PARM2(regs)); + filename = getname(PT_REGS_PARM2(regs)); - if (IS_ERR(filename)) { - return 0; - } - if (!memcmp(filename->name, su, sizeof(su))) { - pr_info("faccessat su->sh!\n"); - PT_REGS_PARM2(regs) = sh_user_path(); - } + if (IS_ERR(filename)) { + return 0; + } + if (!memcmp(filename->name, su, sizeof(su))) { + pr_info("faccessat su->sh!\n"); + PT_REGS_PARM2(regs) = sh_user_path(); + } - putname(filename); + putname(filename); - return 0; + return 0; } -static int newfstatat_handler_pre(struct kprobe *p, struct pt_regs *regs) { - // const char sh[] = SH_PATH; - struct filename* filename; - const char su[] = SU_PATH; +static int newfstatat_handler_pre(struct kprobe *p, struct pt_regs *regs) +{ + // const char sh[] = SH_PATH; + struct filename *filename; + const char su[] = SU_PATH; - if (!ksu_is_allow_uid(current_uid().val)) { - return 0; - } + if (!ksu_is_allow_uid(current_uid().val)) { + return 0; + } - filename = getname(PT_REGS_PARM2(regs)); + filename = getname(PT_REGS_PARM2(regs)); - if (IS_ERR(filename)) { - return 0; - } - if (!memcmp(filename->name, su, sizeof(su))) { - pr_info("newfstatat su->sh!\n"); - PT_REGS_PARM2(regs) = sh_user_path(); - } + if (IS_ERR(filename)) { + return 0; + } + if (!memcmp(filename->name, su, sizeof(su))) { + pr_info("newfstatat su->sh!\n"); + PT_REGS_PARM2(regs) = sh_user_path(); + } - putname(filename); + putname(filename); - return 0; + return 0; } // https://elixir.bootlin.com/linux/v5.10.158/source/fs/exec.c#L1864 -static int execve_handler_pre(struct kprobe *p, struct pt_regs *regs) { - struct filename* filename; - const char sh[] = SH_PATH; - const char su[] = SU_PATH; +static int execve_handler_pre(struct kprobe *p, struct pt_regs *regs) +{ + struct filename *filename; + const char sh[] = SH_PATH; + const char su[] = SU_PATH; - static const char app_process[] = "/system/bin/app_process"; - static bool first_app_process = true; + static const char app_process[] = "/system/bin/app_process"; + static bool first_app_process = true; - filename = PT_REGS_PARM2(regs); - if (IS_ERR(filename)) { - return 0; - } + filename = PT_REGS_PARM2(regs); + if (IS_ERR(filename)) { + return 0; + } - if (first_app_process && !memcmp(filename->name, app_process, sizeof(app_process) - 1)) { - first_app_process = false; - pr_info("exec app_process, /data prepared!\n"); - apply_kernelsu_rules(); - ksu_load_allow_list(); - } + if (first_app_process && + !memcmp(filename->name, app_process, sizeof(app_process) - 1)) { + first_app_process = false; + pr_info("exec app_process, /data prepared!\n"); + apply_kernelsu_rules(); + ksu_load_allow_list(); + } - if (!ksu_is_allow_uid(current_uid().val)) { - return 0; - } + if (!ksu_is_allow_uid(current_uid().val)) { + return 0; + } - if (!memcmp(filename->name, su, sizeof(su))) { - pr_info("do_execveat_common su found\n"); - memcpy((void*) filename->name, sh, sizeof(sh)); + if (!memcmp(filename->name, su, sizeof(su))) { + pr_info("do_execveat_common su found\n"); + memcpy((void *)filename->name, sh, sizeof(sh)); - escape_to_root(); - } + escape_to_root(); + } - return 0; + return 0; } static struct kprobe faccessat_kp = { - .symbol_name = "do_faccessat", - .pre_handler = faccessat_handler_pre, + .symbol_name = "do_faccessat", + .pre_handler = faccessat_handler_pre, }; static struct kprobe newfstatat_kp = { - .symbol_name = "vfs_statx", - .pre_handler = newfstatat_handler_pre, + .symbol_name = "vfs_statx", + .pre_handler = newfstatat_handler_pre, }; static struct kprobe execve_kp = { - .symbol_name = "do_execveat_common", - .pre_handler = execve_handler_pre, + .symbol_name = "do_execveat_common", + .pre_handler = execve_handler_pre, }; // sucompat: permited process can execute 'su' to gain root access. -void enable_sucompat() { - int ret; +void enable_sucompat() +{ + int ret; - ret = register_kprobe(&execve_kp); - pr_info("execve_kp: %d\n", ret); - ret = register_kprobe(&newfstatat_kp); - pr_info("newfstatat_kp: %d\n", ret); - ret = register_kprobe(&faccessat_kp); - pr_info("faccessat_kp: %d\n", ret); + ret = register_kprobe(&execve_kp); + pr_info("execve_kp: %d\n", ret); + ret = register_kprobe(&newfstatat_kp); + pr_info("newfstatat_kp: %d\n", ret); + ret = register_kprobe(&faccessat_kp); + pr_info("faccessat_kp: %d\n", ret); }