Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
5fe9840
refactor(kernel, ksud, manager): Switch webview zygote umount to allo…
aviraxp Aug 30, 2026
f5992bf
fix(kernel): Preserve a ebitmap's size for each policy type (https://…
aviraxp Sep 4, 2026
fdd1880
feat(ksud): Implement SIGSYS handler (https://github.com/tiann/Kernel…
aviraxp Sep 6, 2026
f1ae2ce
kernel, uapi, ksud: make fd wrapper work with app profile (https://gi…
Dr-TSNG Sep 6, 2026
ff765f8
feat: new version matching detection mechanism (https://github.com/ti…
5ec1cff Sep 7, 2026
4e82e32
feat(resetprop): support update long value for ro props (https://gith…
5ec1cff Sep 8, 2026
830a5ae
kernel: Reject all signature block id except v2 (https://github.com/t…
aviraxp Sep 9, 2026
23a40c0
manager: update translations from Weblate (#395)
weblate Sep 9, 2026
1e25a4c
manager: update translations from Weblate (#400)
weblate Sep 10, 2026
246d3e5
manager: replace SettingsJumpPageWidget with SettingsChooseWidget (#401)
luyanci Sep 10, 2026
7ad75c5
kernel: get session_keyring from key_permission LSM call
AlexLiuDev233 Sep 11, 2026
07a28eb
build(deps): bump the crates group in /userspace/ksuinit with 2 updat…
dependabot[bot] Sep 11, 2026
4f27ee1
build(deps): bump the crates group across 1 directory with 4 updates …
dependabot[bot] Sep 11, 2026
6930e97
kernel: add setup submodule command(#183)
luyanci Sep 11, 2026
052ca27
kernel: compat for old version of susfs and include task_stack.h for …
omajili-manbu Sep 11, 2026
19b6f42
manager: bump the maven group across 1 directory with 18 updates and …
dependabot[bot] Sep 12, 2026
fa1da13
manager: update translations from Weblate (#402)
weblate Sep 12, 2026
3380d41
ksud: sync upstream commit
Tools-cx-app Sep 12, 2026
b195422
manager: workaround for ListItem crash
AlexLiuDev233 Sep 13, 2026
601f6d2
manager: refine home page state get
AlexLiuDev233 Sep 13, 2026
c04159f
manager: improve superuser sort (#405)
luyanci Sep 13, 2026
7741f87
kernel: retain capabilities across execve for non-root profiles (http…
u9521 Sep 13, 2026
7e92d45
ksud, ksuinit: use our forks for dependencies (#412)
AlexLiuDev233 Sep 14, 2026
3341f9c
manager: Add floating navigation bar with a customization toggle (#334)
Bouteillepleine Sep 14, 2026
3576e6a
manager: update translations from Weblate (#404)
weblate Sep 14, 2026
a5bb612
ksubot: fix release
luyanci Sep 14, 2026
833edb0
manager: Restrict floating bottom bar to Android 12+
luyanci Sep 14, 2026
e3fcb18
manager: fix cannot following showNavigationBarBadge when floatingbot…
luyanci Sep 15, 2026
b22a46e
ci: Fix setup Android SDK
luyanci Sep 15, 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
2 changes: 2 additions & 0 deletions .github/workflows/build-manager.yml
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ jobs:

- name: Setup Android SDK
uses: android-actions/setup-android@v4
with:
packages: "platform-tools"

- name: Build APK
run: |
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/lints-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ jobs:

- name: Setup Android SDK
uses: android-actions/setup-android@v4
with:
packages: "platform-tools"

- name: Check Manager Lint
run: |
Expand Down
24 changes: 5 additions & 19 deletions kernel/compat/kernel_compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/errno.h>

#include "klog.h" // IWYU pragma: keep
#include "kernel_compat.h"
Expand Down Expand Up @@ -196,39 +197,24 @@ void ksu_run_in_init_if_possible(void (*callback)(void *), void *data)
}

#ifdef KSU_COMPAT_REQUIRE_SESSION_KEYRING
#include <linux/key.h>
#include <linux/errno.h>
#include <linux/cred.h>
#include "ksu.h"

static inline struct key *ksu_get_session_keyring(const struct cred *cred)
{
// https://github.com/torvalds/linux/commit/3a50597de8635cd05133bd12c95681c82fe7b878
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
return rcu_dereference(cred->session_keyring);
#else
return rcu_dereference(current->cred->tgcred->session_keyring);
#endif
}

struct key *init_session_keyring = NULL;
extern int install_session_keyring_to_cred(struct cred *, struct key *);

// WARNING! Make sure caller in init!!!
// https://github.com/torvalds/linux/commit/5c7e372caa35d303e414caeb64ee2243fd3cac3d
// in our target kernel version, it are protected by rcu, so let's rcu_dereference here
void setup_ksu_cred_session_keyring(void)
{
if (ksu_get_session_keyring(ksu_cred)) {
// if we have session_keyring, skip
return;
}

if (strcmp(current->comm, "init")) {
// we are only interested in `init` process
if (init_session_keyring == NULL) {
// if init_session_keyring is null, skip
return;
}

install_session_keyring_to_cred(ksu_cred, ksu_get_session_keyring(current_cred()));
install_session_keyring_to_cred(ksu_cred, init_session_keyring);

pr_info("kernel_compat: %s: install init_session_keyring to ksu_cred\n", __func__);
}
Expand Down
13 changes: 13 additions & 0 deletions kernel/compat/kernel_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,20 @@ extern void ksu_run_in_init_if_possible(void (*callback)(void *), void *data);
#if defined(CONFIG_KEYS) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(KSU_COMPAT_IS_HISI_LEGACY) || \
defined(KSU_COMPAT_IS_HISI_LEGACY_HM2))
#define KSU_COMPAT_REQUIRE_SESSION_KEYRING
#include <linux/key.h>

extern struct key *init_session_keyring;
extern void setup_ksu_cred_session_keyring(void);

static inline struct key *ksu_get_session_keyring(const struct cred *cred)
{
// https://github.com/torvalds/linux/commit/3a50597de8635cd05133bd12c95681c82fe7b878
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
return rcu_dereference(cred->session_keyring);
#else
return rcu_dereference(current->cred->tgcred->session_keyring);
#endif
}
#endif

#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0) || defined(KSU_HAS_MODERN_STATIC_KEY_INTERFACE)
Expand Down
9 changes: 9 additions & 0 deletions kernel/core/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,10 @@ void setup_ksu_cred(void)
{
setup_ksu_cred_selinux();
#ifdef KSU_COMPAT_REQUIRE_SESSION_KEYRING
if (init_session_keyring == NULL) {
init_session_keyring = ksu_get_session_keyring(current_cred());
}

setup_ksu_cred_session_keyring();
#endif
}
Expand All @@ -155,6 +159,11 @@ bool allow_shell = false;
bool ksu_no_custom_rc = false;
module_param_named(norc, ksu_no_custom_rc, bool, 0);

#ifdef MODULE
bool ksu_bundled = false;
module_param_named(bundled, ksu_bundled, bool, 0);
#endif

char ksu_block_modules[256];
module_param_string(block_modules, ksu_block_modules, sizeof(ksu_block_modules), 0);
MODULE_PARM_DESC(block_modules, "Comma-separated preset module names to acknowledge without loading");
Expand Down
6 changes: 6 additions & 0 deletions kernel/feature/adb_root.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
#include <linux/ptrace.h>
#include <linux/static_key.h>
#include <linux/slab.h>
#include <linux/version.h>

// https://github.com/torvalds/linux/commit/68db0cf10678630d286f4bbbbdfa102951a35faa
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
#include <linux/sched/task_stack.h>
#endif

#include "adb_root.h"
#include "arch.h"
Expand Down
29 changes: 1 addition & 28 deletions kernel/feature/kernel_umount.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
#include <linux/slab.h>
#include <linux/version.h>
#include <linux/cred.h>
#include <linux/compiler.h>
#include <linux/fs.h>
#include <linux/mount.h>
#include <linux/namei.h>
Expand Down Expand Up @@ -31,7 +30,6 @@
#include "feature/sucompat.h"

static bool ksu_kernel_umount_enabled = true;
bool ksu_webview_zygote_umount_enabled = false;

static int kernel_umount_feature_get(u64 *value)
{
Expand All @@ -54,27 +52,6 @@ static const struct ksu_feature_handler kernel_umount_handler = {
.set_handler = kernel_umount_feature_set,
};

static int webview_zygote_umount_feature_get(u64 *value)
{
*value = ksu_webview_zygote_umount_enabled ? 1 : 0;
return 0;
}

static int webview_zygote_umount_feature_set(u64 value)
{
bool enable = value != 0;
ksu_webview_zygote_umount_enabled = enable;
pr_info("webview_zygote_umount: set to %d\n", enable);
return 0;
}

static const struct ksu_feature_handler webview_zygote_umount_handler = {
.feature_id = KSU_FEATURE_WEBVIEW_ZYGOTE_UMOUNT,
.name = "webview_zygote_umount",
.get_handler = webview_zygote_umount_feature_get,
.set_handler = webview_zygote_umount_feature_set,
};

#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) || defined(KSU_HAS_PATH_UMOUNT)
extern int path_umount(struct path *path, int flags);
static void ksu_umount_mnt(const char *mnt, struct path *path, int flags)
Expand Down Expand Up @@ -152,7 +129,7 @@ int ksu_handle_umount(uid_t old_uid, uid_t new_uid)
// 1. Normal app: zygote -> appuid
// 2. Isolated process forked from zygote: zygote -> isolated_process
// 3. App zygote forked from zygote: zygote -> appuid
// 4. Webview zygote forked from zygote: zygote -> webview_zygote (controlled by feature policy)
// 4. Webview zygote forked from zygote: zygote -> webview_zygote
// 5. Isolated process forked from app zygote: appuid -> isolated_process (already handled by 3)
// 6. Isolated process forked from webview zygote (already handled by 4)
if (!is_appuid(new_uid) && new_uid != WEBVIEW_ZYGOTE_UID && !is_isolated_process(new_uid)) {
Expand Down Expand Up @@ -205,13 +182,9 @@ void __init ksu_kernel_umount_init(void)
if (ksu_register_feature_handler(&kernel_umount_handler)) {
pr_err("Failed to register kernel_umount feature handler\n");
}
if (ksu_register_feature_handler(&webview_zygote_umount_handler)) {
pr_err("Failed to register webview_zygote_umount feature handler\n");
}
}

void __exit ksu_kernel_umount_exit(void)
{
ksu_unregister_feature_handler(KSU_FEATURE_WEBVIEW_ZYGOTE_UMOUNT);
ksu_unregister_feature_handler(KSU_FEATURE_KERNEL_UMOUNT);
}
1 change: 0 additions & 1 deletion kernel/feature/kernel_umount.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

void ksu_kernel_umount_init(void);
void ksu_kernel_umount_exit(void);
extern bool ksu_webview_zygote_umount_enabled;

// Handler function to be called from setresuid hook
int ksu_handle_umount(uid_t old_uid, uid_t new_uid);
Expand Down
63 changes: 52 additions & 11 deletions kernel/feature/sucompat.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "runtime/ksud.h"
#include "feature/sucompat.h"
#include "policy/app_profile.h"
#include "supercall/supercall.h"
#ifdef CONFIG_KSU_TRACEPOINT_HOOK
#include "hook/syscall_hook.h"
#else
Expand Down Expand Up @@ -235,6 +236,7 @@ static long ksu_handle_execve_sucompat_common_internal(const char __user **filen
char path[sizeof(su_path) + 1];
long ret, orig_regs[5];
unsigned long addr;
int su_fd = -1;
int tmp_fd;
struct file *ksud_file;
const struct cred *old_cred;
Expand Down Expand Up @@ -309,6 +311,13 @@ static long ksu_handle_execve_sucompat_common_internal(const char __user **filen
regs->__PT_PARM3_REG = orig_regs[2];
regs->__PT_SYSCALL_PARM4_REG = orig_regs[3];
regs->__PT_PARM5_REG = orig_regs[4];
} else {
// Only grant the scoped driver capability after the selected root
// profile has been applied successfully.
su_fd = ksu_install_su_fd();
if (su_fd < 0) {
pr_warn("install su session fd failed: %d\n", su_fd);
}
}
return ret;

Expand Down Expand Up @@ -343,19 +352,19 @@ static inline int do_ksu_handle_execveat_sucompat(int *fd, const char *filename,
// Yep, maybe someusers love turn off sucompat <- idk how they managed to keep using it
// But for mostly users, sucompat is enabled, so unlikely here
if (!static_branch_unlikely(&ksu_su_compat_enabled)) {
return 0;
return -EINVAL;
}
#else
if (!ksu_su_compat_enabled) {
return 0;
return -EINVAL;
}
#endif

if (!is_allowed)
return 0;
return -EINVAL;

if (likely(memcmp(filename, su_path, sizeof(su_path))))
return 0;
return -EINVAL;

pr_info("do_execveat_common su found\n");

Expand All @@ -375,6 +384,24 @@ static inline int do_ksu_handle_execveat_sucompat(int *fd, const char *filename,
memcpy((void *)filename, ksud_path, sizeof(ksud_path));
out:
ksu_sulog_emit_pending(pending_sucompat, 0, GFP_KERNEL);
// always flag that, to avoid old version of susfs hang in boot
set_thread_flag(TIF_PROC_IN_KSU_EXECVE);
return 0;
}

// fd, filename, argv, envp, flags and retval were NOT provided in bprm_committed_creds (KSU_COMPAT_NO_POST_EXECVE_HOOK)!
int ksu_handle_post_execve(int *fd, const char *filename, void *argv, void *envp, int *flags, int *retval)
{
if (likely(!test_thread_flag(TIF_PROC_IN_KSU_EXECVE))) {
return -EINVAL;
}
#ifndef KSU_COMPAT_HAS_SUSFS_INSTALL_SU_FD_DIRECT_CALL
ksu_install_su_fd();
#endif
// #ifdef KSU_COMPAT_NO_POST_EXECVE_HOOK
// return 0;
// #endif
// TODO Implement tmpfd of ksud when KSU_COMPAT_NO_POST_EXECVE_HOOK is not defined
return 0;
}

Expand Down Expand Up @@ -412,7 +439,7 @@ int ksu_handle_execve(int *fd, const char *filename, void *argv, void *envp, int

#ifndef CONFIG_KSU_TRACEPOINT_HOOK
if (ksu_is_current_proc_unprivillege()) {
return 0;
return -EINVAL;
}
#endif

Expand All @@ -424,7 +451,7 @@ int ksu_handle_execve(int *fd, const char *filename, void *argv, void *envp, int
}

if (*fd != AT_FDCWD || *flags != 0) {
return 0;
return -EINVAL;
}

skip_check:
Expand Down Expand Up @@ -453,21 +480,29 @@ int ksu_handle_execve(int *fd, const char *filename, void *argv, void *envp, int
return ret;
}

// old hook, link to ksu_handle_execve
int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv, void *envp, int *flags)
{
struct filename *filename;
filename = *filename_ptr;
if (IS_ERR(filename)) {
return 0;
return -EINVAL;
}

return ksu_handle_execve(fd, filename->name, argv, envp, flags);
}

// because simonpunk, he do check in hook side
// and call ksu_handle_execveat_sucompat
// we need unpack filename* in here, and pass it to ksu_handle_execveat
int ksu_handle_post_execveat(int *fd, struct filename **filename_ptr, void *argv, void *envp, int *flags, int *retval)
{
struct filename *filename;
filename = *filename_ptr;
if (IS_ERR(filename)) {
return -EINVAL;
}

return ksu_handle_post_execve(fd, filename->name, argv, envp, flags, retval);
}

// compat for check in hook
#ifdef CONFIG_KSU_SUSFS
int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr, void *argv, void *envp, int *flags)
{
Expand All @@ -479,6 +514,12 @@ int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr, void *

return ksu_handle_execveat(fd, filename_ptr, argv, envp, flags);
}

int ksu_handle_post_execveat_sucompat(int *fd, struct filename **filename_ptr, void *argv, void *envp, int *flags,
int *retval)
{
return ksu_handle_post_execveat(fd, filename_ptr, argv, envp, flags, retval);
}
#endif
#endif

Expand Down
16 changes: 16 additions & 0 deletions kernel/feature/sucompat.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ int ksu_handle_stat(int *dfd, struct filename **filename, int *flags);
#else
int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, int *__unused_flags);
int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags);
int ksu_handle_post_execve(int *fd, const char *filename, void *argv, void *envp, int *flags, int *retval);
#endif // #ifdef CONFIG_KSU_SUSFS

#ifdef CONFIG_KSU_TRACEPOINT_HOOK
Expand All @@ -42,17 +43,32 @@ long ksu_handle_execveat_sucompat_internal(const char __user **filename_user, in
#elif defined(CONFIG_KSU_SUSFS) // susfs
#include <linux/susfs_def.h>

// sync with manual hook
#define TIF_PROC_IN_KSU_EXECVE 61

#define ksu_is_current_proc_unprivillege susfs_is_current_proc_no_su
#define ksu_set_current_proc_unprivillege susfs_set_current_proc_no_su
#define ksu_clear_current_proc_unprivillege susfs_clear_current_proc_no_su
#else // manual hook

// we have a huge number spare TIFs can use
// https://elixir.bootlin.com/linux/v7.2.2/source/arch/arm64/include/asm/thread_info.h#L90
// https://elixir.bootlin.com/linux/v7.2.2/source/arch/arm/include/asm/thread_info.h#L154
// https://elixir.bootlin.com/linux/v7.2.2/source/arch/x86/include/asm/thread_info.h#L103
// 23 - 31 is spare in arm32 (9 tifs)
// 32 - 63 is spare in arm64 (32 tifs)
// 28 - 31 is spare in x86 (4 tifs)
// 28 - 63 is spare in x86-64 (36 tifs)

// 63 already used as TIF_KSU_DISABLE_ESCAPE_WITH_ROOT (64bit)
// 31 already used as TIF_KSU_DISABLE_ESCAPE_WITH_ROOT (32bit)
// TIF_PROC_IN_KSU_EXECVE may reuse in future? because it only useful when current->in_execve=1
#ifdef CONFIG_64BIT
#define TIF_PROC_NON_PRIVILEGE 62
#define TIF_PROC_IN_KSU_EXECVE 61
#else
#define TIF_PROC_NON_PRIVILEGE 30
#define TIF_PROC_IN_KSU_EXECVE 29
#endif

static inline bool ksu_is_current_proc_unprivillege(void)
Expand Down
Loading