Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
afd3e2f
begin mksu
5ec1cff Mar 14, 2026
b4766d4
actions: quote shell vars
5ec1cff Nov 1, 2024
7c7287b
actions: setup my sign key
5ec1cff Nov 2, 2024
216bc7b
actions: use var for chat id
5ec1cff Nov 23, 2024
e73cbc5
actions: add more path to trigger build manager when pull request
5ec1cff Nov 6, 2025
9362db8
ksubot: make MESSAGE_THREAD_ID optional
5ec1cff Nov 23, 2024
46ff9e4
ksubot: collect all commits
5ec1cff Sep 7, 2025
dc29d8d
ksubot: add upstream diff
5ec1cff Nov 6, 2025
5a1749e
add switch to init pgrp
5ec1cff Nov 13, 2025
1d8d9ec
feature: allow shell & enable adbd
5ec1cff Nov 19, 2025
54dce28
ci: Add workflow_dispatch trigger to build-manager
5ec1cff Dec 15, 2025
2b3060f
kernel: allow use with official manager
5ec1cff Dec 22, 2025
de06d6c
CONFIG_KSU=m
5ec1cff Dec 22, 2025
40d7b91
also generate compdb for kernel source code
5ec1cff Dec 22, 2025
6cd5f9a
use syscall table hook
5ec1cff Dec 21, 2025
f22707d
try blacklist mkp
5ec1cff Jan 2, 2026
0b2d964
inline hook tracepoint
5ec1cff Feb 25, 2026
c561199
fix cfi
5ec1cff Feb 25, 2026
6f5e7a6
make more functions non-atomic-context
5ec1cff Feb 25, 2026
6f6e30b
use aarch64_addr_write to modify memory
5ec1cff Feb 26, 2026
6c631fa
add ksu_patch_text
5ec1cff Feb 27, 2026
699017c
use fixmap
5ec1cff Feb 28, 2026
027154b
use stop_machine instead of stop_machine_cpuslocked
5ec1cff Feb 28, 2026
d932324
add comments about hooking tracepoint and ksu_patch_text
5ec1cff Feb 28, 2026
5124e2f
ksud: Save output image when flash is disabled
5ec1cff Mar 13, 2026
bd4099e
ksud: magica: use own adb_client to avoid providing private key path
5ec1cff Mar 13, 2026
8d1c828
ksud: add soft-reboot
5ec1cff Mar 13, 2026
5191d80
manager: use ksud soft-reboot
5ec1cff Mar 13, 2026
02271fe
fix upload
5ec1cff Mar 13, 2026
28106ed
sync with upstream
5ec1cff Nov 19, 2025
315418f
rename apk
5ec1cff Mar 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/build-lkm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ on:
jobs:
build-lkm:
strategy:
fail-fast: false
matrix:
kmi:
- android12-5.10
Expand Down
20 changes: 11 additions & 9 deletions .github/workflows/build-manager.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ on:
- 'manager/**'
- 'kernel/**'
- 'userspace/**'
- 'scripts/ksubot.py'
pull_request:
branches: [ "main", "dev" ]
paths:
Expand All @@ -21,7 +22,9 @@ on:
- 'manager/**'
- 'kernel/**'
- 'userspace/**'
- 'scripts/ksubot.py'
workflow_call:
workflow_dispatch:

jobs:
generate-key:
Expand Down Expand Up @@ -141,14 +144,14 @@ jobs:
- name: Setup need_upload
id: need_upload
run: |
if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then
if [ ! -z "${{ secrets.BOT_TOKEN }}" ] && [ "${{ github.event_name }}" != "workflow_dispatch" ]; then
echo "UPLOAD=true" >> $GITHUB_OUTPUT
else
echo "UPLOAD=false" >> $GITHUB_OUTPUT
fi

