Skip to content

Commit

Permalink
20230225-GithubActions-1
Browse files Browse the repository at this point in the history
  • Loading branch information
CoolestEnoch committed Feb 25, 2023
1 parent 79efdac commit 881ee5b
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 66 deletions.
3 changes: 2 additions & 1 deletion kernel/drivers/kernelsu/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ endif
ccflags-y += -DEXPECTED_SIZE=$(EXPECTED_SIZE)
ccflags-y += -DEXPECTED_HASH=$(EXPECTED_HASH)
ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat
ccflags-y += -Wno-macro-redefined -Wno-declaration-after-statement -std=gnu11
ccflags-y += -Wno-macro-redefined -Wno-declaration-after-statement
ccflags-y += -std=gnu11
16 changes: 8 additions & 8 deletions kernel/drivers/kernelsu/allowlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,12 @@ void do_persistent_allow_list(struct work_struct *work)
}

// store magic and version
if (kernel_write_compat(fp, &magic, sizeof(magic), &off) != sizeof(magic)) {
if (ksu_kernel_write_compat(fp, &magic, sizeof(magic), &off) != sizeof(magic)) {
pr_err("save_allow_list write magic failed.\n");
goto exit;
}

if (kernel_write_compat(fp, &version, sizeof(version), &off) !=
if (ksu_kernel_write_compat(fp, &version, sizeof(version), &off) !=
sizeof(version)) {
pr_err("save_allow_list write version failed.\n");
goto exit;
Expand All @@ -144,8 +144,8 @@ void do_persistent_allow_list(struct work_struct *work)
p = list_entry(pos, struct perm_data, list);
pr_info("save allow list uid :%d, allow: %d\n", p->uid,
p->allow);
kernel_write_compat(fp, &p->uid, sizeof(p->uid), &off);
kernel_write_compat(fp, &p->allow, sizeof(p->allow), &off);
ksu_kernel_write_compat(fp, &p->uid, sizeof(p->uid), &off);
ksu_kernel_write_compat(fp, &p->allow, sizeof(p->allow), &off);
}

exit:
Expand Down Expand Up @@ -195,13 +195,13 @@ void do_load_allow_list(struct work_struct *work)
}

// verify magic
if (kernel_read_compat(fp, &magic, sizeof(magic), &off) != sizeof(magic) ||
if (ksu_kernel_read_compat(fp, &magic, sizeof(magic), &off) != sizeof(magic) ||
magic != FILE_MAGIC) {
pr_err("allowlist file invalid: %d!\n", magic);
goto exit;
}

if (kernel_read_compat(fp, &version, sizeof(version), &off) !=
if (ksu_kernel_read_compat(fp, &version, sizeof(version), &off) !=
sizeof(version)) {
pr_err("allowlist read version: %d failed\n", version);
goto exit;
Expand All @@ -212,12 +212,12 @@ void do_load_allow_list(struct work_struct *work)
while (true) {
u32 uid;
bool allow = false;
ret = kernel_read_compat(fp, &uid, sizeof(uid), &off);
ret = ksu_kernel_read_compat(fp, &uid, sizeof(uid), &off);
if (ret <= 0) {
pr_info("load_allow_list read err: %d\n", ret);
break;
}
ret = kernel_read_compat(fp, &allow, sizeof(allow), &off);
ret = ksu_kernel_read_compat(fp, &allow, sizeof(allow), &off);

pr_info("load_allow_uid: %d, allow: %d\n", uid, allow);

Expand Down
35 changes: 18 additions & 17 deletions kernel/drivers/kernelsu/apk_sign.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ check_v2_signature(char *path, unsigned expected_size, unsigned expected_hash)
loff_t pos;

int sign = -1;
int i;
struct file *fp = filp_open(path, O_RDONLY, 0);
if (IS_ERR(fp)) {
pr_err("open %s error.", path);
Expand All @@ -26,13 +27,13 @@ check_v2_signature(char *path, unsigned expected_size, unsigned expected_hash)

sign = 1;
// https://en.wikipedia.org/wiki/Zip_(file_format)#End_of_central_directory_record_(EOCD)
for (int i = 0;; ++i) {
for (i = 0;; ++i) {
unsigned short n;
pos = generic_file_llseek(fp, -i - 2, SEEK_END);
kernel_read_compat(fp, &n, 2, &pos);
ksu_kernel_read_compat(fp, &n, 2, &pos);
if (n == i) {
pos -= 22;
kernel_read_compat(fp, &size4, 4, &pos);
ksu_kernel_read_compat(fp, &size4, 4, &pos);
if ((size4 ^ 0xcafebabeu) == 0xccfbf1eeu) {
break;
}
Expand All @@ -45,55 +46,55 @@ check_v2_signature(char *path, unsigned expected_size, unsigned expected_hash)

pos += 12;
// offset
kernel_read_compat(fp, &size4, 0x4, &pos);
ksu_kernel_read_compat(fp, &size4, 0x4, &pos);
pos = size4 - 0x18;

kernel_read_compat(fp, &size8, 0x8, &pos);
kernel_read_compat(fp, buffer, 0x10, &pos);
ksu_kernel_read_compat(fp, &size8, 0x8, &pos);
ksu_kernel_read_compat(fp, buffer, 0x10, &pos);
if (strcmp((char *)buffer, "APK Sig Block 42")) {
goto clean;
}

pos = size4 - (size8 + 0x8);
kernel_read_compat(fp, &size_of_block, 0x8, &pos);
ksu_kernel_read_compat(fp, &size_of_block, 0x8, &pos);
if (size_of_block != size8) {
goto clean;
}

for (;;) {
uint32_t id;
uint32_t offset;
kernel_read_compat(fp, &size8, 0x8, &pos); // sequence length
ksu_kernel_read_compat(fp, &size8, 0x8, &pos); // sequence length
if (size8 == size_of_block) {
break;
}
kernel_read_compat(fp, &id, 0x4, &pos); // id
ksu_kernel_read_compat(fp, &id, 0x4, &pos); // id
offset = 4;
pr_info("id: 0x%08x\n", id);
if ((id ^ 0xdeadbeefu) == 0xafa439f5u ||
(id ^ 0xdeadbeefu) == 0x2efed62f) {
kernel_read_compat(fp, &size4, 0x4,
ksu_kernel_read_compat(fp, &size4, 0x4,
&pos); // signer-sequence length
kernel_read_compat(fp, &size4, 0x4, &pos); // signer length
kernel_read_compat(fp, &size4, 0x4,
ksu_kernel_read_compat(fp, &size4, 0x4, &pos); // signer length
ksu_kernel_read_compat(fp, &size4, 0x4,
&pos); // signed data length
offset += 0x4 * 3;

kernel_read_compat(fp, &size4, 0x4,
ksu_kernel_read_compat(fp, &size4, 0x4,
&pos); // digests-sequence length
pos += size4;
offset += 0x4 + size4;

kernel_read_compat(fp, &size4, 0x4,
ksu_kernel_read_compat(fp, &size4, 0x4,
&pos); // certificates length
kernel_read_compat(fp, &size4, 0x4,
ksu_kernel_read_compat(fp, &size4, 0x4,
&pos); // certificate length
offset += 0x4 * 2;
#if 0
int hash = 1;
signed char c;
for (unsigned i = 0; i < size4; ++i) {
kernel_read_compat(fp, &c, 0x1, &pos);
ksu_kernel_read_compat(fp, &c, 0x1, &pos);
hash = 31 * hash + c;
}
offset += size4;
Expand All @@ -103,7 +104,7 @@ check_v2_signature(char *path, unsigned expected_size, unsigned expected_hash)
int hash = 1;
signed char c;
for (unsigned i = 0; i < size4; ++i) {
kernel_read_compat(fp, &c, 0x1, &pos);
ksu_kernel_read_compat(fp, &c, 0x1, &pos);
hash = 31 * hash + c;
}
offset += size4;
Expand Down
58 changes: 31 additions & 27 deletions kernel/drivers/kernelsu/core_hook.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,9 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
u32 version = KERNEL_SU_VERSION;
if (copy_to_user(arg3, &version, sizeof(version))) {
pr_err("prctl reply error, cmd: %d\n", arg2);
return 0;
}
}
return 0;
}

if (arg2 == CMD_REPORT_EVENT) {
Expand Down Expand Up @@ -253,6 +253,31 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
return 0;
}

if (arg2 == CMD_GET_ALLOW_LIST || arg2 == CMD_GET_DENY_LIST) {
if (is_manager() || 0 == current_uid().val) {
u32 array[128];
u32 array_length;
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);
}
} else {
pr_err("prctl copy allowlist error\n");
}
}
}
return 0;
}

// all other cmds are for 'root manager'
if (!is_manager()) {
pr_info("Only manager can do cmd: %d\n", arg2);
Expand All @@ -271,25 +296,7 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
}
}
ksu_show_allow_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);
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);
}
} else {
pr_err("prctl copy allowlist error\n");
}
}
return 0;
}

return 0;
Expand Down Expand Up @@ -369,16 +376,13 @@ static int ksu_task_prctl(int option, unsigned long arg2, unsigned long arg3,
}
// kernel 4.4 and 4.9
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
static int ksu_key_permission(key_ref_t key_ref,
const struct cred *cred,
unsigned perm)
static int ksu_key_permission(key_ref_t key_ref, const struct cred *cred,
unsigned perm)
{
if (init_session_keyring != NULL)
{
if (init_session_keyring != NULL) {
return 0;
}
if (strcmp(current->comm, "init"))
{
if (strcmp(current->comm, "init")) {
// we are only interested in `init` process
return 0;
}
Expand Down
4 changes: 2 additions & 2 deletions kernel/drivers/kernelsu/kernel_compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include "linux/errno.h"
struct key *init_session_keyring = NULL;
#endif
ssize_t kernel_read_compat(struct file *p, void *buf, size_t count, loff_t *pos){
ssize_t ksu_kernel_read_compat(struct file *p, void *buf, size_t count, loff_t *pos){
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
return kernel_read(p, buf, count, pos);
#else
Expand All @@ -19,7 +19,7 @@ ssize_t kernel_read_compat(struct file *p, void *buf, size_t count, loff_t *pos)
#endif
}

ssize_t kernel_write_compat(struct file *p, const void *buf, size_t count, loff_t *pos){
ssize_t ksu_kernel_write_compat(struct file *p, const void *buf, size_t count, loff_t *pos){
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
return kernel_write(p, buf, count, pos);
#else
Expand Down
4 changes: 2 additions & 2 deletions kernel/drivers/kernelsu/kernel_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

extern struct key *init_session_keyring;

extern ssize_t kernel_read_compat(struct file *p, void *buf, size_t count, loff_t *pos);
extern ssize_t kernel_write_compat(struct file *p, const void *buf, size_t count, loff_t *pos);
extern ssize_t ksu_kernel_read_compat(struct file *p, void *buf, size_t count, loff_t *pos);
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(4, 10, 0)
static inline int install_session_keyring(struct key *keyring)
Expand Down
57 changes: 52 additions & 5 deletions kernel/drivers/kernelsu/ksud.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "asm/current.h"
#include "linux/string.h"
#include "linux/cred.h"
#include "linux/dcache.h"
#include "linux/err.h"
Expand Down Expand Up @@ -62,7 +63,7 @@ void on_post_fs_data(void)
return;
}
done = true;
pr_info("ksu_load_allow_list");
pr_info("on_post_fs_data!");
ksu_load_allow_list();
// sanity check, this may influence the performance
stop_input_hook();
Expand Down Expand Up @@ -113,6 +114,35 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
return 0;
}

static ssize_t (*orig_read)(struct file *, char __user *, size_t, loff_t *);
static ssize_t (*orig_read_iter)(struct kiocb *, struct iov_iter *);
static struct file_operations fops_proxy;
static ssize_t read_count_append = 0;

static ssize_t read_proxy(struct file *file, char __user *buf, size_t count,
loff_t *pos)
{
bool first_read = file->f_pos == 0;
ssize_t ret = orig_read(file, buf, count, pos);
if (first_read) {
pr_info("read_proxy append %ld + %ld", ret, read_count_append);
ret += read_count_append;
}
return ret;
}

static ssize_t read_iter_proxy(struct kiocb *iocb, struct iov_iter *to)
{
bool first_read = iocb->ki_pos == 0;
ssize_t ret = orig_read_iter(iocb, to);
if (first_read) {
pr_info("read_iter_proxy append %ld + %ld", ret,
read_count_append);
ret += read_count_append;
}
return ret;
}

int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
size_t *count_ptr, loff_t **pos)
{
Expand Down Expand Up @@ -185,6 +215,22 @@ int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
return 0;
}

// we've succeed to insert ksud.rc, now we need to proxy the read and modify the result!
// But, we can not modify the file_operations directly, because it's in read-only memory.
// We just replace the whole file_operations with a proxy one.
memcpy(&fops_proxy, file->f_op, sizeof(struct file_operations));
orig_read = file->f_op->read;
if (orig_read) {
fops_proxy.read = read_proxy;
}
orig_read_iter = file->f_op->read_iter;
if (orig_read_iter) {
fops_proxy.read_iter = read_iter_proxy;
}
// replace the file_operations
file->f_op = &fops_proxy;
read_count_append = rc_count;

*buf_ptr = buf + rc_count;
*count_ptr = count - rc_count;

Expand All @@ -193,7 +239,8 @@ int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,

static unsigned int volumedown_pressed_count = 0;

static bool is_volumedown_enough(unsigned int count) {
static bool is_volumedown_enough(unsigned int count)
{
return count >= 3;
}

Expand All @@ -220,14 +267,14 @@ int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code,
return 0;
}

bool ksu_is_safe_mode() {

bool ksu_is_safe_mode()
{
static bool safe_mode = false;
if (safe_mode) {
// don't need to check again, userspace may call multiple times
return true;
}

// stop hook first!
stop_input_hook();

Expand Down
Loading

0 comments on commit 881ee5b

Please sign in to comment.