Skip to content

Commit

Permalink
version 0.10.0 (bmax121#56)
Browse files Browse the repository at this point in the history
1. Feature: update patch and unpatch supported (current version >= 0.9.0)
2. Feature: add KPM control interface
3. Feature: Embed extra-item (such as KPM, executable, shell ...) into kernel image early support. These extra-items will trigger execution at appropriate time. (current only support KPM triggered at "pre-kernel-init" event)
4. bug fix

---------

Co-authored-by: bmax <bmax@placeholder.com>
  • Loading branch information
bmax121 and bmax authored Feb 22, 2024
1 parent d8b9d97 commit add4759
Show file tree
Hide file tree
Showing 74 changed files with 1,654 additions and 4,277 deletions.
4 changes: 0 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,8 @@ Currently only supports arm64 architecture.
Linux 3.18 - 6.2 (theoretically)
Linux 6.3+ (not yet adapted)
## Get Help
## Get Involved
## Community Discussion
## More Information
[Documentation](./doc/)
Expand Down
3 changes: 2 additions & 1 deletion doc/build.md → doc/en/build.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Require a bare-metal cross compiler
```shell
export TARGET_COMPILE=aarch64-none-elf-
cd kernel
# export ANDROID=1 # Android version, including support for the 'su' command
export ANDROID=1 # Android version, including support for the 'su' command
make
```

Expand All @@ -19,6 +19,7 @@ kptools can run anywhere, just compile it.
- Using Makefile

```shell
export ANDROID=1
cd tools
make
```
Expand Down
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions doc/en/module.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# KernelPatch Module
File renamed without changes.
File renamed without changes.
5 changes: 0 additions & 5 deletions doc/module.md

This file was deleted.

17 changes: 17 additions & 0 deletions doc/zh-CN/module.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# KernelPatch Module

## 什么是 KernelPatch Module (KPM)

**KPM is an ELF file that can be loaded and run within the kernel space by KernelPatch.**

## How to write a KPM

Here are a few examples that you can use to quickly understand.

1. A simple hello world KPM: [hello-world](/kpm-demo/hello)
2. How to do kernel function inline-hook via KPM: [inline-hook](/kpm-demo/inlinehook)
3. How to hook system call via KPM: [syscallhook](/kpm-demo/syscallhook)

### Working without Kernel source tree

### Working with Kernel soruce tree
5 changes: 3 additions & 2 deletions kernel/base/predata.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ int on_each_extra_item(int (*callback)(const patch_extra_item_t *extra, const ch
while (item_addr < _kp_extra_end) {
patch_extra_item_t *item = (patch_extra_item_t *)item_addr;
if (item->type == EXTRA_TYPE_NONE) break;
rc = callback(item, (const char *)(item_addr + sizeof(patch_extra_item_t)),
(void *)(item_addr + sizeof(patch_extra_item_t) + item->args_size), udata);
const char *args = item->args_size > 0 ? (const char *)(item_addr + sizeof(patch_extra_item_t)) : 0;
const void *con = (void *)(item_addr + sizeof(patch_extra_item_t) + item->args_size);
rc = callback(item, args, con, udata);
if (rc) break;
item_addr += sizeof(patch_extra_item_t);
item_addr += item->args_size;
Expand Down
45 changes: 21 additions & 24 deletions kernel/base/start.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <barrier.h>
#include <stdarg.h>

#include "../banner"
#include "start.h"
#include "hook.h"
#include "tlsf.h"
Expand Down Expand Up @@ -42,14 +43,6 @@ KP_EXPORT_SYMBOL(printk);

int (*vsprintf)(char *buf, const char *fmt, va_list args) = 0;

const char kernel_patch_logo[] = "\n"
" _ __ _ ____ _ _ \n"
"| |/ /___ _ __ _ __ ___| | _ \\ __ _| |_ ___| |__ \n"
"| ' // _ \\ '__| '_ \\ / _ \\ | |_) / _` | __/ __| '_ \\ \n"
"| . \\ __/ | | | | | __/ | __/ (_| | || (__| | | |\n"
"|_|\\_\\___|_| |_| |_|\\___|_|_| \\__,_|\\__\\___|_| |_|\n";
KP_EXPORT_SYMBOL(kernel_patch_logo);

static struct vm_struct
{
struct vm_struct *next;
Expand Down Expand Up @@ -93,6 +86,9 @@ int64_t kernel_size = 0;
int64_t page_shift = 0;
int64_t page_size = 0;
int64_t va_bits = 0;
int64_t page_level;
uint64_t pgd_pa;
uint64_t pgd_va;
// int64_t pa_bits = 0;

uint64_t kernel_stext_va = 0;
Expand Down Expand Up @@ -126,26 +122,18 @@ void log_boot(const char *fmt, ...)
boot_log_offset += ret;
}

uint64_t *pgtable_entry_kernel(uint64_t va)
uint64_t *pgtable_entry(uint64_t pgd, uint64_t va)
{
uint64_t page_level = (va_bits - 4) / (page_shift - 3);
uint64_t pxd_bits = page_shift - 3;
uint64_t pxd_ptrs = 1u << pxd_bits;
uint64_t ttbr1_el1;
asm volatile("mrs %0, ttbr1_el1" : "=r"(ttbr1_el1));

uint64_t baddr = ttbr1_el1 & 0xFFFFFFFFFFFE;
uint64_t page_size = 1 << page_shift;
uint64_t page_size_mask = ~(page_size - 1);
uint64_t pxd_pa = baddr & page_size_mask;
uint64_t pxd_va = phys_to_virt(pxd_pa);
uint64_t pxd_va = pgd;
uint64_t pxd_pa = virt_to_phys(pxd_va);
uint64_t pxd_entry_va = 0;
uint64_t block_lv = 0;

// ================
// todo:
// branch to some function (even empty) will work, but I don't know why,
// if anyone knows, please let me know. thank you very much.
// Branch to some function (even empty), It can work,
// I don't know why, if anyone knows, please let me know. thank you very much.
// ================
__flush_dcache_area((void *)pxd_va, page_size);

Expand All @@ -171,7 +159,7 @@ uint64_t *pgtable_entry_kernel(uint64_t va)
break;
}
}
#if 1
#if 0
uint64_t left_bit = page_shift + (block_lv ? (3 - block_lv) * pxd_bits : 0);
uint64_t tpa = pxd_pa + (va & ((1u << left_bit) - 1));
uint64_t tlva = phys_to_virt(tpa);
Expand All @@ -182,7 +170,7 @@ uint64_t *pgtable_entry_kernel(uint64_t va)
#endif
return (uint64_t *)pxd_entry_va;
}
KP_EXPORT_SYMBOL(pgtable_entry_kernel);
KP_EXPORT_SYMBOL(pgtable_entry);

static void prot_myself()
{
Expand Down Expand Up @@ -403,7 +391,7 @@ static void start_init(uint64_t kimage_voff, uint64_t linear_voff)

vsprintf = (typeof(vsprintf))kallsyms_lookup_name("vsprintf");

log_boot(kernel_patch_logo);
log_boot(KERNEL_PATCH_BANNER);

endian = *(unsigned char *)&(uint16_t){ 1 } ? little : big;
setup_header_t *header = &start_preset.header;
Expand Down Expand Up @@ -435,6 +423,15 @@ static void start_init(uint64_t kimage_voff, uint64_t linear_voff)
page_shift = 16;
}
page_size = 1 << page_shift;

page_level = (va_bits - 4) / (page_shift - 3);

uint64_t ttbr1_el1;
asm volatile("mrs %0, ttbr1_el1" : "=r"(ttbr1_el1));
uint64_t baddr = ttbr1_el1 & 0xFFFFFFFFFFFE;
uint64_t page_size_mask = ~(page_size - 1);
pgd_pa = baddr & page_size_mask;
pgd_va = phys_to_virt(pgd_pa);
}

static int nice_zone()
Expand Down
14 changes: 9 additions & 5 deletions kernel/include/kpmodule.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,19 @@
#define KPM_AUTHOR(x) KPM_INFO(author, x, KPM_AUTHOR_LEN)
#define KPM_DESCRIPTION(x) KPM_INFO(description, x, KPM_DESCRIPTION_LEN)

typedef int (*mod_initcall_t)(const char *args, void *reserved);
typedef int (*mod_ctlcall_t)(const char *ctl_args, char *__user out_msg, int outlen);
typedef int (*mod_exitcall_t)(void *reserved);
typedef long (*mod_initcall_t)(const char *args, const char *event, void *reserved);
typedef long (*mod_ctl0call_t)(const char *ctl_args, char *__user out_msg, int outlen);
typedef long (*mod_ctl1call_t)(void *a1, void *a2, void *a3);
typedef long (*mod_exitcall_t)(void *reserved);

#define KPM_INIT(fn) \
static mod_initcall_t __kpm_initcall_##fn __attribute__((__used__)) __attribute__((__section__(".kpm.init"))) = fn

#define KPM_CTL(fn) \
static mod_ctlcall_t __kpm_ctlmodule_##fn __attribute__((__used__)) __attribute__((__section__(".kpm.ctl"))) = fn
#define KPM_CTL0(fn) \
static mod_ctl0call_t __kpm_ctlmodule_##fn __attribute__((__used__)) __attribute__((__section__(".kpm.ctl0"))) = fn

#define KPM_CTL1(fn) \
static mod_ctl1call_t __kpm_ctlmodule_##fn __attribute__((__used__)) __attribute__((__section__(".kpm.ctl1"))) = fn

#define KPM_EXIT(fn) \
static mod_exitcall_t __kpm_exitcall_##fn __attribute__((__used__)) __attribute__((__section__(".kpm.exit"))) = fn
Expand Down
10 changes: 9 additions & 1 deletion kernel/include/pgtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ extern int64_t kernel_size;
extern int64_t page_shift;
extern int64_t page_size;
extern int64_t va_bits;
extern int64_t page_level;
extern uint64_t pgd_pa;
extern uint64_t pgd_va;
// extern int64_t pa_bits;

static inline uint64_t phys_to_virt(uint64_t phys)
Expand Down Expand Up @@ -159,6 +162,11 @@ static inline int is_kimg_range(uint64_t addr)
return addr >= kernel_va && addr < (kernel_va + kernel_size);
}