- name: Write key
if: ${{ ( github.event_name != 'pull_request' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev' )) || github.ref_type == 'tag' }}
if: ${{ github.event_name != 'pull_request' || github.ref_type == 'tag' }}
run: |
if [ ! -z "${{ secrets.KEYSTORE }}" ]; then
{
Expand All @@ -157,7 +160,7 @@ jobs:
echo KEY_PASSWORD='${{ secrets.KEY_PASSWORD }}'
echo KEYSTORE_FILE='key.jks'
} >> gradle.properties
echo ${{ secrets.KEYSTORE }} | base64 -d > key.jks
echo "${{ secrets.KEYSTORE }}" | base64 -d > key.jks
fi

- name: Write PR key
Expand Down Expand Up @@ -215,15 +218,15 @@ jobs:
fi

- name: Upload build artifact
if: ${{ github.event_name == 'pull_request' || (github.event_name != 'pull_request' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev')) || github.ref_type == 'tag' }}
if: ${{ github.event_name != 'pull_request' || github.ref_type == 'tag' }}
uses: actions/upload-artifact@v6
with:
name: manager
path: manager/app/build/outputs/apk/release/*.apk

- name: Upload mappings
uses: actions/upload-artifact@v6
if: ${{ ( github.event_name != 'pull_request' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev' )) || github.ref_type == 'tag' }}
if: ${{ github.event_name != 'pull_request' || github.ref_type == 'tag' }}
with:
name: "mappings"
path: "manager/app/build/outputs/mapping/release/"
Expand All @@ -239,11 +242,10 @@ jobs:
- name: Upload to telegram
if: github.event_name != 'pull_request' && steps.need_upload.outputs.UPLOAD == 'true'
env:
CHAT_ID: ${{ secrets.CHAT_ID }}
CHAT_ID: ${{ vars.CHAT_ID }}
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
MESSAGE_THREAD_ID: ${{ secrets.MESSAGE_THREAD_ID }}
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
COMMIT_URL: ${{ github.event.head_commit.url }}
MESSAGE_THREAD_ID: ${{ vars.MESSAGE_THREAD_ID }}
GITHUB_EVENT: ${{ toJson(github.event) }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
TITLE: Manager
BRANCH: ${{ github.ref_name }}
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.idea
.vscode
/.vscode
CLAUDE.md
AGENTS.md
4 changes: 2 additions & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
**English** | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [한국어](README_KR.md) | [Polski](README_PL.md) | [Português (Brasil)](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_IW.md) | [हिंदी](README_IN.md) | [Italiano](README_IT.md)

# KernelSU
# My KernelSU

<img src="https://kernelsu.org/logo.png" style="width: 96px;" alt="logo">

A kernel-based root solution for Android devices.
A [KernelSU](https://github.com/tiann/KernelSU/commit/218502a0e129cef326097497503923a62b5d870a)-based root solution for Android devices.

[![Latest release](https://img.shields.io/github/v/release/tiann/KernelSU?label=Release&logo=github)](https://github.com/tiann/KernelSU/releases/latest)
[![Weblate](https://img.shields.io/badge/Localization-Weblate-teal?logo=weblate)](https://hosted.weblate.org/engage/kernelsu)
Expand Down
2 changes: 1 addition & 1 deletion kernel/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ compile_commands.json
*.mod.c
*.symvers*
*.order
.*.ko.cmd
.*.cmd
.tmp_versions/
libs/
obj/
Expand Down
2 changes: 2 additions & 0 deletions kernel/.vscode/generate_compdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ def gen_compile_commands(cmd_file_search_path, out_dir):

if not cmd_file_search_path:
cmd_file_search_path = [out_dir]
else:
cmd_file_search_path += [out_dir]

cmd_files = []
for search_path in cmd_file_search_path:
Expand Down
42 changes: 39 additions & 3 deletions kernel/Kbuild
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ kernelsu-objs += feature.o
kernelsu-objs += ksud.o
kernelsu-objs += seccomp_cache.o
kernelsu-objs += file_wrapper.o
kernelsu-objs += util.o
kernelsu-objs += pte.o
kernelsu-objs += patch.o
kernelsu-objs += inline_hook.o
kernelsu-objs += trampoline.o

kernelsu-objs += selinux/selinux.o
kernelsu-objs += selinux/sepolicy.o
Expand Down Expand Up @@ -60,12 +63,35 @@ $(warning "KSU_GIT_VERSION not defined! It is better to make KernelSU a git repo
ccflags-y += -DKSU_VERSION=16
endif

KSU_NEW_DCACHE_FLUSH := $(shell grep -q __flush_dcache_area $(srctree)/arch/arm64/include/asm/cacheflush.h ; echo $$?)
$(info -- KSU_NEW_DCACHE_FLUSH: $(KSU_NEW_DCACHE_FLUSH))

KSU_MTE_SYNC_TAGS_DEF := $(shell grep 'void mte_sync_tags' $(srctree)/arch/arm64/include/asm/mte.h | grep -v 'static inline')
# 6.6
KSU_MTE_SYNC_TAGS_NR_PAGES := $(shell echo '$(KSU_MTE_SYNC_TAGS_DEF)' | grep -q 'nr_pages' && echo 1 || echo 0)
# 6.1
KSU_MTE_SYNC_TAGS_NORMAL := $(shell echo '$(KSU_MTE_SYNC_TAGS_DEF)' | grep -q '(pte_t pte)' && echo 1 || echo 0)
# 13-5.10
KSU_MTE_SYNC_TAGS_OLD_PTE := $(shell echo '$(KSU_MTE_SYNC_TAGS_DEF)' | grep -q 'old_pte' && echo 1 || echo 0)
# 12-5.10
KSU_MTE_SYNC_TAGS_PTEP := $(shell echo '$(KSU_MTE_SYNC_TAGS_DEF)' | grep -q '*ptep' && echo 1 || echo 0)
KSU_DEF_MTE_SYNC_TAGS := 'extern $(KSU_MTE_SYNC_TAGS_DEF)'

$(info -- KSU_DEF_MTE_SYNC_TAGS: $(KSU_DEF_MTE_SYNC_TAGS))
$(info -- KSU_MTE_SYNC_TAGS_NR_PAGES: $(KSU_MTE_SYNC_TAGS_NR_PAGES))
$(info -- KSU_MTE_SYNC_TAGS_PTEP: $(KSU_MTE_SYNC_TAGS_PTEP))
$(info -- KSU_MTE_SYNC_TAGS_OLD_PTE: $(KSU_MTE_SYNC_TAGS_OLD_PTE))
$(info -- KSU_MTE_SYNC_TAGS_NORMAL: $(KSU_MTE_SYNC_TAGS_NORMAL))

OFFICIAL_EXPECTED_SIZE := 0x033b
OFFICIAL_EXPECTED_HASH := c371061b19d8c7d7d6133c6a9bafe198fa944e50c1b31c9d8daa8d7f1fc2d2d6

ifndef KSU_EXPECTED_SIZE
KSU_EXPECTED_SIZE := 0x033b
KSU_EXPECTED_SIZE := 384
endif

ifndef KSU_EXPECTED_HASH
KSU_EXPECTED_HASH := c371061b19d8c7d7d6133c6a9bafe198fa944e50c1b31c9d8daa8d7f1fc2d2d6
KSU_EXPECTED_HASH := 7e0c6d7278a3bb8e364e0fcba95afaf3666cf5ff3c245a3b63c8833bd0445cc4
endif

ifdef KSU_MANAGER_PACKAGE
Expand All @@ -78,6 +104,8 @@ $(info -- KernelSU Manager signature hash: $(KSU_EXPECTED_HASH))

ccflags-y += -DEXPECTED_SIZE=$(KSU_EXPECTED_SIZE)
ccflags-y += -DEXPECTED_HASH=\"$(KSU_EXPECTED_HASH)\"
ccflags-y += -DOFFICIAL_EXPECTED_SIZE=$(OFFICIAL_EXPECTED_SIZE)
ccflags-y += -DOFFICIAL_EXPECTED_HASH=\"$(OFFICIAL_EXPECTED_HASH)\"

ifdef KSU_EXPECTED_SIZE2
ifndef KSU_EXPECTED_HASH2
Expand All @@ -89,6 +117,14 @@ $(info -- KernelSU Manager signature size2: $(KSU_EXPECTED_SIZE2))
$(info -- KernelSU Manager signature hash2: $(KSU_EXPECTED_HASH2))
endif

ccflags-y += -DKSU_NEW_DCACHE_FLUSH=$(KSU_NEW_DCACHE_FLUSH)

ccflags-y += -DKSU_DEF_MTE_SYNC_TAGS=$(KSU_DEF_MTE_SYNC_TAGS)
ccflags-y += -DKSU_MTE_SYNC_TAGS_NR_PAGES=$(KSU_MTE_SYNC_TAGS_NR_PAGES)
ccflags-y += -DKSU_MTE_SYNC_TAGS_PTEP=$(KSU_MTE_SYNC_TAGS_PTEP)
ccflags-y += -DKSU_MTE_SYNC_TAGS_OLD_PTE=$(KSU_MTE_SYNC_TAGS_OLD_PTE)
ccflags-y += -DKSU_MTE_SYNC_TAGS_NORMAL=$(KSU_MTE_SYNC_TAGS_NORMAL)

ccflags-y += -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat -Wno-missing-prototypes
ccflags-y += -Wno-declaration-after-statement -Wno-unused-function

Expand Down
2 changes: 1 addition & 1 deletion kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ $(info -- MDIR: $(MDIR))
.PHONY: all compdb clean format check-format

all: check_symbol
make -C $(KDIR) M=$(MDIR) modules
CONFIG_KSU=m make -C $(KDIR) M=$(MDIR) modules
./check_symbol kernelsu.ko $(KDIR)/vmlinux
compdb:
python3 $(MDIR)/.vscode/generate_compdb.py -O $(KDIR) $(MDIR)
Expand Down
8 changes: 8 additions & 0 deletions kernel/allowlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,10 @@ bool __ksu_is_allow_uid(uid_t uid)
return true;
}

if (unlikely(allow_shell) && uid == 2000) {
return true;
}

if (likely(uid <= BITMAP_UID_MAX)) {
return !!(allow_list_bitmap[uid / BITS_PER_BYTE] &
(1 << (uid % BITS_PER_BYTE)));
Expand Down Expand Up @@ -340,6 +344,10 @@ void ksu_get_root_profile(uid_t uid, struct root_profile *profile)
goto use_default;
}

if (unlikely(allow_shell && uid == SHELL_UID)) {
goto use_default;
}

rcu_read_lock();
list_for_each_entry_rcu (p, &allow_list, list) {
if (uid == p->profile.current_uid && p->profile.allow_su) {
Expand Down
2 changes: 2 additions & 0 deletions kernel/allowlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,5 @@ static inline bool is_isolated_process(uid_t uid)
return appid >= FIRST_ISOLATED_UID && appid <= LAST_ISOLATED_UID;
}
#endif

extern bool allow_shell;
4 changes: 3 additions & 1 deletion kernel/apk_sign.c
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,9 @@ bool is_manager_apk(char *path)
return false;
}
#endif
if (check_v2_signature(path, EXPECTED_SIZE, EXPECTED_HASH)) {
if (check_v2_signature(path, EXPECTED_SIZE, EXPECTED_HASH) ||
check_v2_signature(path, OFFICIAL_EXPECTED_SIZE,
OFFICIAL_EXPECTED_HASH)) {
return true;
}
#ifdef EXPECTED_SIZE2
Expand Down
2 changes: 1 addition & 1 deletion kernel/app_profile.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ static void disable_seccomp(void)
{
struct task_struct *fake;

fake = kmalloc(sizeof(*fake), GFP_ATOMIC);
fake = kmalloc(sizeof(*fake), GFP_KERNEL);
if (!fake) {
pr_warn("failed to alloc fake task_struct\n");
return;
Expand Down
93 changes: 93 additions & 0 deletions kernel/hook.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2023 bmax121. All Rights Reserved.
*/

#ifndef __KSU_H_HOOK_
#define __KSU_H_HOOK_
#include "linux/types.h" // IWYU pragma: keep
#include "linux/version.h"

#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0)
#include "asm/patching.h" // IWYU pragma: keep
#else
#include "asm/insn.h" // IWYU pragma: keep
#endif

// https://github.com/bmax121/KernelPatch/blob/94e5be9cc3f8a6fbd9574155e3e9753200ab9bfb/kernel/include/hook.h#L54

#define HOOK_INTO_BRANCH_FUNC

typedef enum {
HOOK_NO_ERR = 0,
HOOK_BAD_ADDRESS = 4095,
HOOK_DUPLICATED = 4094,
HOOK_NO_MEM = 4093,
HOOK_BAD_RELO = 4092,
HOOK_TRANSIT_NO_MEM = 4091,
HOOK_CHAIN_FULL = 4090,
} hook_err_t;

#define HOOK_MEM_REGION_NUM 4
#define TRAMPOLINE_MAX_NUM 6
#define RELOCATE_INST_NUM (4 * 8 + 8 - 4)

#define HOOK_CHAIN_NUM 0x10

#define ARM64_NOP 0xd503201f
#define ARM64_BTI_C 0xd503245f
#define ARM64_BTI_J 0xd503249f
#define ARM64_BTI_JC 0xd50324df
#define ARM64_PACIASP 0xd503233f
#define ARM64_PACIBSP 0xd503237f

typedef struct {
// in
uint64_t func_addr;
uint64_t origin_addr;
uint64_t replace_addr;
uint64_t relo_addr;
// out
int32_t tramp_insts_num;
int32_t relo_insts_num;
uint32_t origin_insts[TRAMPOLINE_MAX_NUM] __attribute__((aligned(8)));
uint32_t tramp_insts[TRAMPOLINE_MAX_NUM] __attribute__((aligned(8)));
uint32_t relo_insts[RELOCATE_INST_NUM] __attribute__((aligned(8)));
} hook_t __attribute__((aligned(8)));

static inline int is_bad_address(void *addr)
{
return ((uint64_t)addr & 0x8000000000000000) != 0x8000000000000000;
}

int32_t branch_from_to(uint32_t *tramp_buf, uint64_t src_addr,
uint64_t dst_addr);
int32_t branch_relative(uint32_t *buf, uint64_t src_addr, uint64_t dst_addr);
int32_t branch_absolute(uint32_t *buf, uint64_t addr);
int32_t ret_absolute(uint32_t *buf, uint64_t addr);

hook_err_t hook_prepare(hook_t *hook);
int hook_install(hook_t *hook);

/**
* @brief Inline-hook function which address is @param func with function @param replace,
* after hook, original @param func is backuped in @param backup.
*
* @note If multiple modules hook this function simultaneously,
* it will cause abnormality when unload the modules. Please use hook_wrap instead
*
* @see hook_wrap
*
* @param func
* @param replace
* @param backup
* @return hook_err_t
*/
hook_err_t hook(void *func, void *replace, void **backup);

#define KSU_PATCH_TEXT_FLUSH_DCACHE 1
#define KSU_PATCH_TEXT_FLUSH_ICACHE 2

int ksu_patch_text(void *dst, void *src, size_t len, int flags);

#endif
Loading
Loading