uint64_t *pgtable_entry_kernel(uint64_t va);
uint64_t *pgtable_entry(uint64_t pgd, uint64_t va);

static inline uint64_t *pgtable_entry_kernel(uint64_t va)
{
return pgtable_entry(pgd_va, va);
}

#endif
2 changes: 1 addition & 1 deletion kernel/include/predata.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
#define _KP_PREDATA_H_

#include <ktypes.h>
#include <stdbool.h>
#include <preset.h>

int superkey_auth(const char *key);
const char *get_superkey();
uint64_t get_build_config();
struct patch_symbol *get_preset_patch_sym();
int on_each_extra_item(int (*callback)(const patch_extra_item_t *extra, const char *arg, const void *data, void *udata),
void *udata);
Expand Down
33 changes: 31 additions & 2 deletions kernel/include/preset.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@

#define PATCH_SYMBOL_LEN (512)

#define PATCH_EXTRA_ITEM_LEN (64)
#define ADDITIONAL_LEN (512)

#define PATCH_EXTRA_ITEM_LEN (128)

#define VERSION(major, minor, patch) (((major) << 16) + ((minor) << 8) + (patch))

Expand Down Expand Up @@ -135,12 +137,36 @@ _Static_assert(sizeof(patch_symbol_t) == PATCH_SYMBOL_LEN, "sizeof patch_symbol_
#ifndef __ASSEMBLY__

#define EXTRA_ALIGN 0x10
#define EXTRA_NAME_LEN 0x20
#define EXTRA_EVENT_LEN 0x20

typedef int32_t extra_item_type;

#define EXTRA_TYPE_NONE 0
#define EXTRA_TYPE_KPM 1
#define EXTRA_TYPE_SHELL 2
#define EXTRA_TYPE_EXEC 3
#define EXTRA_TYPE_RAW 4
#define EXTRA_TYPE_ANDROID_RC 5

#define EXTRA_TYPE_NONE_STR "none"
#define EXTRA_TYPE_KPM_STR "kpm"
#define EXTRA_TYPE_SHELL_STR "shell"
#define EXTRA_TYPE_EXEC_STR "exec"
#define EXTRA_TYPE_RAW_STR "raw"
#define EXTRA_TYPE_ANDROID_RC_STR "android_rc"

// todo
#define EXTRA_EVENT_PAGING_INIT "paging-init"
#define EXTRA_EVENT_PRE_KERNEL_INIT "pre-kernel-init"
#define EXTRA_EVENT_KPM_DEFAULT EXTRA_EVENT_PRE_KERNEL_INIT
#define EXTRA_EVENT_POST_KERNEL_INIT "post-kernel-init"
#define EXTRA_EVENT_PRE_INIT "pre-init"
#define EXTRA_EVENT_POST_INIT "post-init"
#define EXTRA_EVENT_PRE_SECOND_STAGE "pre-second-stage"
#define EXTRA_EVENT_POST_SECOND_STAGE "post-second-stage"
#define EXTRA_EVENT_PRE_ZYGOTE_START "pre-zygote-start"
#define EXTRA_EVENT_POST_ZYGOTE_START "post-zygote-start"

struct _patch_extra_item
{
Expand All @@ -149,9 +175,11 @@ struct _patch_extra_item
struct
{
extra_item_type type;
char name[EXTRA_NAME_LEN];
char event[EXTRA_EVENT_LEN];
int32_t priority;
int32_t con_size;
int32_t args_size;
int32_t con_size;
};
char _cap[PATCH_EXTRA_ITEM_LEN];
};
Expand Down Expand Up @@ -181,6 +209,7 @@ typedef struct _setup_preset_t
uint8_t header_backup[HDR_BACKUP_SIZE];
uint8_t superkey[SUPER_KEY_LEN];
patch_symbol_t patch_symbol;
char additional[ADDITIONAL_LEN];
} setup_preset_t;
#else
#define setup_kernel_version_offset 0
Expand Down
22 changes: 2 additions & 20 deletions kernel/linux/arch/arm64/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,8 @@
// #define THREAD_START_SP (THREAD_SIZE - 16)
// #define task_pt_regs(p) ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)

static inline struct pt_regs *_task_pt_reg(struct task_struct *task)
{
unsigned long stack = (unsigned long)task_stack_page(task);
uintptr_t addr = (uintptr_t)(thread_size + stack);
if (kver < VERSION(4, 4, 19)) {
// todo: fault on 3.18 ranch-27
addr -= 16;
addr -= sizeof(struct pt_regs_lt4419);
} else if (kver < VERSION(4, 14, 0)) {
addr -= 16;
addr -= sizeof(struct pt_regs_lt4140);
} else if (kver < VERSION(5, 10, 0)) {
addr -= sizeof(struct pt_regs_lt5100);
} else {
addr -= sizeof(struct pt_regs);
}
struct pt_regs *regs;
regs = (struct pt_regs *)(addr);
return regs;
}
// implemented in utils
struct pt_regs *_task_pt_reg(struct task_struct *task);

#define task_pt_regs(p) _task_pt_reg(p)

Expand Down
2 changes: 1 addition & 1 deletion kernel/linux/arch/arm64/include/asm/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ static inline void forget_syscall(struct pt_regs *regs)

static inline unsigned long user_stack_pointer(struct pt_regs *regs)
{
if (compat_user_mode(regs)) return regs->compat_sp;
// if (compat_user_mode(regs)) return regs->compat_sp;
return regs->sp;
}

Expand Down
Loading

0 comments on commit add4759

Please sign in to comment.