Compare commits

..

475 Commits

Author SHA1 Message Date
Rifat Azad
db7d73c202 kernel/Kconfig: KSU_SUSFS_SUS_SU now also depends on KSU_KPROBES_HOOK 2025-07-21 02:22:15 +06:00
Rifat Azad
e15652c758 kernel: bumped version 12803 2025-07-21 02:20:36 +06:00
Rifat Azad
194ba5820a kernel: guard syscall hook types
- for kernel syscall hooks we need to pass additional guards for ksun (#ifdef CONFIG_KSU -> #if defined(CONFIG_KSU) && !defined(CONFIG_KSU_KPROBES_HOOK)) or else it will fail to build because of undefined symbol

- reference https://github.com/KernelSU-Next/kernel_patches/blob/main/syscall_hook/min_scope_syscall_hooks_v1.4.patch
2025-07-21 02:20:06 +06:00
Rifat Azad
2165241049 kernel: bumped version 12802 2025-07-19 23:52:40 +06:00
Rifat Azad
0c6c0a512c kernel: implement v2_signature size/hash override from userspace through kernel module parameter
- /sys/module/kernelsu/parameters/expected_manager_*
2025-07-19 23:49:44 +06:00
Rifat Azad
d88bffdba2 kernel: bumped version 12800 2025-07-18 01:06:40 +06:00
Rifat Azad
278b1226dc kernel: bumped version 2025-07-16 22:37:16 +06:00
Rifat Azad
89c9b1b8b8 kernel: use ksu_strncpy_from_user_retry when kprobes hook sucompat pagefaults 2025-07-16 22:20:43 +06:00
Rifat Azad
b04f45c278 kernel: set fasle to /sbin for susfs_try_umount_all 2025-07-16 21:20:44 +06:00
Rifat Azad
e4a6ade958 kernel/Makefile: hardcore driver version 2025-07-16 01:39:55 +06:00
Rifat Azad
6fe4fcbce0 kernel: susfs 1.5.9 a13-5.15 patch 2025-07-15 22:53:17 +06:00
Rifat Azad
52112a7ee3 source: clean up 2025-07-15 21:33:26 +06:00
Edrick Sinsuan
81f4f09d0c ksud: Address pagefault in ksu_handle_execveat_ksud (#662)
* ksud: Address pagefault in ksu_handle_execveat_ksud

As pointed out by @backslashxx, when strncpy pagefaults, it causes
the first_arg to be completely NULL in some systems. This causes
second_stage initialization to fail hence causing SU to be
non-functional.

This patch copies ksu_strncpy_from_user_retry from @backslashxx's
commit:
e2fe25e485

This adds a fallback to perform a normal strncpy_from_user when nofault
fails which allows us to get the first_arg in such cases.

Co-authored-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
Signed-off-by: Edrick Sinsuan <evcsinsuan@gmail.com>

* Revert "ksud: Add second_stage init variant (#653)"

This reverts commit c6b60a24e8.

---------

Signed-off-by: Edrick Sinsuan <evcsinsuan@gmail.com>
Co-authored-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-07-15 21:24:20 +06:00
Rifat Azad
2241696498 ksud: fix rust fmt 2025-07-15 04:02:34 +06:00
Rifat Azad
514c5458ed manager: append 'spoofed' tag to the app version name 2025-07-15 03:58:11 +06:00
Rifat Azad
d30bb33a9c ksud: removed banner 2025-07-15 03:36:11 +06:00
Rifat Azad
ec7fe6b039 manager: minor improvement to flash screen topbar status 2025-07-15 03:35:58 +06:00
Rifat Azad
3fd61e0ee5 New Crowdin updates (#646)
* New translations manager/app/src/main/res/values-hi-rIN/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-pt-rBR/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-vi-rVN/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-de-rDE/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-in-rID/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-pt-rBR/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-de-rDE/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-ru-rRU/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-uk-rUA/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-vi-rVN/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-ar-rSA/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-bn-rBD/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-bg-rBG/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-zh-rCN/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-zh-rTW/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-fr-rFR/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-de-rDE/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-hi-rIN/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-hu-rHU/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-in-rID/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-it-rIT/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-ja-rJP/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-ko-rKR/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-fa-rIR/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-pl-rPL/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-pt-rBR/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-ru-rRU/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-es-rEM/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-sv-rSE/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-th-rTH/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-tr-rTR/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-uk-rUA/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-vi-rVN/strings.xml (bundle: 8)
2025-07-15 01:10:58 +06:00
Rifat Azad
8fc85993f1 ksud: fix clippy errors 2025-07-14 22:55:22 +06:00
Rifat Azad
df07860e44 ksud: fix rust fmt errors 2025-07-14 20:22:31 +06:00
Rifat Azad
bd03c296a1 kernel/Makefile: remove redundant get_cred_rcu backports 2025-07-14 20:11:13 +06:00
Rifat Azad
14b7861f44 template: add feature request template 2025-07-14 19:59:38 +06:00
Rifat Azad
3c421b1362 manager: added more module list sort options ( enabled, action and webui) 2025-07-13 20:59:33 +06:00
Edrick Sinsuan
c6b60a24e8 ksud: Add second_stage init variant (#653)
There are some ROMs based on AOSP that calls on second stage init
with argc: 2 but with first_arg: "". This causes KSU to not work
properly on those systems.

Signed-off-by: Edrick Sinsuan <evcsinsuan@gmail.com>
2025-07-13 05:26:10 +06:00
Rifat Azad
1baedd89b7 manager: add eruda console (v3.4.3) to webui-next 2025-07-12 23:18:26 +06:00
Rifat Azad
b567e9b275 kernel: add better error message if CMD_GET_MANAGWR_UID fails to fetch manager_uid 2025-07-11 04:11:17 +06:00
Rifat Azad
3ba5b028d4 manager: fix hook mode status showing blank when Natives.getHookMode() is null 2025-07-10 18:10:14 +06:00
Tashfin Shakeer Rhythm
4d633a1e0e kernel: selinux: rules: Fix illegal RCU lock usage in apply_kernelsu_rules() (#2646)
When kernel is compiled with CONFIG_DEBUG_ATOMIC_SLEEP enabled, it
prints the following splat in dmesg during post boot:

[ 6.739169] init: Opening SELinux policy
[ 6.751520] init: Loading SELinux policy
[ 6.894684] SELinux: policy capability network_peer_controls=1 [
6.894688] SELinux: policy capability open_perms=1 [ 6.894690] SELinux:
policy capability extended_socket_class=1 [ 6.894691] SELinux: policy
capability always_check_network=0 [ 6.894693] SELinux: policy capability
cgroup_seclabel=0 [ 6.894695] SELinux: policy capability
nnp_nosuid_transition=1 [ 7.214323] selinux: SELinux: Loaded file
context from: [ 7.214332] selinux:
/system/etc/selinux/plat_file_contexts [ 7.214339] selinux:
/system_ext/etc/selinux/system_ext_file_contexts [ 7.214345] selinux:
/product/etc/selinux/product_file_contexts [ 7.214350] selinux:
/vendor/etc/selinux/vendor_file_contexts [ 7.214356] selinux:
/odm/etc/selinux/odm_file_contexts [ 7.216398] KernelSU:
/system/bin/init argc: 2
[ 7.216401] KernelSU: /system/bin/init first arg: second_stage [
7.216403] KernelSU: /system/bin/init second_stage executed [ 7.216506]
BUG: sleeping function called from invalid context at
security/selinux/ss/hashtab.c:47 [ 7.216512] in_atomic(): 0,
irqs_disabled(): 0, non_block: 0, pid: 1, name: init [ 7.216516]
preempt_count: 0, expected: 0
[ 7.216518] RCU nest depth: 1, expected: 0
[ 7.216524] CPU: 6 PID: 1 Comm: init Not tainted
5.4.289-Scarlet-v2.0-beta3 #1 [ 7.216526] Hardware name: redwood based
Qualcomm Technologies, Inc. SM7325 (DT) [ 7.216528] Call trace:
[ 7.216536] dump_backtrace+0x0/0x210
[ 7.216539] show_stack+0x14/0x20
[ 7.216544] dump_stack+0x9c/0xec
[ 7.216548] __might_resched+0x1f0/0x210
[ 7.216552] hashtab_insert+0x38/0x230
[ 7.216557] add_type+0xd4/0x2e0
[ 7.216559] ksu_type+0x24/0x60
[ 7.216562] apply_kernelsu_rules+0xa8/0x650
[ 7.216565] ksu_handle_execveat_ksud+0x2a8/0x460
[ 7.216568] ksu_handle_execveat+0x2c/0x60
[ 7.216571] __arm64_sys_execve+0xe8/0xf0
[ 7.216574] el0_svc_common+0xf4/0x1a0
[ 7.216577] do_el0_svc+0x2c/0x40
[ 7.216579] el0_sync_handler+0x18c/0x200
[ 7.216582] el0_sync+0x140/0x180

This is because apply_kernelsu_rules() uses rcu_read_lock() to protect
SELinux policy modifications. However, cond_resched() from
hashtab_insert() at security/selinux/ss/hashtab.c is internally called
and it sleeps which is illegal under an RCU read-side critical section.

While replacing it with a spinlock would suppress the warning, this is
fundamentally incorrect because sleeping is illegal while holding a
spinlock and spinlock would turn off preemption which isn't an ideal
solution since it intentionally turns off rescheduling, and can lead to
deadlocks.

Instead, replace the RCU lock with a mutex lock. Mutex lock allows
sleeping when necessary, which is appropriate here because
apply_kernelsu_rules() runs in process context, not in atomic or
interrupt context. As apply_kernelsu_rules() is invoked only once during
post boot (SYSTEM_RUNNING), the mutex lock does not introduce any major
runtime performance regression and provides correct synchronization.

Fixes: https://github.com/tiann/KernelSU/issues/2637

Signed-off-by: Tashfin Shakeer Rhythm <tashfinshakeerrhythm@gmail.com>
2025-07-10 17:50:14 +06:00
Rifat Azad
f08fcec777 kernel: changed constant value for CMD_HOOK_MODE to 0xC0DEAD1A and CMD_GET_MANAGER_UID to 16, to avoid future conflitcs with upstream 2025-07-10 00:50:45 +06:00
Rifat Azad
afe6ad7261 docs: add crowdin localization progress 2025-07-10 00:04:22 +06:00
Rifat Azad
54b26fd32c New Crowdin updates (#644)
* New translations manager/app/src/main/res/values-zh-rCN/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-zh-rTW/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-de-rDE/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-hi-rIN/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-ru-rRU/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-vi-rVN/strings.xml (bundle: 8)
2025-07-08 22:00:14 +06:00
Berserkr2k
4b56b14a4f docs: Add Spanish README (#628)
Add the README_ES.md file to provide documentation for Spanish-speaking users.
2025-07-08 00:39:25 +06:00
Rifat Azad
9b4c6057a0 New Crowdin updates (#634)
* New translations manager/app/src/main/res/values-ar-rSA/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-bn-rBD/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-bg-rBG/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-zh-rCN/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-zh-rTW/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-fr-rFR/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-de-rDE/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-hi-rIN/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-hu-rHU/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-in-rID/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-it-rIT/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-ja-rJP/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-ko-rKR/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-fa-rIR/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-pl-rPL/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-pt-rBR/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-ru-rRU/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-es-rEM/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-sv-rSE/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-th-rTH/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-tr-rTR/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-uk-rUA/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-vi-rVN/strings.xml (bundle: 8)
2025-07-07 17:27:03 +06:00
Rifat Azad
873740ef1c docs: added Crowdin Translators credits to README 2025-07-07 17:25:53 +06:00
Rifat Azad
ad80c1ea77 manager: remove current locale format to fix locale format to android_code 2025-07-07 17:12:03 +06:00
Rifat Azad
d5c6f0affb New Crowdin updates (#629)
* New translations manager/app/src/main/res/values-de/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-pl/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-ru/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-es/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-zh/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-ru/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-es/strings.xml (bundle: 8)
2025-07-07 13:10:09 +06:00
Rifat Azad
162056f9ff New Crowdin updates (#627)
* New translations manager/app/src/main/res/values-ar/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-bn/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-bg/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-zh/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-fr/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-de/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-hi/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-hu/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-id/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-it/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-ja/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-ko/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-fa/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-pl/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-pt/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-ru/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-es/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-sv/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-th/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-tr/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-uk/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-vi/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-ar/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-de/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-id/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-it/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-ja/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-fa/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-es/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-vi/strings.xml (bundle: 8)
2025-07-07 04:20:04 +06:00
Eren
3af1d0354d docs: Update README_TR.md (#598) 2025-07-06 13:52:41 +06:00
kam821
6adb2eaf51 Update Polish README (#624)
- Moved to the new README format
- Added missing languages in the header
- Updated README_UA.md link title.
2025-07-06 13:46:43 +06:00
Rifat Azad
ce91e4fedb New Crowdin updates (#623)
* New translations manager/app/src/main/res/values-ar/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-bn/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-bg/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-zh/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-fr/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-de/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-hi/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-hu/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-id/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-it/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-ja/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-ko/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-fa/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-pl/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-pt/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-ru/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-es/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-sv/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-th/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-tr/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-uk/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-vi/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-ar/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-bn/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-bg/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-de/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-id/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-ja/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-ru/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-es/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-tr/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-uk/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-vi/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-ar/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-bn/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-de/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-hi/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-id/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-pl/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-pt/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-ru/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-es/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-fr/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-de/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-id/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-it/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-pl/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-es/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-tr/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-uk/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-zh/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-de/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-pt/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-vi/strings.xml (bundle: 8)

* New translations manager/app/src/main/res/values-bn/strings.xml (bundle: 8)
2025-07-06 13:45:36 +06:00
Rifat Azad
a36390ea03 Update Crowdin configuration file 2025-07-05 21:47:41 +06:00
Rifat Azad
e31e0271cb manager: clean translations 2025-07-05 21:37:48 +06:00
Rifat Azad
b97fc2bec2 Revert "kernel/Makefile: check kernelsu driver version from online git repo first, if fails then check local .git and if that also fails then use hardcoded fallback"
This reverts commit a37f398cc7.

- this is a very flawed logic for when we try to build with release tags or specific commit hashes instead of latest commit, the online logic will always append latest version instead of the actual version of code (i.e release tags or commit hashes)
2025-07-05 17:35:25 +06:00
Rifat Azad
10875ee190 manager: refactor home module/superuser plural/singular strings 2025-07-04 23:52:20 +06:00
Rifat Azad
fdb01c918a docs: add webui-next api documentation 2025-07-04 21:38:41 +06:00
Rifat Azad
6afa86d2ae manager/webui: let getPackagesIcons generate icon and store in cache as well when called 2025-07-04 01:22:53 +06:00
Rifat Azad
25fa6b7b9b manager: webui-next is now amoled mode compliant 2025-07-03 22:27:18 +06:00
Rifat Azad
a361fa3272 manager: implement getPackagesIcons and cacheAllPackageIcons api to webui-next 2025-07-03 22:03:13 +06:00
Rifat Azad
4a9733c078 manager: sort a-z order for webui-next list packages api 2025-07-03 20:12:21 +06:00
Rifat Azad
31aa571bc2 susfsd: refactored show features & support to match ksu_susfs standards (ref https://gitlab.com/simonpunk/susfs4ksu/-/commit/ad56926) 2025-07-03 19:30:06 +06:00
Rifat Azad
58167a4289 manager: introduce app package info API for webui-next 2025-07-03 15:54:31 +06:00
Rifat Azad
a8bfd1cc7d manager:added more dynamic color vars to webui-next 2025-07-02 16:20:28 +06:00
Rifat Azad
58aeb2697a manager: add monet colors support to webui (webui-next)
- colors are served to /internal/colors.css

the current vars are :

primary
onPrimary
background
onSurface
onSurfaceVariant
tonalSurface
surfaceBright
outlineVariant
error
2025-07-02 14:36:43 +06:00
Rifat Azad
7f68766dc4 manager: move module/allowlist backup directory back to /data/adb/ksu/backup dir since /sdcarf/.ksunext is futile and easily can be used as a detection 2025-07-02 02:30:59 +06:00
Rifat Azad
310c0573c6 manager: fix empty gap shown when zygisk is unavailable (fix #594) 2025-07-02 02:08:54 +06:00
Rifat Azad
d1aad01df3 manager: new zygisk detection method implemented and deprecated old method
Currently only supports ReZygisk and soon ZygiskNext will hopefully follow (ZN users will have issues detecting zygisk injections until then)
2025-07-01 22:21:40 +06:00
Hinata Saine
9733b92d30 Do not translate SELinux status in Japanese (#590) 2025-07-01 15:28:25 +06:00
Pedro.js
aaf776f421 manager: fix integer underflow in get_manager_uid (#591)
This commit fixes the issue where the "uid_t" type variable, typedef'd from unsigned int, was being assigned -1, causing an integer underflow.
2025-06-30 22:17:15 +06:00
Rifat Azad
5e33aee99f manager: fix pull to refresh handling in ModuleList 2025-06-30 19:08:14 +06:00
Rifat Azad
4e3f06d405 kernel: added new prctl CMD_GET_MANAGER_UID to get the uid of the crowned manager
manager: show crowned manager uid in infocard when developer options is enabled
2025-06-30 14:22:19 +06:00
роизен
98b9863041 Update README_UA.md (#577)
Co-authored-by: Rifat Azad <33044977+rifsxd@users.noreply.github.com>
2025-06-30 13:22:45 +06:00
luigimak
29ae76d1fb Update and fix Italian translation (#583) 2025-06-30 13:21:13 +06:00
igor
2c3841558e Update translations (#580) 2025-06-30 13:20:55 +06:00
Juno Bủh
c8b357e31b Update Vietnamese Translation (#578)
* Update Vietnamese Translation

* Update Vietnamese Translation

* Update Vietnamese Strings

* Update Vietnamese Translation
2025-06-30 13:20:43 +06:00
AxelPLN(Axel Yinjia Huang)
3ad02ff50b fix: update translation for zh-rCH & zh-rTW (#575)
* docs: sync README_CN & README_TW with en

* fix: update manager translation for zh-rCN & zh-rTW

* docs: fixed some text issue

* fix: update translation about su compatibility
2025-06-30 13:20:23 +06:00
mr_vokintos
6a54b30a9d Update Russian (#574)
* Update Russian

again

* Update strings.xml
2025-06-30 13:20:06 +06:00
роизен
b0cb3bb4c2 Update Ukranian (#573)
* Update Uk

* Update strings.xml
2025-06-30 13:19:47 +06:00
Rifat Azad
7f957be99b manager: fix ListItem title size 2025-06-29 20:10:31 +06:00
Rifat Azad
a54c319d55 manager: improve padding 2025-06-29 18:50:04 +06:00
Rifat Azad
2c71531533 manager: UI overhaul 2025-06-29 15:31:17 +06:00
Rifat Azad
5c61a70e5a manager: fix disable back instance if flashing.status is flashing 2025-06-29 00:05:51 +06:00
Rifat Azad
fdf1d61735 manager: remove unused lib of mmrl and pro guard rules 2025-06-28 20:21:14 +06:00
Rifat Azad
93dc61e113 manager: change FAB visibility with scrolling gestures on module screen list 2025-06-28 19:45:32 +06:00
Rifat Azad
d80a3ebcda manager: removed deprecated webuix and allow superuser and module management capabilities even with su compat disabled 2025-06-28 17:17:49 +06:00
igor
4270fd8b1e update translations in docs and manager (#571)
Co-authored-by: Rifat Azad <33044977+rifsxd@users.noreply.github.com>
2025-06-27 22:51:05 +06:00
роизен
764dbc3782 Improve README_UA (#569)
* Improve README_UA

* Update README_UA.md
2025-06-27 22:48:49 +06:00
роизен
080ab9a952 Update Uk (#566) 2025-06-27 22:48:32 +06:00
AxelPLN(Axel Yinjia Huang)
a9cab5ccfd fix: complete the text of the module labels (#558)
- replace the string Resource ID of uninstalled & those can be updated modules
2025-06-27 22:48:18 +06:00
Rifat Azad
3d44602537 manager: check additional zygisk 64 libs instead of only 32 bit lib for zygisk detection 2025-06-27 21:13:25 +06:00
Eren
88eb2a2723 Improve README (#562)
* Improve README

* Update README.md
2025-06-27 18:39:33 +06:00
NkBe
e272e557b0 manger: fix lkm detection (#2654)
原因请看
https://github.com/SukiSU-Ultra/SukiSU-Ultra/pull/217#issuecomment-3004461174

文中介绍的是lkm的问题 但实测下来gki也有这样的问题 但修复方法通用
2025-06-27 18:02:42 +06:00
Rifat Azad
2a4794e422 manager: implemented zygisk required label for module card 2025-06-27 18:02:34 +06:00
mr_vokintos
818bdbead6 Update Russian (#557) 2025-06-27 14:37:54 +06:00
Nhật Minh
76249fa67d Update strings.xml (#553) 2025-06-27 14:37:39 +06:00
AxelPLN(Axel Yinjia Huang)
ed50b57b57 fix: update manager translation for zh-rCN & zh-rTW (#556)
* docs: complete text for README_CN & README_TW

* fix: update manager translation for zh-rCN & zh-rTW

also complete some text for module label and language switching functionality
2025-06-27 14:37:10 +06:00
Rifat Azad
f05f776a08 manager: fix Condition is always 'true' 2025-06-27 12:02:16 +06:00
Axel Yinjia Huang
c9b79c3016 manager: add basic language switching functionality 2025-06-27 11:37:12 +06:00
Rifat Azad
3ff10d6622 susfsd: remove deprecated CONFIG_KSU_SUSFS_SUS_OVERLAYFS and add CONFIG_KSU_SUSFS_HAS_MAGIC_MOUNT 2025-06-26 23:55:29 +06:00
Rifat Azad
b95d2b69b6 manager: add vendor_boot suggestion for LKM patch 2025-06-26 23:44:46 +06:00
Rifat Azad
2cd8453877 Revert "manager: move the wx platform init to the Application class so it starts as soon as the app process launches"
This reverts commit d5c4f85d73.
2025-06-26 23:25:37 +06:00
роизен
b7300b0525 Update translation for UK (#552) 2025-06-26 22:02:09 +06:00
kam821
3a278d560f Update Polish translation (#521)
* Update Polish translation

- Improve cosmetics / context-sensitive lines

* Update Polish translation - backup/restore

- Cosmetics, worth considering changing it in the future to keep option name in one line.

* Update Polish translation - homepage

- Shortened translation to work around broken formatting
2025-06-26 20:01:55 +06:00
igor
03fa2eddb2 Update portuguese translation (#518) 2025-06-26 17:43:27 +06:00
Rifat Azad
b74e953ad2 ksud: implement patching LKM vendor_ramdisk/ramdisk.cpio for compatibily needed for some pixel devices 2025-06-26 10:33:58 +06:00
Rifat Azad
39717b0a3f Revert "ksud: rust FMT"
This reverts commit 78eb3b0b22.
2025-06-25 17:58:52 +06:00
Rifat Azad
7f0eccd3d5 ksud: handle errors and non compatible ramdisk 2025-06-25 17:43:59 +06:00
Rifat Azad
78eb3b0b22 ksud: rust FMT 2025-06-25 13:25:28 +06:00
Rifat Azad
39f20bf573 manager: fix uneven spacing for empty label for superuser app section with DEFAULT label (fix #547) 2025-06-25 12:54:13 +06:00
Rifat Azad
092eb1b23d manager: use busybox for tar and du commands as not all devices has it most likely and if module size is 0 bytes then show null 2025-06-24 17:56:50 +06:00
Rifat Azad
30e2ed5db5 ksud: third test properly check if vendor is already patched or not for lkm restoration and also handle magisk patched vendor boot 2025-06-24 16:47:44 +06:00
Rifat Azad
dc7ae2db5f manager: fix status card startActivity intent fallback to not allow lkm install on non gki 2025-06-24 09:53:20 +06:00
Rifat Azad
b3b7ef1cb3 manager: dont show developer options and banner toggle when ksuversion is null 2025-06-24 09:26:14 +06:00
Rifat Azad
4de4d1e091 ksud: second test of vendor_boot patching now handling vendor_boot partition and restore partition 2025-06-24 09:17:24 +06:00
Rifat Azad
0beea57ab7 ksud: test vendor_boot patching for some newer devices 2025-06-23 18:17:46 +06:00
Rifat Azad
49aee1ff4c manager: remove susfs info from status card and merge it to info card 2025-06-21 17:01:21 +06:00
Rifat Azad
f7a3699fe3 manager: show module update count as badge in bottom bar instead of status card 2025-06-21 12:44:29 +06:00
5ec1cff
66d42de599 app: persist show system app settings 2025-06-20 00:54:23 +06:00
Kaorun
d562594ae1 Update Module.kt 2025-06-19 13:35:05 +06:00
Rifat Azad
02afc6710c manager: show sucmpat when both sucompat is disabled and sus_su enabled 2025-06-18 20:23:35 +06:00
Caner Karaca
9d9f9ed5d5 Update 2025-06-16 06:00:17 +06:00
kam821
b3b6320946 Update Polish translation
- Added missing strings
2025-06-16 05:56:46 +06:00
Rifat Azad
d43b8320ad manager: minor improvements 2025-06-16 05:55:14 +06:00
dependabot[bot]
a2260ae330 build(deps): bump the crates group across 1 directory with 27 updates
Bumps the crates group with 22 updates in the /userspace/ksud_overlayfs directory:

| Package | From | To |
| --- | --- | --- |
| [clap](https://github.com/clap-rs/clap) | `4.5.38` | `4.5.40` |
| [which](https://github.com/harryfei/which-rs) | `7.0.3` | `8.0.0` |
| [getopts](https://github.com/rust-lang/getopts) | `0.2.21` | `0.2.23` |
| [adler2](https://github.com/oyvindln/adler2) | `2.0.0` | `2.0.1` |
| [anstream](https://github.com/rust-cli/anstyle) | `0.6.18` | `0.6.19` |
| [anstyle](https://github.com/rust-cli/anstyle) | `1.0.10` | `1.0.11` |
| [anstyle-parse](https://github.com/rust-cli/anstyle) | `0.2.6` | `0.2.7` |
| [anstyle-query](https://github.com/rust-cli/anstyle) | `1.1.2` | `1.1.3` |
| [anstyle-wincon](https://github.com/rust-cli/anstyle) | `3.0.8` | `3.0.9` |
| [bumpalo](https://github.com/fitzgen/bumpalo) | `3.17.0` | `3.18.1` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.23` | `1.2.26` |
| [clap_lex](https://github.com/clap-rs/clap) | `0.7.4` | `0.7.5` |
| [colorchoice](https://github.com/rust-cli/anstyle) | `1.0.3` | `1.0.4` |
| [flate2](https://github.com/rust-lang/flate2-rs) | `1.1.1` | `1.1.2` |
| [memchr](https://github.com/BurntSushi/memchr) | `2.7.4` | `2.7.5` |
| [miniz_oxide](https://github.com/Frommi/miniz_oxide) | `0.8.8` | `0.8.9` |
| [once_cell_polyfill](https://github.com/polyfill-rs/once_cell_polyfill) | `1.70.0` | `1.70.1` |
| [rustc-demangle](https://github.com/rust-lang/rustc-demangle) | `0.1.24` | `0.1.25` |
| [rustversion](https://github.com/dtolnay/rustversion) | `1.0.20` | `1.0.21` |
| [syn](https://github.com/dtolnay/syn) | `2.0.101` | `2.0.102` |
| [tokio](https://github.com/tokio-rs/tokio) | `1.45.0` | `1.45.1` |
| [windows-link](https://github.com/microsoft/windows-rs) | `0.1.1` | `0.1.2` |



Updates `clap` from 4.5.38 to 4.5.40
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.38...clap_complete-v4.5.40)

Updates `which` from 7.0.3 to 8.0.0
- [Release notes](https://github.com/harryfei/which-rs/releases)
- [Changelog](https://github.com/harryfei/which-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/harryfei/which-rs/compare/7.0.3...8.0.0)

Updates `getopts` from 0.2.21 to 0.2.23
- [Release notes](https://github.com/rust-lang/getopts/releases)
- [Changelog](https://github.com/rust-lang/getopts/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/getopts/compare/v0.2.21...v0.2.23)

Updates `adler2` from 2.0.0 to 2.0.1
- [Changelog](https://github.com/oyvindln/adler2/blob/main/CHANGELOG.md)
- [Commits](https://github.com/oyvindln/adler2/commits)

Updates `anstream` from 0.6.18 to 0.6.19
- [Commits](https://github.com/rust-cli/anstyle/compare/anstream-v0.6.18...anstream-v0.6.19)

Updates `anstyle` from 1.0.10 to 1.0.11
- [Commits](https://github.com/rust-cli/anstyle/compare/v1.0.10...v1.0.11)

Updates `anstyle-parse` from 0.2.6 to 0.2.7
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-parse-v0.2.6...anstyle-parse-v0.2.7)

Updates `anstyle-query` from 1.1.2 to 1.1.3
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-query-v1.1.2...anstyle-query-v1.1.3)

Updates `anstyle-wincon` from 3.0.8 to 3.0.9
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-wincon-v3.0.8...anstyle-wincon-v3.0.9)

Updates `bumpalo` from 3.17.0 to 3.18.1
- [Changelog](https://github.com/fitzgen/bumpalo/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fitzgen/bumpalo/compare/3.17.0...v3.18.1)

Updates `cc` from 1.2.23 to 1.2.26
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.23...cc-v1.2.26)

Updates `clap_builder` from 4.5.38 to 4.5.40
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.5.38...v4.5.40)

Updates `clap_derive` from 4.5.32 to 4.5.40
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.5.32...v4.5.40)

Updates `clap_lex` from 0.7.4 to 0.7.5
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_lex-v0.7.4...clap_lex-v0.7.5)

Updates `colorchoice` from 1.0.3 to 1.0.4
- [Commits](https://github.com/rust-cli/anstyle/compare/colorchoice-v1.0.3...colorchoice-v1.0.4)

Updates `flate2` from 1.1.1 to 1.1.2
- [Release notes](https://github.com/rust-lang/flate2-rs/releases)
- [Commits](https://github.com/rust-lang/flate2-rs/compare/1.1.1...1.1.2)

Updates `libz-rs-sys` from 0.5.0 to 0.5.1
- [Release notes](https://github.com/trifectatechfoundation/zlib-rs/releases)
- [Changelog](https://github.com/trifectatechfoundation/zlib-rs/blob/main/docs/release.md)
- [Commits](https://github.com/trifectatechfoundation/zlib-rs/compare/v0.5.0...v0.5.1)

Updates `memchr` from 2.7.4 to 2.7.5
- [Commits](https://github.com/BurntSushi/memchr/compare/2.7.4...2.7.5)

Updates `miniz_oxide` from 0.8.8 to 0.8.9
- [Changelog](https://github.com/Frommi/miniz_oxide/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Frommi/miniz_oxide/commits)

Updates `once_cell_polyfill` from 1.70.0 to 1.70.1
- [Changelog](https://github.com/polyfill-rs/once_cell_polyfill/blob/v1.70.1/CHANGELOG.md)
- [Commits](https://github.com/polyfill-rs/once_cell_polyfill/compare/v1.70.0...v1.70.1)

Updates `rustc-demangle` from 0.1.24 to 0.1.25
- [Commits](https://github.com/rust-lang/rustc-demangle/commits)

Updates `rustversion` from 1.0.20 to 1.0.21
- [Release notes](https://github.com/dtolnay/rustversion/releases)
- [Commits](https://github.com/dtolnay/rustversion/compare/1.0.20...1.0.21)

Updates `syn` from 2.0.101 to 2.0.102
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.101...2.0.102)

Updates `tokio` from 1.45.0 to 1.45.1
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.45.0...tokio-1.45.1)

Updates `unicode-width` from 0.1.14 to 0.2.1
- [Commits](https://github.com/unicode-rs/unicode-width/compare/v0.1.14...v0.2.1)

Updates `windows-link` from 0.1.1 to 0.1.2
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `zlib-rs` from 0.5.0 to 0.5.1
- [Release notes](https://github.com/trifectatechfoundation/zlib-rs/releases)
- [Changelog](https://github.com/trifectatechfoundation/zlib-rs/blob/main/docs/release.md)
- [Commits](https://github.com/trifectatechfoundation/zlib-rs/compare/v0.5.0...v0.5.1)

---
updated-dependencies:
- dependency-name: clap
  dependency-version: 4.5.40
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: which
  dependency-version: 8.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: crates
- dependency-name: getopts
  dependency-version: 0.2.23
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: adler2
  dependency-version: 2.0.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: anstream
  dependency-version: 0.6.19
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: anstyle
  dependency-version: 1.0.11
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: anstyle-parse
  dependency-version: 0.2.7
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: anstyle-query
  dependency-version: 1.1.3
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: anstyle-wincon
  dependency-version: 3.0.9
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: bumpalo
  dependency-version: 3.18.1
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: cc
  dependency-version: 1.2.26
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap_builder
  dependency-version: 4.5.40
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap_derive
  dependency-version: 4.5.40
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap_lex
  dependency-version: 0.7.5
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: colorchoice
  dependency-version: 1.0.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: flate2
  dependency-version: 1.1.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: libz-rs-sys
  dependency-version: 0.5.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: memchr
  dependency-version: 2.7.5
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: miniz_oxide
  dependency-version: 0.8.9
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: once_cell_polyfill
  dependency-version: 1.70.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: rustc-demangle
  dependency-version: 0.1.25
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: rustversion
  dependency-version: 1.0.21
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: syn
  dependency-version: 2.0.102
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: tokio
  dependency-version: 1.45.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: unicode-width
  dependency-version: 0.2.1
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: windows-link
  dependency-version: 0.1.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: zlib-rs
  dependency-version: 0.5.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-15 23:31:53 +06:00
dependabot[bot]
aa221acad1 build(deps): bump the crates group across 1 directory with 28 updates
Bumps the crates group with 23 updates in the /userspace/ksud_magic directory:

| Package | From | To |
| --- | --- | --- |
| [clap](https://github.com/clap-rs/clap) | `4.5.38` | `4.5.40` |
| [which](https://github.com/harryfei/which-rs) | `7.0.3` | `8.0.0` |
| [getopts](https://github.com/rust-lang/getopts) | `0.2.21` | `0.2.23` |
| [adler2](https://github.com/oyvindln/adler2) | `2.0.0` | `2.0.1` |
| [anstream](https://github.com/rust-cli/anstyle) | `0.6.18` | `0.6.19` |
| [anstyle](https://github.com/rust-cli/anstyle) | `1.0.10` | `1.0.11` |
| [anstyle-parse](https://github.com/rust-cli/anstyle) | `0.2.6` | `0.2.7` |
| [anstyle-query](https://github.com/rust-cli/anstyle) | `1.1.2` | `1.1.3` |
| [anstyle-wincon](https://github.com/rust-cli/anstyle) | `3.0.8` | `3.0.9` |
| [bumpalo](https://github.com/fitzgen/bumpalo) | `3.17.0` | `3.18.1` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.23` | `1.2.26` |
| [cfg-if](https://github.com/rust-lang/cfg-if) | `1.0.0` | `1.0.1` |
| [clap_lex](https://github.com/clap-rs/clap) | `0.7.4` | `0.7.5` |
| [colorchoice](https://github.com/rust-cli/anstyle) | `1.0.3` | `1.0.4` |
| [flate2](https://github.com/rust-lang/flate2-rs) | `1.1.1` | `1.1.2` |
| [memchr](https://github.com/BurntSushi/memchr) | `2.7.4` | `2.7.5` |
| [miniz_oxide](https://github.com/Frommi/miniz_oxide) | `0.8.8` | `0.8.9` |
| [once_cell_polyfill](https://github.com/polyfill-rs/once_cell_polyfill) | `1.70.0` | `1.70.1` |
| [rustc-demangle](https://github.com/rust-lang/rustc-demangle) | `0.1.24` | `0.1.25` |
| [rustversion](https://github.com/dtolnay/rustversion) | `1.0.20` | `1.0.21` |
| [syn](https://github.com/dtolnay/syn) | `2.0.101` | `2.0.102` |
| [tokio](https://github.com/tokio-rs/tokio) | `1.45.0` | `1.45.1` |
| [windows-link](https://github.com/microsoft/windows-rs) | `0.1.1` | `0.1.2` |



Updates `clap` from 4.5.38 to 4.5.40
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.38...clap_complete-v4.5.40)

Updates `which` from 7.0.3 to 8.0.0
- [Release notes](https://github.com/harryfei/which-rs/releases)
- [Changelog](https://github.com/harryfei/which-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/harryfei/which-rs/compare/7.0.3...8.0.0)

Updates `getopts` from 0.2.21 to 0.2.23
- [Release notes](https://github.com/rust-lang/getopts/releases)
- [Changelog](https://github.com/rust-lang/getopts/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/getopts/compare/v0.2.21...v0.2.23)

Updates `adler2` from 2.0.0 to 2.0.1
- [Changelog](https://github.com/oyvindln/adler2/blob/main/CHANGELOG.md)
- [Commits](https://github.com/oyvindln/adler2/commits)

Updates `anstream` from 0.6.18 to 0.6.19
- [Commits](https://github.com/rust-cli/anstyle/compare/anstream-v0.6.18...anstream-v0.6.19)

Updates `anstyle` from 1.0.10 to 1.0.11
- [Commits](https://github.com/rust-cli/anstyle/compare/v1.0.10...v1.0.11)

Updates `anstyle-parse` from 0.2.6 to 0.2.7
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-parse-v0.2.6...anstyle-parse-v0.2.7)

Updates `anstyle-query` from 1.1.2 to 1.1.3
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-query-v1.1.2...anstyle-query-v1.1.3)

Updates `anstyle-wincon` from 3.0.8 to 3.0.9
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-wincon-v3.0.8...anstyle-wincon-v3.0.9)

Updates `bumpalo` from 3.17.0 to 3.18.1
- [Changelog](https://github.com/fitzgen/bumpalo/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fitzgen/bumpalo/compare/3.17.0...v3.18.1)

Updates `cc` from 1.2.23 to 1.2.26
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.23...cc-v1.2.26)

Updates `cfg-if` from 1.0.0 to 1.0.1
- [Release notes](https://github.com/rust-lang/cfg-if/releases)
- [Changelog](https://github.com/rust-lang/cfg-if/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cfg-if/compare/1.0.0...v1.0.1)

Updates `clap_builder` from 4.5.38 to 4.5.40
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.5.38...v4.5.40)

Updates `clap_derive` from 4.5.32 to 4.5.40
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.5.32...v4.5.40)

Updates `clap_lex` from 0.7.4 to 0.7.5
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_lex-v0.7.4...clap_lex-v0.7.5)

Updates `colorchoice` from 1.0.3 to 1.0.4
- [Commits](https://github.com/rust-cli/anstyle/compare/colorchoice-v1.0.3...colorchoice-v1.0.4)

Updates `flate2` from 1.1.1 to 1.1.2
- [Release notes](https://github.com/rust-lang/flate2-rs/releases)
- [Commits](https://github.com/rust-lang/flate2-rs/compare/1.1.1...1.1.2)

Updates `libz-rs-sys` from 0.5.0 to 0.5.1
- [Release notes](https://github.com/trifectatechfoundation/zlib-rs/releases)
- [Changelog](https://github.com/trifectatechfoundation/zlib-rs/blob/main/docs/release.md)
- [Commits](https://github.com/trifectatechfoundation/zlib-rs/compare/v0.5.0...v0.5.1)

Updates `memchr` from 2.7.4 to 2.7.5
- [Commits](https://github.com/BurntSushi/memchr/compare/2.7.4...2.7.5)

Updates `miniz_oxide` from 0.8.8 to 0.8.9
- [Changelog](https://github.com/Frommi/miniz_oxide/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Frommi/miniz_oxide/commits)

Updates `once_cell_polyfill` from 1.70.0 to 1.70.1
- [Changelog](https://github.com/polyfill-rs/once_cell_polyfill/blob/v1.70.1/CHANGELOG.md)
- [Commits](https://github.com/polyfill-rs/once_cell_polyfill/compare/v1.70.0...v1.70.1)

Updates `rustc-demangle` from 0.1.24 to 0.1.25
- [Commits](https://github.com/rust-lang/rustc-demangle/commits)

Updates `rustversion` from 1.0.20 to 1.0.21
- [Release notes](https://github.com/dtolnay/rustversion/releases)
- [Commits](https://github.com/dtolnay/rustversion/compare/1.0.20...1.0.21)

Updates `syn` from 2.0.101 to 2.0.102
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.101...2.0.102)

Updates `tokio` from 1.45.0 to 1.45.1
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.45.0...tokio-1.45.1)

Updates `unicode-width` from 0.1.14 to 0.2.1
- [Commits](https://github.com/unicode-rs/unicode-width/compare/v0.1.14...v0.2.1)

Updates `windows-link` from 0.1.1 to 0.1.2
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `zlib-rs` from 0.5.0 to 0.5.1
- [Release notes](https://github.com/trifectatechfoundation/zlib-rs/releases)
- [Changelog](https://github.com/trifectatechfoundation/zlib-rs/blob/main/docs/release.md)
- [Commits](https://github.com/trifectatechfoundation/zlib-rs/compare/v0.5.0...v0.5.1)

---
updated-dependencies:
- dependency-name: clap
  dependency-version: 4.5.40
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: which
  dependency-version: 8.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: crates
- dependency-name: getopts
  dependency-version: 0.2.23
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: adler2
  dependency-version: 2.0.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: anstream
  dependency-version: 0.6.19
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: anstyle
  dependency-version: 1.0.11
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: anstyle-parse
  dependency-version: 0.2.7
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: anstyle-query
  dependency-version: 1.1.3
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: anstyle-wincon
  dependency-version: 3.0.9
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: bumpalo
  dependency-version: 3.18.1
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: cc
  dependency-version: 1.2.26
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: cfg-if
  dependency-version: 1.0.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap_builder
  dependency-version: 4.5.40
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap_derive
  dependency-version: 4.5.40
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap_lex
  dependency-version: 0.7.5
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: colorchoice
  dependency-version: 1.0.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: flate2
  dependency-version: 1.1.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: libz-rs-sys
  dependency-version: 0.5.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: memchr
  dependency-version: 2.7.5
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: miniz_oxide
  dependency-version: 0.8.9
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: once_cell_polyfill
  dependency-version: 1.70.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: rustc-demangle
  dependency-version: 0.1.25
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: rustversion
  dependency-version: 1.0.21
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: syn
  dependency-version: 2.0.102
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: tokio
  dependency-version: 1.45.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: unicode-width
  dependency-version: 0.2.1
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: windows-link
  dependency-version: 0.1.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: zlib-rs
  dependency-version: 0.5.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-15 23:31:36 +06:00
dependabot[bot]
c41d35db62 build(deps): bump the maven group across 1 directory with 9 updates
Bumps the maven group with 9 updates in the /manager directory:

| Package | From | To |
| --- | --- | --- |
| androidx.compose:compose-bom | `2025.05.01` | `2025.06.00` |
| androidx.lifecycle:lifecycle-runtime-ktx | `2.9.0` | `2.9.1` |
| androidx.lifecycle:lifecycle-runtime-compose | `2.9.0` | `2.9.1` |
| androidx.lifecycle:lifecycle-viewmodel-compose | `2.9.0` | `2.9.1` |
| androidx.webkit:webkit | `1.13.0` | `1.14.0` |
| [org.lsposed.libcxx:libcxx](https://github.com/LSPosed/prefab-libcxx) | `27.0.12077973` | `28.1.13356709` |
| com.android.application | `8.10.0` | `8.10.1` |
| com.android.library | `8.10.0` | `8.10.1` |
| [com.google.devtools.ksp](https://github.com/google/ksp) | `2.1.21-2.0.1` | `2.1.21-2.0.2` |



Updates `androidx.compose:compose-bom` from 2025.05.01 to 2025.06.00

Updates `androidx.lifecycle:lifecycle-runtime-ktx` from 2.9.0 to 2.9.1

Updates `androidx.lifecycle:lifecycle-runtime-compose` from 2.9.0 to 2.9.1

Updates `androidx.lifecycle:lifecycle-viewmodel-compose` from 2.9.0 to 2.9.1

Updates `androidx.lifecycle:lifecycle-runtime-compose` from 2.9.0 to 2.9.1

Updates `androidx.lifecycle:lifecycle-viewmodel-compose` from 2.9.0 to 2.9.1

Updates `androidx.webkit:webkit` from 1.13.0 to 1.14.0

Updates `org.lsposed.libcxx:libcxx` from 27.0.12077973 to 28.1.13356709
- [Commits](https://github.com/LSPosed/prefab-libcxx/compare/27.0.12077973...28.1.13356709)

Updates `com.android.application` from 8.10.0 to 8.10.1

Updates `com.android.library` from 8.10.0 to 8.10.1

Updates `com.android.library` from 8.10.0 to 8.10.1

Updates `com.google.devtools.ksp` from 2.1.21-2.0.1 to 2.1.21-2.0.2
- [Release notes](https://github.com/google/ksp/releases)
- [Commits](https://github.com/google/ksp/compare/2.1.21-2.0.1...2.1.21-2.0.2)

---
updated-dependencies:
- dependency-name: androidx.compose:compose-bom
  dependency-version: 2025.06.00
  dependency-type: direct:production
  dependency-group: maven
- dependency-name: androidx.lifecycle:lifecycle-runtime-ktx
  dependency-version: 2.9.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: androidx.lifecycle:lifecycle-runtime-compose
  dependency-version: 2.9.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: androidx.lifecycle:lifecycle-viewmodel-compose
  dependency-version: 2.9.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: androidx.lifecycle:lifecycle-runtime-compose
  dependency-version: 2.9.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: androidx.lifecycle:lifecycle-viewmodel-compose
  dependency-version: 2.9.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: androidx.webkit:webkit
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: org.lsposed.libcxx:libcxx
  dependency-version: 28.1.13356709
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: maven
- dependency-name: com.android.application
  dependency-version: 8.10.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.android.library
  dependency-version: 8.10.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.android.library
  dependency-version: 8.10.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.google.devtools.ksp
  dependency-version: 2.1.21-2.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-15 23:31:19 +06:00
luigimak
e5f0c733b8 Update italian translation
add developer translation, values-it/strings.xml
2025-06-15 23:26:29 +06:00
kam821
70b52f85e9 Update Polish translation
- Added missing strings
- Updated translations for refreshed strings
2025-06-15 23:26:17 +06:00
роизен
303b5192ec Update strings.xml 2025-06-15 23:26:05 +06:00
роизен
443d3a6abe Update strings.xml 2025-06-15 23:26:05 +06:00
роизен
a2a7383343 Update strings.xml 2025-06-15 23:26:05 +06:00
роизен
ed64f933f5 Update strings.xml 2025-06-15 23:26:05 +06:00
роизен
4c7ad8eac4 Update strings.xml 2025-06-15 23:26:05 +06:00
роизен
6a922febcd Update ukranian 2025-06-15 23:26:05 +06:00
Rifat Azad
71eba5df8b manager: disable module and superuser navigation if sucompat is disabled and also show an indicator in status card 2025-06-15 22:07:15 +06:00
Rifat Azad
f1ef0afc20 manager: finish activity after flashing module intent is completed 2025-06-15 21:09:31 +06:00
Rifat Azad
844c9f94e9 manager: fix flashing lkm duplication 2025-06-15 20:13:32 +06:00
Rifat Azad
07a4d3457c manager: add separate developer menu 2025-06-15 13:00:30 +06:00
Rifat Azad
8c9728df95 manager: fix zip not flashing from content:// uri 2025-06-15 12:09:32 +06:00
Rifat Azad
14ec1194e4 manager: add support for opening zip file and directly flash module 2025-06-15 07:09:13 +06:00
Rifat Azad
a37f398cc7 kernel/Makefile: check kernelsu driver version from online git repo first, if fails then check local .git and if that also fails then use hardcoded fallback 2025-06-14 22:52:10 +06:00
backslashxx
80bd797737 kernel: ksud: remove remove read_iter requirement
nothing uses this on old kernels, so even backporting this to file_operations
is not really needed

https://elixir.bootlin.com/linux/v3.16.85/source/include/linux/fs.h#L1487

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-06-14 20:14:12 +06:00
backslashxx
600d9ce5d2 kernel: throne_tracker: resolve s_magic for < 3.9
throne_tracker, cross-fs avoidance:
f_inode is f_path.dentry->d_inode
so file->f_inode->i_sb->s_magic is file->f_path.dentry->d_inode->i_sb->s_magic

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-06-14 20:14:03 +06:00
backslashxx
f15d9b18e9 kernel: ksud: d_is_reg to IS_REG
d_is_reg requires 4.0
 - e36cb0b89c
IS_REG is still there on 6.15 so I do NOT see any issues forcing it for all.

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-06-14 20:13:13 +06:00
backslashxx
aa19e8c609 kernel: throne_tracker: add strscpy/strlcpy compat
strscpy requires 4.3
strscpy on this usage can be replaced with strncpy + null term.
kernel gives us an option though.
strlcpy is fast af, hotrod fast. It’s just memcpy + null term, so lets go with that.
it got dropped in 6.8 due to risk concerns, so for those, lets use og strscpy.

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-06-14 20:13:06 +06:00
backslashxx
2b2320000c kernel: throne_tracker: remove unneeded check here
come to think of it, this part is only about folders
2025-06-14 20:12:51 +06:00
backslashxx
06135cc827 kernel: apk_sign: loop file open on is_manager_apk
lets loop on this and wait for installation to finish

this is the third race.
2025-06-14 20:12:14 +06:00
backslashxx
fc58bdf0e2 kernel: throne_tracker: harden packages.list checker further 2025-06-14 20:08:53 +06:00
backslashxx
9b5e60912d kernel: throne_tracker, apk_sign: functionify d_lock spinlock check 2025-06-14 20:08:23 +06:00
backslashxx
c108a8ed32 kernel: throne_tracker: harden track_throne_function file read
this probably wont happen, but just to make sure, we dont block the rename now
so there is really a chance that this does not exist yet when the kthread runs.

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-06-14 20:07:24 +06:00
F-19-F
adce657583 kernel: ksud: provide is_ksu_transition check v2
context: this is known by many as `selinux hook`, `4.9 hook`

add is_ksu_transition check which allows ksud execution under nosuid.
it also eases up integration on 3.X kernels that does not have check_nnp_nosuid.

Usage:
	if (is_ksu_transition(old_tsec, new_tsec))
		return 0;

on either check_nnp_nosuid or selinux_bprm_set_creds (after execve sid reset)

reference: dfe003c9fd

taken from:
`allow init exec ksud under nosuid`
- 3df9df42a6
- https://github.com/tiann/KernelSU/pull/166#issue-1565872173

250611-edit:
- remove ksu_execveat_hook entry check
- turns out some devices needs the transition for multiple times

Reported-by: edenadversary <143865198+edenadversary@users.noreply.github.com>
Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-06-14 20:07:16 +06:00
rsuntk
d6601e1e54 kernel: core_hook: fix refcount leaks on try_umount (#2635)
Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
Signed-off-by: rsuntk <rsuntk@yukiprjkt.my.id>
Co-authored-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-06-14 20:03:30 +06:00
backslashxx
0d4efa649f kernel: throne_tracker: avoid cross-fs traversal using s_magic check (#2633)
Skip directories that does NOT have the same magic as /data/app.
This is to avoid scanning incfs and any other stacked filesystems.

While this is way dumber, it's way cheaper.
no kern_path(), no missable path_put(), no ref handling.

This supercedes
`throne_tracker: avoid cross fs access
(https://github.com/tiann/KernelSU/pull/2626)`
- upstream
0b6998b474

Signed-off-by: backslashxx
<118538522+backslashxx@users.noreply.github.com>
2025-06-14 20:03:04 +06:00
Wang Han
85f4e6ac27 Switch to prepare_creds/commit_creds (#2631)
Update API as per kernel doc recommends, also fix setup_groups refcount
leak while at it.
2025-06-14 20:01:36 +06:00
Rifat Azad
c91f9c18ec Revert "kernel: ksud, throne_tracker: small changes for UL"
This reverts commit c4deee1e49.
2025-06-14 19:54:59 +06:00
Rifat Azad
bf35f73430 Revert "kernel: throne_tracker: move throne_tracker to kthread"
This reverts commit 6a6fc07cd4.
2025-06-14 19:54:36 +06:00
Rifat Azad
ad290a51a0 manager: fully polish and refactor module card ui 2025-06-12 23:40:14 +06:00
Rifat Azad
d218346613 manager: keep mount system preference persistent without breaking rootAvailable() checks 2025-06-12 21:50:16 +06:00
Rifat Azad
502e5599fe manager: improve module card ui 2025-06-12 21:05:40 +06:00
Rifat Azad
11fb52b929 manager: merge legacy and revamped module card ui, also tapping the card open webui when available and actions when available but if both are available then prefer webui 2025-06-12 13:03:41 +06:00
Rifat Azad
057388ccef manager: do not go at the start of the superuser list and stay where you were after app profile changes (resolves #491) 2025-06-12 10:42:53 +06:00
Rifat Azad
67759ad723 manager: update app state upon app profile changes
properly update the superuser app list state after changes have been made to app profile
2025-06-12 10:18:51 +06:00
Rifat Azad
f231cbdba7 Revert "manager: refresh superuser applist on appprofile exit"
This reverts commit fcbb02a115.
2025-06-12 08:46:38 +06:00
Suraj J Pai
7abc9bc821 [BUGFIX] manager: Fix Module Flashing fails when orientation changes (#503)
The issue is caused by re-rendering of Activity when orientation changes.
All states are reset when it is re-rendered. Using ViewModel to manage zipUri fixes the issue.

Fixes issue: https://github.com/KernelSU-Next/KernelSU-Next/issues/488
2025-06-12 04:44:45 +06:00
GMárton
e7697d86fe Update hungarian translation (#489)
* Update hungarian translation

* Fix typo

---------

Co-authored-by: Marty <marton.garamszegi@mptrdev.com>
2025-06-11 04:30:29 +06:00
1alessandro1
68394fddd5 Update doc (#485) 2025-06-11 04:30:14 +06:00
cvnertnc
90d34bf511 Manager: update values-tr/strings.xml (#469) 2025-06-11 04:29:47 +06:00
luigimak
236fbc7615 Update Italian Translation (#461)
* Update Italian Translation

values-it/strings.xml

* fix use_webuix_summary

Update values-it/strings.xml

* Update values-it/strings.xml

* Add module_size values-it/strings.xml

* Add settings_banner values-it/strings.xml

* fix settings_banner
2025-06-11 04:29:31 +06:00
mr_vokintos
6871cbdba7 Update Russian (#466)
* Update strings.xml

Update Russian

* Update strings.xml

* Update strings.xml
2025-06-11 04:29:15 +06:00
AxelPLN(Axel Yinjia Huang)
38a9949211 Update manager translations for zh-rCN & zh-rTW (#456)
* Update translations for zh-rCN &zh-rTW to 0a42dbf

* Add zh-rCN & zh-rTW translations for functions as legacyUI & module banner and so on.

Improve translations.
2025-06-11 04:27:58 +06:00
igor
9fba0faa43 Update portuguese translation (#453)
* Update portuguese translation

* Update strings.xml

* Update strings.xml

* Update README.md

* Update README_PT-BR.md

* Update strings.xml

* Update strings.xml
2025-06-11 04:26:43 +06:00
Caner Karaca
b1250b002e Workflow Updates (#481)
* Update

* Use ubuntu-22.04

* Revert some renamings

* Create renovate.json

* oops
2025-06-11 04:23:22 +06:00
Rifat Azad
10f7d5cf50 Revert "manager: keep mount system preference persistent"
This reverts commit 609926bff1.
2025-06-10 02:31:14 +06:00
rifsxd
0c883ddfd6 manager: let module banner be set locally from module dir
ex: banner=banner.png , banner=example.webp banner=temp/hello.jpg
if banner string value starts with http, https then it will try to fetch from online.

Co-authored-by: fatalcoder524 <11532648+fatalcoder524@users.noreply.github.com>
2025-06-06 04:09:16 +06:00
Paul
3921175e4c kernel: core_hook: intercept devpts via security_inode_permission LSM (#480)
`ksu handles devpts with selinux lsm hook` - aviraxp

- no, not yet, but yes we can, thats a good idea.

This change tries to do that, so instead of hooking pts_unix98_lookup or
devpts_get_priv, we just watch security_inode_permission, if its devpts,
pass it along to the original handler.

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
Co-authored-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-06-05 06:20:53 +06:00
5ec1cff
84fdcf8bf5 throne_tracker: avoid cross fs access 2025-06-03 03:30:54 +06:00
rifsxd
886cfd5a33 manager: adjusted module banner fade opacity 2025-06-03 03:28:42 +06:00
rifsxd
aea384bdd4 manager: do dynamic fade for banner based on monet when available 2025-06-03 01:49:57 +06:00
rifsxd
84695cea71 manager: do white fade for banner when on light mode 2025-06-03 00:58:58 +06:00
rifsxd
f91afe6c46 manager: add module background banners"
module devs can add banners for their modules through module.prop config

Example:

banner=https://something.com/banner.png
2025-06-03 00:34:37 +06:00
rifsxd
3f7e731df6 manager: fix update tag attached to wrong module after using sort options (fix #473) 2025-06-02 15:34:30 +06:00
rifsxd
582662dce9 manager: fix back gestures conflicting with LKM warning window (fix #474) 2025-06-02 15:12:59 +06:00
rifsxd
f3b49723e8 manager: add sorting by size for module list 2025-06-01 21:03:04 +06:00
backslashxx
c4deee1e49 kernel: ksud, throne_tracker: small changes for UL
Safe Ultra-Legacy changes that don't deserve their own commit

d_is_reg requires 4.0
 - e36cb0b89c
IS_REG is still there on 6.15 so I do NOT see any issues forcing it for all.

strscpy requires 4.3
strscpy on this usage can be replaced with strncpy + null term.
kernel gives us an option though.
strlcpy is fast af, hotrod fast. It’s just memcpy + null term, so lets go with that.
it got dropped in 6.8 due to risk concerns, so for those, lets use og strscpy.
ref: openwrt/packages #26453

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-06-01 20:09:20 +06:00
Yaroslav Zviezda
6a6fc07cd4 kernel: throne_tracker: move throne_tracker to kthread
Runs throne_tracker() in kthread instead of blocking the caller.
Prevents full lockup during installation and removing the manager.

This also looks for manager UID in /data/system/packages.list, not
/data/system/packages.list.tmp

Nice additional side effect is a faster booting.

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
Co-Authored-By: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-06-01 20:03:38 +06:00
rifsxd
d8cb7ef772 manager: fix module sorting state when module list is null initially before modules are fetched (this should fix #470) 2025-06-01 19:47:43 +06:00
rifsxd
dddf2f06a0 manager: show reboot button when flashing LKM directly and inactive slot 2025-06-01 15:46:25 +06:00
rifsxd
e7e935aeb2 manager: added module size label 2025-06-01 15:37:13 +06:00
rifsxd
cb146200aa manager: output full logs of actions and flash modules when developer option is enabled 2025-06-01 04:05:35 +06:00
rifsxd
609926bff1 manager: keep mount system preference persistent 2025-06-01 03:37:10 +06:00
rifsxd
8803058521 manager: added amoled theme for non material u devices 2025-06-01 02:33:02 +06:00
rifsxd
c74805b12b manager: autoexpand infocard when dev option is enabled 2025-06-01 01:43:08 +06:00
rifsxd
43870237fc manager: removed unused imports from backuprestore.kt 2025-06-01 01:17:44 +06:00
rifsxd
ca24085b5b manager: add a separate customization screen in settings 2025-06-01 01:17:35 +06:00
rifsxd
93191c2b8b manager: add legacy ui toggle 2025-06-01 00:20:23 +06:00
rifsxd
ebc3ded2b2 manager: removed module config to override webui engine 2025-05-30 04:18:02 +06:00
rifsxd
d9d1c874ab manager: improved module update detection and pre-load applist and modulelist 2025-05-30 02:09:13 +06:00
rifsxd
08477fc361 manager: improved module update status label 2025-05-29 20:55:11 +06:00
rifsxd
11836b876f manager: change home screen power menu icon to a proper power menu icon 2025-05-29 17:24:20 +06:00
rifsxd
bf20965c46 manager: make the module card neat and clean with less clutter and add useful indicators 2025-05-29 16:14:15 +06:00
rifsxd
22a48e52eb manager: rearrange and refactor the Module Card UI 2025-05-28 21:50:17 +06:00
rifsxd
15b703b5f2 manager: show webui and action label when a module has it 2025-05-28 20:42:57 +06:00
rifsxd
18f0eb8a36 manager: better spacing between app package name and label item in superuser 2025-05-28 18:12:23 +06:00
rifsxd
32cdcc6fbe manager: improve layout and look of module cards 2025-05-28 17:57:46 +06:00
rifsxd
437c4b9bc5 manager: improved AMOLED mode 2025-05-28 16:11:00 +06:00
rifsxd
0a42dbf5ba manager: add amoled mode 2025-05-28 04:21:38 +06:00
igor
ea4f319898 Update strings.xml (#444) 2025-05-28 01:14:02 +06:00
Rifat Azad
7b6b944106 docs: updated architecture support 2025-05-28 01:13:54 +06:00
rifsxd
59c966771e manager: show modules update count on status card only if any update is vailable 2025-05-27 03:24:32 +06:00
rifsxd
a83c20b667 manager: removed the logic for if overlayfs is not found then show warning in module screen
since magic_mount is the default mount system and if overlayfs is not available we cant swtich to use overlayfs anyways
2025-05-27 03:00:04 +06:00
rifsxd
d5c4f85d73 manager: move the wx platform init to the Application class so it starts as soon as the app process launches 2025-05-27 02:05:58 +06:00
rifsxd
36f683a299 manager: fix module list empty until refreshed manually 2025-05-27 01:43:30 +06:00
Rifat Azad
652e9719ed docs: removed LKM deprecation information 2025-05-26 13:31:46 +06:00
Der_Googler
011b658422 manager: Improvements (#443)
* manager: bump mmrl

* manager: use ktx ext Str.toUri

* manager: add "webui-engine" from config.json

This allows the developer to override the user preference of the selected WebUI engine.

Supported engines are:

- `wx` for WebUI X
- `ksu` for the KernelSU WebUI

All not named strings will default to `wx`

R.string.use_webuix_summary needs proper translations

* manager: add support for multilingual module meta
2025-05-26 03:03:31 +06:00
rifsxd
5fa1050e1b src: bring back LKM patching 2025-05-26 03:03:18 +06:00
Rifat Azad
39617497ca manager: change webui TaskDescription title 2025-05-25 10:49:56 +06:00
rifsxd
44ad960da7 src: add x86_64 support 2025-05-24 20:33:38 +06:00
rifsxd
db223a1e92 manager: do not show some infocard item if ksuVersion is null 2025-05-23 22:56:26 +06:00
Der_Googler
ea4b8f51c2 manager: use myUserId as fallback #429 (#432) 2025-05-23 20:34:09 +06:00
rifsxd
407826396b ci: try release artifacts properly 2025-05-23 05:17:08 +06:00
rifsxd
124547c9c5 manager: update root project name to "KernelSU-Next" 2025-05-23 05:02:04 +06:00
igor
db7a9df880 Update translation (#423) 2025-05-23 04:55:37 +06:00
rifsxd
29725214f7 ksud_overlayfs: change find_temp_path to use keep() method for temporary directory since into_path() is deprecated 2025-05-23 04:52:48 +06:00
rifsxd
9189de4db1 manager: refactor backup and restore paths and logic for modules and allowlist 2025-05-23 04:48:36 +06:00
rifsxd
fec0032883 ksud: fix clippy warning/error 2025-05-23 03:18:36 +06:00
роизен
1ee737b1aa Update and rename strings.xml to strings.xml (#422) 2025-05-23 00:43:45 +06:00
dependabot[bot]
2a32e1d746 build(deps): bump the crates group across 1 directory with 18 updates (#417)
Bumps the crates group with 11 updates in the /userspace/ksud_overlayfs directory:

| Package | From | To |
| --- | --- | --- |
| [clap](https://github.com/clap-rs/clap) | `4.5.37` | `4.5.38` |
| rust-embed | `8.7.1` | `8.7.2` |
| [tempfile](https://github.com/Stebalien/tempfile) | `3.19.1` | `3.20.0` |
| [ahash](https://github.com/tkaitchuck/ahash) | `0.8.11` | `0.8.12` |
| [anstyle-wincon](https://github.com/rust-cli/anstyle) | `3.0.7` | `3.0.8` |
| [backtrace](https://github.com/rust-lang/backtrace-rs) | `0.3.74` | `0.3.75` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.21` | `1.2.23` |
| [crc](https://github.com/mrhooray/crc-rs) | `3.2.1` | `3.3.0` |
| [getrandom](https://github.com/rust-random/getrandom) | `0.3.2` | `0.3.3` |
| [libm](https://github.com/rust-lang/compiler-builtins) | `0.2.14` | `0.2.15` |
| [windows-core](https://github.com/microsoft/windows-rs) | `0.61.0` | `0.61.2` |



Updates `clap` from 4.5.37 to 4.5.38
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.37...clap_complete-v4.5.38)

Updates `rust-embed` from 8.7.1 to 8.7.2

Updates `tempfile` from 3.19.1 to 3.20.0
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.19.1...v3.20.0)

Updates `ahash` from 0.8.11 to 0.8.12
- [Release notes](https://github.com/tkaitchuck/ahash/releases)
- [Commits](https://github.com/tkaitchuck/ahash/commits)

Updates `anstyle-wincon` from 3.0.7 to 3.0.8
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-wincon-v3.0.7...anstyle-wincon-v3.0.8)

Updates `backtrace` from 0.3.74 to 0.3.75
- [Release notes](https://github.com/rust-lang/backtrace-rs/releases)
- [Commits](https://github.com/rust-lang/backtrace-rs/compare/0.3.74...0.3.75)

Updates `cc` from 1.2.21 to 1.2.23
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.21...cc-v1.2.23)

Updates `clap_builder` from 4.5.37 to 4.5.38
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.5.37...v4.5.38)

Updates `crc` from 3.2.1 to 3.3.0
- [Release notes](https://github.com/mrhooray/crc-rs/releases)
- [Commits](https://github.com/mrhooray/crc-rs/commits)

Updates `getrandom` from 0.3.2 to 0.3.3
- [Changelog](https://github.com/rust-random/getrandom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/getrandom/compare/v0.3.2...v0.3.3)

Updates `libm` from 0.2.14 to 0.2.15
- [Release notes](https://github.com/rust-lang/compiler-builtins/releases)
- [Changelog](https://github.com/rust-lang/compiler-builtins/blob/master/.release-plz.toml)
- [Commits](https://github.com/rust-lang/compiler-builtins/compare/libm-v0.2.14...libm-v0.2.15)

Updates `rust-embed-impl` from 8.7.0 to 8.7.2

Updates `rust-embed-utils` from 8.7.0 to 8.7.2

Updates `windows-core` from 0.61.0 to 0.61.2
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows-result` from 0.3.2 to 0.3.4
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows-strings` from 0.4.0 to 0.4.2
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `zerocopy` from 0.7.35 to 0.8.25
- [Release notes](https://github.com/google/zerocopy/releases)
- [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md)
- [Commits](https://github.com/google/zerocopy/compare/v0.7.35...v0.8.25)

Updates `zerocopy-derive` from 0.7.35 to 0.8.25
- [Release notes](https://github.com/google/zerocopy/releases)
- [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md)
- [Commits](https://github.com/google/zerocopy/compare/v0.7.35...v0.8.25)

---
updated-dependencies:
- dependency-name: clap
  dependency-version: 4.5.38
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: rust-embed
  dependency-version: 8.7.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: tempfile
  dependency-version: 3.20.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: ahash
  dependency-version: 0.8.12
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: anstyle-wincon
  dependency-version: 3.0.8
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: backtrace
  dependency-version: 0.3.75
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: cc
  dependency-version: 1.2.23
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap_builder
  dependency-version: 4.5.38
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: crc
  dependency-version: 3.3.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: getrandom
  dependency-version: 0.3.3
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: libm
  dependency-version: 0.2.15
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: rust-embed-impl
  dependency-version: 8.7.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: rust-embed-utils
  dependency-version: 8.7.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: windows-core
  dependency-version: 0.61.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: windows-result
  dependency-version: 0.3.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: windows-strings
  dependency-version: 0.4.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: zerocopy
  dependency-version: 0.8.25
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: zerocopy-derive
  dependency-version: 0.8.25
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 00:40:58 +06:00
dependabot[bot]
bdaf50ab0f build(deps): bump the crates group across 1 directory with 18 updates (#416)
Bumps the crates group with 11 updates in the /userspace/ksud_magic directory:

| Package | From | To |
| --- | --- | --- |
| [clap](https://github.com/clap-rs/clap) | `4.5.37` | `4.5.38` |
| rust-embed | `8.7.1` | `8.7.2` |
| [tempfile](https://github.com/Stebalien/tempfile) | `3.19.1` | `3.20.0` |
| [ahash](https://github.com/tkaitchuck/ahash) | `0.8.11` | `0.8.12` |
| [anstyle-wincon](https://github.com/rust-cli/anstyle) | `3.0.7` | `3.0.8` |
| [backtrace](https://github.com/rust-lang/backtrace-rs) | `0.3.74` | `0.3.75` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.21` | `1.2.23` |
| [crc](https://github.com/mrhooray/crc-rs) | `3.2.1` | `3.3.0` |
| [getrandom](https://github.com/rust-random/getrandom) | `0.3.2` | `0.3.3` |
| [libm](https://github.com/rust-lang/compiler-builtins) | `0.2.14` | `0.2.15` |
| [windows-core](https://github.com/microsoft/windows-rs) | `0.61.0` | `0.61.2` |



Updates `clap` from 4.5.37 to 4.5.38
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.37...clap_complete-v4.5.38)

Updates `rust-embed` from 8.7.1 to 8.7.2

Updates `tempfile` from 3.19.1 to 3.20.0
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.19.1...v3.20.0)

Updates `ahash` from 0.8.11 to 0.8.12
- [Release notes](https://github.com/tkaitchuck/ahash/releases)
- [Commits](https://github.com/tkaitchuck/ahash/commits)

Updates `anstyle-wincon` from 3.0.7 to 3.0.8
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-wincon-v3.0.7...anstyle-wincon-v3.0.8)

Updates `backtrace` from 0.3.74 to 0.3.75
- [Release notes](https://github.com/rust-lang/backtrace-rs/releases)
- [Commits](https://github.com/rust-lang/backtrace-rs/compare/0.3.74...0.3.75)

Updates `cc` from 1.2.21 to 1.2.23
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.21...cc-v1.2.23)

Updates `clap_builder` from 4.5.37 to 4.5.38
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.5.37...v4.5.38)

Updates `crc` from 3.2.1 to 3.3.0
- [Release notes](https://github.com/mrhooray/crc-rs/releases)
- [Commits](https://github.com/mrhooray/crc-rs/commits)

Updates `getrandom` from 0.3.2 to 0.3.3
- [Changelog](https://github.com/rust-random/getrandom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/getrandom/compare/v0.3.2...v0.3.3)

Updates `libm` from 0.2.14 to 0.2.15
- [Release notes](https://github.com/rust-lang/compiler-builtins/releases)
- [Changelog](https://github.com/rust-lang/compiler-builtins/blob/master/.release-plz.toml)
- [Commits](https://github.com/rust-lang/compiler-builtins/compare/libm-v0.2.14...libm-v0.2.15)

Updates `rust-embed-impl` from 8.7.0 to 8.7.2

Updates `rust-embed-utils` from 8.7.0 to 8.7.2

Updates `windows-core` from 0.61.0 to 0.61.2
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows-result` from 0.3.2 to 0.3.4
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows-strings` from 0.4.0 to 0.4.2
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `zerocopy` from 0.7.35 to 0.8.25
- [Release notes](https://github.com/google/zerocopy/releases)
- [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md)
- [Commits](https://github.com/google/zerocopy/compare/v0.7.35...v0.8.25)

Updates `zerocopy-derive` from 0.7.35 to 0.8.25
- [Release notes](https://github.com/google/zerocopy/releases)
- [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md)
- [Commits](https://github.com/google/zerocopy/compare/v0.7.35...v0.8.25)

---
updated-dependencies:
- dependency-name: clap
  dependency-version: 4.5.38
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: rust-embed
  dependency-version: 8.7.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: tempfile
  dependency-version: 3.20.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: ahash
  dependency-version: 0.8.12
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: anstyle-wincon
  dependency-version: 3.0.8
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: backtrace
  dependency-version: 0.3.75
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: cc
  dependency-version: 1.2.23
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap_builder
  dependency-version: 4.5.38
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: crc
  dependency-version: 3.3.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: getrandom
  dependency-version: 0.3.3
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: libm
  dependency-version: 0.2.15
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: rust-embed-impl
  dependency-version: 8.7.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: rust-embed-utils
  dependency-version: 8.7.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: windows-core
  dependency-version: 0.61.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: windows-result
  dependency-version: 0.3.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: windows-strings
  dependency-version: 0.4.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: zerocopy
  dependency-version: 0.8.25
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: zerocopy-derive
  dependency-version: 0.8.25
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 00:40:36 +06:00
dependabot[bot]
37a129080a build(deps): bump the maven group across 1 directory with 10 updates (#378)
Bumps the maven group with 10 updates in the /manager directory:

| Package | From | To |
| --- | --- | --- |
| androidx.navigation:navigation-compose | `2.8.9` | `2.9.0` |
| androidx.compose:compose-bom | `2025.04.01` | `2025.05.00` |
| androidx.lifecycle:lifecycle-runtime-ktx | `2.8.7` | `2.9.0` |
| androidx.lifecycle:lifecycle-runtime-compose | `2.8.7` | `2.9.0` |
| androidx.lifecycle:lifecycle-viewmodel-compose | `2.8.7` | `2.9.0` |
| com.android.application | `8.9.2` | `8.10.0` |
| com.android.library | `8.9.2` | `8.10.0` |
| [org.jetbrains.kotlin.android](https://github.com/JetBrains/kotlin) | `2.1.20` | `2.1.21` |
| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.1.20` | `2.1.21` |
| [com.google.devtools.ksp](https://github.com/google/ksp) | `2.1.20-2.0.1` | `2.1.21-2.0.1` |



Updates `androidx.navigation:navigation-compose` from 2.8.9 to 2.9.0

Updates `androidx.compose:compose-bom` from 2025.04.01 to 2025.05.00

Updates `androidx.lifecycle:lifecycle-runtime-ktx` from 2.8.7 to 2.9.0

Updates `androidx.lifecycle:lifecycle-runtime-compose` from 2.8.7 to 2.9.0

Updates `androidx.lifecycle:lifecycle-viewmodel-compose` from 2.8.7 to 2.9.0

Updates `androidx.lifecycle:lifecycle-runtime-compose` from 2.8.7 to 2.9.0

Updates `androidx.lifecycle:lifecycle-viewmodel-compose` from 2.8.7 to 2.9.0

Updates `com.android.application` from 8.9.2 to 8.10.0

Updates `com.android.library` from 8.9.2 to 8.10.0

Updates `com.android.library` from 8.9.2 to 8.10.0

Updates `org.jetbrains.kotlin.android` from 2.1.20 to 2.1.21
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v2.1.20...v2.1.21)

Updates `org.jetbrains.kotlin.plugin.compose` from 2.1.20 to 2.1.21
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v2.1.20...v2.1.21)

Updates `org.jetbrains.kotlin.plugin.compose` from 2.1.20 to 2.1.21
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v2.1.20...v2.1.21)

Updates `com.google.devtools.ksp` from 2.1.20-2.0.1 to 2.1.21-2.0.1
- [Release notes](https://github.com/google/ksp/releases)
- [Commits](https://github.com/google/ksp/compare/2.1.20-2.0.1...2.1.21-2.0.1)

---
updated-dependencies:
- dependency-name: androidx.navigation:navigation-compose
  dependency-version: 2.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: androidx.compose:compose-bom
  dependency-version: 2025.05.00
  dependency-type: direct:production
  dependency-group: maven
- dependency-name: androidx.lifecycle:lifecycle-runtime-ktx
  dependency-version: 2.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: androidx.lifecycle:lifecycle-runtime-compose
  dependency-version: 2.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: androidx.lifecycle:lifecycle-viewmodel-compose
  dependency-version: 2.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: androidx.lifecycle:lifecycle-runtime-compose
  dependency-version: 2.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: androidx.lifecycle:lifecycle-viewmodel-compose
  dependency-version: 2.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: com.android.application
  dependency-version: 8.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: com.android.library
  dependency-version: 8.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: com.android.library
  dependency-version: 8.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: org.jetbrains.kotlin.android
  dependency-version: 2.1.21
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: org.jetbrains.kotlin.plugin.compose
  dependency-version: 2.1.21
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: org.jetbrains.kotlin.plugin.compose
  dependency-version: 2.1.21
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.google.devtools.ksp
  dependency-version: 2.1.21-2.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 00:40:18 +06:00
Rifat Azad
024b6ce292 docs: updated installation link for all README 2025-05-22 20:45:58 +06:00
rifsxd
b13a12e3d5 manager: something interesting? 2025-05-22 11:02:01 +06:00
rifsxd
9d9738eed0 manager: keep screen on when FlashingStatus.FLASHING 2025-05-22 10:21:31 +06:00
rifsxd
135fe1e5d4 manager: made the see more collapse button round for infocard 2025-05-22 10:07:03 +06:00
Rifat Azad
2d033b6b87 manager: disable mount system info if ksuversion is null 2025-05-22 09:48:25 +06:00
cvnertnc
9048ffbdab Manager: update values-tr/strings.xml and Docs: update README-tr.md (#415) 2025-05-22 08:38:47 +06:00
роизен
d43fdd3cb4 Add Ukranian (#414)
* Create README_UA.md

* Update README_UA.md

* Update README.md

* Update README_BG.md

* Update README_CN.md

* Update README_FR.md

* Update README_ID.md

* Update README_IT.md

* Update README_JA.md

* Update README_KO.md

* Update README_PL.md

* Update README_PT-BR.md

* Update README_RU.md

* Update README_TH.md

* Update README_TR.md

* Update README_TW.md

* Update README_VI.md

* Create strings.xml

* МЕГА ПОТУЖНО

* МЕГА ПОТУЖНО

* напотужнічав

---------

Co-authored-by: Rifat Azad <33044977+rifsxd@users.noreply.github.com>
2025-05-22 08:37:51 +06:00
Melamit
14d16eff46 docs: Update translations (#383)
* docs: Update Installation instruction link for BG, JA and EN

* docs: Add Ukrainian translation

* docs: Add LKM mode deprecaton info in English and Ukrainian translations

This informs the user about the recent change in KernelSU Next manager in the Readme

---------

Co-authored-by: melamit <sunshine@melamit.in>
2025-05-22 08:06:07 +06:00
luigimak
1a603c2b48 Update Italian Translation (#413)
Update values-it/strings.xml
2025-05-22 08:02:45 +06:00
mr_vokintos
2092161fe0 Update Russian (#409)
* Update README_RU.md

Donations added

* Update strings.xml

fix

* Update strings.xml

again

* Update README_RU.md

* Update Ru strings.xml

Fixes and additions

* Update README_RU.md

I didn't like the way it looked

* Update strings.xml

* Update strings.xml

* Update strings.xml

* Update strings.xml

* Update strings.xml
2025-05-22 08:01:44 +06:00
igor
a8b92f50cc Update portuguese translation (#401) 2025-05-22 08:00:21 +06:00
itsaschoolbus
4556c9a5d1 manager: Update LKM mode deprecation string for Vietnamese (#396) 2025-05-22 07:59:58 +06:00
Nhật Minh
e6fcae4f02 Update strings.xml (#372) 2025-05-22 07:59:34 +06:00
Rifat Azad
74ab5488e1 manager: rename unmount -> umount for superuser label item 2025-05-22 07:39:18 +06:00
rifsxd
5cdec242eb manager: keep screen on when isActionRunning (#341) 2025-05-22 00:27:31 +06:00
rifsxd
e938a499f6 manager: disabled auto update by default 2025-05-22 00:09:40 +06:00
rifsxd
84b5915eea manager: use WebUIX as default webui providor 2025-05-22 00:08:07 +06:00
rifsxd
540ce1d2c3 manager: redesign/rearrange home infocard 2025-05-21 23:42:05 +06:00
rifsxd
b40f2af0f0 manager: fix bad prctl calls for native code 2025-05-21 22:55:38 +06:00
rifsxd
324d09a61e manager: added MINIMAL_SUPPORTED_HOOK_MODE and hook_mode info 2025-05-21 18:07:47 +06:00
rifsxd
d5dfecefea Revert "kernel: Makefile: sanity checks"
This reverts commit 26d3ec14a6.
2025-05-21 18:07:46 +06:00
rifsxd
ce37e17c87 kernel: added CMD_HOOK_MODE prctl to get the enabled su hook mode value 2025-05-21 18:07:41 +06:00
rifsxd
3b1d5f15f4 manager: webuix no longer should be stated beta as it is stable enough for release 2025-05-21 15:18:01 +06:00
rifsxd
714ec4695b manager: show home_failure instead of lkm_mode_deprecated 2025-05-21 15:16:37 +06:00
rifsxd
3795d92d7a manager: fix kprobes strings 2025-05-21 15:15:27 +06:00
rifsxd
eed685507a kernel: rename KSU_WITH_KPROBES to KSU_KPROBES_HOOK for better self explanitory 2025-05-21 15:13:17 +06:00
backslashxx
26d3ec14a6 kernel: Makefile: sanity checks 2025-05-21 15:09:33 +06:00
ShirkNeko
96d475407a Add a formatting string for the update list #2556 (#2597)
Fix module update failures caused by spaces and other non Linux readable
characters


Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-05-21 15:03:06 +06:00
backslashxx
27d8bc458f kernel: sucompat: increase reliability of execve_sucompat
On plain ARMv8.0 devices (A53,A57,A73), strncpy_from_user_nofault() sometimes
fails to copy `filename_user` string correctly. This breaks su ofc, breaking
some apps like Termux (Play Store ver), ZArchiver and Root Explorer.

This does NOT seem to affect newer ARMv8.2+ CPUs (A75/A76 and newer)

My speculation? ARMv8.0 has weak speculation :)

here we replace `strncpy_from_user_nofault()` with another routine:
 - access_ok() to validate the pointer
 - strncpy_from_user() to copy and validate string
 - manual null-termination just in case, as strncpy_from_user_nofault also does it
 - remove that memset, seems useless as it is an strncpy, not strncat

Kind of mimicking _nofault, but yes with this one we allow pagefaults.

Tested on:
- ARMv8.0 A73.a53, A57.a53, A53.a53
- ARMv8.2 A76.a55

Tested-by: iDead XD <rafifirdaus12bb@gmail.com>
Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-05-21 15:01:01 +06:00
Der_Googler
519f86c47e manager: refactor label item in superuser list (#403) 2025-05-19 22:50:11 +06:00
backslashxx
980f71c1bd kernel: core_hook: fixup 217d230b (#402)
Reported-by: Trijal Saha <97483939+Trijal08@users.noreply.github.com>
2025-05-19 22:49:44 +06:00
Rifat Azad
7692665428 manager: warn about LKM mode deprecation for GKI2 kernels 2025-05-19 00:07:05 +06:00
Trijal Saha
aaca0b5283 ci: Only have one task for susfsd irrespective of the target architecture (#395) 2025-05-18 22:49:39 +06:00
Der_Googler
e5a495489d Improve StatusCard and fix WX wrappers of WebUI X (#393)
* manager: bump mmrl to 1998c70b77

* manager: improve StatusCard
2025-05-18 22:11:38 +06:00
Der_Googler
e07a6fb3ff manager: Bump MMRL and possible fix #384 (#391)
* manager: bump mmrl to 346470abb8

- Possible fix a bug where IUserManager.getUsers(ZZZ) are not defined in the framework.jar
- Refactored WebUI X to meet the new WXInterface
- Only fetch the app from the current user and not all users

* manager: remove unused AIDL interfaces
2025-05-18 16:50:51 +06:00
Rifat Azad
b8c2660996 manager: add ABI info icon 2025-05-18 12:30:20 +06:00
rifsxd
ec2ecdcacb manager: fix unresolved referance 2025-05-18 12:22:34 +06:00
rifsxd
3c3ab77f65 manager: Add ABI archirecture info for manager 2025-05-18 12:09:08 +06:00
rifsxd
ffb2c89c36 manager: add kernel ABI info 2025-05-18 12:03:49 +06:00
rifsxd
bda62cc8a1 manager: refine working mode designation 2025-05-18 11:54:41 +06:00
Wang Han
a052af4180 Fix fallback option for createRootShell() (#2593) 2025-05-18 11:30:47 +06:00
rifsxd
8835c37536 ksud_magic: Update zip-extensions and set needed features for zip
zip-extensions does not export time and deflate64 features now.
2025-05-18 11:29:58 +06:00
Wang Han
69f3c9f6ab Update zip-extensions and set needed features for zip (#2592)
zip-extensions does not export time and deflate64 features now.
2025-05-18 11:25:38 +06:00
Rifat Azad
af3e0bd6a5 ci: fux ksud armv7a artifact download 2025-05-18 10:40:31 +06:00
Rifat Azad
5b14512323 ci: fux susfsd artifact download 2025-05-18 10:32:41 +06:00
Rifat Azad
6f176ad1c4 ksud_magic: removed loopdev 2025-05-18 10:24:39 +06:00
Rifat Azad
bc9d720a3c ksud_overlayfs: use upstream loopdev 2025-05-18 10:18:35 +06:00
Rifat Azad
93c5013251 ksud_overlayfs: use upstream hole-punch 2025-05-18 10:01:05 +06:00
Rifat Azad
bc5c993093 manager: added armv7a abi 2025-05-18 09:14:14 +06:00
Rifat Azad
759b3c5baf ci: fix workflow 2025-05-18 04:10:23 +06:00
Rifat Azad
e1303d13a3 ci: fix duplicate susfsd artifact upload error 2025-05-18 04:05:50 +06:00
Rifat Azad
8824115697 ci: upload armv7a susfsd artifact 2025-05-18 03:57:09 +06:00
Rifat Azad
a78a1e7d2e ci: fixed syntax error 2025-05-18 03:49:41 +06:00
backslashxx
9e150b2c44 ksud/installer: /odm handling
we move the folder out of system if it exists in real filesystem and it
is not a symlink.
this is already supported on init_event.rs so only handle_partition
logic was needed to make it happen

since KernelSU is using overlayfs, we need to move these out.

Signed-off-by: backslashxx
<118538522+backslashxx@users.noreply.github.com>

---------

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-05-18 03:42:32 +06:00
backslashxx
217d230b61 kernel: expose KSU_LSM_SECURITY_HOOKS on Kconfig
disabling this removes the need for LSM_HOOK_INIT, security_add_hooks and such,.
furthermore, this will also allow easier integration on pre-4.1 kernels.
Expose this and make it a configurable option.

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-05-18 03:23:12 +06:00
backslashxx
ba1b3c4fc7 kernel/throne_tracker: we just uninstalled the manager, stop looking for it
When the manager UID disappears from packages.list, we correctly
invalidate it — good. But, in the very next breath, we start scanning
/data/app hoping to find it again?

This event is just unnecessary I/O, exactly when we should be doing less.
Apparently this causes hangups and stuckups which is REALLY noticeable
on Ultra-Legacy devices.

Skip the scan — we’ll catch the reinstall next time packages.list updates.

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-05-18 03:23:12 +06:00
backslashxx
5f871cd713 kernel/selinux: fix pointer mismatch with 32-bit ksud on 64-bit kernels
Since KernelSU Manager can now be built for 32-bit, theres this problematic
setup where userspace is 32-bit (armeabi-v7a) and kernel is 64bit (aarch64).

On 64-bit kernels with CONFIG_COMPAT=y, 32-bit userspace passes 32-bit pointers.
These values are interpreted as 64-bit pointers without proper casting and that
results in invalid or near-null memory access.

This patch adds proper compat-mode handling with the ff changes:
- introduce a dedicated struct (`sepol_compat_data`) using u32 fields
- use `compat_ptr()` to safely convert 32-bit user pointers to kernel pointers
- adding a runtime `ksu_is_compat` flag to dynamically select between struct layouts

This prevents a near-null pointer dereference when handling SELinux
policy updates from 32-bit ksud in a 64-bit kernel.

Truth table:

kernel 32 + ksud 32, struct is u32, no compat_ptr
kernel 64 + ksud 32, struct is u32, yes compat_ptr
kernel 64 + ksud 64, struct is u64, no compat_ptr

Preprocessor check

64BIT=y COMPAT=y: define both structs, select dynamically
64BIT=y COMPAT=n: struct u64
64BIT=n: struct u32

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-05-18 03:23:12 +06:00
backslashxx
4a37422af5 kernel/sucompat: sync to KSU pr #2506
kernel: sucompat: sucompat toggle support for non-kp

This is done like how vfs_read_hook, input_hook and execve_hook is disabled.
While this is not exactly the same thing, this CAN achieve the same results.
The complete disabling of all KernelSU hooks.

While this is likely unneeded, It keeps feature parity to non-kprobe builds.

adapted from upstream:
	kernel: Allow to re-enable sucompat - 4593ae81c7

Rejected: https://github.com/tiann/KernelSU/pull/2506

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>

kernel: sucompat: fix compile issue on kprobe builds, unused variable
2025-05-18 03:23:12 +06:00
Rifat Azad
a081fc87c9 manager/userspace: added 32bit (armv7a) support 2025-05-18 03:19:50 +06:00
Rifat Azad
0e8286e195 manager: refactor working mode designation 2025-05-18 01:56:47 +06:00
Rifat Azad
e9d53c4084 manager: removed overlayfs check for modules screen
since magic_mount is the default mount system which most UL (ultra legacy) devices will depend on
2025-05-17 10:41:22 +06:00
Rifat Azad
697a0ac9fc issue_template: we don't accept features requests anymore 2025-05-13 10:14:34 +06:00
dependabot[bot]
7f12e1c19a build(deps): bump the crates group across 1 directory with 4 updates (#365)
Bumps the crates group with 4 updates in the /userspace/ksud_magic directory: rust-embed, [cc](https://github.com/rust-lang/cc-rs), [libm](https://github.com/rust-lang/compiler-builtins) and [tokio](https://github.com/tokio-rs/tokio).


Updates `rust-embed` from 8.7.0 to 8.7.1

Updates `cc` from 1.2.20 to 1.2.21
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.20...cc-v1.2.21)

Updates `libm` from 0.2.13 to 0.2.14
- [Release notes](https://github.com/rust-lang/compiler-builtins/releases)
- [Changelog](https://github.com/rust-lang/compiler-builtins/blob/master/.release-plz.toml)
- [Commits](https://github.com/rust-lang/compiler-builtins/compare/libm-v0.2.13...libm-v0.2.14)

Updates `tokio` from 1.44.2 to 1.45.0
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.44.2...tokio-1.45.0)

---
updated-dependencies:
- dependency-name: rust-embed
  dependency-version: 8.7.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: cc
  dependency-version: 1.2.21
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: libm
  dependency-version: 0.2.14
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: tokio
  dependency-version: 1.45.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-07 02:36:03 +06:00
dependabot[bot]
bf99cb50fd build(deps): bump the crates group across 1 directory with 4 updates (#364)
Bumps the crates group with 4 updates in the /userspace/ksud_overlayfs directory: rust-embed, [cc](https://github.com/rust-lang/cc-rs), [libm](https://github.com/rust-lang/compiler-builtins) and [tokio](https://github.com/tokio-rs/tokio).


Updates `rust-embed` from 8.7.0 to 8.7.1

Updates `cc` from 1.2.20 to 1.2.21
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.20...cc-v1.2.21)

Updates `libm` from 0.2.13 to 0.2.14
- [Release notes](https://github.com/rust-lang/compiler-builtins/releases)
- [Changelog](https://github.com/rust-lang/compiler-builtins/blob/master/.release-plz.toml)
- [Commits](https://github.com/rust-lang/compiler-builtins/compare/libm-v0.2.13...libm-v0.2.14)

Updates `tokio` from 1.44.2 to 1.45.0
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.44.2...tokio-1.45.0)

---
updated-dependencies:
- dependency-name: rust-embed
  dependency-version: 8.7.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: cc
  dependency-version: 1.2.21
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: libm
  dependency-version: 0.2.14
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: tokio
  dependency-version: 1.45.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-07 02:35:26 +06:00
dependabot[bot]
1333f0113f build(deps): bump the maven group in /manager with 2 updates (#349)
Bumps the maven group in /manager with 2 updates: [io.github.raamcosta.compose-destinations:core](https://github.com/raamcosta/compose-destinations) and [io.github.raamcosta.compose-destinations:ksp](https://github.com/raamcosta/compose-destinations).


Updates `io.github.raamcosta.compose-destinations:core` from 2.1.0 to 2.1.1
- [Release notes](https://github.com/raamcosta/compose-destinations/releases)
- [Commits](https://github.com/raamcosta/compose-destinations/compare/2.1.0...2.1.1)

Updates `io.github.raamcosta.compose-destinations:ksp` from 2.1.0 to 2.1.1
- [Release notes](https://github.com/raamcosta/compose-destinations/releases)
- [Commits](https://github.com/raamcosta/compose-destinations/compare/2.1.0...2.1.1)

Updates `io.github.raamcosta.compose-destinations:ksp` from 2.1.0 to 2.1.1
- [Release notes](https://github.com/raamcosta/compose-destinations/releases)
- [Commits](https://github.com/raamcosta/compose-destinations/compare/2.1.0...2.1.1)

---
updated-dependencies:
- dependency-name: io.github.raamcosta.compose-destinations:core
  dependency-version: 2.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: io.github.raamcosta.compose-destinations:ksp
  dependency-version: 2.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: io.github.raamcosta.compose-destinations:ksp
  dependency-version: 2.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-07 02:35:03 +06:00
igor
1b544bd22d Update Portuguese translation (#361) 2025-05-07 02:33:03 +06:00
mr_vokintos
24f514c949 Fixes for Russian translation (#358)
* Update README_RU.md

Donations added

* Update strings.xml

fix

* Update strings.xml

again

* Update README_RU.md

* Update Ru strings.xml

Fixes and additions

* Update README_RU.md

I didn't like the way it looked
2025-05-07 02:32:31 +06:00
Bachpooh
8eed26e0a1 manager: Update values-vi/strings.xml (#357)
* Corrects mistranslation
* Fix issues #335
2025-05-07 02:32:17 +06:00
luigimak
3c5b3f0a49 Update Italian translation (#355) 2025-05-07 02:32:03 +06:00
Caner Karaca
1d23b4bb67 ksud: fix rustfmt errors (#359) 2025-05-06 22:48:58 +06:00
Rifat Azad
48e533f660 ksud_overlayfs: removed custom_sparse_size text file extension 2025-05-04 19:39:06 +06:00
Der_Googler
86fbed60eb Add Eruda Support for WebUI X (#354)
* manager: Improvements

- Bump MMRL version
- Improved SwitchItem when it is not enabled
- Added option to enable eruda

* manager: Use custom user agent for WebUI X
2025-05-04 01:08:34 +06:00
dependabot[bot]
164341b543 build(deps): bump the crates group across 1 directory with 2 updates (#344)
Bumps the crates group with 2 updates in the /userspace/ksud_magic directory: [chrono](https://github.com/chronotope/chrono) and [sha2](https://github.com/RustCrypto/hashes).


Updates `chrono` from 0.4.40 to 0.4.41
- [Release notes](https://github.com/chronotope/chrono/releases)
- [Changelog](https://github.com/chronotope/chrono/blob/main/CHANGELOG.md)
- [Commits](https://github.com/chronotope/chrono/compare/v0.4.40...v0.4.41)

Updates `sha2` from 0.10.8 to 0.10.9
- [Commits](https://github.com/RustCrypto/hashes/compare/sha2-v0.10.8...sha2-v0.10.9)

---
updated-dependencies:
- dependency-name: chrono
  dependency-version: 0.4.41
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: sha2
  dependency-version: 0.10.9
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-02 00:06:52 +06:00
dependabot[bot]
94942fe488 build(deps): bump the crates group across 1 directory with 2 updates (#343)
Bumps the crates group with 2 updates in the /userspace/ksud_overlayfs directory: [chrono](https://github.com/chronotope/chrono) and [sha2](https://github.com/RustCrypto/hashes).


Updates `chrono` from 0.4.40 to 0.4.41
- [Release notes](https://github.com/chronotope/chrono/releases)
- [Changelog](https://github.com/chronotope/chrono/blob/main/CHANGELOG.md)
- [Commits](https://github.com/chronotope/chrono/compare/v0.4.40...v0.4.41)

Updates `sha2` from 0.10.8 to 0.10.9
- [Commits](https://github.com/RustCrypto/hashes/compare/sha2-v0.10.8...sha2-v0.10.9)

---
updated-dependencies:
- dependency-name: chrono
  dependency-version: 0.4.41
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: sha2
  dependency-version: 0.10.9
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-02 00:06:28 +06:00
dependabot[bot]
ca64f6c8ac build(deps): bump the maven group across 1 directory with 5 updates (#322)
Bumps the maven group with 5 updates in the /manager directory:

| Package | From | To |
| --- | --- | --- |
| androidx.compose:compose-bom | `2025.03.01` | `2025.04.00` |
| [org.jetbrains.kotlinx:kotlinx-coroutines-core](https://github.com/Kotlin/kotlinx.coroutines) | `1.10.1` | `1.10.2` |
| com.android.application | `8.9.1` | `8.9.2` |
| com.android.library | `8.9.1` | `8.9.2` |
| [com.google.devtools.ksp](https://github.com/google/ksp) | `2.1.20-1.0.32` | `2.1.20-2.0.0` |



Updates `androidx.compose:compose-bom` from 2025.03.01 to 2025.04.00

Updates `org.jetbrains.kotlinx:kotlinx-coroutines-core` from 1.10.1 to 1.10.2
- [Release notes](https://github.com/Kotlin/kotlinx.coroutines/releases)
- [Changelog](https://github.com/Kotlin/kotlinx.coroutines/blob/master/CHANGES.md)
- [Commits](https://github.com/Kotlin/kotlinx.coroutines/compare/1.10.1...1.10.2)

Updates `com.android.application` from 8.9.1 to 8.9.2

Updates `com.android.library` from 8.9.1 to 8.9.2

Updates `com.android.library` from 8.9.1 to 8.9.2

Updates `com.google.devtools.ksp` from 2.1.20-1.0.32 to 2.1.20-2.0.0
- [Release notes](https://github.com/google/ksp/releases)
- [Commits](https://github.com/google/ksp/compare/2.1.20-1.0.32...2.1.20-2.0.0)

---
updated-dependencies:
- dependency-name: androidx.compose:compose-bom
  dependency-version: 2025.04.00
  dependency-type: direct:production
  dependency-group: maven
- dependency-name: org.jetbrains.kotlinx:kotlinx-coroutines-core
  dependency-version: 1.10.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.android.application
  dependency-version: 8.9.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.android.library
  dependency-version: 8.9.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.android.library
  dependency-version: 8.9.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.google.devtools.ksp
  dependency-version: 2.1.20-2.0.0
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-02 00:06:11 +06:00
luigimak
e8ef483098 Update italian translation (#342)
* Update values-it/strings.xml

Update Italian Translation

* Update italian translation
2025-05-02 00:05:16 +06:00
cvnertnc
85faf43fdd manager: Update values-tr/strings.xml (#334) 2025-05-02 00:04:14 +06:00
igor
09620c269e Update portuguese & english (#333) 2025-05-02 00:03:29 +06:00
itsaschoolbus
0c05a4c375 manager: Update WebUI X translation string for Vietnamese (#332) 2025-05-02 00:03:10 +06:00
Der_Googler
298aa7960e Improve Platform (#345)
* Add option to use WebUI X

- Added WebUI X from MMRL to KernelSU Next

* Some improvements

* Again some improvements

* Fix NPE

* Still not fixed

Use mappings from the action to decode the stacktrace

* bump mmrl

does still not work

* Works

* WORKS

* small fixes

* manager: only launch webui x when Platform.isAlive is `true`

* manager: disable "Use WebUI X" option when Platform.isAlive is `false`

* manager: improve app list loading

* manager: use system packageManager api

* ci: add spoofed manager workflow

* ci: add spoofed manager workflow

---------

Co-authored-by: rifsxd <rifat.44.azad.rifs@gmail.com>
Co-authored-by: Rifat Azad <33044977+rifsxd@users.noreply.github.com>
2025-05-01 20:24:00 +06:00
rifsxd
b112513df0 ci: add spoofed manager workflow 2025-05-01 19:52:36 +06:00
rifsxd
f19b5a453a ksud: changed deps repo to fetch from KernelSU-Next org 2025-05-01 17:29:08 +06:00
rifsxd
72e54653a2 ksud: disabled BootRestore command 2025-05-01 16:54:09 +06:00
rifsxd
5696d72a3f ksud: fix rustfmt errors 2025-05-01 16:47:20 +06:00
rifsxd
757d20166a manager: clean lkm remnants
ksud: clean clippy warnings
2025-05-01 16:30:09 +06:00
rifsxd
1336996129 manager: disabled KMI/LKM installation
manager: check if overlayfs is available to allow mount system switching
ksud: disabled KMI/LKM commands
ci: disabled LKM build workflow
ksud: removed ksuinit
2025-05-01 15:58:18 +06:00
Rifat Azad
4f35240203 ci/gki-kernel: run the sed command for BAZEL only if BUILD.bazel exists to avoid file not found error on non BAZEL kernel common tree 2025-05-01 11:48:41 +06:00
Rifat Azad
5565a6b3f8 ci: fix BAZEL build while remove protected module exports 2025-05-01 01:02:25 +06:00
Der_Googler
9dbe135e66 Fix Shortcuts in WebUI X (#339)
* manager: fix webui x shortcuts
2025-04-30 11:08:25 +06:00
rifsxd
fe5c031701 ci/gki-kernel: keep abi_gki_protected_exports to avoid BAZEL build errors 2025-04-29 01:30:48 +06:00
rifsxd
0511a90640 manager: fully optimize the broken/buggy bottom navbar 2025-04-28 23:25:52 +06:00
Re*Index. (ot_inc)
2c87dfbb35 Add Japanese README. (#320)
* Add Japanese README

* Update README.md

* Update README_JA.md
2025-04-28 01:56:00 +06:00
Caner Karaca
9b4d07008d ci: update workflows (#329) 2025-04-28 01:55:16 +06:00
Caner Karaca
c40218a919 manager: update gradle and NDK (#327)
* manager: update gradle

* manager: update NDK
2025-04-28 01:54:58 +06:00
Caner Karaca
0c410b87ec ksud: cargo lock file maintenance (#328) 2025-04-28 01:54:46 +06:00
rifsxd
114a07a440 manager: fixed buggy bottombar with a neat workaround 2025-04-28 00:14:29 +06:00
Der_Googler
babae3b2ad Add WebUI X (#316)
* Add option to use WebUI X

- Added WebUI X from MMRL to KernelSU Next

* Some improvements

* Again some improvements

* Fix NPE

* Still not fixed

Use mappings from the action to decode the stacktrace

* bump mmrl

does still not work

* Works

* WORKS

* small fixes
2025-04-27 22:01:25 +06:00
muhammadbahaa2001
a7a9f86a71 Updated Arabic (#312) 2025-04-25 20:15:46 +06:00
Aliza
c65fcd5133 Adding Persian Language (#305)
* Adding Persian Language

* Create app.yml

* Delete .github/workflows/app.yml
2025-04-17 21:40:59 +06:00
Oscar1640
b298b4203a Fix su --shell argument handling for ksud magic mount (#309)
Co-authored-by: Wang Han <416810799@qq.com>
2025-04-17 21:36:04 +06:00
onlymash
250310fc9f improve manager translations for zh-rCN (#300) 2025-04-13 22:35:11 +06:00
GMárton
89cf05d3a4 Added Hungarian translation (#284) 2025-04-09 01:10:13 +06:00
Rifat Azad
1d258196b1 CI: try uploading artifacts properly for release 2025-04-03 22:13:56 +06:00
rifsxd
63ebf730f9 manager: improved floating button for module & LKM flashing screen 2025-04-03 19:22:08 +06:00
dependabot[bot]
810889a964 build(deps): bump the crates group across 1 directory with 41 updates (#277)
Bumps the crates group with 31 updates in the /userspace/ksud_magic directory:

| Package | From | To |
| --- | --- | --- |
| [anyhow](https://github.com/dtolnay/anyhow) | `1.0.96` | `1.0.97` |
| [clap](https://github.com/clap-rs/clap) | `4.5.30` | `4.5.35` |
| [zip](https://github.com/zip-rs/zip2) | `2.2.2` | `2.5.0` |
| [log](https://github.com/rust-lang/log) | `0.4.26` | `0.4.27` |
| [env_logger](https://github.com/rust-cli/env_logger) | `0.11.6` | `0.11.8` |
| [serde_json](https://github.com/serde-rs/json) | `1.0.139` | `1.0.140` |
| [libc](https://github.com/rust-lang/libc) | `0.2.170` | `0.2.171` |
| [rust-embed](https://github.com/pyros2097/rust-embed) | `8.5.0` | `8.6.0` |
| [sha256](https://github.com/baoyachi/sha256-rs) | `1.5.0` | `1.6.0` |
| [tempfile](https://github.com/Stebalien/tempfile) | `3.17.1` | `3.19.1` |
| [chrono](https://github.com/chronotope/chrono) | `0.4.39` | `0.4.40` |
| [android_logger](https://github.com/rust-mobile/android_logger-rs) | `0.14.1` | `0.15.0` |
| [async-trait](https://github.com/dtolnay/async-trait) | `0.1.86` | `0.1.88` |
| [bytes](https://github.com/tokio-rs/bytes) | `1.10.0` | `1.10.1` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.15` | `1.2.17` |
| [either](https://github.com/rayon-rs/either) | `1.14.0` | `1.15.0` |
| [flate2](https://github.com/rust-lang/flate2-rs) | `1.1.0` | `1.1.1` |
| [getrandom](https://github.com/rust-random/getrandom) | `0.3.1` | `0.3.2` |
| [iana-time-zone](https://github.com/strawlab/iana-time-zone) | `0.1.61` | `0.1.63` |
| [indexmap](https://github.com/indexmap-rs/indexmap) | `2.7.1` | `2.8.0` |
| [itoa](https://github.com/dtolnay/itoa) | `1.0.14` | `1.0.15` |
| [once_cell](https://github.com/matklad/once_cell) | `1.20.3` | `1.21.3` |
| [proc-macro2](https://github.com/dtolnay/proc-macro2) | `1.0.93` | `1.0.94` |
| [quote](https://github.com/dtolnay/quote) | `1.0.38` | `1.0.40` |
| [rustversion](https://github.com/dtolnay/rustversion) | `1.0.19` | `1.0.20` |
| [ryu](https://github.com/dtolnay/ryu) | `1.0.19` | `1.0.20` |
| [serde](https://github.com/serde-rs/serde) | `1.0.218` | `1.0.219` |
| [syn](https://github.com/dtolnay/syn) | `2.0.98` | `2.0.100` |
| [time](https://github.com/time-rs/time) | `0.3.37` | `0.3.41` |
| [tokio](https://github.com/tokio-rs/tokio) | `1.43.0` | `1.44.1` |
| [unicode-ident](https://github.com/dtolnay/unicode-ident) | `1.0.17` | `1.0.18` |



Updates `anyhow` from 1.0.96 to 1.0.97
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.96...1.0.97)

Updates `clap` from 4.5.30 to 4.5.35
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.30...clap_complete-v4.5.35)

Updates `zip` from 2.2.2 to 2.5.0
- [Release notes](https://github.com/zip-rs/zip2/releases)
- [Changelog](https://github.com/zip-rs/zip2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zip-rs/zip2/compare/v2.2.2...v2.5.0)

Updates `log` from 0.4.26 to 0.4.27
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.26...0.4.27)

Updates `env_logger` from 0.11.6 to 0.11.8
- [Release notes](https://github.com/rust-cli/env_logger/releases)
- [Changelog](https://github.com/rust-cli/env_logger/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-cli/env_logger/compare/v0.11.6...v0.11.8)

Updates `serde_json` from 1.0.139 to 1.0.140
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.139...v1.0.140)

Updates `libc` from 0.2.170 to 0.2.171
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.171/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.170...0.2.171)

Updates `rust-embed` from 8.5.0 to 8.6.0
- [Changelog](https://github.com/pyrossh/rust-embed/blob/master/changelog.md)
- [Commits](https://github.com/pyros2097/rust-embed/commits)

Updates `sha256` from 1.5.0 to 1.6.0
- [Release notes](https://github.com/baoyachi/sha256-rs/releases)
- [Commits](https://github.com/baoyachi/sha256-rs/compare/1.5.0...1.6.0)

Updates `tempfile` from 3.17.1 to 3.19.1
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.17.1...v3.19.1)

Updates `chrono` from 0.4.39 to 0.4.40
- [Release notes](https://github.com/chronotope/chrono/releases)
- [Changelog](https://github.com/chronotope/chrono/blob/main/CHANGELOG.md)
- [Commits](https://github.com/chronotope/chrono/compare/v0.4.39...v0.4.40)

Updates `android_logger` from 0.14.1 to 0.15.0
- [Release notes](https://github.com/rust-mobile/android_logger-rs/releases)
- [Changelog](https://github.com/rust-mobile/android_logger-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-mobile/android_logger-rs/compare/0.14.1...v0.15.0)

Updates `android_log-sys` from 0.3.1 to 0.3.2
- [Commits](https://github.com/rust-mobile/android_log-sys-rs/commits)

Updates `async-trait` from 0.1.86 to 0.1.88
- [Release notes](https://github.com/dtolnay/async-trait/releases)
- [Commits](https://github.com/dtolnay/async-trait/compare/0.1.86...0.1.88)

Updates `bytes` from 1.10.0 to 1.10.1
- [Release notes](https://github.com/tokio-rs/bytes/releases)
- [Changelog](https://github.com/tokio-rs/bytes/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/bytes/compare/v1.10.0...v1.10.1)

Updates `cc` from 1.2.15 to 1.2.17
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.15...cc-v1.2.17)

Updates `clap_builder` from 4.5.30 to 4.5.35
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.5.30...v4.5.35)

Updates `clap_derive` from 4.5.28 to 4.5.32
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.5.28...v4.5.32)

Updates `either` from 1.14.0 to 1.15.0
- [Commits](https://github.com/rayon-rs/either/compare/1.14.0...1.15.0)

Updates `flate2` from 1.1.0 to 1.1.1
- [Release notes](https://github.com/rust-lang/flate2-rs/releases)
- [Commits](https://github.com/rust-lang/flate2-rs/compare/1.1.0...1.1.1)

Updates `getrandom` from 0.3.1 to 0.3.2
- [Changelog](https://github.com/rust-random/getrandom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/getrandom/compare/v0.3.1...v0.3.2)

Updates `iana-time-zone` from 0.1.61 to 0.1.63
- [Changelog](https://github.com/strawlab/iana-time-zone/blob/main/CHANGELOG.md)
- [Commits](https://github.com/strawlab/iana-time-zone/compare/v0.1.61...v0.1.63)

Updates `indexmap` from 2.7.1 to 2.8.0
- [Changelog](https://github.com/indexmap-rs/indexmap/blob/main/RELEASES.md)
- [Commits](https://github.com/indexmap-rs/indexmap/compare/2.7.1...2.8.0)

Updates `itoa` from 1.0.14 to 1.0.15
- [Release notes](https://github.com/dtolnay/itoa/releases)
- [Commits](https://github.com/dtolnay/itoa/compare/1.0.14...1.0.15)

Updates `once_cell` from 1.20.3 to 1.21.3
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.20.3...v1.21.3)

Updates `proc-macro2` from 1.0.93 to 1.0.94
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.93...1.0.94)

Updates `quote` from 1.0.38 to 1.0.40
- [Release notes](https://github.com/dtolnay/quote/releases)
- [Commits](https://github.com/dtolnay/quote/compare/1.0.38...1.0.40)

Updates `rust-embed-impl` from 8.5.0 to 8.6.0
- [Changelog](https://github.com/pyrossh/rust-embed/blob/master/changelog.md)
- [Commits](https://github.com/pyros2097/rust-embed/commits)

Updates `rust-embed-utils` from 8.5.0 to 8.6.0
- [Changelog](https://github.com/pyrossh/rust-embed/blob/master/changelog.md)
- [Commits](https://github.com/pyros2097/rust-embed/commits)

Updates `rustversion` from 1.0.19 to 1.0.20
- [Release notes](https://github.com/dtolnay/rustversion/releases)
- [Commits](https://github.com/dtolnay/rustversion/compare/1.0.19...1.0.20)

Updates `ryu` from 1.0.19 to 1.0.20
- [Release notes](https://github.com/dtolnay/ryu/releases)
- [Commits](https://github.com/dtolnay/ryu/compare/1.0.19...1.0.20)

Updates `serde` from 1.0.218 to 1.0.219
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.218...v1.0.219)

Updates `serde_derive` from 1.0.218 to 1.0.219
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.218...v1.0.219)

Updates `syn` from 2.0.98 to 2.0.100
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.98...2.0.100)

Updates `time` from 0.3.37 to 0.3.41
- [Release notes](https://github.com/time-rs/time/releases)
- [Changelog](https://github.com/time-rs/time/blob/main/CHANGELOG.md)
- [Commits](https://github.com/time-rs/time/compare/v0.3.37...v0.3.41)

Updates `time-core` from 0.1.2 to 0.1.4
- [Release notes](https://github.com/time-rs/time/releases)
- [Changelog](https://github.com/time-rs/time/blob/main/CHANGELOG.md)
- [Commits](https://github.com/time-rs/time/commits)

Updates `tokio` from 1.43.0 to 1.44.1
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.43.0...tokio-1.44.1)

Updates `unicode-ident` from 1.0.17 to 1.0.18
- [Release notes](https://github.com/dtolnay/unicode-ident/releases)
- [Commits](https://github.com/dtolnay/unicode-ident/compare/1.0.17...1.0.18)

Updates `wasi` from 0.13.3+wasi-0.2.2 to 0.14.2+wasi-0.2.4
- [Commits](https://github.com/bytecodealliance/wasi-rs/compare/0.13.3...0.14.2)

Updates `windows-core` from 0.52.0 to 0.61.0
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/compare/0.52.0...0.61.0)

Updates `wit-bindgen-rt` from 0.33.0 to 0.39.0
- [Release notes](https://github.com/bytecodealliance/wit-bindgen/releases)
- [Commits](https://github.com/bytecodealliance/wit-bindgen/compare/v0.33.0...v0.39.0)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: zip
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: log
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: env_logger
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: libc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: rust-embed
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: sha256
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: tempfile
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: chrono
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: android_logger
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: android_log-sys
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: async-trait
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: bytes
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: cc
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap_builder
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap_derive
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: either
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: flate2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: getrandom
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: iana-time-zone
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: indexmap
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: itoa
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: once_cell
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: proc-macro2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: quote
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: rust-embed-impl
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: rust-embed-utils
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: rustversion
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: ryu
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: serde
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: serde_derive
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: syn
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: time
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: time-core
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: tokio
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: unicode-ident
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: wasi
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: windows-core
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: wit-bindgen-rt
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-03 17:29:00 +06:00
dependabot[bot]
0a97eee7ad build(deps): bump the crates group across 1 directory with 41 updates (#276)
Bumps the crates group with 31 updates in the /userspace/ksud_overlayfs directory:

| Package | From | To |
| --- | --- | --- |
| [anyhow](https://github.com/dtolnay/anyhow) | `1.0.96` | `1.0.97` |
| [clap](https://github.com/clap-rs/clap) | `4.5.31` | `4.5.35` |
| [zip](https://github.com/zip-rs/zip2) | `2.2.2` | `2.5.0` |
| [log](https://github.com/rust-lang/log) | `0.4.26` | `0.4.27` |
| [env_logger](https://github.com/rust-cli/env_logger) | `0.11.6` | `0.11.8` |
| [serde_json](https://github.com/serde-rs/json) | `1.0.139` | `1.0.140` |
| [libc](https://github.com/rust-lang/libc) | `0.2.170` | `0.2.171` |
| [rust-embed](https://github.com/pyros2097/rust-embed) | `8.5.0` | `8.6.0` |
| [sha256](https://github.com/baoyachi/sha256-rs) | `1.5.0` | `1.6.0` |
| [tempfile](https://github.com/Stebalien/tempfile) | `3.17.1` | `3.19.1` |
| [chrono](https://github.com/chronotope/chrono) | `0.4.39` | `0.4.40` |
| [android_logger](https://github.com/rust-mobile/android_logger-rs) | `0.14.1` | `0.15.0` |
| [async-trait](https://github.com/dtolnay/async-trait) | `0.1.86` | `0.1.88` |
| [bytes](https://github.com/tokio-rs/bytes) | `1.10.0` | `1.10.1` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.15` | `1.2.17` |
| [either](https://github.com/rayon-rs/either) | `1.14.0` | `1.15.0` |
| [flate2](https://github.com/rust-lang/flate2-rs) | `1.1.0` | `1.1.1` |
| [getrandom](https://github.com/rust-random/getrandom) | `0.3.1` | `0.3.2` |
| [iana-time-zone](https://github.com/strawlab/iana-time-zone) | `0.1.61` | `0.1.63` |
| [indexmap](https://github.com/indexmap-rs/indexmap) | `2.7.1` | `2.8.0` |
| [itoa](https://github.com/dtolnay/itoa) | `1.0.14` | `1.0.15` |
| [once_cell](https://github.com/matklad/once_cell) | `1.20.3` | `1.21.3` |
| [proc-macro2](https://github.com/dtolnay/proc-macro2) | `1.0.93` | `1.0.94` |
| [quote](https://github.com/dtolnay/quote) | `1.0.38` | `1.0.40` |
| [rustversion](https://github.com/dtolnay/rustversion) | `1.0.19` | `1.0.20` |
| [ryu](https://github.com/dtolnay/ryu) | `1.0.19` | `1.0.20` |
| [serde](https://github.com/serde-rs/serde) | `1.0.218` | `1.0.219` |
| [syn](https://github.com/dtolnay/syn) | `2.0.98` | `2.0.100` |
| [time](https://github.com/time-rs/time) | `0.3.37` | `0.3.41` |
| [tokio](https://github.com/tokio-rs/tokio) | `1.43.0` | `1.44.1` |
| [unicode-ident](https://github.com/dtolnay/unicode-ident) | `1.0.17` | `1.0.18` |



Updates `anyhow` from 1.0.96 to 1.0.97
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.96...1.0.97)

Updates `clap` from 4.5.31 to 4.5.35
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.5.31...clap_complete-v4.5.35)

Updates `zip` from 2.2.2 to 2.5.0
- [Release notes](https://github.com/zip-rs/zip2/releases)
- [Changelog](https://github.com/zip-rs/zip2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zip-rs/zip2/compare/v2.2.2...v2.5.0)

Updates `log` from 0.4.26 to 0.4.27
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.26...0.4.27)

Updates `env_logger` from 0.11.6 to 0.11.8
- [Release notes](https://github.com/rust-cli/env_logger/releases)
- [Changelog](https://github.com/rust-cli/env_logger/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-cli/env_logger/compare/v0.11.6...v0.11.8)

Updates `serde_json` from 1.0.139 to 1.0.140
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.139...v1.0.140)

Updates `libc` from 0.2.170 to 0.2.171
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.171/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.170...0.2.171)

Updates `rust-embed` from 8.5.0 to 8.6.0
- [Changelog](https://github.com/pyrossh/rust-embed/blob/master/changelog.md)
- [Commits](https://github.com/pyros2097/rust-embed/commits)

Updates `sha256` from 1.5.0 to 1.6.0
- [Release notes](https://github.com/baoyachi/sha256-rs/releases)
- [Commits](https://github.com/baoyachi/sha256-rs/compare/1.5.0...1.6.0)

Updates `tempfile` from 3.17.1 to 3.19.1
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.17.1...v3.19.1)

Updates `chrono` from 0.4.39 to 0.4.40
- [Release notes](https://github.com/chronotope/chrono/releases)
- [Changelog](https://github.com/chronotope/chrono/blob/main/CHANGELOG.md)
- [Commits](https://github.com/chronotope/chrono/compare/v0.4.39...v0.4.40)

Updates `android_logger` from 0.14.1 to 0.15.0
- [Release notes](https://github.com/rust-mobile/android_logger-rs/releases)
- [Changelog](https://github.com/rust-mobile/android_logger-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-mobile/android_logger-rs/compare/0.14.1...v0.15.0)

Updates `android_log-sys` from 0.3.1 to 0.3.2
- [Commits](https://github.com/rust-mobile/android_log-sys-rs/commits)

Updates `async-trait` from 0.1.86 to 0.1.88
- [Release notes](https://github.com/dtolnay/async-trait/releases)
- [Commits](https://github.com/dtolnay/async-trait/compare/0.1.86...0.1.88)

Updates `bytes` from 1.10.0 to 1.10.1
- [Release notes](https://github.com/tokio-rs/bytes/releases)
- [Changelog](https://github.com/tokio-rs/bytes/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/bytes/compare/v1.10.0...v1.10.1)

Updates `cc` from 1.2.15 to 1.2.17
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.15...cc-v1.2.17)

Updates `clap_builder` from 4.5.31 to 4.5.35
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.5.31...v4.5.35)

Updates `clap_derive` from 4.5.28 to 4.5.32
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.5.28...v4.5.32)

Updates `either` from 1.14.0 to 1.15.0
- [Commits](https://github.com/rayon-rs/either/compare/1.14.0...1.15.0)

Updates `flate2` from 1.1.0 to 1.1.1
- [Release notes](https://github.com/rust-lang/flate2-rs/releases)
- [Commits](https://github.com/rust-lang/flate2-rs/compare/1.1.0...1.1.1)

Updates `getrandom` from 0.3.1 to 0.3.2
- [Changelog](https://github.com/rust-random/getrandom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/getrandom/compare/v0.3.1...v0.3.2)

Updates `iana-time-zone` from 0.1.61 to 0.1.63
- [Changelog](https://github.com/strawlab/iana-time-zone/blob/main/CHANGELOG.md)
- [Commits](https://github.com/strawlab/iana-time-zone/compare/v0.1.61...v0.1.63)

Updates `indexmap` from 2.7.1 to 2.8.0
- [Changelog](https://github.com/indexmap-rs/indexmap/blob/main/RELEASES.md)
- [Commits](https://github.com/indexmap-rs/indexmap/compare/2.7.1...2.8.0)

Updates `itoa` from 1.0.14 to 1.0.15
- [Release notes](https://github.com/dtolnay/itoa/releases)
- [Commits](https://github.com/dtolnay/itoa/compare/1.0.14...1.0.15)

Updates `once_cell` from 1.20.3 to 1.21.3
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.20.3...v1.21.3)

Updates `proc-macro2` from 1.0.93 to 1.0.94
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.93...1.0.94)

Updates `quote` from 1.0.38 to 1.0.40
- [Release notes](https://github.com/dtolnay/quote/releases)
- [Commits](https://github.com/dtolnay/quote/compare/1.0.38...1.0.40)

Updates `rust-embed-impl` from 8.5.0 to 8.6.0
- [Changelog](https://github.com/pyrossh/rust-embed/blob/master/changelog.md)
- [Commits](https://github.com/pyros2097/rust-embed/commits)

Updates `rust-embed-utils` from 8.5.0 to 8.6.0
- [Changelog](https://github.com/pyrossh/rust-embed/blob/master/changelog.md)
- [Commits](https://github.com/pyros2097/rust-embed/commits)

Updates `rustversion` from 1.0.19 to 1.0.20
- [Release notes](https://github.com/dtolnay/rustversion/releases)
- [Commits](https://github.com/dtolnay/rustversion/compare/1.0.19...1.0.20)

Updates `ryu` from 1.0.19 to 1.0.20
- [Release notes](https://github.com/dtolnay/ryu/releases)
- [Commits](https://github.com/dtolnay/ryu/compare/1.0.19...1.0.20)

Updates `serde` from 1.0.218 to 1.0.219
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.218...v1.0.219)

Updates `serde_derive` from 1.0.218 to 1.0.219
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.218...v1.0.219)

Updates `syn` from 2.0.98 to 2.0.100
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.98...2.0.100)

Updates `time` from 0.3.37 to 0.3.41
- [Release notes](https://github.com/time-rs/time/releases)
- [Changelog](https://github.com/time-rs/time/blob/main/CHANGELOG.md)
- [Commits](https://github.com/time-rs/time/compare/v0.3.37...v0.3.41)

Updates `time-core` from 0.1.2 to 0.1.4
- [Release notes](https://github.com/time-rs/time/releases)
- [Changelog](https://github.com/time-rs/time/blob/main/CHANGELOG.md)
- [Commits](https://github.com/time-rs/time/commits)

Updates `tokio` from 1.43.0 to 1.44.1
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.43.0...tokio-1.44.1)

Updates `unicode-ident` from 1.0.17 to 1.0.18
- [Release notes](https://github.com/dtolnay/unicode-ident/releases)
- [Commits](https://github.com/dtolnay/unicode-ident/compare/1.0.17...1.0.18)

Updates `wasi` from 0.13.3+wasi-0.2.2 to 0.14.2+wasi-0.2.4
- [Commits](https://github.com/bytecodealliance/wasi-rs/compare/0.13.3...0.14.2)

Updates `windows-core` from 0.52.0 to 0.61.0
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/compare/0.52.0...0.61.0)

Updates `wit-bindgen-rt` from 0.33.0 to 0.39.0
- [Release notes](https://github.com/bytecodealliance/wit-bindgen/releases)
- [Commits](https://github.com/bytecodealliance/wit-bindgen/compare/v0.33.0...v0.39.0)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: zip
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: log
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: env_logger
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: libc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: rust-embed
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: sha256
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: tempfile
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: chrono
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: android_logger
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: android_log-sys
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: async-trait
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: bytes
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: cc
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap_builder
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap_derive
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: either
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: flate2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: getrandom
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: iana-time-zone
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: indexmap
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: itoa
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: once_cell
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: proc-macro2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: quote
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: rust-embed-impl
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: rust-embed-utils
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: rustversion
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: ryu
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: serde
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: serde_derive
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: syn
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: time
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: time-core
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: tokio
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: unicode-ident
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: wasi
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: windows-core
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: wit-bindgen-rt
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-03 17:28:48 +06:00
dependabot[bot]
cc8f0e456a build(deps): bump the maven group across 1 directory with 10 updates (#253)
Bumps the maven group with 10 updates in the /manager directory:

| Package | From | To |
| --- | --- | --- |
| androidx.navigation:navigation-compose | `2.8.8` | `2.8.9` |
| androidx.compose:compose-bom | `2025.02.00` | `2025.03.00` |
| androidx.webkit:webkit | `1.12.1` | `1.13.0` |
| [io.github.raamcosta.compose-destinations:core](https://github.com/raamcosta/compose-destinations) | `2.1.0-beta16` | `2.1.0` |
| [io.github.raamcosta.compose-destinations:ksp](https://github.com/raamcosta/compose-destinations) | `2.1.0-beta16` | `2.1.0` |
| com.android.application | `8.8.2` | `8.9.0` |
| com.android.library | `8.8.2` | `8.9.0` |
| [org.jetbrains.kotlin.android](https://github.com/JetBrains/kotlin) | `2.1.10` | `2.1.20` |
| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.1.10` | `2.1.20` |
| [com.google.devtools.ksp](https://github.com/google/ksp) | `2.1.10-1.0.31` | `2.1.20-1.0.31` |



Updates `androidx.navigation:navigation-compose` from 2.8.8 to 2.8.9

Updates `androidx.compose:compose-bom` from 2025.02.00 to 2025.03.00

Updates `androidx.webkit:webkit` from 1.12.1 to 1.13.0

Updates `io.github.raamcosta.compose-destinations:core` from 2.1.0-beta16 to 2.1.0
- [Release notes](https://github.com/raamcosta/compose-destinations/releases)
- [Commits](https://github.com/raamcosta/compose-destinations/compare/2.1.0-beta16...2.1.0)

Updates `io.github.raamcosta.compose-destinations:ksp` from 2.1.0-beta16 to 2.1.0
- [Release notes](https://github.com/raamcosta/compose-destinations/releases)
- [Commits](https://github.com/raamcosta/compose-destinations/compare/2.1.0-beta16...2.1.0)

Updates `io.github.raamcosta.compose-destinations:ksp` from 2.1.0-beta16 to 2.1.0
- [Release notes](https://github.com/raamcosta/compose-destinations/releases)
- [Commits](https://github.com/raamcosta/compose-destinations/compare/2.1.0-beta16...2.1.0)

Updates `com.android.application` from 8.8.2 to 8.9.0

Updates `com.android.library` from 8.8.2 to 8.9.0

Updates `com.android.library` from 8.8.2 to 8.9.0

Updates `org.jetbrains.kotlin.android` from 2.1.10 to 2.1.20
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v2.1.10...v2.1.20)

Updates `org.jetbrains.kotlin.plugin.compose` from 2.1.10 to 2.1.20
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v2.1.10...v2.1.20)

Updates `org.jetbrains.kotlin.plugin.compose` from 2.1.10 to 2.1.20
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v2.1.10...v2.1.20)

Updates `com.google.devtools.ksp` from 2.1.10-1.0.31 to 2.1.20-1.0.31
- [Release notes](https://github.com/google/ksp/releases)
- [Commits](https://github.com/google/ksp/compare/2.1.10-1.0.31...2.1.20-1.0.31)

---
updated-dependencies:
- dependency-name: androidx.navigation:navigation-compose
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: androidx.compose:compose-bom
  dependency-type: direct:production
  dependency-group: maven
- dependency-name: androidx.webkit:webkit
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: io.github.raamcosta.compose-destinations:core
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: io.github.raamcosta.compose-destinations:ksp
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: io.github.raamcosta.compose-destinations:ksp
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.android.application
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: com.android.library
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: com.android.library
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: org.jetbrains.kotlin.android
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: org.jetbrains.kotlin.plugin.compose
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: org.jetbrains.kotlin.plugin.compose
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.google.devtools.ksp
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-03 17:28:36 +06:00
Kangmin Kim
0f7e8d3214 Update Korean strings.xml (#280) 2025-04-03 15:50:34 +06:00
igor
2c193e0dd4 Update portuguese translation (#279)
* manager: improved mount system info fetching logic

* Update portuguese translation

---------

Co-authored-by: rifsxd <rifat.44.azad.rifs@gmail.com>
Co-authored-by: Rifat Azad <33044977+rifsxd@users.noreply.github.com>
2025-04-03 15:50:21 +06:00
Rifat Azad
2512239ea7 ksud_overlayfs: fixed rust formatting error 2025-04-03 15:13:21 +06:00
cvnertnc
6f6b797e22 Update values-tr/strings.xml (#278)
* manager: improved mount system info fetching logic

* Update values-tr/strings.xml

---------

Co-authored-by: rifsxd <rifat.44.azad.rifs@gmail.com>
Co-authored-by: Rifat Azad <33044977+rifsxd@users.noreply.github.com>
2025-04-03 02:28:03 +06:00
the slaytanic one~
d5f25590a5 Added Bulgaran Readme + Fix my older writing style of the bulgarian translatation in strings.xml (#273)
* Added Bulgaran Readme (By boyan)

* manager: improved mount system info fetching logic

* UPDATE BULGARIAN STRINGS.xml

no questions asked

---------

Co-authored-by: rifsxd <rifat.44.azad.rifs@gmail.com>
Co-authored-by: Rifat Azad <33044977+rifsxd@users.noreply.github.com>
2025-04-03 01:36:42 +06:00
Nhật Minh
bf81c9a17b Update strings.xml (#270)
update vietnamese

Co-authored-by: Rifat Azad <33044977+rifsxd@users.noreply.github.com>
2025-04-03 01:35:50 +06:00
rifsxd
5cec5aa656 manager: improved mount system info fetching logic 2025-04-03 00:21:53 +06:00
rifsxd
02dbb7d0f7 ksud: added module mount command to check current mount system enabled 2025-04-02 15:12:44 +06:00
rifsxd
c5aa6ffffc manager: module & allowlist backup directory changed to /data/adb/ksu/
manager: placed export logs list item to the bottom
2025-04-02 14:46:23 +06:00
rifsxd
335ea3190f docs: removed redundant web page 2025-04-02 14:11:22 +06:00
5ec1cff
35c98aee76 Fix off-by-one when iterating dir (#2530)
Fix https://github.com/tiann/KernelSU/issues/2528
2025-04-02 14:09:44 +06:00
Wang Han
dc992818de Fix su --shell argument handling (#2529)
This fixes https://github.com/tiann/KernelSU/issues/2523.
2025-04-02 14:09:34 +06:00
Wang Han
dfea38e0f2 Skip staging package when searching manager (#2511) 2025-04-02 14:09:22 +06:00
ZGX089
6452427b6c Added Arabic translation (#267) 2025-03-30 01:46:24 +06:00
Caner Karaca
feb3c47bdc Fix formatting (#266) 2025-03-30 01:46:06 +06:00
kam821
de44373599 Update Polish translation (#264)
- Added settings_language translation
2025-03-27 22:20:21 +06:00
luigimak
4bd7e7cc9f Update values-it/strings.xml (#261)
Update Italian Translation
2025-03-27 22:20:04 +06:00
igor
39014fb89c Update portuguese translation (#260) 2025-03-27 00:56:09 +06:00
AJleKcAHgP68
eeecbf255a Update Ru translate (#256) 2025-03-27 00:55:51 +06:00
Saksham Singla
11e4729519 Update README.md (#262)
Changed Installation Instructions Link according to new website ksunext.org
2025-03-27 00:55:33 +06:00
kam821
f3093eace6 Add Polish documentation (#249)
- Added README_PL.md
- Added link to Polish version in other language versions
2025-03-24 22:15:16 +06:00
rifsxd
3a7edf48bf manager: remove beta warning for mount system switch 2025-03-23 23:27:10 +06:00
rifsxd
de189fe426 ksud_overlayfs: ability to specify custom sparse image size 2025-03-23 23:15:47 +06:00
rifsxd
30835787c9 Revert "ksud: determine modules's size by checking partion size"
This reverts commit c40bfd694c.
2025-03-23 22:38:01 +06:00
mr_vokintos
9fc1bd1876 Update README_RU.md (#248)
Donations added
2025-03-23 17:53:45 +06:00
AxelPLN(Axel Yinjia Huang)
a223781fae improve manager translations for zh-rCN & zh-rTW (#247)
* add README_TW

* Update README_CN.md

* add Simplified Chinese for website

add Simplified Chinese for website

fix some mistakes in README_CN

* Update zh/devices.html

* Update zh/features.html

* Update zh/devices.html

* Update zh/features.html

* Update zh/index.html

* Add Traditional Chinese translation for manager

* Try to add switching function for website

* fix manager translations for zh-rCH & zh-rTW

* try to add language switcher for manager

* try to add language switcher for manager

* try to add language switching function for manager app

* try to add language switching function for manager app

* try to add language switching function for manager app

* discard invalid changes
2025-03-23 17:50:22 +06:00
kam821
2a154c1985 Update Polish translation - SUSFS/sus_su (#243)
Added SUSFS/sus_su strings translation
2025-03-23 17:49:05 +06:00
luigimak
110b8e92dc Update Italian Translation (#242)
* Update values-it/strings.xml

Update Italian translation

* Added Italian link README_IT.md

* Added Italian link README_IT.md

* Added Italian link README_IT.md

* Added Italian link README_IT.md

* Added Italian link README_IT.md

* Added Italian link README_IT.md

* Added Italian link README_IT.md

* Added Italian link README_IT.md

* Added Italian link README_IT.md

* Added Italian link README_IT.md

* Added Italian link README_IT.md

* Create README_IT.md

Create Italian README
2025-03-23 17:48:37 +06:00
igor
3b87014bf9 Update Portuguese Brazilian translation (#240) 2025-03-23 17:47:27 +06:00
AJleKcAHgP68
bd0bcc4337 Russian translation updated (#239) 2025-03-23 17:46:24 +06:00
the slaytanic one~
916f8151ea UPDATE BG translation...thats all (#237)
* Create strings.xml

* UPDATE BULGARIAN XD
2025-03-23 17:45:24 +06:00
rifsxd
59ca8fa2c2 manager: susfs and sus_su status now global strings 2025-03-16 00:50:57 +06:00
AJleKcAHgP68
238f2ee008 Update Ru strings.xml (#234)
Update Ru string
2025-03-14 16:47:45 +06:00
kam821
7eaf37bc4a Update Polish Translation (#229)
* Update Polish Translation - UpdateJson

UpdateJson in this context doesn't mean 'update the json file', but 'a link to a JSON file that contains info so manager can update the module'.
It is also a field described in the Magisk documentation, so it's best to leave the original form.

* Update Polish Translation - Export logs

Mostly a cosmetic change, should fit better with the other options in the settings menu
2025-03-14 16:47:27 +06:00
JuicerV3
022ee4bb1c README_TH: Update Thai translation (#224) 2025-03-14 16:47:07 +06:00
Ksawlii
d209dc087e Update selinux strings in values-pl (#218)
Signed-off-by: Ksawlii <ksawery.blaszczak@proton.me>
2025-03-14 16:46:39 +06:00
rifsxd
d79ea50c6e Revert "ksud_magic: probe for more workdir candidates (#221)"
This reverts commit a68b4fe7e0.
2025-03-11 23:31:30 +06:00
rifsxd
d8944d641c ksud_magic: reformat rust codes 2025-03-10 23:51:02 +06:00
Wang Han
1c9705fdd0 Set KSU_APP_PROFILE_VER for shell (#2481)
This reverts commit bd24044ec3.
2025-03-10 22:16:22 +06:00
AlexLiuDev233
f369297be9 kernel: fix sometimes sucompat can not toggle by manager (#2484)
When the manager is already running, if other programs / kernel toggle
the sucompat enable status,
The manager "Disable SU Compat" toggle button can not work, kmesg print
"cmd enable su but no need to change."

I think we should still return reply_ok when the syscall value is
consistent with the kernel, which would fix the issue.
2025-03-10 22:16:03 +06:00
backslashxx
a68b4fe7e0 ksud_magic: probe for more workdir candidates (#221)
- reuses old ksu functions
- makes sure its an empty dir
- adapted from https://github.com/rsuntk/KernelSU/commit/141f010 71cb86c2e9

Co-authored-by: powellnorma <101364699+powellnorma@users.noreply.github.com>
Co-authored-by: Rissu <90097027+rsuntk@users.noreply.github.com>
2025-03-09 14:48:24 +06:00
kam821
52399f7fd1 Update Polish Translation (#212)
- Fixed incorrect translations
- Unified nomenclature
- Added splitting to preserve both forms where needed
2025-03-09 14:33:48 +06:00
backslashxx
7218a504c9 kernel: ksud: add ksu_handle_execve_ksud (#217)
adapted from sys_execve_handler_pre()
upstream, https://github.com/tiann/KernelSU/commit/2027ac3

this completes the puzzle where all hooks are on syscalls

ksu_handle_execve_ksud
- sets argv to __argv, dunno what this is for, I just copied.
- creates dummy struct `filename_in` to store filename in `filename_in.name`
- strncpy filename to path, assign path to .name
- simply a shim for ksu_handle_execveat_ksud

usage: `ksu_handle_execve_ksud(filename, argv);` on sys_execve

tested on 4.14, 6.1

Tested-by: selfmusing <mirandamehek@gmail.com>
Tested-by: Adam W. Willis <return.of.octobot@gmail.com>

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
Co-authored-by: Another Guy <25584417+anotherjin@users.noreply.github.com>
2025-03-09 14:33:26 +06:00
luigimak
9d5999c8c3 Create values-it/strings.xml (#208)
Italian translation
2025-03-08 10:41:51 +06:00
the slaytanic one~
204805852c Create strings.xml (#205) 2025-03-05 01:22:08 +06:00
xradens
36b42e611e Update Bahasa Indonesia Translation (#203)
Fixed some translations
2025-03-03 20:54:24 +06:00
dependabot[bot]
c50bbd32aa build(deps): bump the maven group across 1 directory with 5 updates (#201)
Bumps the maven group with 5 updates in the /manager directory:

| Package | From | To |
| --- | --- | --- |
| androidx.activity:activity-compose | `1.10.0` | `1.10.1` |
| androidx.navigation:navigation-compose | `2.8.7` | `2.8.8` |
| com.android.application | `8.8.1` | `8.8.2` |
| com.android.library | `8.8.1` | `8.8.2` |
| [com.google.devtools.ksp](https://github.com/google/ksp) | `2.1.10-1.0.30` | `2.1.10-1.0.31` |



Updates `androidx.activity:activity-compose` from 1.10.0 to 1.10.1

Updates `androidx.navigation:navigation-compose` from 2.8.7 to 2.8.8

Updates `com.android.application` from 8.8.1 to 8.8.2

Updates `com.android.library` from 8.8.1 to 8.8.2

Updates `com.android.library` from 8.8.1 to 8.8.2

Updates `com.google.devtools.ksp` from 2.1.10-1.0.30 to 2.1.10-1.0.31
- [Release notes](https://github.com/google/ksp/releases)
- [Commits](https://github.com/google/ksp/compare/2.1.10-1.0.30...2.1.10-1.0.31)

---
updated-dependencies:
- dependency-name: androidx.activity:activity-compose
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: androidx.navigation:navigation-compose
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.android.application
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.android.library
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.android.library
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.google.devtools.ksp
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-03 20:54:11 +06:00
Anaël
d2f6d00327 manager: translations: Update french translations (#198)
* manager: translations: Update french translations

* Fixed typos
* Added su compat translations
* Added allowlist backup/restore translations
* Added about source code translation

* manager: translations: fix typo

* This was missed in commit 4097d55716

* manager: translations: fix another typo

* i really have to get some sleep duh im tired
2025-03-02 01:20:57 +06:00
rifsxd
c9e4c8e186 manager: remove unnecessary isManager definition in Settings screen 2025-02-28 01:40:28 +06:00
Wang Han
3a6c30fba1 Avoid popping back stack right after navigation (#2477)
This fixes https://github.com/tiann/KernelSU/issues/2462.
2025-02-28 00:50:50 +06:00
rifsxd
d5d4304120 manager: hide su related settings screen items if ksuVersion is null 2025-02-28 00:35:13 +06:00
rifsxd
4eac2f783e manager: change MINIMAL_SUPPORTED_SU_COMPAT to 12404 (where disable su compat feature was fully implemented) 2025-02-28 00:25:59 +06:00
rifsxd
2cc765ee0a manager: add back navigation to BackupRestore screen 2025-02-28 00:22:37 +06:00
cvnertnc
453524d382 Update values-tr/strings.xml (#195) 2025-02-27 03:33:34 +06:00
Mateusz Chrząszcz
fccc3db5c5 Update strings.xml fix, update (#194) 2025-02-26 03:10:27 +06:00
rifsxd
7a08683c74 kernel: remove unnecessary umount calls for configuration directories (evil modifications) 2025-02-25 19:48:20 +06:00
rifsxd
2f3f444905 ksud_magic: use unsafe block for setting PATH environment variable 2025-02-25 17:51:04 +06:00
rifsxd
7746569fe9 manager: guard isOverlayAvailable only if useOverlayFs is not used 2025-02-25 17:12:36 +06:00
dependabot[bot]
3a601f86a5 build(deps): bump the crates group (#193)
Bumps the crates group in /userspace/ksud_overlayfs with 2 updates: [clap](https://github.com/clap-rs/clap) and [clap_builder](https://github.com/clap-rs/clap).


Updates `clap` from 4.5.30 to 4.5.31
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.30...v4.5.31)

Updates `clap_builder` from 4.5.30 to 4.5.31
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.5.30...v4.5.31)

---
updated-dependencies:
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap_builder
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-25 15:40:24 +06:00
rifsxd
e7dab63837 manager: remove beta label from OverlayFS usage strings 2025-02-25 15:38:53 +06:00
rifsxd
487e7d0012 kernel: simplify umount calls for configuration files 2025-02-25 15:37:12 +06:00
Tiann
ee71a992a3 ksud: migrate to Rust 2024 edition 2025-02-25 15:34:27 +06:00
Tiann
195e1ba494 ksud: upgrade nom to 8.0 2025-02-25 14:11:26 +06:00
dependabot[bot]
a0e4d01269 build(deps): bump the crates group across 1 directory with 15 updates (#191)
Bumps the crates group with 13 updates in the /userspace/ksud_magic directory:

| Package | From | To |
| --- | --- | --- |
| [anyhow](https://github.com/dtolnay/anyhow) | `1.0.95` | `1.0.96` |
| [clap](https://github.com/clap-rs/clap) | `4.5.29` | `4.5.30` |
| [log](https://github.com/rust-lang/log) | `0.4.25` | `0.4.26` |
| [serde_json](https://github.com/serde-rs/json) | `1.0.138` | `1.0.139` |
| [libc](https://github.com/rust-lang/libc) | `0.2.169` | `0.2.170` |
| [tempfile](https://github.com/Stebalien/tempfile) | `3.16.0` | `3.17.1` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.14` | `1.2.15` |
| [either](https://github.com/rayon-rs/either) | `1.13.0` | `1.14.0` |
| [flate2](https://github.com/rust-lang/flate2-rs) | `1.0.35` | `1.1.0` |
| [miniz_oxide](https://github.com/Frommi/miniz_oxide) | `0.8.4` | `0.8.5` |
| [serde](https://github.com/serde-rs/serde) | `1.0.217` | `1.0.218` |
| [typenum](https://github.com/paholg/typenum) | `1.17.0` | `1.18.0` |
| [unicode-ident](https://github.com/dtolnay/unicode-ident) | `1.0.16` | `1.0.17` |



Updates `anyhow` from 1.0.95 to 1.0.96
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.95...1.0.96)

Updates `clap` from 4.5.29 to 4.5.30
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.29...clap_complete-v4.5.30)

Updates `log` from 0.4.25 to 0.4.26
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.25...0.4.26)

Updates `serde_json` from 1.0.138 to 1.0.139
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.138...v1.0.139)

Updates `libc` from 0.2.169 to 0.2.170
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.170/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.169...0.2.170)

Updates `tempfile` from 3.16.0 to 3.17.1
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.16.0...v3.17.1)

Updates `cc` from 1.2.14 to 1.2.15
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.14...cc-v1.2.15)

Updates `clap_builder` from 4.5.29 to 4.5.30
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.5.29...v4.5.30)

Updates `either` from 1.13.0 to 1.14.0
- [Commits](https://github.com/rayon-rs/either/compare/1.13.0...1.14.0)

Updates `flate2` from 1.0.35 to 1.1.0
- [Release notes](https://github.com/rust-lang/flate2-rs/releases)
- [Changelog](https://github.com/rust-lang/flate2-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/flate2-rs/compare/1.0.35...1.1.0)

Updates `miniz_oxide` from 0.8.4 to 0.8.5
- [Changelog](https://github.com/Frommi/miniz_oxide/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Frommi/miniz_oxide/compare/0.8.4...0.8.5)

Updates `serde` from 1.0.217 to 1.0.218
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.217...v1.0.218)

Updates `serde_derive` from 1.0.217 to 1.0.218
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.217...v1.0.218)

Updates `typenum` from 1.17.0 to 1.18.0
- [Release notes](https://github.com/paholg/typenum/releases)
- [Changelog](https://github.com/paholg/typenum/blob/main/CHANGELOG.md)
- [Commits](https://github.com/paholg/typenum/compare/v1.17.0...v1.18.0)

Updates `unicode-ident` from 1.0.16 to 1.0.17
- [Release notes](https://github.com/dtolnay/unicode-ident/releases)
- [Commits](https://github.com/dtolnay/unicode-ident/compare/1.0.16...1.0.17)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: log
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: libc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: tempfile
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: cc
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap_builder
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: either
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: flate2
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: miniz_oxide
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: serde
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: serde_derive
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: typenum
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: unicode-ident
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-25 05:09:07 +06:00
dependabot[bot]
b8b0dc724a build(deps): bump the crates group across 1 directory with 16 updates (#192)
Bumps the crates group with 14 updates in the /userspace/ksud_overlayfs directory:

| Package | From | To |
| --- | --- | --- |
| [anyhow](https://github.com/dtolnay/anyhow) | `1.0.95` | `1.0.96` |
| [clap](https://github.com/clap-rs/clap) | `4.5.29` | `4.5.30` |
| [log](https://github.com/rust-lang/log) | `0.4.25` | `0.4.26` |
| [serde_json](https://github.com/serde-rs/json) | `1.0.138` | `1.0.139` |
| [libc](https://github.com/rust-lang/libc) | `0.2.169` | `0.2.170` |
| [tempfile](https://github.com/Stebalien/tempfile) | `3.16.0` | `3.17.1` |
| [fs4](https://github.com/al8n/fs4-rs) | `0.12.0` | `0.13.0` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.14` | `1.2.15` |
| [either](https://github.com/rayon-rs/either) | `1.13.0` | `1.14.0` |
| [flate2](https://github.com/rust-lang/flate2-rs) | `1.0.35` | `1.1.0` |
| [miniz_oxide](https://github.com/Frommi/miniz_oxide) | `0.8.4` | `0.8.5` |
| [serde](https://github.com/serde-rs/serde) | `1.0.217` | `1.0.218` |
| [typenum](https://github.com/paholg/typenum) | `1.17.0` | `1.18.0` |
| [unicode-ident](https://github.com/dtolnay/unicode-ident) | `1.0.16` | `1.0.17` |



Updates `anyhow` from 1.0.95 to 1.0.96
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.95...1.0.96)

Updates `clap` from 4.5.29 to 4.5.30
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.29...clap_complete-v4.5.30)

Updates `log` from 0.4.25 to 0.4.26
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.25...0.4.26)

Updates `serde_json` from 1.0.138 to 1.0.139
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.138...v1.0.139)

Updates `libc` from 0.2.169 to 0.2.170
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.170/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.169...0.2.170)

Updates `tempfile` from 3.16.0 to 3.17.1
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.16.0...v3.17.1)

Updates `fs4` from 0.12.0 to 0.13.0
- [Release notes](https://github.com/al8n/fs4-rs/releases)
- [Changelog](https://github.com/al8n/fs4-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/al8n/fs4-rs/commits)

Updates `cc` from 1.2.14 to 1.2.15
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.14...cc-v1.2.15)

Updates `clap_builder` from 4.5.29 to 4.5.30
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.5.29...v4.5.30)

Updates `either` from 1.13.0 to 1.14.0
- [Commits](https://github.com/rayon-rs/either/compare/1.13.0...1.14.0)

Updates `flate2` from 1.0.35 to 1.1.0
- [Release notes](https://github.com/rust-lang/flate2-rs/releases)
- [Changelog](https://github.com/rust-lang/flate2-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/flate2-rs/compare/1.0.35...1.1.0)

Updates `miniz_oxide` from 0.8.4 to 0.8.5
- [Changelog](https://github.com/Frommi/miniz_oxide/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Frommi/miniz_oxide/compare/0.8.4...0.8.5)

Updates `serde` from 1.0.217 to 1.0.218
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.217...v1.0.218)

Updates `serde_derive` from 1.0.217 to 1.0.218
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.217...v1.0.218)

Updates `typenum` from 1.17.0 to 1.18.0
- [Release notes](https://github.com/paholg/typenum/releases)
- [Changelog](https://github.com/paholg/typenum/blob/main/CHANGELOG.md)
- [Commits](https://github.com/paholg/typenum/compare/v1.17.0...v1.18.0)

Updates `unicode-ident` from 1.0.16 to 1.0.17
- [Release notes](https://github.com/dtolnay/unicode-ident/releases)
- [Commits](https://github.com/dtolnay/unicode-ident/compare/1.0.16...1.0.17)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: log
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: libc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: tempfile
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: fs4
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: cc
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap_builder
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: either
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: flate2
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: miniz_oxide
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: serde
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: serde_derive
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: typenum
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: unicode-ident
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-25 05:08:51 +06:00
Vndkbopp77
39777f301d Create strings.xml (#189)
Add german translation
2025-02-25 00:42:22 +06:00
Azyr Ruthless
f20662c6b6 manager: update Indonesian translations (#188)
Signed-off-by: AzyrRuthless <132790292+AzyrRuthless@users.noreply.github.com>
2025-02-24 20:45:23 +06:00
Kangmin Kim
3532f20b2f Update Korean strings.xml (#187)
Make strings more formal
Add new strings
2025-02-24 20:44:10 +06:00
Anaël
14218e81be Update french translations (#184)
* Update french translations

* update french translation

* fix french translation typo

* add french translations

* Update french translations and fix typos
2025-02-24 20:40:59 +06:00
igor
d104250770 manager: update translations (#183) 2025-02-24 20:38:15 +06:00
rifsxd
6100df6f8c manager: remove redundant enabled state check in SettingScreen 2025-02-24 20:33:25 +06:00
rifsxd
e597bd1c66 manager: MINIMAL_SUPPORTED_SU_COMPAT set to 12402 to support disable sucompat mode in settings 2025-02-24 04:26:56 +06:00
Wang Han
0038ba6566 Fix reference count leak in nuke_ext4_sysfs() (#2467)
We need to call path_put() to decrease the refcount.
2025-02-24 02:48:39 +06:00
Js0n
7bebb2a461 fix: crash #2463 (#2465)
my bad
2025-02-24 02:48:21 +06:00
Js0n
f3fee49f8c feat: properly set OkHttp header (#2463)
properly send `User-Agent` and `Accept-Language` to `updateJson` server,
module developers can check `User-Agent` whether to send update to user
and set user preferred language for changelog.

also added cache to reduce update server load
2025-02-24 02:48:01 +06:00
rifsxd
e8c080ba09 src: adapt git links to KernelSU-Next org 2025-02-24 02:18:02 +06:00
Rifat Azad
785d8143fb kernel: remove KSU_WITH_KPROBES definition since it's already defined by Kconfig 2025-02-24 01:29:28 +06:00
backslashxx
cd0031e8a5 kernel: expose variables used by manual hooks always 2025-02-23 22:58:00 +06:00
rifsxd
c1273d35f4 manager: fix native jni calls and minor change to strings 2025-02-23 22:42:30 +06:00
backslashxx
15371bb1d6 kernel: add non-kprobe support for sucompat disable/enable
I have no idea if this is needed or any useful for manual fs hooks users.
Upstream, this is likely to, well, simply disable hooking of those functions,
to remove and mitigate timing issues as some detection methods can actually
differentiate these.

This is done like how vfs_read_hook, input_hook and execve_hook is disabled.
While this is not exactly the same thing, this *CAN* achieve the same results.
The complete disabling of all KernelSU hooks.

While this is probably not so useful for us, honestly, I have no idea for shit
what I am doing, but lets still port it for the sake of feature parity.

cherry pick from:
	kernel: backport support for sucompat disable/enable
	https://github.com/backslashxx/KernelSU/commit/20ffabb

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-02-23 22:11:50 +06:00
backslashxx
097451d578 kernel: guard functionality that requires kprobes
Since upstream is now making kprobes a requirement, we adapt this tree to still allow
building with manual hooks in an easier way. Furthermore, this also allows a user to
build with manual hooks even with kprobes enabled.

Offending commit:
	kernel: remove unused CONFIG guard becuase GKI kernel enable kprobe by default
	upstream: https://github.com/tiann/KernelSU/commit/500ff9b

Other changes:
	ksud.c, stop_input_hook(), short-circuit redundant logic left by this change.
	cherry pick from: https://github.com/backslashxx/KernelSU/commit/a3d3e93

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-02-23 21:00:59 +06:00
weishu
85866848ea kernel: Allow to re-enable sucompat 2025-02-23 20:37:34 +06:00
weishu
d05d16c15d manager: Add support to disable sucompat mode. 2025-02-23 20:06:09 +06:00
weishu
bb6c20339c kernel: add support for disable sucompat 2025-02-23 20:05:55 +06:00
igor
af012ce349 Update portuguese translation (#182) 2025-02-23 00:07:55 +06:00
Wang Han
43d30c8f2b Drop module image if no module remaining (#2447)
This fixes the issue that module image will always exist even if there
is no module to be loaded. Sadly we need to boot twice because we can
only know module status after image is mounted.
2025-02-22 04:50:51 +06:00
Wang Han
a89985f33e Allow toggling unmount setting for all apps (#2450)
This fixes https://github.com/tiann/KernelSU/issues/2416.
2025-02-22 04:48:44 +06:00
rifsxd
42896dfab1 kernel: add umount calls for pixelify gphotos spoof configs and lsposed dex2oat bin 2025-02-22 04:40:28 +06:00
Wang Han
36111f4b89 Provide TMPDIR for boot image repacking (#2458)
/data/local/tmp is never writable for normal apps, why previously it
works is that Rust's temp_dir() gets path from env, and since A13,
TMPDIR is set to app's cache dir. This is not the case for A12, so it
breaks. Fix it by set TMPDIR ourselves.
2025-02-21 17:33:21 +06:00
weishu
74171a2930 kernel: unregister sysfs for module's ext4 image 2025-02-21 17:02:33 +06:00
weishu
c40bfd694c ksud: determine modules's size by checking partion size 2025-02-21 17:02:03 +06:00
rifsxd
aa22fd880d ksud_overlayfs: better hide modules.img (create a sparse image without journaling) and run e2fsck for eliminating possible data corruption after umount 2025-02-21 16:57:24 +06:00
rifsxd
fe9578433c manager: update module installation prompt string 2025-02-21 16:49:11 +06:00
rifsxd
a0278b1e45 manager: refactor: remove FlashModule and update navigation to FlashModules 2025-02-21 16:38:00 +06:00
rifsxd
0c7ba4dc6e manager: fix syntax and unresolved function 2025-02-21 00:27:57 +06:00
Tiann
b98c531ff8 manager: refine flashing module confirm dialog 2025-02-21 00:16:21 +06:00
Tiann
373025248d manager: refine flash utilities 2025-02-20 23:45:04 +06:00
Kangmin Kim
60d2ad39d6 Update Korean Translation & Add Vietnamese README link (#173)
* Update allowlist-related Korean Strings

* Add Vietnamease README Link to other READMEs
2025-02-20 19:41:56 +06:00
HiN
b807b38892 add strings translate indonesia (#174) 2025-02-20 19:41:35 +06:00
Nhật Minh
5ca5e2b027 update vietnamese (#170)
* Create strings.xml

added vietnamese (fix smt
)

* Update strings.xml

* update vietnamese

* added vietnamese for readme
2025-02-17 18:15:54 +06:00
dependabot[bot]
608e949e23 build(deps): bump the crates group across 1 directory with 2 updates (#167)
Bumps the crates group with 2 updates in the /userspace/ksud_overlayfs directory: [cc](https://github.com/rust-lang/cc-rs) and [equivalent](https://github.com/indexmap-rs/equivalent).


Updates `cc` from 1.2.13 to 1.2.14
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.13...cc-v1.2.14)

Updates `equivalent` from 1.0.1 to 1.0.2
- [Commits](https://github.com/indexmap-rs/equivalent/compare/v1.0.1...v1.0.2)

---
updated-dependencies:
- dependency-name: cc
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: equivalent
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-16 21:57:41 +06:00
dependabot[bot]
c9dd12d50b build(deps): bump the maven group across 1 directory with 5 updates (#160)
Bumps the maven group with 5 updates in the /manager directory:

| Package | From | To |
| --- | --- | --- |
| androidx.navigation:navigation-compose | `2.8.6` | `2.8.7` |
| androidx.compose:compose-bom | `2025.01.01` | `2025.02.00` |
| com.android.application | `8.8.0` | `8.8.1` |
| com.android.library | `8.8.0` | `8.8.1` |
| [com.google.devtools.ksp](https://github.com/google/ksp) | `2.1.10-1.0.29` | `2.1.10-1.0.30` |



Updates `androidx.navigation:navigation-compose` from 2.8.6 to 2.8.7

Updates `androidx.compose:compose-bom` from 2025.01.01 to 2025.02.00

Updates `com.android.application` from 8.8.0 to 8.8.1

Updates `com.android.library` from 8.8.0 to 8.8.1

Updates `com.android.library` from 8.8.0 to 8.8.1

Updates `com.google.devtools.ksp` from 2.1.10-1.0.29 to 2.1.10-1.0.30
- [Release notes](https://github.com/google/ksp/releases)
- [Commits](https://github.com/google/ksp/compare/2.1.10-1.0.29...2.1.10-1.0.30)

---
updated-dependencies:
- dependency-name: androidx.navigation:navigation-compose
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: androidx.compose:compose-bom
  dependency-type: direct:production
  dependency-group: maven
- dependency-name: com.android.application
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.android.library
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.android.library
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.google.devtools.ksp
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-16 21:57:29 +06:00
dependabot[bot]
7319dd25a3 build(deps): bump the crates group across 1 directory with 2 updates (#168)
Bumps the crates group with 2 updates in the /userspace/ksud_magic directory: [cc](https://github.com/rust-lang/cc-rs) and [equivalent](https://github.com/indexmap-rs/equivalent).


Updates `cc` from 1.2.13 to 1.2.14
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.13...cc-v1.2.14)

Updates `equivalent` from 1.0.1 to 1.0.2
- [Commits](https://github.com/indexmap-rs/equivalent/compare/v1.0.1...v1.0.2)

---
updated-dependencies:
- dependency-name: cc
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: equivalent
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-16 21:57:12 +06:00
rifsxd
fdd307fe8b ksud_overlayfs: bring back journaling for sparse image (futile for hiding so reverting until a possible better way is discovered) 2025-02-16 20:36:03 +06:00
igor
b6c8203a97 Update translations (#165) 2025-02-16 16:02:05 +06:00
rifsxd
b2a8fb66d3 ksud_overlayfs: reduce sparse image size to 6GB 2025-02-16 03:10:30 +06:00
rifsxd
74f55dd807 manager: disable restore module button on overlayfs mount mode (since the restore module code for overlayfs mount never got out of internal testing, wull be implemented in the future) 2025-02-16 03:07:36 +06:00
rifsxd
8560f35c8b manager: added divider for backup and restore screen catagories 2025-02-15 19:51:39 +06:00
rifsxd
b0f01cf7ff docs: fix nightly manager link (#164) 2025-02-15 19:51:39 +06:00
rifsxd
8ae0192b47 manager: update Chinese translations (@Xiaomichael) 2025-02-15 19:51:38 +06:00
rifsxd
f247a6d5d8 ksud_overlayfs: better hide modules.img (create a sparse image without journaling) and run e2fsck for eliminating possible data corruption after umount 2025-02-15 19:51:30 +06:00
rifsxd
d85bff2943 manager: added allowlist backup and restore (#9)
manager: create separate module & restore screen
2025-02-15 02:00:24 +06:00
rifsxd
f5ac0f3589 manager: renamed log files output 2025-02-14 21:54:12 +06:00
rifsxd
a2fcd157a2 Revert "kernel: do not umount modules by default"
This reverts commit bbb05b292a.
2025-02-14 21:32:43 +06:00
rifsxd
70ce97660e manager: fix syntax for strings of zh-CN 2025-02-14 21:17:51 +06:00
Kangmin Kim
67967a8251 Update Korean strings.xml (#158) 2025-02-14 20:16:33 +06:00
rifsxd
b25a21770d manager: updated Chinese translations (by @Xiaomichael) 2025-02-14 20:13:55 +06:00
rifsxd
bbb05b292a kernel: do not umount modules by default 2025-02-14 19:45:19 +06:00
rifsxd
8696ed8f36 Revert "manager: fix umountModule toggle not showing as enabled after manager restart"
This reverts commit 682f93667b.
2025-02-14 19:34:46 +06:00
rifsxd
682f93667b manager: fix umountModule toggle not showing as enabled after manager restart 2025-02-14 12:52:44 +06:00
rifsxd
00cab2209e manager: added developer options toggle
manager: removed module card onClick open webui
manager: diabled umount modules by default
2025-02-13 23:17:48 +06:00
Wang Han
b6fcea9277 Hide namespace config in app profiles (#2426)
This is never implemented in kernel (and likely never will be), so let's
remove it from UI for now to avoid misleading users.
2025-02-13 20:09:44 +06:00
rifsxd
623f5e3f64 manager: avoid factory data reset popup when rebooting into recovery 2025-02-13 20:08:32 +06:00
Caner Karaca
b18f89b434 Updates (#151)
* Update

* Fix
2025-02-13 05:54:36 +06:00
Kangmin Kim
2a152fdb22 Fix Nightly Release Download Link (#152)
* Update README.md

Fix Nightly Release Download Link

* Update every other READMEs
2025-02-13 04:05:05 +06:00
Nhật Minh
dbadad1027 Create strings.xml (#139)
added vietnamese (fix smt
)
2025-02-10 14:03:13 +06:00
rifsxd
fcc4f0d206 ksud_overlayfs: fix sparse image journal size being 0 block and cause error to format into ext4 with mke2fs 2025-02-07 14:23:56 +06:00
rifsxd
c20fe6c886 ksud_overlayfs: changed sparse image journal size to 64MB for good balance of performance and efficiency 2025-02-06 19:22:48 +06:00
5ec1cff
19a15a71eb ksud: fix stat 2025-02-06 18:56:29 +06:00
rifsxd
c446ee76f5 github: fix outdated link in issue_templete 2025-02-06 18:05:33 +06:00
rifsxd
5435992911 kernel: KernelSU-Next version fallback set to 11998 2025-02-06 17:58:00 +06:00
weishu
c2ae844f65 manager: Create a new root shell for action.sh to avoid blocking the global root shell. 2025-02-06 17:49:36 +06:00
weishu
8832532f09 ksud: make clippy happy 2025-02-06 17:46:14 +06:00
Furkan
cba275cde2 Small Fix Turkish strings.xml (#113)
Trying to fix Superuser text spacing problem on Turkish translate with deleting blank space, changing module section to Modules section (Moduller) to be able to add plural meaning.
2025-02-02 23:34:51 +06:00
rifsxd
4401e28f57 Revert "build(deps): bump the crates group across 1 directory with 9 updates (#103)"
This reverts commit d4db74f0fb.
2025-02-02 22:55:41 +06:00
rifsxd
ece6e3f694 Revert "build(deps): bump the crates group across 1 directory with 9 updates (#104)"
This reverts commit e931792a4f.
2025-02-02 22:54:42 +06:00
dependabot[bot]
d4db74f0fb build(deps): bump the crates group across 1 directory with 9 updates (#103)
Bumps the crates group with 7 updates in the /userspace/ksud_overlayfs directory:

| Package | From | To |
| --- | --- | --- |
| [serde_json](https://github.com/serde-rs/json) | `1.0.137` | `1.0.138` |
| [nom](https://github.com/rust-bakery/nom) | `7.1.3` | `8.0.0` |
| [tempfile](https://github.com/Stebalien/tempfile) | `3.15.0` | `3.16.0` |
| [bumpalo](https://github.com/fitzgen/bumpalo) | `3.16.0` | `3.17.0` |
| [cpufeatures](https://github.com/RustCrypto/utils) | `0.2.16` | `0.2.17` |
| [ryu](https://github.com/dtolnay/ryu) | `1.0.18` | `1.0.19` |
| [unicode-ident](https://github.com/dtolnay/unicode-ident) | `1.0.15` | `1.0.16` |



Updates `serde_json` from 1.0.137 to 1.0.138
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.137...v1.0.138)

Updates `nom` from 7.1.3 to 8.0.0
- [Changelog](https://github.com/rust-bakery/nom/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-bakery/nom/compare/7.1.3...8.0.0)

Updates `tempfile` from 3.15.0 to 3.16.0
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.15.0...v3.16.0)

Updates `bumpalo` from 3.16.0 to 3.17.0
- [Changelog](https://github.com/fitzgen/bumpalo/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fitzgen/bumpalo/compare/3.16.0...3.17.0)

Updates `cpufeatures` from 0.2.16 to 0.2.17
- [Commits](https://github.com/RustCrypto/utils/compare/cpufeatures-v0.2.16...cpufeatures-v0.2.17)

Updates `getrandom` from 0.2.15 to 0.3.1
- [Changelog](https://github.com/rust-random/getrandom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/getrandom/compare/v0.2.15...v0.3.1)

Updates `ryu` from 1.0.18 to 1.0.19
- [Release notes](https://github.com/dtolnay/ryu/releases)
- [Commits](https://github.com/dtolnay/ryu/compare/1.0.18...1.0.19)

Updates `unicode-ident` from 1.0.15 to 1.0.16
- [Release notes](https://github.com/dtolnay/unicode-ident/releases)
- [Commits](https://github.com/dtolnay/unicode-ident/compare/1.0.15...1.0.16)

Updates `wasi` from 0.11.0+wasi-snapshot-preview1 to 0.13.3+wasi-0.2.2
- [Commits](https://github.com/bytecodealliance/wasi-rs/compare/0.11.0...0.13.3)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: nom
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: crates
- dependency-name: tempfile
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: bumpalo
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: cpufeatures
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: getrandom
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: ryu
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: unicode-ident
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: wasi
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 22:28:52 +06:00
dependabot[bot]
e931792a4f build(deps): bump the crates group across 1 directory with 9 updates (#104)
Bumps the crates group with 7 updates in the /userspace/ksud_magic directory:

| Package | From | To |
| --- | --- | --- |
| [serde_json](https://github.com/serde-rs/json) | `1.0.137` | `1.0.138` |
| [nom](https://github.com/rust-bakery/nom) | `7.1.3` | `8.0.0` |
| [tempfile](https://github.com/Stebalien/tempfile) | `3.15.0` | `3.16.0` |
| [bumpalo](https://github.com/fitzgen/bumpalo) | `3.16.0` | `3.17.0` |
| [cpufeatures](https://github.com/RustCrypto/utils) | `0.2.16` | `0.2.17` |
| [ryu](https://github.com/dtolnay/ryu) | `1.0.18` | `1.0.19` |
| [unicode-ident](https://github.com/dtolnay/unicode-ident) | `1.0.15` | `1.0.16` |



Updates `serde_json` from 1.0.137 to 1.0.138
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.137...v1.0.138)

Updates `nom` from 7.1.3 to 8.0.0
- [Changelog](https://github.com/rust-bakery/nom/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-bakery/nom/compare/7.1.3...8.0.0)

Updates `tempfile` from 3.15.0 to 3.16.0
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.15.0...v3.16.0)

Updates `bumpalo` from 3.16.0 to 3.17.0
- [Changelog](https://github.com/fitzgen/bumpalo/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fitzgen/bumpalo/compare/3.16.0...3.17.0)

Updates `cpufeatures` from 0.2.16 to 0.2.17
- [Commits](https://github.com/RustCrypto/utils/compare/cpufeatures-v0.2.16...cpufeatures-v0.2.17)

Updates `getrandom` from 0.2.15 to 0.3.1
- [Changelog](https://github.com/rust-random/getrandom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/getrandom/compare/v0.2.15...v0.3.1)

Updates `ryu` from 1.0.18 to 1.0.19
- [Release notes](https://github.com/dtolnay/ryu/releases)
- [Commits](https://github.com/dtolnay/ryu/compare/1.0.18...1.0.19)

Updates `unicode-ident` from 1.0.15 to 1.0.16
- [Release notes](https://github.com/dtolnay/unicode-ident/releases)
- [Commits](https://github.com/dtolnay/unicode-ident/compare/1.0.15...1.0.16)

Updates `wasi` from 0.11.0+wasi-snapshot-preview1 to 0.13.3+wasi-0.2.2
- [Commits](https://github.com/bytecodealliance/wasi-rs/compare/0.11.0...0.13.3)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: nom
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: crates
- dependency-name: tempfile
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: bumpalo
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: cpufeatures
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: getrandom
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: ryu
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: unicode-ident
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: wasi
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 22:27:41 +06:00
dependabot[bot]
3876b6b474 build(deps): bump the maven group across 1 directory with 7 updates (#111)
Bumps the maven group with 7 updates in the /manager directory:

| Package | From | To |
| --- | --- | --- |
| androidx.navigation:navigation-compose | `2.8.5` | `2.8.6` |
| androidx.compose:compose-bom | `2025.01.00` | `2025.01.01` |
| [io.github.raamcosta.compose-destinations:core](https://github.com/raamcosta/compose-destinations) | `2.1.0-beta15` | `2.1.0-beta16` |
| [io.github.raamcosta.compose-destinations:ksp](https://github.com/raamcosta/compose-destinations) | `2.1.0-beta15` | `2.1.0-beta16` |
| [org.jetbrains.kotlin.android](https://github.com/JetBrains/kotlin) | `2.1.0` | `2.1.10` |
| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.1.0` | `2.1.10` |
| [com.google.devtools.ksp](https://github.com/google/ksp) | `2.1.0-1.0.29` | `2.1.10-1.0.29` |



Updates `androidx.navigation:navigation-compose` from 2.8.5 to 2.8.6

Updates `androidx.compose:compose-bom` from 2025.01.00 to 2025.01.01

Updates `io.github.raamcosta.compose-destinations:core` from 2.1.0-beta15 to 2.1.0-beta16
- [Release notes](https://github.com/raamcosta/compose-destinations/releases)
- [Commits](https://github.com/raamcosta/compose-destinations/compare/2.1.0-beta15...2.1.0-beta16)

Updates `io.github.raamcosta.compose-destinations:ksp` from 2.1.0-beta15 to 2.1.0-beta16
- [Release notes](https://github.com/raamcosta/compose-destinations/releases)
- [Commits](https://github.com/raamcosta/compose-destinations/compare/2.1.0-beta15...2.1.0-beta16)

Updates `io.github.raamcosta.compose-destinations:ksp` from 2.1.0-beta15 to 2.1.0-beta16
- [Release notes](https://github.com/raamcosta/compose-destinations/releases)
- [Commits](https://github.com/raamcosta/compose-destinations/compare/2.1.0-beta15...2.1.0-beta16)

Updates `org.jetbrains.kotlin.android` from 2.1.0 to 2.1.10
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v2.1.0...v2.1.10)

Updates `org.jetbrains.kotlin.plugin.compose` from 2.1.0 to 2.1.10
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v2.1.0...v2.1.10)

Updates `org.jetbrains.kotlin.plugin.compose` from 2.1.0 to 2.1.10
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v2.1.0...v2.1.10)

Updates `com.google.devtools.ksp` from 2.1.0-1.0.29 to 2.1.10-1.0.29
- [Release notes](https://github.com/google/ksp/releases)
- [Commits](https://github.com/google/ksp/compare/2.1.0-1.0.29...2.1.10-1.0.29)

---
updated-dependencies:
- dependency-name: androidx.navigation:navigation-compose
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: androidx.compose:compose-bom
  dependency-type: direct:production
  dependency-group: maven
- dependency-name: io.github.raamcosta.compose-destinations:core
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: io.github.raamcosta.compose-destinations:ksp
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: io.github.raamcosta.compose-destinations:ksp
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: org.jetbrains.kotlin.android
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: org.jetbrains.kotlin.plugin.compose
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: org.jetbrains.kotlin.plugin.compose
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.google.devtools.ksp
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 22:24:56 +06:00
backslashxx
ae36e2085c kernel: handle optional backports (#99)
Cherry pick from 8bb9518060 a4a7db7f40

Backporting is cool, but not everyone has the skills for it.
This commit does NOT make it required, but it will allow compiler
to use whats in-kernel if it exists.

The following are backportable:
 - kernel_read / kernel_write
 	< 4.14, backport chain, tested on 4.9
 	e13ec939e9
	bdd1d2d3d2
	c41fbad015
	ac452acae1

 - strncpy_from_user_nofault
 	for 5.4, apply: bd88bb5d40
 	for 4.x, apply: 424e21f3b0
 	for any failures, just SKIP THIS or check dependency chain of, 3d7081822f
 		this got backported to v4.4.236, v4.9.236, v4.14.197, v4.19.144

- hint, `curl $url.patch | git am`

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-01-28 14:53:35 +06:00
Caner Karaca
3a8f4a2596 manager: update gradle (#85) 2025-01-28 01:41:47 +06:00
5ec1cff
87fc6b2784 kernel: clear securebits
fix adb shell cannot escape to root after https://github.com/tiann/KernelSU/pull/2381
2025-01-27 20:05:54 +06:00
Caner Karaca
25b57204ef ci: update workflows (#83)
* ci: update workflows

* Revert
2025-01-27 15:13:18 +06:00
Mateusz Chrząszcz
4ed362bea4 Add Polish Translation (#91)
* Create colors.xml

* Create themes.xml

* Create strings.xml and 1/2 translate

* Delete manager/app/src/main/res/values-pl/colors.xml

* Delete manager/app/src/main/res/values-pl/themes.xml

* Update strings.xml 2/2 translate

* Update strings.xml fix
2025-01-27 15:10:42 +06:00
MONE FIERA
a2976fd926 Add Japanese Translation (#90)
* Add Japanese Translation

* Update strings.xml
2025-01-27 15:10:23 +06:00
igor
b2bcc93f9a update translation (#93) 2025-01-27 13:24:53 +06:00
Rifat Azad
57b8dd54c5 docs: add donation crypto addresses 2025-01-26 11:29:52 +06:00
changhuapeng
ef32f3f9d2 manager: Disable interactions for uninstalled & disabled module (#2380)
Uninstalled module has no enabled interactions (e.g. run action script,
open webui, update).
Disabled module cannot run action script or open webui.
2025-01-25 21:01:53 +06:00
Caner Karaca
4ac264135d ksud: updates (#84) 2025-01-25 20:57:03 +06:00
Wang Han
a05b790da6 Avoid unnecessarily overriding capabilities (#2381)
Previously all capabilities were overridden with 0xffffffffffffffff,
which is
not what normal processes have. This causes PR_CAPBSET_DROP prctl
fail because it is dropping invalid caps. Fix it.

This fixes
https://gitlab.com/kalilinux/nethunter/apps/kali-nethunter-app/-/issues/378.

Co-Authored-By: 5ec1cff <56485584+5ec1cff@users.noreply.github.com>

Co-authored-by: 5ec1cff <56485584+5ec1cff@users.noreply.github.com>
2025-01-25 20:54:06 +06:00
232 changed files with 1691 additions and 29112 deletions

View File

@@ -1,33 +0,0 @@
name: Contribute to Unofficially Supported Devices
description: Add your device kernel source to KernelSU Next's Unofficially Supported Device List
title: "[Add Device]: "
labels: ["add-device"]
body:
- type: markdown
attributes:
value: |
Thanks for supporting KernelSU Next!
- type: input
id: repo-url
attributes:
label: Repository URL
description: Your repository URL
placeholder: https://github.com/rifsxd/KernelSU-Next
validations:
required: true
- type: input
id: device
attributes:
label: Device
description: Please describe the device maintained by you.
placeholder: GKI 2.0 Device
validations:
required: true
- type: checkboxes
id: terms
attributes:
label: Code of Conduct
description: By submitting this issue, you should be the maintainer of the repository.
options:
- label: I'm the maintainer of this repository
required: true

View File

@@ -1,72 +0,0 @@
name: Bug report
description: Create a report to help us improve KernelSU Next
labels: [Bug]
body:
- type: checkboxes
attributes:
label: Please check before submitting an issue
options:
- label: I have searched the issues and haven't found anything relevant
required: true
- label: I will upload bugreport file in KernelSU Manager - Settings - Report log
required: true
- label: I know how to reproduce the issue which may not be specific to my device
required: false
- type: textarea
attributes:
label: Describe the bug
description: A clear and concise description of what the bug is
validations:
required: true
- type: textarea
attributes:
label: To Reproduce
description: Steps to reproduce the behaviour
placeholder: |
- 1. Go to '...'
- 2. Click on '....'
- 3. Scroll down to '....'
- 4. See error
- type: textarea
attributes:
label: Expected behavior
description: A clear and concise description of what you expected to happen.
- type: textarea
attributes:
label: Screenshots
description: If applicable, add screenshots to help explain your problem.
- type: textarea
attributes:
label: Logs
description: If applicable, add crash or any other logs to help us figure out the problem.
- type: textarea
attributes:
label: Device info
value: |
- Device:
- OS Version:
- KernelSU Version:
- Kernel Version:
validations:
required: true
- type: textarea
attributes:
label: Additional context
description: Add any other context about the problem here.

View File

@@ -1,5 +0,0 @@
blank_issues_enabled: false
contact_links:
- name: Feature Request
url: https://t.me/ksunext_discussions
about: "We accept external Feature Requests, see this link for more details."

View File

@@ -1,11 +0,0 @@
name: Custom issue template
description: WARNING! If you are reporting a bug but use this template, the issue will be closed directly.
title: '[Custom]'
body:
- type: textarea
id: description
attributes:
label: "Describe your problem."
validations:
required: true

View File

@@ -1,38 +0,0 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: daily
groups:
actions:
patterns:
- "*"
- package-ecosystem: cargo
directory: userspace/ksud_magic
schedule:
interval: daily
allow:
- dependency-type: "all"
groups:
crates:
patterns:
- "*"
- package-ecosystem: cargo
directory: userspace/ksud_overlayfs
schedule:
interval: daily
allow:
- dependency-type: "all"
groups:
crates:
patterns:
- "*"
- package-ecosystem: gradle
directory: manager
schedule:
interval: daily
groups:
maven:
patterns:
- "*"

View File

@@ -1,71 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!--https://ci.android.com/builds/submitted/9964412/kernel_virt_x86_64/latest/manifest_9964412.xml-->
<manifest>
<remote name="aosp" fetch="https://android.googlesource.com/" review="https://android.googlesource.com/" />
<default revision="master" remote="aosp" sync-j="4" />
<superproject name="kernel/superproject" remote="aosp" revision="common-android14-6.1" />
<project path="build/kernel" name="kernel/build" revision="b0377a072bb3f78cdacfd6d809914a9d1b0c0148">
<linkfile dest="tools/bazel" src="kleaf/bazel.sh" />
<linkfile dest="WORKSPACE" src="kleaf/bazel.WORKSPACE" />
<linkfile dest="build/build.sh" src="build.sh" />
<linkfile dest="build/build_abi.sh" src="build_abi.sh" />
<linkfile dest="build/build_test.sh" src="build_test.sh" />
<linkfile dest="build/build_utils.sh" src="build_utils.sh" />
<linkfile dest="build/config.sh" src="config.sh" />
<linkfile dest="build/envsetup.sh" src="envsetup.sh" />
<linkfile dest="build/_setup_env.sh" src="_setup_env.sh" />
<linkfile dest="build/multi-switcher.sh" src="multi-switcher.sh" />
<linkfile dest="build/abi" src="abi" />
<linkfile dest="build/static_analysis" src="static_analysis" />
</project>
<project path="common" name="kernel/common" revision="7e35917775b8b3e3346a87f294e334e258bf15e6">
<linkfile dest=".source_date_epoch_dir" src="." />
</project>
<project path="kernel/tests" name="kernel/tests" revision="c90a1c1b226b975cc31e709fa96fc1c6ecdbe272" />
<project path="kernel/configs" name="kernel/configs" revision="52a7267d6a9f9efabf3cb43839bb5e7f7ff05be3" />
<project path="common-modules/virtual-device" name="kernel/common-modules/virtual-device" revision="0d03de3246301028775f05ea388c2c444344a268" />
<project path="prebuilts/clang/host/linux-x86" name="platform/prebuilts/clang/host/linux-x86" clone-depth="1" revision="4f7e5adc160ab726ac5bafb260de98e612904c50" />
<project path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.17-4.8" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.17-4.8" clone-depth="1" revision="f7b0d5b0ee369864d5ac3e96ae24ec9e2b6a52da" />
<project path="prebuilts/build-tools" name="platform/prebuilts/build-tools" clone-depth="1" revision="dc92e06585a7647bf739a2309a721b82fcfa01d4" />
<project path="prebuilts/clang-tools" name="platform/prebuilts/clang-tools" clone-depth="1" revision="5611871963f54c688d3ac49e527aecdef21e8567" />
<project path="prebuilts/kernel-build-tools" name="kernel/prebuilts/build-tools" clone-depth="1" revision="2597cb1b5525e419b7fa806373be673054a68d29" />
<project path="tools/mkbootimg" name="platform/system/tools/mkbootimg" revision="2680066d0844544b3e78d6022cd21321d31837c3" />
<project path="prebuilts/bazel/linux-x86_64" name="platform/prebuilts/bazel/linux-x86_64" clone-depth="1" revision="4fdb9395071ff22118311d434d697c2b6fd887b4" />
<project path="prebuilts/jdk/jdk11" name="platform/prebuilts/jdk/jdk11" clone-depth="1" revision="491e6aa056676f29c4541f71bd738e4e876e4ba2" />
<project path="prebuilts/ndk-r23" name="toolchain/prebuilts/ndk/r23" clone-depth="1" revision="19ac7e4eded12adb99d4f613490dde6dd0e72664" />
<project path="external/bazel-skylib" name="platform/external/bazel-skylib" revision="f998e5dc13c03f0eae9e373263d3afff0932c738" />
<project path="build/bazel_common_rules" name="platform/build/bazel_common_rules" revision="707b2c5fe3d0d7d934a93e00a8a4062e83557831" />
<project path="external/stardoc" name="platform/external/stardoc" revision="e83f522ee95419e55d2c5654aa6e0143beeef595" />
<project path="external/python/absl-py" name="platform/external/python/absl-py" revision="393d0b1e3f0fea3e95944a2fd3282cc9f76d4f14" />
</manifest>

View File

@@ -1,89 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- https://ci.android.com/builds/submitted/11577653/kernel_virt_aarch64/latest/manifest_11577653.xml -->
<manifest>
<remote name="aosp" fetch="https://android.googlesource.com/" review="https://android.googlesource.com/" />
<default revision="main" remote="aosp" sync-j="4" />
<superproject name="kernel/superproject" remote="aosp" revision="common-android15-6.6" />
<project path="build/kernel" name="kernel/build" groups="ddk" revision="9a2196a1ec1048c2869750c9d3969c88ac18adcd">
<linkfile dest="tools/bazel" src="kleaf/bazel.sh" />
<linkfile dest="WORKSPACE" src="kleaf/bazel.WORKSPACE" />
<linkfile dest="MODULE.bazel" src="kleaf/bzlmod/bazel.MODULE.bazel" />
<linkfile dest="WORKSPACE.bzlmod" src="kleaf/bzlmod/bazel.WORKSPACE.bzlmod" />
</project>
<project path="common" name="kernel/common" revision="ac1a7c65ff1bc7ece5569d62f02b121b4f2364f8" />
<project path="kernel/common-patches" name="kernel/common-patches" revision="3807ce65081de12ef4baa2a04487306672685160">
<linkfile dest="common/patches" src="android-mainline" />
</project>
<project path="kernel/tests" name="kernel/tests" revision="ca9fd66f5b48abc92990c9c770f73380b428362b" />
<project path="kernel/configs" name="kernel/configs" revision="be625f2ccf377a75d0ea86c082c716c322b8d4c6" />
<project path="common-modules/virtual-device" name="kernel/common-modules/virtual-device" revision="60a24583ac921279e40a44f818040e40abb3ef46" />
<project path="prebuilts/clang/host/linux-x86" name="platform/prebuilts/clang/host/linux-x86" revision="93a1369ba33743a87bdf0183373f590a36ff7cb1" clone-depth="1" groups="ddk" />
<project path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.17-4.8" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.17-4.8" clone-depth="1" groups="ddk" revision="cef8f53bb61fbdb02dbf4d433004f6cb637c3bc6" />
<project path="prebuilts/build-tools" name="platform/prebuilts/build-tools" clone-depth="1" groups="ddk" revision="5aca9957ab19d2668c7f1da1954bbe89652d5fed" />
<project path="prebuilts/clang-tools" name="platform/prebuilts/clang-tools" clone-depth="1" revision="69f9fb9b8e75c6f1ff01f380d5251757785bb823" />
<project path="prebuilts/kernel-build-tools" name="kernel/prebuilts/build-tools" clone-depth="1" groups="ddk" revision="b09295493adc8d804b6d24286660f6e451e387fd" />
<project path="prebuilts/rust" name="platform/prebuilts/rust" revision="adc0e5499c3ddac831ca596d12cbef8d9747f737" clone-depth="1" />
<project path="prebuilts/tradefed" name="platform/tools/tradefederation/prebuilts" clone-depth="1" revision="a76ca09c5593e22e65b0d823d508882c6c64c13e" />
<project path="prebuilts/asuite" name="platform/prebuilts/asuite" clone-depth="1" revision="24510f175cb313a92241500efee917c2930d5d30" />
<project path="tools/mkbootimg" name="platform/system/tools/mkbootimg" revision="28b7934249c2885db8b561f1439d74663fcdce93" />
<project path="prebuilts/jdk/jdk11" name="platform/prebuilts/jdk/jdk11" revision="c6c90521b7c317f13d41bbd9336a8d45ee202cec" clone-depth="1" groups="ddk" />
<project path="prebuilts/ndk-r26" name="toolchain/prebuilts/ndk/r26" clone-depth="1" groups="ddk" revision="e535051ebc04204cec44bde38f62385d63180388" />
<project path="external/bazel-skylib" name="platform/external/bazel-skylib" groups="ddk" revision="6b103c40d8113f001475d5e13672922ef2aa0e5a" />
<project path="build/bazel_common_rules" name="platform/build/bazel_common_rules" groups="ddk" revision="2a10807a06153b5862da0369f4b6b368afc2dd08" />
<project path="external/libcap-ng" name="platform/external/libcap-ng" revision="2bcc92ae19481dd2b8d3ce3abdfbbee49261abe6" />
<project path="external/libcap" name="platform/external/libcap" revision="d7d1a0a38c5be06a7e7d6391d140b54878836f48" />
<project path="external/stardoc" name="platform/external/stardoc" groups="ddk" revision="f31250f9f5b03834d9964aaee7a3794c1d73d4a2" />
<project path="external/python/absl-py" name="platform/external/python/absl-py" groups="ddk" revision="9ae5a78fc57c3cd539398373ae39601a8b923e62" />
<project path="external/bazelbuild-bazel-central-registry" name="platform/external/bazelbuild-bazel-central-registry" revision="3422f064566c274ea66633442521704d4a22486d" groups="ddk" />
<project path="external/bazelbuild-platforms" name="platform/external/bazelbuild-platforms" groups="ddk" revision="e352aabd0131f3ac3f340282a43ba85ffc3fe8fa" />
<project path="external/bazelbuild-apple_support" name="platform/external/bazelbuild-apple_support" groups="ddk" revision="f6003e1e3763f8aad9fb9acae79cfa5fff9ae988" />
<project path="external/bazelbuild-rules_cc" name="platform/external/bazelbuild-rules_cc" groups="ddk" revision="f0df148dbeb9b9ed3816aad328ebe7c65efaaa24" />
<project path="external/bazelbuild-rules_java" name="platform/external/bazelbuild-rules_java" groups="ddk" revision="8e548c7053dffd1717d565f0409a88992f401da1" />
<project path="external/bazelbuild-rules_license" name="platform/external/bazelbuild-rules_license" groups="ddk" revision="f578df4fd057ffe2023728444759535685631548" />
<project path="external/bazelbuild-rules_pkg" name="platform/external/bazelbuild-rules_pkg" groups="ddk" revision="429887dfd8db834498ad95e99043f771a3882af0" />
<project path="external/bazelbuild-rules_python" name="platform/external/bazelbuild-rules_python" groups="ddk" revision="f71847ac898655b67634bb14e77a7408c4fb5e00" />
<project path="external/bazelbuild-rules_rust" name="platform/external/bazelbuild-rules_rust" groups="ddk" revision="1520b49835be9122c2424231357d4db80069cc38" />
<project path="external/pigz" name="platform/external/pigz" groups="ddk" revision="9bc9fa17d499ddde88b77820f6d063e16c0cdd42" />
<project path="external/zlib" name="platform/external/zlib" groups="ddk" revision="eff168fd731068a3faddd9aae056875e10014a51" />
<project path="external/zopfli" name="platform/external/zopfli" groups="ddk" revision="36c79f00e5229800d2aaa13fc42c301ec8ef1153" />
</manifest>

View File

@@ -1,89 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- https://ci.android.com/builds/submitted/11577653/kernel_virt_x86_64/latest/manifest_11577653.xml -->
<manifest>
<remote name="aosp" fetch="https://android.googlesource.com/" review="https://android.googlesource.com/" />
<default revision="main" remote="aosp" sync-j="4" />
<superproject name="kernel/superproject" remote="aosp" revision="common-android15-6.6" />
<project path="build/kernel" name="kernel/build" groups="ddk" revision="9a2196a1ec1048c2869750c9d3969c88ac18adcd">
<linkfile dest="tools/bazel" src="kleaf/bazel.sh" />
<linkfile dest="WORKSPACE" src="kleaf/bazel.WORKSPACE" />
<linkfile dest="MODULE.bazel" src="kleaf/bzlmod/bazel.MODULE.bazel" />
<linkfile dest="WORKSPACE.bzlmod" src="kleaf/bzlmod/bazel.WORKSPACE.bzlmod" />
</project>
<project path="common" name="kernel/common" revision="ac1a7c65ff1bc7ece5569d62f02b121b4f2364f8" />
<project path="kernel/common-patches" name="kernel/common-patches" revision="3807ce65081de12ef4baa2a04487306672685160">
<linkfile dest="common/patches" src="android-mainline" />
</project>
<project path="kernel/tests" name="kernel/tests" revision="ca9fd66f5b48abc92990c9c770f73380b428362b" />
<project path="kernel/configs" name="kernel/configs" revision="be625f2ccf377a75d0ea86c082c716c322b8d4c6" />
<project path="common-modules/virtual-device" name="kernel/common-modules/virtual-device" revision="60a24583ac921279e40a44f818040e40abb3ef46" />
<project path="prebuilts/clang/host/linux-x86" name="platform/prebuilts/clang/host/linux-x86" revision="93a1369ba33743a87bdf0183373f590a36ff7cb1" clone-depth="1" groups="ddk" />
<project path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.17-4.8" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.17-4.8" clone-depth="1" groups="ddk" revision="cef8f53bb61fbdb02dbf4d433004f6cb637c3bc6" />
<project path="prebuilts/build-tools" name="platform/prebuilts/build-tools" clone-depth="1" groups="ddk" revision="5aca9957ab19d2668c7f1da1954bbe89652d5fed" />
<project path="prebuilts/clang-tools" name="platform/prebuilts/clang-tools" clone-depth="1" revision="69f9fb9b8e75c6f1ff01f380d5251757785bb823" />
<project path="prebuilts/kernel-build-tools" name="kernel/prebuilts/build-tools" clone-depth="1" groups="ddk" revision="b09295493adc8d804b6d24286660f6e451e387fd" />
<project path="prebuilts/rust" name="platform/prebuilts/rust" revision="adc0e5499c3ddac831ca596d12cbef8d9747f737" clone-depth="1" />
<project path="prebuilts/tradefed" name="platform/tools/tradefederation/prebuilts" clone-depth="1" revision="a76ca09c5593e22e65b0d823d508882c6c64c13e" />
<project path="prebuilts/asuite" name="platform/prebuilts/asuite" clone-depth="1" revision="24510f175cb313a92241500efee917c2930d5d30" />
<project path="tools/mkbootimg" name="platform/system/tools/mkbootimg" revision="28b7934249c2885db8b561f1439d74663fcdce93" />
<project path="prebuilts/jdk/jdk11" name="platform/prebuilts/jdk/jdk11" revision="c6c90521b7c317f13d41bbd9336a8d45ee202cec" clone-depth="1" groups="ddk" />
<project path="prebuilts/ndk-r26" name="toolchain/prebuilts/ndk/r26" clone-depth="1" groups="ddk" revision="e535051ebc04204cec44bde38f62385d63180388" />
<project path="external/bazel-skylib" name="platform/external/bazel-skylib" groups="ddk" revision="6b103c40d8113f001475d5e13672922ef2aa0e5a" />
<project path="build/bazel_common_rules" name="platform/build/bazel_common_rules" groups="ddk" revision="2a10807a06153b5862da0369f4b6b368afc2dd08" />
<project path="external/libcap-ng" name="platform/external/libcap-ng" revision="2bcc92ae19481dd2b8d3ce3abdfbbee49261abe6" />
<project path="external/libcap" name="platform/external/libcap" revision="d7d1a0a38c5be06a7e7d6391d140b54878836f48" />
<project path="external/stardoc" name="platform/external/stardoc" groups="ddk" revision="f31250f9f5b03834d9964aaee7a3794c1d73d4a2" />
<project path="external/python/absl-py" name="platform/external/python/absl-py" groups="ddk" revision="9ae5a78fc57c3cd539398373ae39601a8b923e62" />
<project path="external/bazelbuild-bazel-central-registry" name="platform/external/bazelbuild-bazel-central-registry" revision="3422f064566c274ea66633442521704d4a22486d" groups="ddk" />
<project path="external/bazelbuild-platforms" name="platform/external/bazelbuild-platforms" groups="ddk" revision="e352aabd0131f3ac3f340282a43ba85ffc3fe8fa" />
<project path="external/bazelbuild-apple_support" name="platform/external/bazelbuild-apple_support" groups="ddk" revision="f6003e1e3763f8aad9fb9acae79cfa5fff9ae988" />
<project path="external/bazelbuild-rules_cc" name="platform/external/bazelbuild-rules_cc" groups="ddk" revision="f0df148dbeb9b9ed3816aad328ebe7c65efaaa24" />
<project path="external/bazelbuild-rules_java" name="platform/external/bazelbuild-rules_java" groups="ddk" revision="8e548c7053dffd1717d565f0409a88992f401da1" />
<project path="external/bazelbuild-rules_license" name="platform/external/bazelbuild-rules_license" groups="ddk" revision="f578df4fd057ffe2023728444759535685631548" />
<project path="external/bazelbuild-rules_pkg" name="platform/external/bazelbuild-rules_pkg" groups="ddk" revision="429887dfd8db834498ad95e99043f771a3882af0" />
<project path="external/bazelbuild-rules_python" name="platform/external/bazelbuild-rules_python" groups="ddk" revision="f71847ac898655b67634bb14e77a7408c4fb5e00" />
<project path="external/bazelbuild-rules_rust" name="platform/external/bazelbuild-rules_rust" groups="ddk" revision="1520b49835be9122c2424231357d4db80069cc38" />
<project path="external/pigz" name="platform/external/pigz" groups="ddk" revision="9bc9fa17d499ddde88b77820f6d063e16c0cdd42" />
<project path="external/zlib" name="platform/external/zlib" groups="ddk" revision="eff168fd731068a3faddd9aae056875e10014a51" />
<project path="external/zopfli" name="platform/external/zopfli" groups="ddk" revision="36c79f00e5229800d2aaa13fc42c301ec8ef1153" />
</manifest>

View File

@@ -1,64 +0,0 @@
#!/bin/bash
set -euo pipefail
build_from_image() {
export TITLE
TITLE=kernel-aarch64-${1//Image-/}
echo "[+] title: $TITLE"
export PATCH_LEVEL
PATCH_LEVEL=$(echo "$1" | awk -F_ '{ print $2}')
echo "[+] patch level: $PATCH_LEVEL"
echo '[+] Download prebuilt ramdisk'
GKI_URL=https://dl.google.com/android/gki/gki-certified-boot-android12-5.10-"${PATCH_LEVEL}"_r1.zip
FALLBACK_URL=https://dl.google.com/android/gki/gki-certified-boot-android12-5.10-2023-01_r1.zip
status=$(curl -sL -w "%{http_code}" "$GKI_URL" -o /dev/null)
if [ "$status" = "200" ]; then
curl -Lo gki-kernel.zip "$GKI_URL"
else
echo "[+] $GKI_URL not found, using $FALLBACK_URL"
curl -Lo gki-kernel.zip "$FALLBACK_URL"
fi
unzip gki-kernel.zip && rm gki-kernel.zip
echo '[+] Unpack prebuilt boot.img'
BOOT_IMG=$(find . -maxdepth 1 -name "boot*.img")
$UNPACK_BOOTIMG --boot_img="$BOOT_IMG"
rm "$BOOT_IMG"
echo '[+] Building Image.gz'
$GZIP -n -k -f -9 Image >Image.gz
echo '[+] Building boot.img'
$MKBOOTIMG --header_version 4 --kernel Image --output boot.img --ramdisk out/ramdisk --os_version 12.0.0 --os_patch_level "${PATCH_LEVEL}"
$AVBTOOL add_hash_footer --partition_name boot --partition_size $((64 * 1024 * 1024)) --image boot.img --algorithm SHA256_RSA2048 --key ../kernel-build-tools/linux-x86/share/avb/testkey_rsa2048.pem
echo '[+] Building boot-gz.img'
$MKBOOTIMG --header_version 4 --kernel Image.gz --output boot-gz.img --ramdisk out/ramdisk --os_version 12.0.0 --os_patch_level "${PATCH_LEVEL}"
$AVBTOOL add_hash_footer --partition_name boot --partition_size $((64 * 1024 * 1024)) --image boot-gz.img --algorithm SHA256_RSA2048 --key ../kernel-build-tools/linux-x86/share/avb/testkey_rsa2048.pem
echo '[+] Building boot-lz4.img'
$MKBOOTIMG --header_version 4 --kernel Image.lz4 --output boot-lz4.img --ramdisk out/ramdisk --os_version 12.0.0 --os_patch_level "${PATCH_LEVEL}"
$AVBTOOL add_hash_footer --partition_name boot --partition_size $((64 * 1024 * 1024)) --image boot-lz4.img --algorithm SHA256_RSA2048 --key ../kernel-build-tools/linux-x86/share/avb/testkey_rsa2048.pem
echo '[+] Compress images'
for image in boot*.img; do
$GZIP -n -f -9 "$image"
mv "$image".gz "${1//Image-/}"-"$image".gz
done
echo "[+] Images to upload"
find . -type f -name "*.gz"
# find . -type f -name "*.gz" -exec python3 "$GITHUB_WORKSPACE"/KernelSU-Next/scripts/ksunextbot.py {} +
}
for dir in Image*; do
if [ -d "$dir" ]; then
echo "----- Building $dir -----"
cd "$dir"
build_from_image "$dir"
cd ..
fi
done

View File

@@ -1,43 +0,0 @@
#!/bin/bash
set -euo pipefail
build_from_image() {
export TITLE
TITLE=kernel-aarch64-${1//Image-/}
echo "[+] title: $TITLE"
echo '[+] Building Image.gz'
$GZIP -n -k -f -9 Image >Image.gz
echo '[+] Building boot.img'
$MKBOOTIMG --header_version 4 --kernel Image --output boot.img
$AVBTOOL add_hash_footer --partition_name boot --partition_size $((64 * 1024 * 1024)) --image boot.img --algorithm SHA256_RSA2048 --key ../kernel-build-tools/linux-x86/share/avb/testkey_rsa2048.pem
echo '[+] Building boot-gz.img'
$MKBOOTIMG --header_version 4 --kernel Image.gz --output boot-gz.img
$AVBTOOL add_hash_footer --partition_name boot --partition_size $((64 * 1024 * 1024)) --image boot-gz.img --algorithm SHA256_RSA2048 --key ../kernel-build-tools/linux-x86/share/avb/testkey_rsa2048.pem
echo '[+] Building boot-lz4.img'
$MKBOOTIMG --header_version 4 --kernel Image.lz4 --output boot-lz4.img
$AVBTOOL add_hash_footer --partition_name boot --partition_size $((64 * 1024 * 1024)) --image boot-lz4.img --algorithm SHA256_RSA2048 --key ../kernel-build-tools/linux-x86/share/avb/testkey_rsa2048.pem
echo '[+] Compress images'
for image in boot*.img; do
$GZIP -n -f -9 "$image"
mv "$image".gz "${1//Image-/}"-"$image".gz
done
echo '[+] Images to upload'
find . -type f -name "*.gz"
# find . -type f -name "*.gz" -exec python3 "$GITHUB_WORKSPACE"/KernelSU-Next/scripts/ksunextbot.py {} +
}
for dir in Image*; do
if [ -d "$dir" ]; then
echo "----- Building $dir -----"
cd "$dir"
build_from_image "$dir"
cd ..
fi
done

View File

@@ -1,137 +0,0 @@
name: GKI Kernel Build
on:
workflow_call:
inputs:
version_name:
required: true
type: string
description: >
With SUBLEVEL of kernel,
for example: android12-5.10.66
arch:
required: true
type: string
description: >
Build arch: aarch64/x86_64
debug:
required: false
type: boolean
default: true
manifest_name:
required: false
type: string
description: >
Local repo manifest xml path,
typically for AVD kernel build.
secrets:
BOOT_SIGN_KEY:
required: false
CHAT_ID:
required: false
BOT_TOKEN:
required: false
MESSAGE_THREAD_ID:
required: false
jobs:
build:
name: Build ${{ inputs.version_name }}
runs-on: ubuntu-latest
steps:
- name: Maximize build space
uses: easimon/maximize-build-space@master
with:
root-reserve-mb: 8192
temp-reserve-mb: 2048
remove-dotnet: 'true'
remove-android: 'true'
remove-haskell: 'true'
remove-codeql: 'true'
- uses: actions/checkout@v4
with:
path: KernelSU-Next
fetch-depth: 0
- name: Setup need_upload
id: need_upload
run: |
if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then
echo "UPLOAD=true" >> $GITHUB_OUTPUT
else
echo "UPLOAD=false" >> $GITHUB_OUTPUT
fi
- name: Setup kernel source
run: |
echo "Free space:"
df -h
cd $GITHUB_WORKSPACE
sudo apt-get install repo -y
mkdir android-kernel && cd android-kernel
repo init --depth=1 -u https://android.googlesource.com/kernel/manifest -m "$GITHUB_WORKSPACE/KernelSU-Next/.github/manifests/${{ inputs.manifest_name }}" --repo-rev=v2.16
repo --version
repo --trace sync -c -j$(nproc --all) --no-tags
df -h
- name: Setup KernelSU-Next
env:
PATCH_PATH: ${{ inputs.patch_path }}
IS_DEBUG_KERNEL: ${{ inputs.debug }}
run: |
cd $GITHUB_WORKSPACE/android-kernel
echo "[+] KernelSU-Next setup"
GKI_ROOT=$(pwd)
echo "[+] GKI_ROOT: $GKI_ROOT"
echo "[+] Copy KernelSU-Next driver to $GKI_ROOT/common/drivers"
ln -sf $GITHUB_WORKSPACE/KernelSU-Next/kernel $GKI_ROOT/common/drivers/kernelsu
echo "[+] Add KernelSU-Next driver to Makefile"
DRIVER_MAKEFILE=$GKI_ROOT/common/drivers/Makefile
DRIVER_KCONFIG=$GKI_ROOT/common/drivers/Kconfig
grep -q "kernelsu" "$DRIVER_MAKEFILE" || printf "\nobj-\$(CONFIG_KSU) += kernelsu/\n" >> "$DRIVER_MAKEFILE"
grep -q "kernelsu" "$DRIVER_KCONFIG" || sed -i "/endmenu/i\\source \"drivers/kernelsu/Kconfig\"" "$DRIVER_KCONFIG"
echo "[+] Apply KernelSU-Next patches"
cd $GKI_ROOT/common/ && git apply $GITHUB_WORKSPACE/KernelSU-Next/.github/patches/$PATCH_PATH/*.patch || echo "[-] No patch found"
if [ "$IS_DEBUG_KERNEL" = "true" ]; then
echo "[+] Enable debug features for kernel"
printf "\nccflags-y += -DCONFIG_KSU_DEBUG\n" >> $GITHUB_WORKSPACE/KernelSU-Next/kernel/Makefile
fi
repo status
echo "[+] KernelSU-Next setup done."
cd $GITHUB_WORKSPACE/KernelSU-Next
VERSION=$(($(git rev-list --count HEAD) + 10200))
echo "VERSION: $VERSION"
echo "kernelsu_version=$VERSION" >> $GITHUB_ENV
- name: Make working directory clean to avoid dirty
working-directory: android-kernel
run: |
rm common/android/abi_gki_protected_exports_* || echo "No protected exports!"
git config --global user.email "bot@kernelsu.org"
git config --global user.name "KernelSU-NextBot"
cd common/ && git add -A && git commit -a -m "Add KernelSU-Next"
repo status
- name: Build kernel
working-directory: android-kernel
run: |
if [ ! -z ${{ vars.EXPECTED_SIZE }} ] && [ ! -z ${{ vars.EXPECTED_HASH }} ]; then
export KSU_EXPECTED_SIZE=${{ vars.EXPECTED_SIZE }}
export KSU_EXPECTED_HASH=${{ vars.EXPECTED_HASH }}
fi
tools/bazel run --config=fast --config=stamp --lto=thin //common-modules/virtual-device:virtual_device_${{ inputs.arch }}_dist -- --dist_dir=dist
NAME=kernel-${{ inputs.arch }}-avd-${{ inputs.version_name }}-${{ env.kernelsu_version }}
TARGET_IMAGE=dist/bzImage
if [ ! -e $TARGET_IMAGE ]; then
TARGET_IMAGE=dist/Image
fi
mv $TARGET_IMAGE $NAME
echo "file_path=android-kernel/$NAME" >> $GITHUB_ENV
- name: Upload Kernel
uses: actions/upload-artifact@v4
with:
name: kernel-${{ inputs.arch }}-avd-${{ inputs.version_name }}-${{ env.kernelsu_version }}
path: "${{ env.file_path }}"

View File

@@ -1,62 +0,0 @@
name: Build debug kernel
on:
workflow_dispatch:
jobs:
build-debug-kernel-a12:
uses: ./.github/workflows/gki-kernel.yml
with:
version: android12-5.10
version_name: android12-5.10.226
tag: android12-5.10-2024-11
os_patch_level: 2024-11
patch_path: "5.10"
debug: true
build-debug-kernel-a13:
strategy:
matrix:
include:
- version: "5.10"
sub_level: 223
os_patch_level: 2024-11
- version: "5.15"
sub_level: 167
os_patch_level: 2024-11
uses: ./.github/workflows/gki-kernel.yml
with:
version: android13-${{ matrix.version }}
version_name: android13-${{ matrix.version }}.${{ matrix.sub_level }}
tag: android13-${{ matrix.version }}-${{ matrix.os_patch_level }}
patch_path: ${{ matrix.version }}
debug: true
build-debug-kernel-a14:
strategy:
matrix:
include:
- version: "5.15"
sub_level: 167
os_patch_level: 2024-11
- version: "6.1"
sub_level: 115
os_patch_level: 2024-12
uses: ./.github/workflows/gki-kernel.yml
with:
version: android14-${{ matrix.version }}
version_name: android14-${{ matrix.version }}.${{ matrix.sub_level }}
tag: android14-${{ matrix.version }}-${{ matrix.os_patch_level }}
patch_path: ${{ matrix.version }}
debug: true
build-debug-kernel-a15:
strategy:
matrix:
include:
- version: "6.6"
sub_level: 57
os_patch_level: 2024-12
uses: ./.github/workflows/gki-kernel.yml
with:
version: android15-${{ matrix.version }}
version_name: android15-${{ matrix.version }}.${{ matrix.sub_level }}
tag: android15-${{ matrix.version }}-${{ matrix.os_patch_level }}
patch_path: ${{ matrix.version }}
debug: true

View File

@@ -1,118 +0,0 @@
name: Build Kernel - Android 12
on:
push:
branches: [ "next" ]
paths:
- ".github/workflows/build-kernel-a12.yml"
- ".github/workflows/gki-kernel.yml"
- ".github/scripts/build_a12.sh"
- "kernel/**"
pull_request:
branches: [ "next" ]
paths:
- ".github/workflows/build-kernel-a12.yml"
- ".github/workflows/gki-kernel.yml"
- ".github/scripts/build-a12.sh"
- "kernel/**"
workflow_call:
jobs:
build-kernel:
if: github.event_name != 'pull_request' && github.ref != 'refs/heads/next'
strategy:
matrix:
include:
- sub_level: 209
os_patch_level: 2024-05
- sub_level: 218
os_patch_level: 2024-08
- sub_level: 226
os_patch_level: 2024-11
uses: ./.github/workflows/gki-kernel.yml
secrets: inherit
with:
version: android12-5.10
version_name: android12-5.10.${{ matrix.sub_level }}
tag: android12-5.10-${{ matrix.os_patch_level }}
os_patch_level: ${{ matrix.os_patch_level }}
patch_path: "5.10"
upload-artifacts:
needs: build-kernel
runs-on: ubuntu-latest
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/next' ) || github.ref_type == 'tag' || github.ref == 'refs/heads/next' }}
env:
CHAT_ID: ${{ secrets.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 }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
- uses: actions/checkout@v4
with:
path: KernelSU-Next
fetch-depth: 0
- name: List artifacts
run: |
tree
- name: Download prebuilt toolchain
run: |
AOSP_MIRROR=https://android.googlesource.com
BRANCH=main-kernel-build-2024
git clone $AOSP_MIRROR/platform/prebuilts/build-tools -b $BRANCH --depth 1 build-tools
git clone $AOSP_MIRROR/kernel/prebuilts/build-tools -b $BRANCH --depth 1 kernel-build-tools
git clone $AOSP_MIRROR/platform/system/tools/mkbootimg -b $BRANCH --depth 1
pip3 install telethon
- name: Set boot sign key
env:
BOOT_SIGN_KEY: ${{ secrets.BOOT_SIGN_KEY }}
run: |
if [ ! -z "$BOOT_SIGN_KEY" ]; then
echo "$BOOT_SIGN_KEY" > ./kernel-build-tools/linux-x86/share/avb/testkey_rsa2048.pem
fi
- name: Bot session cache
id: bot_session_cache
uses: actions/cache@v4
if: false
with:
path: scripts/ksunextbot.session
key: ${{ runner.os }}-bot-session
- name: Build boot images
run: |
export AVBTOOL=$GITHUB_WORKSPACE/kernel-build-tools/linux-x86/bin/avbtool
export GZIP=$GITHUB_WORKSPACE/build-tools/path/linux-x86/gzip
export LZ4=$GITHUB_WORKSPACE/build-tools/path/linux-x86/lz4
export MKBOOTIMG=$GITHUB_WORKSPACE/mkbootimg/mkbootimg.py
export UNPACK_BOOTIMG=$GITHUB_WORKSPACE/mkbootimg/unpack_bootimg.py
cd $GITHUB_WORKSPACE/KernelSU-Next
export VERSION=$(($(git rev-list --count HEAD) + 10200))
echo "VERSION: $VERSION"
cd -
bash $GITHUB_WORKSPACE/KernelSU-Next/.github/scripts/build_a12.sh
- name: Display structure of boot files
run: ls -R
- name: Upload images artifact
uses: actions/upload-artifact@v4
with:
name: boot-images-android12
path: Image-android12*/*.img.gz
check-build-kernel:
if: (github.event_name == 'pull_request' && !github.event.pull_request.draft) || github.ref == 'refs/heads/next'
uses: ./.github/workflows/gki-kernel.yml
with:
version: android12-5.10
version_name: android12-5.10.223
tag: android12-5.10-2024-11
os_patch_level: 2024-11
patch_path: "5.10"

View File

@@ -1,151 +0,0 @@
name: Build Kernel - Android 13
on:
push:
branches: [ "next" ]
paths:
- ".github/workflows/build-kernel-a13.yml"
- ".github/workflows/gki-kernel.yml"
- ".github/scripts/build_a13.sh"
- "kernel/**"
pull_request:
branches: [ "next" ]
paths:
- ".github/workflows/build-kernel-a13.yml"
- ".github/workflows/gki-kernel.yml"
- ".github/scripts/build-a13.sh"
- "kernel/**"
workflow_call:
jobs:
build-kernel:
if: github.event_name != 'pull_request' && github.ref != 'refs/heads/next'
strategy:
matrix:
include:
- version: "5.10"
sub_level: 209
os_patch_level: 2024-05
- version: "5.10"
sub_level: 210
os_patch_level: 2024-06
- version: "5.10"
sub_level: 214
os_patch_level: 2024-07
- version: "5.10"
sub_level: 218
os_patch_level: 2024-08
- version: "5.10"
sub_level: 223
os_patch_level: 2024-11
- version: "5.15"
sub_level: 148
os_patch_level: 2024-05
- version: "5.15"
sub_level: 149
os_patch_level: 2024-07
- version: "5.15"
sub_level: 151
os_patch_level: 2024-08
- version: "5.15"
sub_level: 153
os_patch_level: 2024-09
- version: "5.15"
sub_level: 167
os_patch_level: 2024-11
uses: ./.github/workflows/gki-kernel.yml
secrets: inherit
with:
version: android13-${{ matrix.version }}
version_name: android13-${{ matrix.version }}.${{ matrix.sub_level }}
tag: android13-${{ matrix.version }}-${{ matrix.os_patch_level }}
os_patch_level: ${{ matrix.os_patch_level }}
patch_path: ${{ matrix.version }}
upload-artifacts:
needs: build-kernel
runs-on: ubuntu-latest
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/next' ) || github.ref_type == 'tag' || github.ref == 'refs/heads/next' }}
env:
CHAT_ID: ${{ secrets.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 }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
- uses: actions/checkout@v4
with:
path: KernelSU-Next
fetch-depth: 0
- name: List artifacts
run: |
tree
- name: Download prebuilt toolchain
run: |
AOSP_MIRROR=https://android.googlesource.com
BRANCH=main-kernel-build-2024
git clone $AOSP_MIRROR/platform/prebuilts/build-tools -b $BRANCH --depth 1 build-tools
git clone $AOSP_MIRROR/kernel/prebuilts/build-tools -b $BRANCH --depth 1 kernel-build-tools
git clone $AOSP_MIRROR/platform/system/tools/mkbootimg -b $BRANCH --depth 1
pip3 install telethon
- name: Set boot sign key
env:
BOOT_SIGN_KEY: ${{ secrets.BOOT_SIGN_KEY }}
run: |
if [ ! -z "$BOOT_SIGN_KEY" ]; then
echo "$BOOT_SIGN_KEY" > ./kernel-build-tools/linux-x86/share/avb/testkey_rsa2048.pem
fi
- name: Bot session cache
id: bot_session_cache
uses: actions/cache@v4
if: false
with:
path: scripts/ksunextbot.session
key: ${{ runner.os }}-bot-session
- name: Build boot images
run: |
export AVBTOOL=$GITHUB_WORKSPACE/kernel-build-tools/linux-x86/bin/avbtool
export GZIP=$GITHUB_WORKSPACE/build-tools/path/linux-x86/gzip
export LZ4=$GITHUB_WORKSPACE/build-tools/path/linux-x86/lz4
export MKBOOTIMG=$GITHUB_WORKSPACE/mkbootimg/mkbootimg.py
export UNPACK_BOOTIMG=$GITHUB_WORKSPACE/mkbootimg/unpack_bootimg.py
cd $GITHUB_WORKSPACE/KernelSU-Next
export VERSION=$(($(git rev-list --count HEAD) + 10200))
echo "VERSION: $VERSION"
cd -
bash $GITHUB_WORKSPACE/KernelSU-Next/.github/scripts/build_a13.sh
- name: Display structure of boot files
run: ls -R
- name: Upload images artifact
uses: actions/upload-artifact@v4
with:
name: boot-images-android13
path: Image-android13*/*.img.gz
check-build-kernel:
if: (github.event_name == 'pull_request' && !github.event.pull_request.draft) || github.ref == 'refs/heads/next'
strategy:
matrix:
include:
- version: "5.10"
sub_level: 223
os_patch_level: 2024-11
- version: "5.15"
sub_level: 167
os_patch_level: 2024-11
uses: ./.github/workflows/gki-kernel.yml
with:
version: android13-${{ matrix.version }}
version_name: android13-${{ matrix.version }}.${{ matrix.sub_level }}
tag: android13-${{ matrix.version }}-${{ matrix.os_patch_level }}
os_patch_level: ${{ matrix.os_patch_level }}
patch_path: ${{ matrix.version }}

View File

@@ -1,163 +0,0 @@
name: Build Kernel - Android 14
on:
push:
branches: [ "next" ]
paths:
- ".github/workflows/build-kernel-a14.yml"
- ".github/workflows/gki-kernel.yml"
- ".github/scripts/build_a13.sh"
- "kernel/**"
pull_request:
branches: [ "next" ]
paths:
- ".github/workflows/build-kernel-a14.yml"
- ".github/workflows/gki-kernel.yml"
- ".github/scripts/build-a13.sh"
- "kernel/**"
workflow_call:
jobs:
build-kernel:
if: github.event_name != 'pull_request' && github.ref != 'refs/heads/next'
strategy:
matrix:
include:
- version: "5.15"
sub_level: 148
os_patch_level: 2024-05
- version: "5.15"
sub_level: 149
os_patch_level: 2024-06
- version: "5.15"
sub_level: 153
os_patch_level: 2024-07
- version: "5.15"
sub_level: 158
os_patch_level: 2024-08
- version: "5.15"
sub_level: 164
os_patch_level: 2024-09
- version: "5.15"
sub_level: 167
os_patch_level: 2024-11
- version: "6.1"
sub_level: 75
os_patch_level: 2024-05
- version: "6.1"
sub_level: 78
os_patch_level: 2024-06
- version: "6.1"
sub_level: 84
os_patch_level: 2024-07
- version: "6.1"
sub_level: 90
os_patch_level: 2024-08
- version: "6.1"
sub_level: 93
os_patch_level: 2024-09
- version: "6.1"
sub_level: 99
os_patch_level: 2024-10
- version: "6.1"
sub_level: 112
os_patch_level: 2024-11
- version: "6.1"
sub_level: 115
os_patch_level: 2024-12
uses: ./.github/workflows/gki-kernel.yml
secrets: inherit
with:
version: android14-${{ matrix.version }}
version_name: android14-${{ matrix.version }}.${{ matrix.sub_level }}
tag: android14-${{ matrix.version }}-${{ matrix.os_patch_level }}
os_patch_level: ${{ matrix.os_patch_level }}
patch_path: ${{ matrix.version }}
upload-artifacts:
needs: build-kernel
runs-on: ubuntu-latest
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/next' ) || github.ref_type == 'tag' || github.ref == 'refs/heads/next' }}
env:
CHAT_ID: ${{ secrets.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 }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
- uses: actions/checkout@v4
with:
path: KernelSU-Next
fetch-depth: 0
- name: List artifacts
run: |
tree
- name: Download prebuilt toolchain
run: |
AOSP_MIRROR=https://android.googlesource.com
BRANCH=main-kernel-build-2024
git clone $AOSP_MIRROR/platform/prebuilts/build-tools -b $BRANCH --depth 1 build-tools
git clone $AOSP_MIRROR/kernel/prebuilts/build-tools -b $BRANCH --depth 1 kernel-build-tools
git clone $AOSP_MIRROR/platform/system/tools/mkbootimg -b $BRANCH --depth 1
pip3 install telethon
- name: Set boot sign key
env:
BOOT_SIGN_KEY: ${{ secrets.BOOT_SIGN_KEY }}
run: |
if [ ! -z "$BOOT_SIGN_KEY" ]; then
echo "$BOOT_SIGN_KEY" > ./kernel-build-tools/linux-x86/share/avb/testkey_rsa2048.pem
fi
- name: Bot session cache
id: bot_session_cache
uses: actions/cache@v4
if: false
with:
path: scripts/ksunextbot.session
key: ${{ runner.os }}-bot-session
- name: Build boot images
run: |
export AVBTOOL=$GITHUB_WORKSPACE/kernel-build-tools/linux-x86/bin/avbtool
export GZIP=$GITHUB_WORKSPACE/build-tools/path/linux-x86/gzip
export LZ4=$GITHUB_WORKSPACE/build-tools/path/linux-x86/lz4
export MKBOOTIMG=$GITHUB_WORKSPACE/mkbootimg/mkbootimg.py
export UNPACK_BOOTIMG=$GITHUB_WORKSPACE/mkbootimg/unpack_bootimg.py
cd $GITHUB_WORKSPACE/KernelSU-Next
export VERSION=$(($(git rev-list --count HEAD) + 10200))
echo "VERSION: $VERSION"
cd -
bash $GITHUB_WORKSPACE/KernelSU-Next/.github/scripts/build_a13.sh
- name: Display structure of boot files
run: ls -R
- name: Upload images artifact
uses: actions/upload-artifact@v4
with:
name: boot-images-android14
path: Image-android14*/*.img.gz
check-build-kernel:
if: (github.event_name == 'pull_request' && !github.event.pull_request.draft) || github.ref == 'refs/heads/next'
strategy:
matrix:
include:
- version: "5.15"
sub_level: 167
os_patch_level: 2024-11
- version: "6.1"
sub_level: 115
os_patch_level: 2024-12
uses: ./.github/workflows/gki-kernel.yml
with:
version: android14-${{ matrix.version }}
version_name: android14-${{ matrix.version }}.${{ matrix.sub_level }}
tag: android14-${{ matrix.version }}-${{ matrix.os_patch_level }}
os_patch_level: ${{ matrix.os_patch_level }}
patch_path: ${{ matrix.version }}

View File

@@ -1,133 +0,0 @@
name: Build Kernel - Android 15
on:
push:
branches: [ "next" ]
paths:
- ".github/workflows/build-kernel-a15.yml"
- ".github/workflows/gki-kernel.yml"
- ".github/scripts/build_a13.sh"
- "kernel/**"
pull_request:
branches: [ "next" ]
paths:
- ".github/workflows/build-kernel-a15.yml"
- ".github/workflows/gki-kernel.yml"
- ".github/scripts/build-a13.sh"
- "kernel/**"
workflow_call:
jobs:
build-kernel:
if: github.event_name != 'pull_request' && github.ref != 'refs/heads/next'
strategy:
matrix:
include:
- version: "6.6"
sub_level: 30
os_patch_level: 2024-08
- version: "6.6"
sub_level: 46
os_patch_level: 2024-09
- version: "6.6"
sub_level: 50
os_patch_level: 2024-10
- version: "6.6"
sub_level: 56
os_patch_level: 2024-11
- version: "6.6"
sub_level: 57
os_patch_level: 2024-12
uses: ./.github/workflows/gki-kernel.yml
secrets: inherit
with:
version: android15-${{ matrix.version }}
version_name: android15-${{ matrix.version }}.${{ matrix.sub_level }}
tag: android15-${{ matrix.version }}-${{ matrix.os_patch_level }}
os_patch_level: ${{ matrix.os_patch_level }}
patch_path: ${{ matrix.version }}
upload-artifacts:
needs: build-kernel
runs-on: ubuntu-latest
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/next' ) || github.ref_type == 'tag' || github.ref == 'refs/heads/next' }}
env:
CHAT_ID: ${{ secrets.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 }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
- uses: actions/checkout@v4
with:
path: KernelSU-Next
fetch-depth: 0
- name: List artifacts
run: |
tree
- name: Download prebuilt toolchain
run: |
AOSP_MIRROR=https://android.googlesource.com
BRANCH=main-kernel-build-2024
git clone $AOSP_MIRROR/platform/prebuilts/build-tools -b $BRANCH --depth 1 build-tools
git clone $AOSP_MIRROR/kernel/prebuilts/build-tools -b $BRANCH --depth 1 kernel-build-tools
git clone $AOSP_MIRROR/platform/system/tools/mkbootimg -b $BRANCH --depth 1
pip3 install telethon
- name: Set boot sign key
env:
BOOT_SIGN_KEY: ${{ secrets.BOOT_SIGN_KEY }}
run: |
if [ ! -z "$BOOT_SIGN_KEY" ]; then
echo "$BOOT_SIGN_KEY" > ./kernel-build-tools/linux-x86/share/avb/testkey_rsa2048.pem
fi
- name: Bot session cache
id: bot_session_cache
uses: actions/cache@v4
if: false
with:
path: scripts/ksunextbot.session
key: ${{ runner.os }}-bot-session
- name: Build boot images
run: |
export AVBTOOL=$GITHUB_WORKSPACE/kernel-build-tools/linux-x86/bin/avbtool
export GZIP=$GITHUB_WORKSPACE/build-tools/path/linux-x86/gzip
export LZ4=$GITHUB_WORKSPACE/build-tools/path/linux-x86/lz4
export MKBOOTIMG=$GITHUB_WORKSPACE/mkbootimg/mkbootimg.py
export UNPACK_BOOTIMG=$GITHUB_WORKSPACE/mkbootimg/unpack_bootimg.py
cd $GITHUB_WORKSPACE/KernelSU-Next
export VERSION=$(($(git rev-list --count HEAD) + 10200))
echo "VERSION: $VERSION"
cd -
bash $GITHUB_WORKSPACE/KernelSU-Next/.github/scripts/build_a13.sh
- name: Display structure of boot files
run: ls -R
- name: Upload images artifact
uses: actions/upload-artifact@v4
with:
name: boot-images-android15
path: Image-android15*/*.img.gz
check-build-kernel:
if: (github.event_name == 'pull_request' && !github.event.pull_request.draft) || github.ref == 'refs/heads/next'
strategy:
matrix:
include:
- version: "6.6"
sub_level: 57
os_patch_level: 2024-12
uses: ./.github/workflows/gki-kernel.yml
with:
version: android15-${{ matrix.version }}
version_name: android15-${{ matrix.version }}.${{ matrix.sub_level }}
tag: android15-${{ matrix.version }}-${{ matrix.os_patch_level }}
os_patch_level: ${{ matrix.os_patch_level }}
patch_path: ${{ matrix.version }}

View File

@@ -1,41 +0,0 @@
name: Build LKM for KernelSU-Next
on:
push:
branches: [ "next" ]
paths:
- ".github/workflows/build-lkm.yml"
pull_request:
branches: [ "next" ]
paths:
- ".github/workflows/build-lkm.yml"
workflow_call:
jobs:
build-lkm:
strategy:
matrix:
include:
- version: "android12-5.10"
sub_level: 226
os_patch_level: 2024-11
- version: "android13-5.10"
sub_level: 223
os_patch_level: 2024-11
- version: "android13-5.15"
sub_level: 167
os_patch_level: 2024-11
- version: "android14-5.15"
sub_level: 167
os_patch_level: 2024-11
- version: "android14-6.1"
sub_level: 115
os_patch_level: 2024-12
- version: "android15-6.6"
sub_level: 57
os_patch_level: 2024-12
uses: ./.github/workflows/gki-kernel.yml
with:
version: ${{ matrix.version }}
version_name: ${{ matrix.version }}.${{ matrix.sub_level }}
tag: ${{ matrix.version }}-${{ matrix.os_patch_level }}
os_patch_level: ${{ matrix.os_patch_level }}
build_lkm: true

View File

@@ -1,190 +0,0 @@
name: Build Manager
on:
push:
branches: [ "next" ]
paths:
- '.github/workflows/build-manager-ci.yml'
- 'manager/**'
- 'kernel/**'
- 'userspace/ksud_overlayfs**'
- 'userspace/ksud_magic/**'
- 'userspace/susfsd/**'
pull_request:
branches: [ "next" ]
paths:
- 'manager/**'
workflow_call:
workflow_dispatch:
jobs:
build-lkm:
uses: ./.github/workflows/build-lkm.yml
secrets: inherit
build-susfsd:
needs: build-lkm
strategy:
matrix:
include:
- target: aarch64-linux-android
os: ubuntu-latest
uses: ./.github/workflows/susfsd.yml
with:
target: ${{ matrix.target }}
os: ${{ matrix.os }}
build-ksud_overlayfs:
needs: build-susfsd
strategy:
matrix:
include:
- target: aarch64-linux-android
os: ubuntu-latest
uses: ./.github/workflows/ksud_overlayfs.yml
with:
target: ${{ matrix.target }}
os: ${{ matrix.os }}
build-ksud_magic:
needs: build-ksud_overlayfs
strategy:
matrix:
include:
- target: aarch64-linux-android
os: ubuntu-latest
uses: ./.github/workflows/ksud_magic.yml
with:
target: ${{ matrix.target }}
os: ${{ matrix.os }}
build-manager:
needs: build-ksud_magic
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./manager
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup need_upload
id: need_upload
run: |
if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then
echo "UPLOAD=true" >> $GITHUB_OUTPUT
else
echo "UPLOAD=false" >> $GITHUB_OUTPUT
fi
- name: Write key
run: |
if [ ! -z "${{ secrets.KEYSTORE }}" ]; then
{
echo KEYSTORE_PASSWORD='${{ secrets.KEYSTORE_PASSWORD }}'
echo KEY_ALIAS='${{ secrets.KEY_ALIAS }}'
echo KEY_PASSWORD='${{ secrets.KEY_PASSWORD }}'
echo KEYSTORE_FILE='key.jks'
} >> gradle.properties
echo ${{ secrets.KEYSTORE }} | base64 -d > key.jks
fi
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 21
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
- name: Setup Android SDK
uses: android-actions/setup-android@v3
- name: Download arm64 susfsd
uses: actions/download-artifact@v4
with:
name: susfsd-aarch64-linux-android
path: .
- name: Copy susfsd to app jniLibs
run: |
mkdir -p app/src/main/jniLibs/arm64-v8a
cp -f ../arm64-v8a/susfsd ../manager/app/src/main/jniLibs/arm64-v8a/libsusfsd.so
- name: Download arm64 ksud_overlayfs
uses: actions/download-artifact@v4
with:
name: ksud_overlayfs-aarch64-linux-android
path: ksud_overlayfs
- name: Copy ksud_overlayfs to app jniLibs
run: |
cp -f ../ksud_overlayfs/aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud_overlayfs.so
- name: Download arm64 ksud_magic
uses: actions/download-artifact@v4
with:
name: ksud_magic-aarch64-linux-android
path: ksud_magic
- name: Copy ksud_magic to app jniLibs
run: |
cp -f ../ksud_magic/aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud_magic.so
- name: Build with Gradle
run: |
{
echo 'org.gradle.parallel=true'
echo 'org.gradle.vfs.watch=true'
echo 'org.gradle.jvmargs=-Xmx2048m'
echo 'android.native.buildOutput=verbose'
} >> gradle.properties
sed -i 's/org.gradle.configuration-cache=true//g' gradle.properties
chmod +x gradlew
./gradlew clean assembleRelease
- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
name: manager
path: manager/app/build/outputs/apk/release/*.apk
- name: Upload mappings
uses: actions/upload-artifact@v4
with:
name: "mappings"
path: "manager/app/build/outputs/mapping/release/"
- name: Bot session cache
if: steps.need_upload.outputs.UPLOAD == 'true'
id: bot_session_cache
uses: actions/cache@v4
with:
path: scripts/ksunextbot.session
key: ${{ runner.os }}-bot-session
- name: Upload to telegram
if: steps.need_upload.outputs.UPLOAD == 'true'
env:
API_ID: ${{ secrets.API_ID }}
API_HASH: ${{ secrets.API_HASH }}
CHAT_ID: ${{ secrets.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 }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
TITLE: CI Manager (TEST BUILD)
run: |
if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then
export VERSION=$(git rev-list --count HEAD)
APK=$(find ./app/build/outputs/apk/release -name "*.apk")
pip3 install telethon
python3 $GITHUB_WORKSPACE/scripts/ksunextbot.py $APK
fi

View File

@@ -1,190 +0,0 @@
name: Build Manager
on:
# push:
# branches: [ "next" ]
# paths:
# - '.github/workflows/build-manager.yml'
# - 'manager/**'
# - 'kernel/**'
# - 'userspace/ksud_overlayfs**'
# - 'userspace/ksud_magic/**'
# - 'userspace/susfsd/**'
# pull_request:
# branches: [ "next" ]
# paths:
# - 'manager/**'
workflow_call:
workflow_dispatch:
jobs:
build-lkm:
uses: ./.github/workflows/build-lkm.yml
secrets: inherit
build-susfsd:
needs: build-lkm
strategy:
matrix:
include:
- target: aarch64-linux-android
os: ubuntu-latest
uses: ./.github/workflows/susfsd.yml
with:
target: ${{ matrix.target }}
os: ${{ matrix.os }}
build-ksud_overlayfs:
needs: build-susfsd
strategy:
matrix:
include:
- target: aarch64-linux-android
os: ubuntu-latest
uses: ./.github/workflows/ksud_overlayfs.yml
with:
target: ${{ matrix.target }}
os: ${{ matrix.os }}
build-ksud_magic:
needs: build-ksud_overlayfs
strategy:
matrix:
include:
- target: aarch64-linux-android
os: ubuntu-latest
uses: ./.github/workflows/ksud_magic.yml
with:
target: ${{ matrix.target }}
os: ${{ matrix.os }}
build-manager:
needs: build-ksud_magic
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./manager
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup need_upload
id: need_upload
run: |
if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then
echo "UPLOAD=true" >> $GITHUB_OUTPUT
else
echo "UPLOAD=false" >> $GITHUB_OUTPUT
fi
- name: Write key
run: |
if [ ! -z "${{ secrets.KEYSTORE }}" ]; then
{
echo KEYSTORE_PASSWORD='${{ secrets.KEYSTORE_PASSWORD }}'
echo KEY_ALIAS='${{ secrets.KEY_ALIAS }}'
echo KEY_PASSWORD='${{ secrets.KEY_PASSWORD }}'
echo KEYSTORE_FILE='key.jks'
} >> gradle.properties
echo ${{ secrets.KEYSTORE }} | base64 -d > key.jks
fi
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 21
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
- name: Setup Android SDK
uses: android-actions/setup-android@v3
- name: Download arm64 susfsd
uses: actions/download-artifact@v4
with:
name: susfsd-aarch64-linux-android
path: .
- name: Copy susfsd to app jniLibs
run: |
mkdir -p app/src/main/jniLibs/arm64-v8a
cp -f ../arm64-v8a/susfsd ../manager/app/src/main/jniLibs/arm64-v8a/libsusfsd.so
- name: Download arm64 ksud_overlayfs
uses: actions/download-artifact@v4
with:
name: ksud_overlayfs-aarch64-linux-android
path: ksud_overlayfs
- name: Copy ksud_overlayfs to app jniLibs
run: |
cp -f ../ksud_overlayfs/aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud_overlayfs.so
- name: Download arm64 ksud_magic
uses: actions/download-artifact@v4
with:
name: ksud_magic-aarch64-linux-android
path: ksud_magic
- name: Copy ksud_magic to app jniLibs
run: |
cp -f ../ksud_magic/aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud_magic.so
- name: Build with Gradle
run: |
{
echo 'org.gradle.parallel=true'
echo 'org.gradle.vfs.watch=true'
echo 'org.gradle.jvmargs=-Xmx2048m'
echo 'android.native.buildOutput=verbose'
} >> gradle.properties
sed -i 's/org.gradle.configuration-cache=true//g' gradle.properties
chmod +x gradlew
./gradlew clean assembleRelease
- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
name: manager
path: manager/app/build/outputs/apk/release/*.apk
- name: Upload mappings
uses: actions/upload-artifact@v4
with:
name: "mappings"
path: "manager/app/build/outputs/mapping/release/"
- name: Bot session cache
if: steps.need_upload.outputs.UPLOAD == 'true'
id: bot_session_cache
uses: actions/cache@v4
with:
path: scripts/ksunextbot.session
key: ${{ runner.os }}-bot-session
- name: Upload to telegram
if: steps.need_upload.outputs.UPLOAD == 'true'
env:
API_ID: ${{ secrets.API_ID }}
API_HASH: ${{ secrets.API_HASH }}
CHAT_ID: ${{ secrets.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 }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
TITLE: Release Manager (STABLE BUILD)
run: |
if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then
export VERSION=$(git rev-list --count HEAD)
APK=$(find ./app/build/outputs/apk/release -name "*.apk")
pip3 install telethon
python3 $GITHUB_WORKSPACE/scripts/ksunextbot.py $APK
fi

View File

@@ -1,36 +0,0 @@
name: Build SU
on:
push:
branches: [ "next" ]
paths:
- '.github/workflows/build-su.yml'
- 'userspace/su/**'
- 'scripts/ksunextbot.py'
pull_request:
branches: [ "next" ]
paths:
- 'userspace/su/**'
jobs:
build-su:
name: Build userspace su
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup need_upload
id: need_upload
run: |
if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then
echo "UPLOAD=true" >> $GITHUB_OUTPUT
else
echo "UPLOAD=false" >> $GITHUB_OUTPUT
fi
- name: Build su
working-directory: ./userspace/su
run: $ANDROID_NDK/ndk-build
- name: Upload a Build Artifact
uses: actions/upload-artifact@v4
with:
name: su
path: ./userspace/su/libs

View File

@@ -1,37 +0,0 @@
name: Clippy check
on:
push:
branches:
- next
paths:
- '.github/workflows/clippy.yml'
- 'userspace/ksud/**'
pull_request:
branches:
- main
paths:
- '.github/workflows/clippy.yml'
- 'userspace/ksud/**'
env:
RUSTFLAGS: '-Dwarnings'
jobs:
clippy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: rustup update --force-non-host stable-x86_64-unknown-linux-gnu
- uses: Swatinem/rust-cache@v2
with:
workspaces: userspace/ksud
- name: Install cross
run: |
cargo install cross --git https://github.com/cross-rs/cross --rev 66845c1
- name: Run clippy
run: |
cross clippy --manifest-path userspace/ksud/Cargo.toml --target aarch64-linux-android --release
cross clippy --manifest-path userspace/ksud/Cargo.toml --target x86_64-linux-android --release

View File

@@ -1,258 +0,0 @@
name: GKI Kernel Build
on:
workflow_call:
inputs:
version:
required: true
type: string
description: >
Output directory of gki,
for example: android12-5.10
version_name:
required: true
type: string
description: >
With SUBLEVEL of kernel,
for example: android12-5.10.66
tag:
required: true
type: string
description: >
Part of branch name of common kernel manifest,
for example: android12-5.10-2021-11
os_patch_level:
required: false
type: string
description: >
Patch level of common kernel manifest,
for example: 2021-11
default: 2022-05
patch_path:
required: false
type: string
description: >
Directory name of .github/patches/<patch_path>
for example: 5.10
use_cache:
required: false
type: boolean
default: true
embed_ksud:
required: false
type: string
default: ksud-aarch64-linux-android
description: >
Artifact name of prebuilt ksud to be embedded
for example: ksud-aarch64-linux-android
debug:
required: false
type: boolean
default: false
build_lkm:
required: false
type: boolean
default: false
secrets:
BOOT_SIGN_KEY:
required: false
CHAT_ID:
required: false
BOT_TOKEN:
required: false
MESSAGE_THREAD_ID:
required: false
jobs:
build:
name: Build ${{ inputs.version_name }}
runs-on: ubuntu-latest
env:
CCACHE_COMPILERCHECK: "%compiler% -dumpmachine; %compiler% -dumpversion"
CCACHE_NOHASHDIR: "true"
CCACHE_HARDLINK: "true"
steps:
- name: Maximize build space
uses: easimon/maximize-build-space@master
with:
root-reserve-mb: 8192
temp-reserve-mb: 2048
remove-dotnet: 'true'
remove-android: 'true'
remove-haskell: 'true'
remove-codeql: 'true'
- uses: actions/checkout@v4
with:
path: KernelSU-Next
fetch-depth: 0
- name: Setup need_upload
id: need_upload
run: |
if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then
echo "UPLOAD=true" >> $GITHUB_OUTPUT
else
echo "UPLOAD=false" >> $GITHUB_OUTPUT
fi
- name: Setup kernel source
run: |
echo "Free space:"
df -h
cd $GITHUB_WORKSPACE
sudo apt-get install repo -y
mkdir android-kernel && cd android-kernel
repo init --depth=1 --u https://android.googlesource.com/kernel/manifest -b common-${{ inputs.tag }} --repo-rev=v2.16
REMOTE_BRANCH=$(git ls-remote https://android.googlesource.com/kernel/common ${{ inputs.tag }})
DEFAULT_MANIFEST_PATH=.repo/manifests/default.xml
if grep -q deprecated <<< $REMOTE_BRANCH; then
echo "Found deprecated branch: ${{ inputs.tag }}"
sed -i 's/"${{ inputs.tag }}"/"deprecated\/${{ inputs.tag }}"/g' $DEFAULT_MANIFEST_PATH
cat $DEFAULT_MANIFEST_PATH
fi
repo --version
repo --trace sync -c -j$(nproc --all) --no-tags
df -h
- name: Setup KernelSU-Next
env:
PATCH_PATH: ${{ inputs.patch_path }}
IS_DEBUG_KERNEL: ${{ inputs.debug }}
run: |
cd $GITHUB_WORKSPACE/android-kernel
echo "[+] KernelSU-Next setup"
GKI_ROOT=$(pwd)
echo "[+] GKI_ROOT: $GKI_ROOT"
echo "[+] Copy KernelSU-Next driver to $GKI_ROOT/common/drivers"
ln -sf $GITHUB_WORKSPACE/KernelSU-Next/kernel $GKI_ROOT/common/drivers/kernelsu
echo "[+] Add KernelSU-Next driver to Makefile"
DRIVER_MAKEFILE=$GKI_ROOT/common/drivers/Makefile
DRIVER_KCONFIG=$GKI_ROOT/common/drivers/Kconfig
grep -q "kernelsu" "$DRIVER_MAKEFILE" || printf "\nobj-\$(CONFIG_KSU) += kernelsu/\n" >> "$DRIVER_MAKEFILE"
grep -q "kernelsu" "$DRIVER_KCONFIG" || sed -i "/endmenu/i\\source \"drivers/kernelsu/Kconfig\"" "$DRIVER_KCONFIG"
echo "[+] Apply Compilation Patches"
if [ ! -e build/build.sh ]; then
GLIBC_VERSION=$(ldd --version 2>/dev/null | head -n 1 | awk '{print $NF}')
echo "GLIBC_VERSION: $GLIBC_VERSION"
if [ "$(printf '%s\n' "2.38" "$GLIBC_VERSION" | sort -V | head -n1)" = "2.38" ]; then
echo "Patching resolve_btfids/Makefile"
cd $GKI_ROOT/common/ && sed -i '/\$(Q)\$(MAKE) -C \$(SUBCMD_SRC) OUTPUT=\$(abspath \$(dir \$@))\/ \$(abspath \$@)/s//$(Q)$(MAKE) -C $(SUBCMD_SRC) EXTRA_CFLAGS="$(CFLAGS)" OUTPUT=$(abspath $(dir $@))\/ $(abspath $@)/' tools/bpf/resolve_btfids/Makefile || echo "No patch needed."
fi
fi
if [ "$IS_DEBUG_KERNEL" = "true" ]; then
echo "[+] Enable debug features for kernel"
printf "\nccflags-y += -DCONFIG_KSU_DEBUG\n" >> $GITHUB_WORKSPACE/KernelSU-Next/kernel/Makefile
fi
repo status
echo "[+] KernelSU-Next setup done."
- name: Symbol magic
run: |
echo "[+] Export all symbol from abi_gki_aarch64.xml"
COMMON_ROOT=$GITHUB_WORKSPACE/android-kernel/common
KSU_ROOT=$GITHUB_WORKSPACE/KernelSU-Next
ABI_XML=$COMMON_ROOT/android/abi_gki_aarch64.xml
SYMBOL_LIST=$COMMON_ROOT/android/abi_gki_aarch64
# python3 $KSU_ROOT/scripts/abi_gki_all.py $ABI_XML > $SYMBOL_LIST
echo "[+] Add KernelSU-Next symbols"
cat $KSU_ROOT/kernel/export_symbol.txt | awk '{sub("[ \t]+","");print " "$0}' >> $SYMBOL_LIST
- name: Setup ccache
if: inputs.use_cache == true
uses: hendrikmuhs/ccache-action@v1
with:
key: gki-kernel-aarch64-${{ inputs.version_name }}
max-size: 2G
save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
- name: Setup for LKM
if: ${{ inputs.build_lkm == true }}
working-directory: android-kernel
run: |
pip install ast-grep-cli
sudo apt-get install llvm-15 -y
ast-grep -U -p '$$$ check_exports($$$) {$$$}' -r '' common/scripts/mod/modpost.c
ast-grep -U -p 'check_exports($$$);' -r '' common/scripts/mod/modpost.c
sed -i '/config KSU/,/help/{s/default y/default m/}' common/drivers/kernelsu/Kconfig
echo "drivers/kernelsu/kernelsu.ko" >> common/android/gki_aarch64_modules
# bazel build, android14-5.15, android14-6.1 use bazel
if [ ! -e build/build.sh ]; then
sed -i 's/needs unknown symbol/Dont abort when unknown symbol/g' build/kernel/*.sh || echo "No unknown symbol scripts found"
if [ -e common/modules.bzl ]; then
sed -i 's/_COMMON_GKI_MODULES_LIST = \[/_COMMON_GKI_MODULES_LIST = \[ "drivers\/kernelsu\/kernelsu.ko",/g' common/modules.bzl
fi
else
TARGET_FILE="build/kernel/build.sh"
if [ ! -e "$TARGET_FILE" ]; then
TARGET_FILE="build/build.sh"
fi
sed -i 's/needs unknown symbol/Dont abort when unknown symbol/g' $TARGET_FILE || echo "No unknown symbol in $TARGET_FILE"
sed -i 's/if ! diff -u "\${KERNEL_DIR}\/\${MODULES_ORDER}" "\${OUT_DIR}\/modules\.order"; then/if false; then/g' $TARGET_FILE
sed -i 's@${ROOT_DIR}/build/abi/compare_to_symbol_list@echo@g' $TARGET_FILE
sed -i 's/needs unknown symbol/Dont abort when unknown symbol/g' build/kernel/*.sh || echo "No unknown symbol scripts found"
fi
- name: Make working directory clean to avoid dirty
working-directory: android-kernel
run: |
rm common/android/abi_gki_protected_exports_* || echo "No protected exports!"
git config --global user.email "bot@kernelsu.org"
git config --global user.name "KernelSU-NextBot"
cd common/ && git add -A && git commit -a -m "Add KernelSU-Next"
repo status
- name: Build Kernel/LKM
working-directory: android-kernel
run: |
if [ ! -z ${{ vars.EXPECTED_SIZE }} ] && [ ! -z ${{ vars.EXPECTED_HASH }} ]; then
export KSU_EXPECTED_SIZE=${{ vars.EXPECTED_SIZE }}
export KSU_EXPECTED_HASH=${{ vars.EXPECTED_HASH }}
fi
if [ -e build/build.sh ]; then
LTO=thin BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh CC="/usr/bin/ccache clang"
else
tools/bazel run --disk_cache=/home/runner/.cache/bazel --config=fast --config=stamp --lto=thin //common:kernel_aarch64_dist -- --dist_dir=dist
fi
- name: Prepare artifacts
id: prepareArtifacts
run: |
OUTDIR=android-kernel/out/${{ inputs.version }}/dist
if [ ! -e $OUTDIR ]; then
OUTDIR=android-kernel/dist
fi
mkdir output
if [ "${{ inputs.build_lkm}}" = "true" ]; then
llvm-strip-15 -d $OUTDIR/kernelsu.ko
mv $OUTDIR/kernelsu.ko ./output/${{ inputs.version }}_kernelsu.ko
else
cp $OUTDIR/Image ./output/
cp $OUTDIR/Image.lz4 ./output/
git clone https://github.com/Kernel-SU/AnyKernel3
rm -rf ./AnyKernel3/.git
cp $OUTDIR/Image ./AnyKernel3/
fi
- name: Upload Image and Image.gz
uses: actions/upload-artifact@v4
if: ${{ inputs.build_lkm == false }}
with:
name: Image-${{ inputs.version_name }}_${{ inputs.os_patch_level }}
path: ./output/*
- name: Upload AnyKernel3
if: ${{ inputs.build_lkm == false }}
uses: actions/upload-artifact@v4
with:
name: AnyKernel3-${{ inputs.version_name }}_${{ inputs.os_patch_level }}
path: ./AnyKernel3/*
- name: Upload LKM
uses: actions/upload-artifact@v4
if: ${{ inputs.build_lkm == true }}
with:
name: ${{ inputs.version }}-lkm
path: ./output/*_kernelsu.ko

View File

@@ -1,61 +0,0 @@
name: Build ksud_magic
on:
workflow_call:
inputs:
target:
required: true
type: string
os:
required: false
type: string
default: ubuntu-latest
pack_lkm:
required: false
type: boolean
default: true
use_cache:
required: false
type: boolean
default: true
jobs:
build:
runs-on: ${{ inputs.os }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download artifacts
uses: actions/download-artifact@v4
- name: Prepare LKM fies
if: ${{ inputs.pack_lkm }}
run: |
cp android*-lkm/*_kernelsu.ko ./userspace/ksud_magic/bin/aarch64/
- name: Import susfsd lib
run: |
cp susfsd-aarch64-linux-android/arm64-v8a/susfsd ./userspace/ksud_magic/bin/aarch64/
- name: Setup rustup
run: |
rustup update stable
rustup target add x86_64-apple-darwin
rustup target add aarch64-apple-darwin
- uses: Swatinem/rust-cache@v2
with:
workspaces: userspace/ksud_magic
cache-targets: false
- name: Install cross
run: |
cargo install cross --git https://github.com/cross-rs/cross --rev 66845c1 --force
- name: Build ksud_magic
run: CROSS_NO_WARNINGS=0 cross build --target ${{ inputs.target }} --release --manifest-path ./userspace/ksud_magic/Cargo.toml
- name: Upload ksud_magic artifact
uses: actions/upload-artifact@v4
with:
name: ksud_magic-${{ inputs.target }}
path: userspace/ksud_magic/target/**/release/ksud*

View File

@@ -1,61 +0,0 @@
name: Build ksud_overlayfs
on:
workflow_call:
inputs:
target:
required: true
type: string
os:
required: false
type: string
default: ubuntu-latest
pack_lkm:
required: false
type: boolean
default: true
use_cache:
required: false
type: boolean
default: true
jobs:
build:
runs-on: ${{ inputs.os }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download artifacts
uses: actions/download-artifact@v4
- name: Prepare LKM fies
if: ${{ inputs.pack_lkm }}
run: |
cp android*-lkm/*_kernelsu.ko ./userspace/ksud_overlayfs/bin/aarch64/
- name: Import susfsd lib
run: |
cp susfsd-aarch64-linux-android/arm64-v8a/susfsd ./userspace/ksud_overlayfs/bin/aarch64/
- name: Setup rustup
run: |
rustup update stable
rustup target add x86_64-apple-darwin
rustup target add aarch64-apple-darwin
- uses: Swatinem/rust-cache@v2
with:
workspaces: userspace/ksud_overlayfs
cache-targets: false
- name: Install cross
run: |
cargo install cross --git https://github.com/cross-rs/cross --rev 66845c1 --force
- name: Build ksud_overlayfs
run: CROSS_NO_WARNINGS=0 cross build --target ${{ inputs.target }} --release --manifest-path ./userspace/ksud_overlayfs/Cargo.toml
- name: Upload ksud_overlayfs artifact
uses: actions/upload-artifact@v4
with:
name: ksud_overlayfs-${{ inputs.target }}
path: userspace/ksud_overlayfs/target/**/release/ksud*

View File

@@ -1,56 +0,0 @@
name: Release
on:
push:
tags:
- "v*"
workflow_dispatch:
jobs:
build-manager:
uses: ./.github/workflows/build-manager.yml
secrets: inherit
build-a12-kernel:
uses: ./.github/workflows/build-kernel-a12.yml
secrets: inherit
build-a13-kernel:
uses: ./.github/workflows/build-kernel-a13.yml
secrets: inherit
build-a14-kernel:
uses: ./.github/workflows/build-kernel-a14.yml
secrets: inherit
build-a15-kernel:
uses: ./.github/workflows/build-kernel-a15.yml
secrets: inherit
release:
needs:
- build-manager
- build-a12-kernel
- build-a13-kernel
- build-a14-kernel
runs-on: ubuntu-latest
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
- name: Zip AnyKernel3
run: |
for dir in AnyKernel3-*; do
if [ -d "$dir" ]; then
echo "----- Zip $dir -----"
(cd $dir && zip -r9 "$dir".zip ./* -x .git .gitignore ./*.zip && mv *.zip ..)
fi
done
- name: Display structure of downloaded files
run: ls -R
- name: release
uses: softprops/action-gh-release@v2
with:
files: |
manager/*.apk
android*-lkm/*_kernelsu.ko
AnyKernel3-*.zip
boot-images-*/Image-*/*.img.gz
ksud_magic-*
ksud_overlayfs-*
susfsd-*

View File

@@ -1,33 +0,0 @@
name: Rustfmt check
on:
push:
branches:
- 'next'
paths:
- '.github/workflows/rustfmt.yml'
- 'userspace/ksud/**'
pull_request:
branches:
- 'next'
paths:
- '.github/workflows/rustfmt.yml'
- 'userspace/ksud/**'
permissions:
checks: write
jobs:
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
with:
components: rustfmt
- uses: LoliGothick/rustfmt-check@master
with:
token: ${{ github.token }}
working-directory: userspace/ksud

View File

@@ -1,27 +0,0 @@
name: ShellCheck
on:
push:
branches:
- 'next'
paths:
- '.github/workflows/shellcheck.yml'
- '**/*.sh'
pull_request:
branches:
- 'next'
paths:
- '.github/workflows/shellcheck.yml'
- '**/*.sh'
jobs:
shellcheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run ShellCheck
uses: ludeeus/action-shellcheck@2.0.0
with:
ignore_names: gradlew
ignore_paths: ./userspace/ksud/src/installer.sh

View File

@@ -1,34 +0,0 @@
name: Build susfsd
on:
push:
branches: [ "next" ]
paths:
- '.github/workflows/susfsd.yml'
- 'userspace/susfsd/**'
workflow_dispatch:
workflow_call:
inputs:
target:
required: true
type: string
os:
required: false
type: string
default: ubuntu-latest
jobs:
build-susfs:
name: Build userspace susfsd
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Build susfsd
working-directory: ./userspace/susfsd
run: $ANDROID_NDK/ndk-build
- name: Upload a Build Artifact
uses: actions/upload-artifact@v4
with:
name: susfsd-aarch64-linux-android
path: ./userspace/susfsd/libs

View File

@@ -1,7 +0,0 @@
# Reporting Security Issues
The KernelSU team and community take security bugs in KernelSU seriously. We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions.
To report a security issue, please use the GitHub Security Advisory ["Report a Vulnerability"](https://github.com/tiann/KernelSU/security/advisories/new) tab, or you can mailto [weishu](mailto:twsxtd@gmail.com) directly.
The KernelSU team will send a response indicating the next steps in handling your report. After the initial reply to your report, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -1,49 +0,0 @@
**English** | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md)
# KernelSU Next
<img src="/assets/kernelsu_next.png" style="width: 96px;" alt="logo">
A Kernel-based root solution for Android devices.
[![Latest Release](https://img.shields.io/github/v/release/rifsxd/KernelSU-Next?label=Release&logo=github)](https://github.com/rifsxd/KernelSU-Next/releases/latest)
[![Nightly Release](https://img.shields.io/badge/Nightly%20Release-gray?logo=hackthebox&logoColor=fff)](https://nightly.link/rifsxd/KernelSU-Next/workflows/build-manager/next/manager)
[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
[![GitHub License](https://img.shields.io/github/license/rifsxd/KernelSU-Next?logo=gnu)](/LICENSE)
## Features
1. Kernel-based `su` and root access management.
2. Module system based on dynamic mount system [Magic Mount](https://topjohnwu.github.io/Magisk/details.html#magic-mount) / [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS).
3. [App Profile](https://kernelsu.org/guide/app-profile.html): Lock up the root power in a cage.
## Compatibility State
KernelSU Next officially supports most Android kernels starting from 4.4 up to 6.6.
- GKI 2.0 (5.10+) kernels can run pre-built images and LKM/KMI.
- GKI 1.0 (4.19 - 5.4) kernels need to rebuilt with KernelSU driver.
- EOL (<4.14) kernels also need to be rebuilt with KernelSU driver (3.18+ is experimental and may need some function backports).
Currently, only `arm64-v8a` is supported.
## Usage
- [Installation instruction](https://rifsxd.github.io/KernelSU-Next/)
## Security
For information on reporting security vulnerabilities in KernelSU, see [SECURITY.md](/SECURITY.md).
## License
- Files under the `kernel` directory are [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html).
- All other parts except the `kernel` directory are [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html).
## Credits
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): the KernelSU idea.
- [Magisk](https://github.com/topjohnwu/Magisk): the powerful root tool.
- [genuine](https://github.com/brevent/genuine/): apk v2 signature validation.
- [Diamorphine](https://github.com/m0nad/Diamorphine): some rootkit skills.
- [KernelSU](https://github.com/tiann/KernelSU): thanks to tiann, or else KernelSU Next wouldn't even exist.
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs): 💜 5ec1cff for saving KernelSU!

View File

@@ -1,49 +0,0 @@
[English](README.md) | **简体中文** | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md)
# KernelSU Next
<img src="/assets/kernelsu_next.png" style="width: 96px;" alt="logo">
安卓基于内核的 Root 方案
[![Latest Release](https://img.shields.io/github/v/release/rifsxd/KernelSU-Next?label=Release&logo=github)](https://github.com/rifsxd/KernelSU-Next/releases/latest)
[![Nightly Release](https://img.shields.io/badge/Nightly%20Release-gray?logo=hackthebox&logoColor=fff)](https://nightly.link/rifsxd/KernelSU-Next/workflows/build-manager/next/manager)
[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
[![GitHub License](https://img.shields.io/github/license/rifsxd/KernelSU-Next?logo=gnu)](/LICENSE)
## 特性
1. 基于内核的 `SU` 和权限管理
2. 基于动态挂载系统 [Magic Mount](https://topjohnwu.github.io/Magisk/details.html#magic-mount) / [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS) 的模块系统。
3. [App Profile](https://kernelsu.org/zh_CN/guide/app-profile.html):把 Root 权限关进笼子里
## 兼容状态
KernelSU Next 支持从 4.4 到 6.6 的大多数安卓内核
- GKI 2.05.10+)内核可运行预置镜像和 LKM/KMI
- GKI 1.04.19 - 5.4)内核需要使用 KernelSU 内核驱动重新编译
- EOL (<4.14) 内核也需要使用 KernelSU 内核驱动重新编译 (3.18+ 的版本处于试验阶段,可能需要移植一些功能)
目前只支持 `arm64-v8a` 架构
## 用法
- [安装说明](https://rifsxd.github.io/KernelSU-Next/)
## 安全性
有关报告 KernelSU Next 漏洞的信息,请参阅 [SECURITY.md](/SECURITY.md).
## 许可证
- 目录 `kernel` 下所有文件为 [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
- `kernel` 目录以外的其他部分均为 [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html)
## 鸣谢
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): KernelSU 的灵感.
- [Magisk](https://github.com/topjohnwu/Magisk): 强大的 Root 工具.
- [genuine](https://github.com/brevent/genuine/): apk v2 签名验证。
- [Diamorphine](https://github.com/m0nad/Diamorphine): 一些 Rootkit 技巧。
- [KernelSU](https://github.com/tiann/KernelSU): 感谢 tiann否则 KernelSU Next 根本不会存在。
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs): 💜 5ec1cff 為了拯救 KernelSU

View File

@@ -1,49 +0,0 @@
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | **Français** | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md)
# KernelSU Next
<img src="/assets/kernelsu_next.png" style="width: 96px;" alt="logo">
Une solution root basée sur le noyau pour les appareils Android.
[![Dernière version](https://img.shields.io/github/v/release/rifsxd/KernelSU-Next?label=Release&logo=github)](https://github.com/rifsxd/KernelSU-Next/releases/latest)
[![Version Nightly](https://img.shields.io/badge/Nightly%20Release-gray?logo=hackthebox&logoColor=fff)](https://nightly.link/rifsxd/KernelSU-Next/workflows/build-manager/next/manager)
[![Licence : GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
[![Licence GitHub](https://img.shields.io/github/license/rifsxd/KernelSU-Next?logo=gnu)](/LICENSE)
## Fonctionnalités
1. Gestion des accès root et de la commande `su` basée sur le noyau.
2. Système de modules basé sur le système de montage dynamique [Magic Mount](https://topjohnwu.github.io/Magisk/details.html#magic-mount) / [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS).
3. [Profil d'application](https://kernelsu.org/guide/app-profile.html) : Enfermez la puissance du root dans une cage.
## État de compatibilité
KernelSU Next prend officiellement en charge la plupart des noyaux Android de la version 4.4 à la version 6.6.
- Les noyaux GKI 2.0 (5.10+) peuvent exécuter des images pré-construites et des modules LKM/KMI.
- Les noyaux GKI 1.0 (4.19 - 5.4) doivent être reconstruits avec le pilote KernelSU.
- Les noyaux EOL (<4.14) doivent également être reconstruits avec le pilote KernelSU (3.18+ est expérimental et peut nécessiter des rétroportages fonctionnels).
Actuellement, seul `arm64-v8a` est pris en charge.
## Utilisation
- [Instructions d'installation](https://rifsxd.github.io/KernelSU-Next/)
## Sécurité
Pour signaler des vulnérabilités de sécurité dans KernelSU, consultez [SECURITY.md](/SECURITY.md).
## Licence
- Les fichiers du répertoire `kernel` sont sous licence [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html).
- Toutes les autres parties, sauf le répertoire `kernel`, sont sous licence [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html).
## Crédits
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/) : l'idée de KernelSU.
- [Magisk](https://github.com/topjohnwu/Magisk) : l'outil root puissant.
- [genuine](https://github.com/brevent/genuine/) : validation de signature apk v2.
- [Diamorphine](https://github.com/m0nad/Diamorphine) : quelques techniques de rootkit.
- [KernelSU](https://github.com/tiann/KernelSU) : merci à tiann, sans qui KernelSU Next n'existerait même pas.
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs) : 💜 5ec1cff pour avoir sauvé KernelSU !

View File

@@ -1,49 +0,0 @@
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | **Bahasa Indonesia** | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md)
# KernelSU Next
<img src="/assets/kernelsu_next.png" style="width: 96px;" alt="logo">
Sebuah solusi root berbasis Kernel untuk perangkat Android.
[![Latest Release](https://img.shields.io/github/v/release/rifsxd/KernelSU-Next?label=Release&logo=github)](https://github.com/rifsxd/KernelSU-Next/releases/latest)
[![Nightly Release](https://img.shields.io/badge/Nightly%20Release-gray?logo=hackthebox&logoColor=fff)](https://nightly.link/rifsxd/KernelSU-Next/workflows/build-manager/next/manager)
[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
[![GitHub License](https://img.shields.io/github/license/rifsxd/KernelSU-Next?logo=gnu)](/LICENSE)
## Fitur
1. Akses root dan manajemen `su` berbasis Kernel.
2. Sistem modul berbasis sistem mount dinamis [Magic Mount](https://topjohnwu.github.io/Magisk/details.html#magic-mount) / [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS).
3. [Profil Aplikasi](https://kernelsu.org/guide/app-profile.html): Mengunci kekuatan root dalam sebuah kandang.
## Status Kompatibilitas
KernelSU Next secara resmi mendukung sebagian besar kernel Android mulai dari 4.4 hingga 6.6.
- Kernel GKI 2.0 (5.10+) dapat menjalankan gambar yang telah dibangun sebelumnya dan LKM/KMI.
- Kernel GKI 1.0 (4.19 - 5.4) perlu dibangun ulang dengan driver KernelSU.
- Kernel EOL (<4.14) juga perlu dibangun ulang dengan driver KernelSU (3.18+ bersifat eksperimental dan mungkin memerlukan beberapa backport fungsi).
Saat ini, hanya `arm64-v8a` yang didukung.
## Penggunaan
- [Petunjuk instalasi](https://rifsxd.github.io/KernelSU-Next/)
## Keamanan
Untuk informasi tentang melaporkan kerentanannya di KernelSU, lihat [SECURITY.md](/SECURITY.md).
## Lisensi
- File di bawah direktori `kernel` menggunakan lisensi [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html).
- Semua bagian lain kecuali direktori `kernel` menggunakan lisensi [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html).
## Kredit
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): ide KernelSU.
- [Magisk](https://github.com/topjohnwu/Magisk): alat root yang kuat.
- [genuine](https://github.com/brevent/genuine/): validasi tanda tangan apk v2.
- [Diamorphine](https://github.com/m0nad/Diamorphine): beberapa keterampilan rootkit.
- [KernelSU](https://github.com/tiann/KernelSU): terima kasih kepada tiann, jika tidak, KernelSU Next bahkan tidak akan ada.
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs): 💜 5ec1cff karena menyelamatkan KernelSU!

View File

@@ -1,49 +0,0 @@
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | **한국어** | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md)
# KernelSU Next
<img src="/assets/kernelsu_next.png" style="width: 96px;" alt="logo">
안드로이드 기기들을 위한 커널 기반 루팅 솔루션입니다.
[![Latest Release](https://img.shields.io/github/v/release/rifsxd/KernelSU-Next?label=Release&logo=github)](https://github.com/rifsxd/KernelSU-Next/releases/latest)
[![Nightly Release](https://img.shields.io/badge/Nightly%20Release-gray?logo=hackthebox&logoColor=fff)](https://nightly.link/rifsxd/KernelSU-Next/workflows/build-manager/next/manager)
[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
[![GitHub License](https://img.shields.io/github/license/rifsxd/KernelSU-Next?logo=gnu)](/LICENSE)
## 기능
1. 커널 기반 `su` 및 루트 권한 관리
2. 동적 마운트 시스템 기반 모듈 시스템 [Magic Mount](https://topjohnwu.github.io/Magisk/details.html#magic-mount) / [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS).
3. [App Profile](https://kernelsu.org/guide/app-profile.html): 루트 권한 제한
## 호환 상태
KernelSU Next는 공식적으로 대부분의 4.4부터 6.6의 안드로이드 커널을 지원합니다.
- GKI 2.0 (5.10+) 커널은 미리 빌드된 이미지와 LKM/KMI를 지원합니다.
- GKI 1.0 (4.19 - 5.4) 커널은 KernelSU 드라이버로 다시 빌드해야 합니다.
- EOL (<4.14) 커널도 역시 KernelSU 드라이버로 다시 빌드해야 합니다.(3.18+는 실험적이며 일부 함수의 이식이 필요할 수 있습니다.).
현재는, `arm64-v8a`만 지원됩니다.
## 사용 방법
- [설치 방법](https://rifsxd.github.io/KernelSU-Next/)
## 보안
KernelSU의 보안 취약점 보고에 대한 자세한 내용은 [SECURITY.md](/SECURITY.md)를 참조하세요.
## 저작권 라이센스
- `kernel` 디렉터리의 파일은 [GPL-2.0전용](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)입니다.
- `kernel` 디렉터리를 제외한 모든 파일은 [GPL-3.0-이상](https://www.gnu.org/licenses/gpl-3.0.html)입니다.
## 크레딧
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): KernelSU의 아이디어
- [Magisk](https://github.com/topjohnwu/Magisk): 강력한 루팅 도구
- [genuine](https://github.com/brevent/genuine/): apk v2 서명 검사
- [Diamorphine](https://github.com/m0nad/Diamorphine): 일부 rootkit 기술
- [KernelSU](https://github.com/tiann/KernelSU): KernelSU Next가 존재할 수 있게 해 준 tiann에게 감사드립니다.
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs): KernelSU를 구해준 5ec1cff에게 감사드립니다!

View File

@@ -1,49 +0,0 @@
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | **Português (Brasil)** | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md)
# KernelSU Next
<img src="/assets/kernelsu_next.png" style="width: 96px;" alt="logo">
Uma solução root baseada em kernel para dispositivos Android.
[![Latest Release](https://img.shields.io/github/v/release/rifsxd/KernelSU-Next?label=Release&logo=github)](https://github.com/rifsxd/KernelSU-Next/releases/latest)
[![Nightly Release](https://img.shields.io/badge/Nightly%20Release-gray?logo=hackthebox&logoColor=fff)](https://nightly.link/rifsxd/KernelSU-Next/workflows/build-manager/next/manager)
[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
[![GitHub License](https://img.shields.io/github/license/rifsxd/KernelSU-Next?logo=gnu)](/LICENSE)
## Características
1. `su` e gerenciamento de acesso root baseado em kernel.
2. Sistema de módulos baseado em sistema de montagem dinâmica [Magic Mount](https://topjohnwu.github.io/Magisk/details.html#magic-mount) / [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS).
3. [Perfil do Aplicativo](https://kernelsu.org/pt_BR/guide/app-profile.html): Tranque o poder root em uma gaiola.
## Estado de compatibilidade
KernelSU Next suporta oficialmente a maioria dos kernels Android a partir de 4.4 até 6.6.
- Os kernels GKI 2.0 (5.10+) podem executar imagens pré-construídas e LKM/KMI.
- Os kernels GKI 1.0 (4.19 - 5.4) precisam ser reconstruídos com o driver KernelSU.
- Os kernels EOL (<4.14) também precisam ser reconstruídos com o driver KernelSU (3.18+ é experimental e pode precisar portar algumas funções).
Atualmente, apenas `arm64-v8a` é suportado.
## Uso
- [Instruções de instalação](https://rifsxd.github.io/KernelSU-Next/)
## Segurança
Para obter informações sobre como relatar vulnerabilidades de segurança do KernelSU, consulte [SECURITY.md](/SECURITY.md).
## Licença
- Os arquivos no diretório `kernel` são [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html).
- Todas as outras partes, exceto o diretório `kernel` são [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html).
## Créditos
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): a ideia do KernelSU.
- [Magisk](https://github.com/topjohnwu/Magisk): a poderosa ferramenta root.
- [genuine](https://github.com/brevent/genuine/): validação de assinatura apk v2.
- [Diamorphine](https://github.com/m0nad/Diamorphine): algumas habilidades de rootkit.
- [KernelSU](https://github.com/tiann/KernelSU): obrigado a tiann, ou então o KernelSU Next nem existiria.
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs): 💜 5ec1cff por salvar o KernelSU!

View File

@@ -1,49 +0,0 @@
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | **Русский** | [ภาษาไทย](README_TH.md)
# KernelSU Next
<img src="/assets/kernelsu_next.png" style="width: 96px;" alt="logo">
Root-решение для Android на базе ядра.
[![Последний релиз](https://img.shields.io/github/v/release/rifsxd/KernelSU-Next?label=Release&logo=github)](https://github.com/rifsxd/KernelSU-Next/releases/latest)
[![Ночные сборки](https://img.shields.io/badge/Nightly%20Release-gray?logo=hackthebox&logoColor=fff)](https://nightly.link/rifsxd/KernelSU-Next/workflows/build-manager/next/manager)
[![Лицензия: GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
[![Лицензия GitHub](https://img.shields.io/github/license/rifsxd/KernelSU-Next?logo=gnu)](/LICENSE)
## Функции
1. Реализация `su` и управление root-доступом прямо на уровне ядра.
2. Динамическая система модулей, построенная на [Magic Mount](https://topjohnwu.github.io/Magisk/details.html#magic-mount) / [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS).
3. [Профиль для приложений](https://kernelsu.org/guide/app-profile.html): позволяет ограничить root-доступ в песочницу для отдельных приложений.
## Совместимость
KernelSU Next работает с большинством ядер Android (4.4 - 6.6):
- GKI 2.0 (5.10+) могут использовать предсобранные образы и LKM/KMI.
- GKI 1.0 (4.19 - 5.4) требуют пересборки с драйвером KernelSU.
- EOL (<4.14) также требуют пересборки с драйвером KernelSU (версии 3.18+ экспериментальные и могут потребовать некоторые функции бэкпортов).
Сейчас поддерживается только `arm64-v8a`.
## Использование
- [Инструкция по установке](https://rifsxd.github.io/KernelSU-Next/)
## Безопасность
Если нашли баг, посмотри [SECURITY.md](/SECURITY.md) — там гайд, как сообщить о проблеме.
## Лицензия
- Всё, что в директории `kernel`, — [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html).
- Остальной код, кроме директории `kernel`, под [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html).
## Благодарность
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): идея KernelSU.
- [Magisk](https://github.com/topjohnwu/Magisk): топовый инструмент для root.
- [genuine](https://github.com/brevent/genuine/): валидация подписи APK v2.
- [Diamorphine](https://github.com/m0nad/Diamorphine): некоторые навыки rootkit.
- [KernelSU](https://github.com/tiann/KernelSU): спасибо tiann, без него KernelSU Next не релизнулся бы.
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs): 💜 5ec1cff за сохранение KernelSU!

View File

@@ -1,49 +0,0 @@
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | **ภาษาไทย**
# KernelSU Next
<img src="/assets/kernelsu_next.png" style="width: 96px;" alt="logo">
โซลูชันรูทบนพื้นฐานเคอร์เนลสำหรับอุปกรณ์ Android
[![Latest Release](https://img.shields.io/github/v/release/rifsxd/KernelSU-Next?label=Release&logo=github)](https://github.com/rifsxd/KernelSU-Next/releases/latest)
[![Nightly Release](https://img.shields.io/badge/Nightly%20Release-gray?logo=hackthebox&logoColor=fff)](https://nightly.link/rifsxd/KernelSU-Next/workflows/build-manager/next/manager)
[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
[![GitHub License](https://img.shields.io/github/license/rifsxd/KernelSU-Next?logo=gnu)](/LICENSE)
## คุณสมบัติ
1. การจัดการการเข้าถึงรูทและ `su` บนเคอร์เนล
2. ระบบโมดูลที่ใช้ระบบการติดตั้งแบบไดนามิก [Magic Mount](https://topjohnwu.github.io/Magisk/details.html#magic-mount) / [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS)
3. [App Profile](https://kernelsu.org/guide/app-profile.html): จำกัดพลังรูทไว้สำหรับแอปต่างๆ
## การเข้ากันในอุปกรณ์ต่างๆ
KernelSU Next รองรับแบบเป็นทางการตั้งแต่เคอร์เนลแอนดรอยด์ 4.4 ถึง 6.6
- GKI 2.0 (5.10+) เคอร์เนลสามารถรันแบบไฟล์สำเร็จรูปและ LKM/KMI ได้
- GKI 1.0 (4.19 - 5.4) เคอร์เนลต้องการ build ร่วมกับไดร์เวอร์ของทาง KernelSU
- EOL (<4.14) เคอร์เนลก็ต้องการ build ร่วมกับไดร์เวอร์ของทาง KernelSU เช่นกัน (3.18+ ยังเป็นการทดลองอยู่และยังต้องการเขียนในหลังบ้านเพิ่มเติม)
ในขณะนี้, มีแค่สถาปัตยกรรม `arm64-v8a` ที่รองรับเท่านั้น
## การใช้งาน
- [คำแนะนำในการติดตั้ง](https://rifsxd.github.io/KernelSU-Next/)
## ความปลอดภัย
สำหรับข้อมูลเกี่ยวกับการรายงานช่องโหว่ด้านความปลอดภัยใน KernelSU โปรดดูที่ [SECURITY.md](/SECURITY.md).
## ใบอนุญาต
- ไฟล์ที่ภายใต้โฟลเดอร์ `kernel` ถือว่าเป็น [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html).
- ไฟล์ที่นอกเหนือจากโฟลเดอร์ `kernel` ถือว่าเป็น [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html).
## เครดิต
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): ที่เป็นคนริเริ่มไอเดียเกี่ยวกับ KernelSU
- [Magisk](https://github.com/topjohnwu/Magisk): อุปกรณ์มือเกี่ยวกับรูทที่ทรงพลัง
- [genuine](https://github.com/brevent/genuine/): การออกลายเซ็นให้กับไฟล์ apk v2
- [Diamorphine](https://github.com/m0nad/Diamorphine): ความรู้ความสามารถเกี่ยวกับ rootkit
- [KernelSU](https://github.com/tiann/KernelSU): ต้องขอบคุณ tiann ถ้าไม่มีคนนั้นก็ไม่มีสิ่งที่เรียกว่า KernelSU เกิดขึ้น
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs): 💜 5ec1cff ที่ช่วย KernelSU ไว้

View File

@@ -1,49 +0,0 @@
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | **Türkçe** | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md)
# KernelSU Next
<img src="/assets/kernelsu_next.png" style="width: 96px;" alt="logo">
Android cihazlar için Kernel tabanlı bir root çözümü.
[![Latest Release](https://img.shields.io/github/v/release/rifsxd/KernelSU-Next?label=Release&logo=github)](https://github.com/rifsxd/KernelSU-Next/releases/latest)
[![Nightly Release](https://img.shields.io/badge/Nightly%20Release-gray?logo=hackthebox&logoColor=fff)](https://nightly.link/rifsxd/KernelSU-Next/workflows/build-manager/next/manager)
[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
[![GitHub License](https://img.shields.io/github/license/rifsxd/KernelSU-Next?logo=gnu)](/LICENSE)
## Özellikler
1. Çekirdek tabanlı `su` ve kök erişim yönetimi.
2. Dinamik montaj sistemine dayalı modül sistemi [Magic Mount](https://topjohnwu.github.io/Magisk/details.html#magic-mount) / [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS).
3. [App Profile](https://kernelsu.org/guide/app-profile.html): Kök gücünü bir kafese kilitleyin.
## Uyumluluk Durumu
KernelSU Next, 4.4'dan başlayarak 6.6'ya kadar çoğu Android çekirdeğini resmi olarak desteklemektedir.
- GKI 2.0 (5.10+) çekirdekleri önceden oluşturulmuş görüntüleri ve LKM/KMI'yi çalıştırabilir.
- GKI 1.0 (4.19 - 5.4) çekirdeklerinin KernelSU sürücüsü ile yeniden oluşturulması gerekir.
- EOL (<4.14) çekirdeklerinin de KernelSU sürücüsü ile yeniden oluşturulması gerekir. (3.18+ deneyseldir ve bazı fonksiyon geri yüklemelerine ihtiyaç duyulabilir.)
Şu anda sadece `arm64-v8a` desteklenmektedir.
## Kullanım
- [Kurulum Talimatı](https://rifsxd.github.io/KernelSU-Next/)
## Güvenlik
KernelSU'daki güvenlik açıklarını bildirme hakkında bilgi için [SECURITY.md](/SECURITY.md) bölümüne bakın.
## Lisans
- `kernel` dizini altındaki dosyalar sadece [GPL-2.0](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) lisansına tabiidir.
- `kernel` dizini dışındaki diğer tüm kısımlar [GPL-3.0](https://www.gnu.org/licenses/gpl-3.0.html) ya da daha sonraki bir sürüm lisansa tabiidir.
## Krediler
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): KernelSU fikri.
- [Magisk](https://github.com/topjohnwu/Magisk): güçlü kök aracı.
- [genuine](https://github.com/brevent/genuine/): apk v2 imza doğrulama.
- [Diamorphine](https://github.com/m0nad/Diamorphine): bazı rootkit becerileri.
- [KernelSU](https://github.com/tiann/KernelSU): tiann'a teşekkürler, yoksa KernelSU Next var olamazdı bile.
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs): 💜 5ec1cff KernelSU'yu kurtardığınız için!

View File

@@ -1,50 +0,0 @@
[English](README.md) | [简体中文](README_CN.md) | **繁體中文** | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md)
# KernelSU Next
<img src="/assets/kernelsu_next.png" style="width: 96px;" alt="logo">
基於內核的 Android 設備 root 解決方案
[![Latest Release](https://img.shields.io/github/v/release/rifsxd/KernelSU-Next?label=Release&logo=github)](https://github.com/rifsxd/KernelSU-Next/releases/latest)
[![Nightly Release](https://img.shields.io/badge/Nightly%20Release-gray?logo=hackthebox&logoColor=fff)](https://nightly.link/rifsxd/KernelSU-Next/workflows/build-manager/next/manager)
[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
[![GitHub License](https://img.shields.io/github/license/rifsxd/KernelSU-Next?logo=gnu)](/LICENSE)
## 特性
1. 基於內核的 `su` 和 root 權限管理
2. 基於動態掛載系統 [Magic Mount](https://topjohnwu.github.io/Magisk/details.html#magic-mount) / [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS) 的模塊系統。
3. [App Profile](https://kernelsu.org/zh_CN/guide/app-profile.html):把 Root 權限關進籠子裡
## 兼容狀態
KernelSU Next 正式支持大多數從 4.4 到 6.6 的 Android 內核
- GKI 2.0 (5.10+) 內核可以運行預構建的映像和 LKM/KMI
- GKI 1.0 (4.19 - 5.4) 內核需要重新編譯 KernelSU 驅動程序
- EOL (<4.14) 內核也需要重新編譯 KernelSU 驅動程序3.18+ 是實驗性的,可能需要移植一些功能)
目前僅支持 `arm64-v8a`
## 用法
- [安裝說明](https://rifsxd.github.io/KernelSU-Next/)
## 安全性
有關報告 KernelSU Next 漏洞的信息,請參閱 [SECURITY.md](/SECURITY.md).
## 許可證
- 目錄 `kernel` 下所有文件為 [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
- `kernel` 目錄以外的其他部分均為 [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html)
## 鳴謝
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): KernelSU 的靈感.
- [Magisk](https://github.com/topjohnwu/Magisk): 強大的 Root 工具.
- [genuine](https://github.com/brevent/genuine/): apk v2 簽名驗證。
- [Diamorphine](https://github.com/m0nad/Diamorphine): 一些 Rootkit 技巧。
- [KernelSU](https://github.com/tiann/KernelSU): 感謝 tiann否則 KernelSU Next 根本不會存在。
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs): 💜 5ec1cff 為了拯救 KernelSU

View File

@@ -1,14 +0,0 @@
alias bk := build_ksud
alias bm := build_manager
build_ksud:
cross build --target aarch64-linux-android --release --manifest-path ./userspace/ksud/Cargo.toml
build_manager: build_ksud
cp userspace/ksud/target/aarch64-linux-android/release/ksud manager/app/src/main/jniLibs/arm64-v8a/libksud.so
cd manager && ./gradlew aDebug
clippy:
cargo fmt --manifest-path ./userspace/ksud/Cargo.toml
cross clippy --target x86_64-pc-windows-gnu --release --manifest-path ./userspace/ksud/Cargo.toml
cross clippy --target aarch64-linux-android --release --manifest-path ./userspace/ksud/Cargo.toml

View File

@@ -9,6 +9,14 @@ config KSU
To compile as a module, choose M here: the
module will be called kernelsu.
config KSU_KPROBES_HOOK
bool "Use kprobes for kernelsu"
depends on KSU
depends on KPROBES
default y
help
Disable if you use manual hooks.
config KSU_DEBUG
bool "KernelSU debug mode"
depends on KSU
@@ -24,4 +32,147 @@ config KSU_ALLOWLIST_WORKAROUND
Enable session keyring init workaround for problematic devices.
Useful for situations where the SU allowlist is not kept after a reboot.
config KSU_LSM_SECURITY_HOOKS
bool "use lsm security hooks"
depends on KSU
default y
help
Disabling this is mostly only useful for kernel 4.1 and older.
Make sure to implement manual hooks on security/security.c.
menu "KernelSU - SUSFS"
config KSU_SUSFS
bool "KernelSU addon - SUSFS"
depends on KSU
depends on THREAD_INFO_IN_TASK
default y
help
Patch and Enable SUSFS to kernel with KernelSU.
config KSU_SUSFS_HAS_MAGIC_MOUNT
bool "Say yes if the current KernelSU repo has magic mount implemented (default y)"
depends on KSU
default y
help
- Enable to indicate that the current SUSFS kernel supports the auto hide features for 5ec1cff's Magic Mount KernelSU
- Every mounts from /debug_ramdisk/workdir will be treated as magic mount and processed differently by susfs
config KSU_SUSFS_SUS_PATH
bool "Enable to hide suspicious path (NOT recommended)"
depends on KSU_SUSFS
default y
help
- Allow hiding the user-defined path and all its sub-paths from various system calls.
- Includes temp fix for the leaks of app path in /sdcard/Android/data directory.
- Effective only on zygote spawned user app process.
- Use with cautious as it may cause performance loss and will be vulnerable to side channel attacks,
just disable this feature if it doesn't work for you or you don't need it at all.
config KSU_SUSFS_SUS_MOUNT
bool "Enable to hide suspicious mounts"
depends on KSU_SUSFS
default y
help
- Allow hiding the user-defined mount paths from /proc/self/[mounts|mountinfo|mountstat].
- Effective on all processes for hiding mount entries.
- Mounts mounted by process with ksu domain will be forced to be assigned the dev name "KSU".
- mnt_id and mnt_group_id of the sus mount will be assigned to a much bigger number to solve the issue of id not being contiguous.
config KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
bool "Enable to hide KSU's default mounts automatically (experimental)"
depends on KSU_SUSFS_SUS_MOUNT
default y
help
- Automatically add KSU's default mounts to sus_mount.
- No susfs command is needed in userspace.
- Only mount operation from process with ksu domain will be checked.
config KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
bool "Enable to hide suspicious bind mounts automatically (experimental)"
depends on KSU_SUSFS_SUS_MOUNT
default y
help
- Automatically add binded mounts to sus_mount.
- No susfs command is needed in userspace.
- Only mount operation from process with ksu domain will be checked.
config KSU_SUSFS_SUS_KSTAT
bool "Enable to spoof suspicious kstat"
depends on KSU_SUSFS
default y
help
- Allow spoofing the kstat of user-defined file/directory.
- Effective only on zygote spawned user app process.
config KSU_SUSFS_TRY_UMOUNT
bool "Enable to use ksu's ksu_try_umount"
depends on KSU_SUSFS
default y
help
- Allow using ksu_try_umount to umount other user-defined mount paths prior to ksu's default umount paths.
- Effective on all NO-root-access-granted processes.
config KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
bool "Enable to add bind mounts to ksu's ksu_try_umount automatically (experimental)"
depends on KSU_SUSFS_TRY_UMOUNT
default y
help
- Automatically add binded mounts to ksu's ksu_try_umount.
- No susfs command is needed in userspace.
- Only mount operation from process with ksu domain will be checked.
config KSU_SUSFS_SPOOF_UNAME
bool "Enable to spoof uname"
depends on KSU_SUSFS
default y
help
- Allow spoofing the string returned by uname syscall to user-defined string.
- Effective on all processes.
config KSU_SUSFS_ENABLE_LOG
bool "Enable logging susfs log to kernel"
depends on KSU_SUSFS
default y
help
- Allow logging susfs log to kernel, uncheck it to completely disable all susfs log.
config KSU_SUSFS_HIDE_KSU_SUSFS_SYMBOLS
bool "Enable to automatically hide ksu and susfs symbols from /proc/kallsyms"
depends on KSU_SUSFS
default y
help
- Automatically hide ksu and susfs symbols from '/proc/kallsyms'.
- Effective on all processes.
config KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG
bool "Enable to spoof /proc/bootconfig (gki) or /proc/cmdline (non-gki)"
depends on KSU_SUSFS
default y
help
- Spoof the output of /proc/bootconfig (gki) or /proc/cmdline (non-gki) with a user-defined file.
- Effective on all processes.
config KSU_SUSFS_OPEN_REDIRECT
bool "Enable to redirect a path to be opened with another path (experimental)"
depends on KSU_SUSFS
default y
help
- Allow redirecting a target path to be opened with another user-defined path.
- Effective only on processes with uid < 2000.
- Please be reminded that process with open access to the target and redirected path can be detected.
config KSU_SUSFS_SUS_SU
bool "Enable SUS-SU in runtime temporarily"
depends on KSU_SUSFS && KPROBES && HAVE_KPROBES && KPROBE_EVENTS && KSU_KPROBES_HOOK
default y
help
- Allow user to enable or disable core ksu kprobes hooks temporarily in runtime. There are 2 working modes for sus_su.
- Mode 0 (default): Disable sus_su, and enable ksu kprobe hooks for su instead.
- Mode 1 (deprecated):
- Mode 2: Enable sus_su, and disable ksu kprobe hooks for su, which means the kernel inline hooks are enabled,
the same as the su implementaion of non-gki kernel without kprobe supported.
- Only apps with root access granted by ksu manager are allowed to get root.
endmenu
endmenu

View File

@@ -16,18 +16,9 @@ ccflags-y += -I$(objtree)/security/selinux -include $(srctree)/include/uapi/asm-
obj-$(CONFIG_KSU) += kernelsu.o
# .git is a text file while the module is imported by 'git submodule add'.
ifeq ($(shell test -e $(srctree)/$(src)/../.git; echo $$?),0)
$(shell cd $(srctree)/$(src); /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin [ -f ../.git/shallow ] && git fetch --unshallow)
KSU_GIT_VERSION := $(shell cd $(srctree)/$(src); /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin git rev-list --count HEAD)
# ksu_version: major * 10000 + git version + 200 for historical reasons
$(eval KSU_VERSION=$(shell expr 10000 + $(KSU_GIT_VERSION) + 200))
$(eval KSU_VERSION=12803)
$(info -- KernelSU-Next version: $(KSU_VERSION))
ccflags-y += -DKSU_VERSION=$(KSU_VERSION)
else # If there is no .git file, the default version will be passed.
$(warning "KSU_GIT_VERSION not defined! It is better to make KernelSU-Next a git submodule!")
ccflags-y += -DKSU_VERSION=16
endif
ifeq ($(shell grep -q " current_sid(void)" $(srctree)/security/selinux/include/objsec.h; echo $$?),0)
ccflags-y += -DKSU_COMPAT_HAS_CURRENT_SID
@@ -37,12 +28,24 @@ ifeq ($(shell grep -q "struct selinux_state " $(srctree)/security/selinux/includ
ccflags-y += -DKSU_COMPAT_HAS_SELINUX_STATE
endif
ifndef KSU_NEXT_EXPECTED_SIZE
KSU_NEXT_EXPECTED_SIZE := 0x3e6
ifeq ($(shell grep -q "strncpy_from_user_nofault" $(srctree)/include/linux/uaccess.h; echo $$?),0)
ccflags-y += -DKSU_STRNCPY_FROM_USER_NOFAULT
endif
ifndef KSU_NEXT_EXPECTED_HASH
KSU_NEXT_EXPECTED_HASH := 79e590113c4c4c0c222978e413a5faa801666957b1212a328e46c00c69821bf7
ifeq ($(shell grep -q "ssize_t kernel_read" $(srctree)/fs/read_write.c; echo $$?),0)
ccflags-y += -DKSU_KERNEL_READ
endif
ifeq ($(shell grep "ssize_t kernel_write" $(srctree)/fs/read_write.c | grep -q "const void" ; echo $$?),0)
ccflags-y += -DKSU_KERNEL_WRITE
endif
ifndef KSU_NEXT_MANAGER_SIZE
KSU_NEXT_MANAGER_SIZE := 0x3e6
endif
ifndef KSU_NEXT_MANAGER_HASH
KSU_NEXT_MANAGER_HASH := 79e590113c4c4c0c222978e413a5faa801666957b1212a328e46c00c69821bf7
endif
ifdef KSU_MANAGER_PACKAGE
@@ -50,48 +53,14 @@ ccflags-y += -DKSU_MANAGER_PACKAGE=\"$(KSU_MANAGER_PACKAGE)\"
$(info -- KernelSU-Next Manager package name: $(KSU_MANAGER_PACKAGE))
endif
$(info -- KernelSU-Next Manager signature size: $(KSU_NEXT_EXPECTED_SIZE))
$(info -- KernelSU-Next Manager signature hash: $(KSU_NEXT_EXPECTED_HASH))
$(info -- KernelSU-Next Manager signature size: $(KSU_NEXT_MANAGER_SIZE))
$(info -- KernelSU-Next Manager signature hash: $(KSU_NEXT_MANAGER_HASH))
ccflags-y += -DEXPECTED_NEXT_SIZE=$(KSU_NEXT_EXPECTED_SIZE)
ccflags-y += -DEXPECTED_NEXT_HASH=\"$(KSU_NEXT_EXPECTED_HASH)\"
ccflags-y += -DKSU_COMPAT_GET_CRED_RCU
ccflags-y += -DEXPECTED_MANAGER_SIZE=$(KSU_NEXT_MANAGER_SIZE)
ccflags-y += -DEXPECTED_MANAGER_HASH=\"$(KSU_NEXT_MANAGER_HASH)\"
ccflags-y += -DKSU_UMOUNT
# Determine the appropriate atomic function and apply patch accordingly
ifeq ($(shell grep -q "atomic_inc_not_zero" $(srctree)/kernel/cred.c; echo $$?),0)
ATOMIC_INC_FUNC = atomic_inc_not_zero
else ifeq ($(shell grep -q "atomic_long_inc_not_zero" $(srctree)/kernel/cred.c; echo $$?),0)
ATOMIC_INC_FUNC = atomic_long_inc_not_zero
else
$(info -- KSU_NEXT: Neither atomic_inc_not_zero nor atomic_long_inc_not_zero found in kernel/cred.c)
endif
# Inform which function is being patched
$(info -- KSU_NEXT: Using $(ATOMIC_INC_FUNC) in get_cred_rcu patch.)
# Add the get_cred_rcu function to cred.h if not already present
ifneq ($(shell grep -Eq "^static inline const struct cred \*get_cred_rcu" $(srctree)/include/linux/cred.h; echo $$?),0)
$(info -- KSU_NEXT: adding function 'static inline const struct cred *get_cred_rcu(const struct cred *cred);' to $(srctree)/include/linux/cred.h)
GET_CRED_RCU = static inline const struct cred *get_cred_rcu(const struct cred *cred)\n\
{\n\t\
struct cred *nonconst_cred = (struct cred *) cred;\n\t\
if (!cred)\n\t\t\
return NULL;\n\t\
if (!$(ATOMIC_INC_FUNC)(&nonconst_cred->usage))\n\t\t\
return NULL;\n\t\
validate_creds(cred);\n\t\
return cred;\n\
}\n
$(shell grep -qF "$(GET_CRED_RCU)" $(srctree)/include/linux/cred.h || sed -i '/^static inline void put_cred/i $(GET_CRED_RCU)' $(srctree)/include/linux/cred.h)
# Modify get_task_cred in cred.c
$(info -- KSU_NEXT: modifying 'get_task_cred' function in $(srctree)/kernel/cred.c)
$(shell sed -i "s/!$(ATOMIC_INC_FUNC)(&((struct cred \*)cred)->usage)/!get_cred_rcu(cred)/g" $(srctree)/kernel/cred.c)
endif
ifneq ($(shell grep -Eq "^static int can_umount" $(srctree)/fs/namespace.c; echo $$?),0)
$(info -- KSU_NEXT: adding function 'static int can_umount(const struct path *path, int flags);' to $(srctree)/fs/namespace.c)
CAN_UMOUNT = static int can_umount(const struct path *path, int flags)\n\
@@ -138,4 +107,81 @@ endif
ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat
ccflags-y += -Wno-declaration-after-statement -Wno-unused-function
## For non-gki compatiblity ##
ifeq ($(shell grep -q " current_sid(void)" $(srctree)/security/selinux/include/objsec.h; echo $$?),0)
ccflags-y += -DKSU_COMPAT_HAS_CURRENT_SID
endif
ifeq ($(shell grep -q "struct selinux_state " $(srctree)/security/selinux/include/security.h; echo $$?),0)
ccflags-y += -DKSU_COMPAT_HAS_SELINUX_STATE
endif
ccflags-y += -DKSU_UMOUNT
ifneq ($(shell grep -Eq "get_cred_rcu" $(srctree)/include/linux/cred.h; echo $$?),0)
$(info -- KSU_SUSFS: adding function 'static inline const struct cred *get_cred_rcu();' to $(srctree)/include/linux/cred.h)
GET_CRED_RCU = static inline const struct cred *get_cred_rcu(const struct cred *cred)\n\
{\n\t\
struct cred *nonconst_cred = (struct cred *) cred;\n\t\
if (!cred)\n\t\t\
return NULL;\n\t\
if (!atomic_inc_not_zero(&nonconst_cred->usage))\n\t\t\
return NULL;\n\t\
validate_creds(cred);\n\t\
return cred;\n\
}\n
$(shell sed -i '/^static inline void put_cred/i $(GET_CRED_RCU)' $(srctree)/include/linux/cred.h;)
endif
ifneq ($(shell grep -Eq "^static int can_umount" $(srctree)/fs/namespace.c; echo $$?),0)
$(info -- KSU_SUSFS: adding function 'static int can_umount(const struct path *path, int flags);' to $(srctree)/fs/namespace.c)
CAN_UMOUNT = static int can_umount(const struct path *path, int flags)\n\
{\n\t\
struct mount *mnt = real_mount(path->mnt);\n\t\
if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))\n\t\t\
return -EINVAL;\n\t\
if (!may_mount())\n\t\t\
return -EPERM;\n\t\
if (path->dentry != path->mnt->mnt_root)\n\t\t\
return -EINVAL;\n\t\
if (!check_mnt(mnt))\n\t\t\
return -EINVAL;\n\t\
if (mnt->mnt.mnt_flags & MNT_LOCKED)\n\t\t\
return -EINVAL;\n\t\
if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN))\n\t\t\
return -EPERM;\n\t\
return 0;\n\
}\n
$(shell sed -i '/^static bool is_mnt_ns_file/i $(CAN_UMOUNT)' $(srctree)/fs/namespace.c;)
endif
ifneq ($(shell grep -Eq "^int path_umount" $(srctree)/fs/namespace.c; echo $$?),0)
$(info -- KSU_SUSFS: adding function 'int path_umount(struct path *path, int flags);' to $(srctree)/fs/namespace.c)
PATH_UMOUNT = int path_umount(struct path *path, int flags)\n\
{\n\t\
struct mount *mnt = real_mount(path->mnt);\n\t\
int ret;\n\t\
ret = can_umount(path, flags);\n\t\
if (!ret)\n\t\t\
ret = do_umount(mnt, flags);\n\t\
dput(path->dentry);\n\t\
mntput_no_expire(mnt);\n\t\
return ret;\n\
}\n
$(shell sed -i '/^static bool is_mnt_ns_file/i $(PATH_UMOUNT)' $(srctree)/fs/namespace.c;)
endif
ifneq ($(shell grep -Eq "^int path_umount" $(srctree)/fs/internal.h; echo $$?),0)
$(shell sed -i '/^extern void __init mnt_init/a int path_umount(struct path *path, int flags);' $(srctree)/fs/internal.h;)
$(info -- KSU_SUSFS: adding 'int path_umount(struct path *path, int flags);' to $(srctree)/fs/internal.h)
endif
## For susfs stuff ##
ifeq ($(shell test -e $(srctree)/fs/susfs.c; echo $$?),0)
$(eval SUSFS_VERSION=$(shell cat $(srctree)/include/linux/susfs.h | grep -E '^#define SUSFS_VERSION' | cut -d' ' -f3 | sed 's/"//g'))
$(info )
$(info -- SUSFS_VERSION: $(SUSFS_VERSION))
else
$(info -- You have not integrate susfs in your kernel.)
$(info -- Read: https://gitlab.com/simonpunk/susfs4ksu)
endif
# Keep a new line here!! Because someone may append config

View File

@@ -1,3 +1,4 @@
#include <linux/capability.h>
#include <linux/compiler.h>
#include <linux/fs.h>
#include <linux/gfp.h>
@@ -64,12 +65,14 @@ static void remove_uid_from_arr(uid_t uid)
static void init_default_profiles()
{
kernel_cap_t full_cap = CAP_FULL_SET;
default_root_profile.uid = 0;
default_root_profile.gid = 0;
default_root_profile.groups_count = 1;
default_root_profile.groups[0] = 0;
memset(&default_root_profile.capabilities, 0xff,
sizeof(default_root_profile.capabilities));
memcpy(&default_root_profile.capabilities.effective, &full_cap,
sizeof(default_root_profile.capabilities.effective));
default_root_profile.namespaces = 0;
strcpy(default_root_profile.selinux_domain, KSU_DEFAULT_SELINUX_DOMAIN);
@@ -92,7 +95,7 @@ static uint8_t allow_list_bitmap[PAGE_SIZE] __read_mostly __aligned(PAGE_SIZE);
static struct work_struct ksu_save_work;
static struct work_struct ksu_load_work;
bool persistent_allow_list(void);
static bool persistent_allow_list(void);
void ksu_show_allow_list(void)
{
@@ -110,6 +113,7 @@ void ksu_show_allow_list(void)
static void ksu_grant_root_to_shell()
{
struct app_profile profile = {
.version = KSU_APP_PROFILE_VER,
.allow_su = true,
.current_uid = 2000,
};
@@ -152,11 +156,6 @@ static bool profile_valid(struct app_profile *profile)
return false;
}
if (forbid_system_uid(profile->current_uid)) {
pr_err("uid lower than 2000 is unsupported: %d\n", profile->current_uid);
return false;
}
if (profile->version < KSU_APP_PROFILE_VER) {
pr_info("Unsupported profile version: %d\n", profile->version);
return false;
@@ -267,7 +266,7 @@ bool __ksu_is_allow_uid(uid_t uid)
if (unlikely(uid == 0)) {
// already root, but only allow our domain.
return is_ksu_domain();
return ksu_is_ksu_domain();
}
if (forbid_system_uid(uid)) {
@@ -352,7 +351,7 @@ bool ksu_get_allow_list(int *array, int *length, bool allow)
return true;
}
void do_save_allow_list(struct work_struct *work)
static void do_save_allow_list(struct work_struct *work)
{
u32 magic = FILE_MAGIC;
u32 version = FILE_FORMAT_VERSION;
@@ -394,7 +393,7 @@ exit:
filp_close(fp, 0);
}
void do_load_allow_list(struct work_struct *work)
static void do_load_allow_list(struct work_struct *work)
{
loff_t off = 0;
ssize_t ret = 0;
@@ -484,7 +483,7 @@ void ksu_prune_allowlist(bool (*is_uid_valid)(uid_t, char *, void *), void *data
}
// make sure allow list works cross boot
bool persistent_allow_list(void)
static bool persistent_allow_list(void)
{
return ksu_queue_work(&ksu_save_work);
}

View File

@@ -3,10 +3,9 @@
#include <linux/gfp.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/version.h>
#ifdef CONFIG_KSU_DEBUG
#include <linux/moduleparam.h>
#endif
#include <crypto/hash.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
#include <crypto/sha2.h>
@@ -17,7 +16,10 @@
#include "apk_sign.h"
#include "klog.h" // IWYU pragma: keep
#include "kernel_compat.h"
#include "throne_tracker.h"
static unsigned int expected_manager_size = EXPECTED_MANAGER_SIZE;
static char expected_manager_hash[SHA256_DIGEST_SIZE * 2 + 1] = EXPECTED_MANAGER_HASH;
struct sdesc {
struct shash_desc shash;
@@ -312,9 +314,80 @@ static struct kernel_param_ops expected_size_ops = {
module_param_cb(ksu_debug_manager_uid, &expected_size_ops,
&ksu_debug_manager_uid, S_IRUSR | S_IWUSR);
#else
static int set_expected_size(const char *val, const struct kernel_param *kp)
{
int rv = param_set_uint(val, kp);
pr_info("expected_manager_size set to %u\n", expected_manager_size);
return rv;
}
static int get_expected_size(char *buf, const struct kernel_param *kp)
{
return snprintf(buf, PAGE_SIZE, "%u\n", expected_manager_size);
}
static int set_expected_hash(const char *val, const struct kernel_param *kp)
{
if (strlen(val) != SHA256_DIGEST_SIZE * 2) {
pr_err("Invalid hash length: %s\n", val);
return -EINVAL;
}
strncpy(expected_manager_hash, val, SHA256_DIGEST_SIZE * 2);
expected_manager_hash[SHA256_DIGEST_SIZE * 2] = '\0';
pr_info("expected_manager_hash set to %s\n", expected_manager_hash);
return 0;
}
static int get_expected_hash(char *buf, const struct kernel_param *kp)
{
return snprintf(buf, PAGE_SIZE, "%s\n", expected_manager_hash);
}
static struct kernel_param_ops expected_size_ops = {
.set = set_expected_size,
.get = get_expected_size,
};
static struct kernel_param_ops expected_hash_ops = {
.set = set_expected_hash,
.get = get_expected_hash,
};
module_param_cb(expected_manager_size, &expected_size_ops, &expected_manager_size, 0644);
module_param_cb(expected_manager_hash, &expected_hash_ops, &expected_manager_hash, 0644);
#endif
bool is_manager_apk(char *path)
bool ksu_is_manager_apk(char *path)
{
return check_v2_signature(path, EXPECTED_NEXT_SIZE, EXPECTED_NEXT_HASH);
}
int tries = 0;
while (tries++ < 10) {
if (!is_lock_held(path))
break;
pr_info("%s: waiting for %s\n", __func__, path);
msleep(100);
}
// let it go, if retry fails, check_v2_signature will fail to open it anyway
if (tries == 10) {
pr_info("%s: timeout for %s\n", __func__, path);
return false;
}
// set debug info to print size and hash to kernel log
pr_info("%s: expected size: %u, expected hash: %s\n",
path, expected_manager_size, expected_manager_hash);
#ifdef CONFIG_KSU_DEBUG
return check_v2_signature(path, EXPECTED_MANAGER_SIZE, EXPECTED_MANAGER_HASH);
#else
return check_v2_signature(path, expected_manager_size, expected_manager_hash);
#endif
}

View File

@@ -3,6 +3,6 @@
#include <linux/types.h>
bool is_manager_apk(char *path);
bool ksu_is_manager_apk(char *path);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -76,6 +76,16 @@ void ksu_android_ns_fs_check()
task_unlock(current);
}
int ksu_access_ok(const void *addr, unsigned long size) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0)
/* For kernels before 5.0.0, pass the type argument to access_ok. */
return access_ok(VERIFY_READ, addr, size);
#else
/* For kernels 5.0.0 and later, ignore the type argument. */
return access_ok(addr, size);
#endif
}
struct file *ksu_filp_open_compat(const char *filename, int flags, umode_t mode)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
@@ -107,7 +117,7 @@ struct file *ksu_filp_open_compat(const char *filename, int flags, umode_t mode)
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)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) || defined(KSU_KERNEL_READ)
return kernel_read(p, buf, count, pos);
#else
loff_t offset = pos ? *pos : 0;
@@ -122,7 +132,7 @@ ssize_t ksu_kernel_read_compat(struct file *p, void *buf, size_t count,
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)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) || defined(KSU_KERNEL_WRITE)
return kernel_write(p, buf, count, pos);
#else
loff_t offset = pos ? *pos : 0;
@@ -134,7 +144,7 @@ ssize_t ksu_kernel_write_compat(struct file *p, const void *buf, size_t count,
#endif
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) || defined(KSU_STRNCPY_FROM_USER_NOFAULT)
long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
long count)
{
@@ -173,3 +183,17 @@ long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
return ret;
}
#endif
long ksu_strncpy_from_user_retry(char *dst, const void __user *unsafe_addr,
long count)
{
long ret = ksu_strncpy_from_user_nofault(dst, unsafe_addr, count);
if (likely(ret >= 0))
return ret;
// we faulted! fallback to slow path
if (unlikely(!ksu_access_ok(unsafe_addr, count)))
return -EFAULT;
return strncpy_from_user(dst, unsafe_addr, count);
}

View File

@@ -23,12 +23,16 @@
extern long ksu_strncpy_from_user_nofault(char *dst,
const void __user *unsafe_addr,
long count);
extern long ksu_strncpy_from_user_retry(char *dst,
const void __user *unsafe_addr,
long count);
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
extern struct key *init_session_keyring;
#endif
extern void ksu_android_ns_fs_check();
extern int ksu_access_ok(const void *addr, unsigned long size);
extern struct file *ksu_filp_open_compat(const char *filename, int flags,
umode_t mode);
extern ssize_t ksu_kernel_read_compat(struct file *p, void *buf, size_t count,

View File

@@ -11,6 +11,10 @@
#include "ksu.h"
#include "throne_tracker.h"
#ifdef CONFIG_KSU_SUSFS
#include <linux/susfs.h>
#endif
static struct workqueue_struct *ksu_workqueue;
bool ksu_queue_work(struct work_struct *work)
@@ -37,7 +41,7 @@ extern void ksu_sucompat_exit();
extern void ksu_ksud_init();
extern void ksu_ksud_exit();
int __init kernelsu_init(void)
int __init ksu_kernelsu_init(void)
{
#ifdef CONFIG_KSU_DEBUG
pr_alert("*************************************************************");
@@ -49,6 +53,10 @@ int __init kernelsu_init(void)
pr_alert("*************************************************************");
#endif
#ifdef CONFIG_KSU_SUSFS
susfs_init();
#endif
ksu_core_init();
ksu_workqueue = alloc_ordered_workqueue("kernelsu_work_queue", 0);
@@ -57,7 +65,7 @@ int __init kernelsu_init(void)
ksu_throne_tracker_init();
#ifdef CONFIG_KPROBES
#ifdef CONFIG_KSU_KPROBES_HOOK
ksu_sucompat_init();
ksu_ksud_init();
#else
@@ -72,7 +80,7 @@ int __init kernelsu_init(void)
return 0;
}
void kernelsu_exit(void)
void ksu_kernelsu_exit(void)
{
ksu_allowlist_exit();
@@ -80,7 +88,7 @@ void kernelsu_exit(void)
destroy_workqueue(ksu_workqueue);
#ifdef CONFIG_KPROBES
#ifdef CONFIG_KSU_KPROBES_HOOK
ksu_ksud_exit();
ksu_sucompat_exit();
#endif
@@ -88,8 +96,8 @@ void kernelsu_exit(void)
ksu_core_exit();
}
module_init(kernelsu_init);
module_exit(kernelsu_exit);
module_init(ksu_kernelsu_init);
module_exit(ksu_kernelsu_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("weishu");

View File

@@ -21,6 +21,11 @@
#define CMD_SET_APP_PROFILE 11
#define CMD_UID_GRANTED_ROOT 12
#define CMD_UID_SHOULD_UMOUNT 13
#define CMD_IS_SU_ENABLED 14
#define CMD_ENABLE_SU 15
#define CMD_GET_MANAGER_UID 16
#define CMD_HOOK_MODE 0xC0DEAD1A
#define EVENT_POST_FS_DATA 1
#define EVENT_BOOT_COMPLETED 2

View File

@@ -54,7 +54,7 @@ static void stop_vfs_read_hook();
static void stop_execve_hook();
static void stop_input_hook();
#ifdef CONFIG_KPROBES
#ifdef CONFIG_KSU_KPROBES_HOOK
static struct work_struct stop_vfs_read_work;
static struct work_struct stop_execve_hook_work;
static struct work_struct stop_input_hook_work;
@@ -64,17 +64,25 @@ bool ksu_execveat_hook __read_mostly = true;
bool ksu_input_hook __read_mostly = true;
#endif
#ifdef CONFIG_KSU_SUSFS_SUS_SU
bool susfs_is_sus_su_ready = false;
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_SU
u32 ksu_devpts_sid;
void on_post_fs_data(void)
#ifdef CONFIG_COMPAT
bool ksu_is_compat __read_mostly = false;
#endif
void ksu_on_post_fs_data(void)
{
static bool done = false;
if (done) {
pr_info("on_post_fs_data already done\n");
pr_info("ksu_on_post_fs_data already done\n");
return;
}
done = true;
pr_info("on_post_fs_data!\n");
pr_info("ksu_on_post_fs_data!\n");
ksu_load_allow_list();
// sanity check, this may influence the performance
stop_input_hook();
@@ -107,6 +115,7 @@ static const char __user *get_user_arg_ptr(struct user_arg_ptr argv, int nr)
if (get_user(compat, argv.ptr.compat + nr))
return ERR_PTR(-EFAULT);
ksu_is_compat = true;
return compat_ptr(compat);
}
#endif
@@ -157,7 +166,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
struct user_arg_ptr *argv,
struct user_arg_ptr *envp, int *flags)
{
#ifndef CONFIG_KPROBES
#ifndef CONFIG_KSU_KPROBES_HOOK
if (!ksu_execveat_hook) {
return 0;
}
@@ -191,13 +200,13 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
const char __user *p = get_user_arg_ptr(*argv, 1);
if (p && !IS_ERR(p)) {
char first_arg[16];
ksu_strncpy_from_user_nofault(
ksu_strncpy_from_user_retry(
first_arg, p, sizeof(first_arg));
pr_info("/system/bin/init first arg: %s\n",
first_arg);
if (!strcmp(first_arg, "second_stage")) {
pr_info("/system/bin/init second_stage executed\n");
apply_kernelsu_rules();
ksu_apply_kernelsu_rules();
init_second_stage_executed = true;
ksu_android_ns_fs_check();
}
@@ -216,12 +225,12 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
const char __user *p = get_user_arg_ptr(*argv, 1);
if (p && !IS_ERR(p)) {
char first_arg[16];
ksu_strncpy_from_user_nofault(
ksu_strncpy_from_user_retry(
first_arg, p, sizeof(first_arg));
pr_info("/init first arg: %s\n", first_arg);
if (!strcmp(first_arg, "--second-stage")) {
pr_info("/init second_stage executed\n");
apply_kernelsu_rules();
ksu_apply_kernelsu_rules();
init_second_stage_executed = true;
ksu_android_ns_fs_check();
}
@@ -241,7 +250,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
}
char env[256];
// Reading environment variable strings from user space
if (ksu_strncpy_from_user_nofault(
if (ksu_strncpy_from_user_retry(
env, p, sizeof(env)) < 0)
continue;
// Parsing environment variable names and values
@@ -258,7 +267,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
(!strcmp(env_value, "1") ||
!strcmp(env_value, "true"))) {
pr_info("/init second_stage executed\n");
apply_kernelsu_rules();
ksu_apply_kernelsu_rules();
init_second_stage_executed =
true;
ksu_android_ns_fs_check();
@@ -273,7 +282,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
first_app_process = false;
pr_info("exec app_process, /data prepared, second_stage: %d\n",
init_second_stage_executed);
on_post_fs_data(); // we keep this for old ksud
ksu_on_post_fs_data(); // we keep this for old ksud
stop_execve_hook();
}
@@ -313,7 +322,7 @@ static ssize_t read_iter_proxy(struct kiocb *iocb, struct iov_iter *to)
int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
size_t *count_ptr, loff_t **pos)
{
#ifndef CONFIG_KPROBES
#ifndef CONFIG_KSU_KPROBES_HOOK
if (!ksu_vfs_read_hook) {
return 0;
}
@@ -332,7 +341,7 @@ int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
return 0;
}
if (!d_is_reg(file->f_path.dentry)) {
if (!S_ISREG(file->f_path.dentry->d_inode->i_mode)) {
return 0;
}
@@ -390,10 +399,12 @@ int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
if (orig_read) {
fops_proxy.read = read_proxy;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
orig_read_iter = file->f_op->read_iter;
if (orig_read_iter) {
fops_proxy.read_iter = read_iter_proxy;
}
#endif
// replace the file_operations
file->f_op = &fops_proxy;
read_count_append = rc_count;
@@ -426,7 +437,7 @@ static bool is_volumedown_enough(unsigned int count)
int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code,
int *value)
{
#ifndef CONFIG_KPROBES
#ifndef CONFIG_KSU_KPROBES_HOOK
if (!ksu_input_hook) {
return 0;
}
@@ -468,7 +479,39 @@ bool ksu_is_safe_mode()
return false;
}
#ifdef CONFIG_KPROBES
/*
* ksu_handle_execve_ksud, execve_ksud handler for non kprobe
* adapted from sys_execve_handler_pre
* https://github.com/tiann/KernelSU/commit/2027ac3
*/
__maybe_unused int ksu_handle_execve_ksud(const char __user *filename_user,
const char __user *const __user *__argv)
{
struct user_arg_ptr argv = { .ptr.native = __argv };
struct filename filename_in, *filename_p;
char path[32];
#ifndef CONFIG_KSU_KPROBES_HOOK
// return early if disabled.
if (!ksu_execveat_hook) {
return 0;
}
#endif
if (!filename_user)
return 0;
memset(path, 0, sizeof(path));
ksu_strncpy_from_user_nofault(path, filename_user, 32);
// this is because ksu_handle_execveat_ksud calls it filename->name
filename_in.name = path;
filename_p = &filename_in;
return ksu_handle_execveat_ksud(AT_FDCWD, &filename_p, &argv, NULL, NULL);
}
#ifdef CONFIG_KSU_KPROBES_HOOK
// 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)
@@ -596,9 +639,32 @@ static void do_stop_input_hook(struct work_struct *work)
}
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
#include "objsec.h" // task_security_struct
bool is_ksu_transition(const struct task_security_struct *old_tsec,
const struct task_security_struct *new_tsec)
{
static u32 ksu_sid;
char *secdata;
u32 seclen;
bool allowed = false;
if (!ksu_sid)
security_secctx_to_secid("u:r:su:s0", strlen("u:r:su:s0"), &ksu_sid);
if (security_secid_to_secctx(old_tsec->sid, &secdata, &seclen))
return false;
allowed = (!strcmp("u:r:init:s0", secdata) && new_tsec->sid == ksu_sid);
security_release_secctx(secdata, seclen);
return allowed;
}
#endif
static void stop_vfs_read_hook()
{
#ifdef CONFIG_KPROBES
#ifdef CONFIG_KSU_KPROBES_HOOK
bool ret = schedule_work(&stop_vfs_read_work);
pr_info("unregister vfs_read kprobe: %d!\n", ret);
#else
@@ -609,26 +675,31 @@ static void stop_vfs_read_hook()
static void stop_execve_hook()
{
#ifdef CONFIG_KPROBES
#ifdef CONFIG_KSU_KPROBES_HOOK
bool ret = schedule_work(&stop_execve_hook_work);
pr_info("unregister execve kprobe: %d!\n", ret);
#else
ksu_execveat_hook = false;
pr_info("stop execve_hook\n");
#endif
#ifdef CONFIG_KSU_SUSFS_SUS_SU
susfs_is_sus_su_ready = true;
pr_info("susfs: sus_su is ready\n");
#endif
}
static void stop_input_hook()
{
#ifdef CONFIG_KSU_KPROBES_HOOK
static bool input_hook_stopped = false;
if (input_hook_stopped) {
return;
}
input_hook_stopped = true;
#ifdef CONFIG_KPROBES
bool ret = schedule_work(&stop_input_hook_work);
pr_info("unregister input kprobe: %d!\n", ret);
#else
if (!ksu_input_hook) { return; }
ksu_input_hook = false;
pr_info("stop input_hook\n");
#endif
@@ -637,7 +708,7 @@ static void stop_input_hook()
// ksud: module support
void ksu_ksud_init()
{
#ifdef CONFIG_KPROBES
#ifdef CONFIG_KSU_KPROBES_HOOK
int ret;
ret = register_kprobe(&execve_kp);
@@ -657,10 +728,10 @@ void ksu_ksud_init()
void ksu_ksud_exit()
{
#ifdef CONFIG_KPROBES
#ifdef CONFIG_KSU_KPROBES_HOOK
unregister_kprobe(&execve_kp);
// this should be done before unregister vfs_read_kp
// unregister_kprobe(&vfs_read_kp);
unregister_kprobe(&input_event_kp);
#endif
}
}

View File

@@ -5,7 +5,7 @@
#define KSUD_PATH "/data/adb/ksud"
void on_post_fs_data(void);
void ksu_on_post_fs_data(void);
bool ksu_is_safe_mode(void);

View File

@@ -13,7 +13,7 @@ static inline bool ksu_is_manager_uid_valid()
return ksu_manager_uid != KSU_INVALID_UID;
}
static inline bool is_manager()
static inline bool ksu_is_manager()
{
return unlikely(ksu_manager_uid == current_uid().val);
}

View File

@@ -36,14 +36,19 @@ static struct policydb *get_policydb(void)
return db;
}
void apply_kernelsu_rules()
static DEFINE_MUTEX(ksu_rules);
void ksu_apply_kernelsu_rules()
{
if (!getenforce()) {
struct policydb *db;
if (!ksu_getenforce()) {
pr_info("SELinux permissive or disabled, apply rules!\n");
}
rcu_read_lock();
struct policydb *db = get_policydb();
mutex_lock(&ksu_rules);
db = get_policydb();
ksu_permissive(db, KERNEL_SU_DOMAIN);
ksu_typeattribute(db, KERNEL_SU_DOMAIN, "mlstrustedsubject");
@@ -130,11 +135,19 @@ void apply_kernelsu_rules()
// Allow all binder transactions
ksu_allow(db, ALL, KERNEL_SU_DOMAIN, "binder", ALL);
// Allow system server kill su process
ksu_allow(db, "system_server", KERNEL_SU_DOMAIN, "process", "getpgid");
ksu_allow(db, "system_server", KERNEL_SU_DOMAIN, "process", "sigkill");
// Allow system server kill su process
ksu_allow(db, "system_server", KERNEL_SU_DOMAIN, "process", "getpgid");
ksu_allow(db, "system_server", KERNEL_SU_DOMAIN, "process", "sigkill");
rcu_read_unlock();
#ifdef CONFIG_KSU_SUSFS
// Allow umount in zygote process without installing zygisk
ksu_allow(db, "zygote", "labeledfs", "filesystem", "unmount");
susfs_set_init_sid();
susfs_set_ksu_sid();
susfs_set_zygote_sid();
#endif
mutex_unlock(&ksu_rules);
}
#define MAX_SEPOL_LEN 128
@@ -149,17 +162,45 @@ void apply_kernelsu_rules()
#define CMD_TYPE_CHANGE 8
#define CMD_GENFSCON 9
#ifdef CONFIG_64BIT
struct sepol_data {
u32 cmd;
u32 subcmd;
char __user *sepol1;
char __user *sepol2;
char __user *sepol3;
char __user *sepol4;
char __user *sepol5;
char __user *sepol6;
char __user *sepol7;
u64 field_sepol1;
u64 field_sepol2;
u64 field_sepol3;
u64 field_sepol4;
u64 field_sepol5;
u64 field_sepol6;
u64 field_sepol7;
};
#ifdef CONFIG_COMPAT
extern bool ksu_is_compat __read_mostly;
struct sepol_compat_data {
u32 cmd;
u32 subcmd;
u32 field_sepol1;
u32 field_sepol2;
u32 field_sepol3;
u32 field_sepol4;
u32 field_sepol5;
u32 field_sepol6;
u32 field_sepol7;
};
#endif // CONFIG_COMPAT
#else
struct sepol_data {
u32 cmd;
u32 subcmd;
u32 field_sepol1;
u32 field_sepol2;
u32 field_sepol3;
u32 field_sepol4;
u32 field_sepol5;
u32 field_sepol6;
u32 field_sepol7;
};
#endif // CONFIG_64BIT
static int get_object(char *buf, char __user *user_object, size_t buf_sz,
char **object)
@@ -195,24 +236,68 @@ static void reset_avc_cache()
selinux_xfrm_notify_policyload();
}
int handle_sepolicy(unsigned long arg3, void __user *arg4)
int ksu_handle_sepolicy(unsigned long arg3, void __user *arg4)
{
if (!arg4) {
return -1;
}
if (!getenforce()) {
if (!ksu_getenforce()) {
pr_info("SELinux permissive or disabled when handle policy!\n");
}
u32 cmd, subcmd;
char __user *sepol1, *sepol2, *sepol3, *sepol4, *sepol5, *sepol6, *sepol7;
#if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT)
if (unlikely(ksu_is_compat)) {
struct sepol_compat_data compat_data;
if (copy_from_user(&compat_data, arg4, sizeof(struct sepol_compat_data))) {
pr_err("sepol: copy sepol_data failed.\n");
return -1;
}
sepol1 = compat_ptr(compat_data.field_sepol1);
sepol2 = compat_ptr(compat_data.field_sepol2);
sepol3 = compat_ptr(compat_data.field_sepol3);
sepol4 = compat_ptr(compat_data.field_sepol4);
sepol5 = compat_ptr(compat_data.field_sepol5);
sepol6 = compat_ptr(compat_data.field_sepol6);
sepol7 = compat_ptr(compat_data.field_sepol7);
cmd = compat_data.cmd;
subcmd = compat_data.subcmd;
} else {
struct sepol_data data;
if (copy_from_user(&data, arg4, sizeof(struct sepol_data))) {
pr_err("sepol: copy sepol_data failed.\n");
return -1;
}
sepol1 = data.field_sepol1;
sepol2 = data.field_sepol2;
sepol3 = data.field_sepol3;
sepol4 = data.field_sepol4;
sepol5 = data.field_sepol5;
sepol6 = data.field_sepol6;
sepol7 = data.field_sepol7;
cmd = data.cmd;
subcmd = data.subcmd;
}
#else
// basically for full native, say (64BIT=y COMPAT=n) || (64BIT=n)
struct sepol_data data;
if (copy_from_user(&data, arg4, sizeof(struct sepol_data))) {
pr_err("sepol: copy sepol_data failed.\n");
return -1;
}
u32 cmd = data.cmd;
u32 subcmd = data.subcmd;
sepol1 = data.field_sepol1;
sepol2 = data.field_sepol2;
sepol3 = data.field_sepol3;
sepol4 = data.field_sepol4;
sepol5 = data.field_sepol5;
sepol6 = data.field_sepol6;
sepol7 = data.field_sepol7;
cmd = data.cmd;
subcmd = data.subcmd;
#endif
rcu_read_lock();
@@ -226,22 +311,22 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
char perm_buf[MAX_SEPOL_LEN];
char *s, *t, *c, *p;
if (get_object(src_buf, data.sepol1, sizeof(src_buf), &s) < 0) {
if (get_object(src_buf, sepol1, sizeof(src_buf), &s) < 0) {
pr_err("sepol: copy src failed.\n");
goto exit;
}
if (get_object(tgt_buf, data.sepol2, sizeof(tgt_buf), &t) < 0) {
if (get_object(tgt_buf, sepol2, sizeof(tgt_buf), &t) < 0) {
pr_err("sepol: copy tgt failed.\n");
goto exit;
}
if (get_object(cls_buf, data.sepol3, sizeof(cls_buf), &c) < 0) {
if (get_object(cls_buf, sepol3, sizeof(cls_buf), &c) < 0) {
pr_err("sepol: copy cls failed.\n");
goto exit;
}
if (get_object(perm_buf, data.sepol4, sizeof(perm_buf), &p) <
if (get_object(perm_buf, sepol4, sizeof(perm_buf), &p) <
0) {
pr_err("sepol: copy perm failed.\n");
goto exit;
@@ -271,24 +356,24 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
char perm_set[MAX_SEPOL_LEN];
char *s, *t, *c;
if (get_object(src_buf, data.sepol1, sizeof(src_buf), &s) < 0) {
if (get_object(src_buf, sepol1, sizeof(src_buf), &s) < 0) {
pr_err("sepol: copy src failed.\n");
goto exit;
}
if (get_object(tgt_buf, data.sepol2, sizeof(tgt_buf), &t) < 0) {
if (get_object(tgt_buf, sepol2, sizeof(tgt_buf), &t) < 0) {
pr_err("sepol: copy tgt failed.\n");
goto exit;
}
if (get_object(cls_buf, data.sepol3, sizeof(cls_buf), &c) < 0) {
if (get_object(cls_buf, sepol3, sizeof(cls_buf), &c) < 0) {
pr_err("sepol: copy cls failed.\n");
goto exit;
}
if (strncpy_from_user(operation, data.sepol4,
if (strncpy_from_user(operation, sepol4,
sizeof(operation)) < 0) {
pr_err("sepol: copy operation failed.\n");
goto exit;
}
if (strncpy_from_user(perm_set, data.sepol5, sizeof(perm_set)) <
if (strncpy_from_user(perm_set, sepol5, sizeof(perm_set)) <
0) {
pr_err("sepol: copy perm_set failed.\n");
goto exit;
@@ -308,7 +393,7 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
} else if (cmd == CMD_TYPE_STATE) {
char src[MAX_SEPOL_LEN];
if (strncpy_from_user(src, data.sepol1, sizeof(src)) < 0) {
if (strncpy_from_user(src, sepol1, sizeof(src)) < 0) {
pr_err("sepol: copy src failed.\n");
goto exit;
}
@@ -328,11 +413,11 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
char type[MAX_SEPOL_LEN];
char attr[MAX_SEPOL_LEN];
if (strncpy_from_user(type, data.sepol1, sizeof(type)) < 0) {
if (strncpy_from_user(type, sepol1, sizeof(type)) < 0) {
pr_err("sepol: copy type failed.\n");
goto exit;
}
if (strncpy_from_user(attr, data.sepol2, sizeof(attr)) < 0) {
if (strncpy_from_user(attr, sepol2, sizeof(attr)) < 0) {
pr_err("sepol: copy attr failed.\n");
goto exit;
}
@@ -352,7 +437,7 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
} else if (cmd == CMD_ATTR) {
char attr[MAX_SEPOL_LEN];
if (strncpy_from_user(attr, data.sepol1, sizeof(attr)) < 0) {
if (strncpy_from_user(attr, sepol1, sizeof(attr)) < 0) {
pr_err("sepol: copy attr failed.\n");
goto exit;
}
@@ -369,28 +454,28 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
char default_type[MAX_SEPOL_LEN];
char object[MAX_SEPOL_LEN];
if (strncpy_from_user(src, data.sepol1, sizeof(src)) < 0) {
if (strncpy_from_user(src, sepol1, sizeof(src)) < 0) {
pr_err("sepol: copy src failed.\n");
goto exit;
}
if (strncpy_from_user(tgt, data.sepol2, sizeof(tgt)) < 0) {
if (strncpy_from_user(tgt, sepol2, sizeof(tgt)) < 0) {
pr_err("sepol: copy tgt failed.\n");
goto exit;
}
if (strncpy_from_user(cls, data.sepol3, sizeof(cls)) < 0) {
if (strncpy_from_user(cls, sepol3, sizeof(cls)) < 0) {
pr_err("sepol: copy cls failed.\n");
goto exit;
}
if (strncpy_from_user(default_type, data.sepol4,
if (strncpy_from_user(default_type, sepol4,
sizeof(default_type)) < 0) {
pr_err("sepol: copy default_type failed.\n");
goto exit;
}
char *real_object;
if (data.sepol5 == NULL) {
if (sepol5 == NULL) {
real_object = NULL;
} else {
if (strncpy_from_user(object, data.sepol5,
if (strncpy_from_user(object, sepol5,
sizeof(object)) < 0) {
pr_err("sepol: copy object failed.\n");
goto exit;
@@ -409,19 +494,19 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
char cls[MAX_SEPOL_LEN];
char default_type[MAX_SEPOL_LEN];
if (strncpy_from_user(src, data.sepol1, sizeof(src)) < 0) {
if (strncpy_from_user(src, sepol1, sizeof(src)) < 0) {
pr_err("sepol: copy src failed.\n");
goto exit;
}
if (strncpy_from_user(tgt, data.sepol2, sizeof(tgt)) < 0) {
if (strncpy_from_user(tgt, sepol2, sizeof(tgt)) < 0) {
pr_err("sepol: copy tgt failed.\n");
goto exit;
}
if (strncpy_from_user(cls, data.sepol3, sizeof(cls)) < 0) {
if (strncpy_from_user(cls, sepol3, sizeof(cls)) < 0) {
pr_err("sepol: copy cls failed.\n");
goto exit;
}
if (strncpy_from_user(default_type, data.sepol4,
if (strncpy_from_user(default_type, sepol4,
sizeof(default_type)) < 0) {
pr_err("sepol: copy default_type failed.\n");
goto exit;
@@ -442,15 +527,15 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
char name[MAX_SEPOL_LEN];
char path[MAX_SEPOL_LEN];
char context[MAX_SEPOL_LEN];
if (strncpy_from_user(name, data.sepol1, sizeof(name)) < 0) {
if (strncpy_from_user(name, sepol1, sizeof(name)) < 0) {
pr_err("sepol: copy name failed.\n");
goto exit;
}
if (strncpy_from_user(path, data.sepol2, sizeof(path)) < 0) {
if (strncpy_from_user(path, sepol2, sizeof(path)) < 0) {
pr_err("sepol: copy path failed.\n");
goto exit;
}
if (strncpy_from_user(context, data.sepol3, sizeof(context)) <
if (strncpy_from_user(context, sepol3, sizeof(context)) <
0) {
pr_err("sepol: copy context failed.\n");
goto exit;

View File

@@ -8,6 +8,14 @@
#define KERNEL_SU_DOMAIN "u:r:su:s0"
#ifdef CONFIG_KSU_SUSFS
#define KERNEL_INIT_DOMAIN "u:r:init:s0"
#define KERNEL_ZYGOTE_DOMAIN "u:r:zygote:s0"
u32 susfs_ksu_sid = 0;
u32 susfs_init_sid = 0;
u32 susfs_zygote_sid = 0;
#endif
static int transive_to_domain(const char *domain)
{
struct cred *cred;
@@ -37,7 +45,7 @@ static int transive_to_domain(const char *domain)
return error;
}
void setup_selinux(const char *domain)
void ksu_setup_selinux(const char *domain)
{
if (transive_to_domain(domain)) {
pr_err("transive domain failed.\n");
@@ -52,7 +60,7 @@ if (!is_domain_permissive) {
}*/
}
void setenforce(bool enforce)
void ksu_setenforce(bool enforce)
{
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
#ifdef KSU_COMPAT_USE_SELINUX_STATE
@@ -63,7 +71,7 @@ void setenforce(bool enforce)
#endif
}
bool getenforce()
bool ksu_getenforce()
{
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
#ifdef KSU_COMPAT_USE_SELINUX_STATE
@@ -99,7 +107,7 @@ static inline u32 current_sid(void)
}
#endif
bool is_ksu_domain()
bool ksu_is_ksu_domain()
{
char *domain;
u32 seclen;
@@ -113,7 +121,7 @@ bool is_ksu_domain()
return result;
}
bool is_zygote(void *sec)
bool ksu_is_zygote(void *sec)
{
struct task_security_struct *tsec = (struct task_security_struct *)sec;
if (!tsec) {
@@ -131,6 +139,83 @@ bool is_zygote(void *sec)
return result;
}
#ifdef CONFIG_KSU_SUSFS
static inline void susfs_set_sid(const char *secctx_name, u32 *out_sid)
{
int err;
if (!secctx_name || !out_sid) {
pr_err("secctx_name || out_sid is NULL\n");
return;
}
err = security_secctx_to_secid(secctx_name, strlen(secctx_name),
out_sid);
if (err) {
pr_err("failed setting sid for '%s', err: %d\n", secctx_name, err);
return;
}
pr_info("sid '%u' is set for secctx_name '%s'\n", *out_sid, secctx_name);
}
bool susfs_is_sid_equal(void *sec, u32 sid2) {
struct task_security_struct *tsec = (struct task_security_struct *)sec;
if (!tsec) {
return false;
}
return tsec->sid == sid2;
}
u32 susfs_get_sid_from_name(const char *secctx_name)
{
u32 out_sid = 0;
int err;
if (!secctx_name) {
pr_err("secctx_name is NULL\n");
return 0;
}
err = security_secctx_to_secid(secctx_name, strlen(secctx_name),
&out_sid);
if (err) {
pr_err("failed getting sid from secctx_name: %s, err: %d\n", secctx_name, err);
return 0;
}
return out_sid;
}
u32 susfs_get_current_sid(void) {
return current_sid();
}
void susfs_set_zygote_sid(void)
{
susfs_set_sid(KERNEL_ZYGOTE_DOMAIN, &susfs_zygote_sid);
}
bool susfs_is_current_zygote_domain(void) {
return unlikely(current_sid() == susfs_zygote_sid);
}
void susfs_set_ksu_sid(void)
{
susfs_set_sid(KERNEL_SU_DOMAIN, &susfs_ksu_sid);
}
bool susfs_is_current_ksu_domain(void) {
return unlikely(current_sid() == susfs_ksu_sid);
}
void susfs_set_init_sid(void)
{
susfs_set_sid(KERNEL_INIT_DOMAIN, &susfs_init_sid);
}
bool susfs_is_current_init_domain(void) {
return unlikely(current_sid() == susfs_init_sid);
}
#endif
#define DEVPTS_DOMAIN "u:object_r:ksu_file:s0"
u32 ksu_get_devpts_sid()

View File

@@ -8,17 +8,29 @@
#define KSU_COMPAT_USE_SELINUX_STATE
#endif
void setup_selinux(const char *);
void ksu_setup_selinux(const char *);
void setenforce(bool);
void ksu_setenforce(bool);
bool getenforce();
bool ksu_getenforce();
bool is_ksu_domain();
bool ksu_is_ksu_domain();
bool is_zygote(void *cred);
bool ksu_is_zygote(void *cred);
void apply_kernelsu_rules();
void ksu_apply_kernelsu_rules();
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
bool susfs_is_sid_equal(void *sec, u32 sid2);
u32 susfs_get_sid_from_name(const char *secctx_name);
u32 susfs_get_current_sid(void);
void susfs_set_zygote_sid(void);
bool susfs_is_current_zygote_domain(void);
void susfs_set_ksu_sid(void);
bool susfs_is_current_ksu_domain(void);
void susfs_set_init_sid(void);
bool susfs_is_current_init_domain(void);
#endif
u32 ksu_get_devpts_sid();

View File

@@ -39,11 +39,11 @@ perform_cleanup() {
# Sets up or update KernelSU-Next environment
setup_kernelsu() {
echo "[+] Setting up KernelSU-Next..."
test -d "$GKI_ROOT/KernelSU-Next" || git clone https://github.com/rifsxd/KernelSU-Next && echo "[+] Repository cloned."
test -d "$GKI_ROOT/KernelSU-Next" || git clone https://github.com/KernelSU-Next/KernelSU-Next && echo "[+] Repository cloned."
cd "$GKI_ROOT/KernelSU-Next"
git stash && echo "[-] Stashed current changes."
if [ "$(git status | grep -Po 'v\d+(\.\d+)*' | head -n1)" ]; then
git checkout next && echo "[-] Switched to next branch."
git checkout next-susfs-a13-5.15-dev && echo "[-] Switched to next-susfs-a13-5.15-dev branch."
fi
git pull && echo "[+] Repository updated."
if [ -z "${1-}" ]; then

View File

@@ -13,6 +13,9 @@
#else
#include <linux/sched.h>
#endif
#ifdef CONFIG_KSU_SUSFS_SUS_SU
#include <linux/susfs_def.h>
#endif
#include "objsec.h"
#include "allowlist.h"
@@ -24,9 +27,17 @@
#define SU_PATH "/system/bin/su"
#define SH_PATH "/system/bin/sh"
extern void escape_to_root();
#ifndef CONFIG_KSU_KPROBES_HOOK
static bool ksu_sucompat_non_kp __read_mostly = true;
#endif
static void __user *userspace_stack_buffer(const void *d, size_t len)
extern void ksu_escape_to_root();
static const char sh_path[] = "/system/bin/sh";
static const char ksud_path[] = KSUD_PATH;
static const char su[] = SU_PATH;
static inline 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. */
@@ -35,31 +46,37 @@ static void __user *userspace_stack_buffer(const void *d, size_t len)
return copy_to_user(p, d, len) ? NULL : p;
}
static char __user *sh_user_path(void)
static inline char __user *sh_user_path(void)
{
static const char sh_path[] = "/system/bin/sh";
return userspace_stack_buffer(sh_path, sizeof(sh_path));
}
static char __user *ksud_user_path(void)
static inline char __user *ksud_user_path(void)
{
static const char ksud_path[] = KSUD_PATH;
return userspace_stack_buffer(ksud_path, sizeof(ksud_path));
}
int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
int *__unused_flags)
{
const char su[] = SU_PATH;
if (!ksu_is_allow_uid(current_uid().val)) {
#ifndef CONFIG_KSU_KPROBES_HOOK
if (!ksu_sucompat_non_kp) {
return 0;
}
#endif
#ifndef CONFIG_KSU_SUSFS_SUS_SU
if (!ksu_is_allow_uid(current_uid().val)) {
return 0;
}
#endif
#ifdef CONFIG_KSU_SUSFS_SUS_SU
char path[sizeof(su)] = {0};
#else
char path[sizeof(su) + 1];
memset(path, 0, sizeof(path));
#endif
ksu_strncpy_from_user_nofault(path, *filename_user, sizeof(path));
if (unlikely(!memcmp(path, su, sizeof(su)))) {
@@ -70,21 +87,49 @@ int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
return 0;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) && defined(CONFIG_KSU_SUSFS_SUS_SU)
struct filename* susfs_ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags) {
struct filename *name = getname_flags(*filename_user, getname_statx_lookup_flags(*flags), NULL);
if (unlikely(IS_ERR(name) || name->name == NULL)) {
return name;
}
if (likely(memcmp(name->name, su, sizeof(su)))) {
return name;
}
const char sh[] = SH_PATH;
pr_info("vfs_fstatat su->sh!\n");
memcpy((void *)name->name, sh, sizeof(sh));
return name;
}
#endif
int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags)
{
// const char sh[] = SH_PATH;
const char su[] = SU_PATH;
#ifndef CONFIG_KSU_KPROBES_HOOK
if (!ksu_sucompat_non_kp){
return 0;
}
#endif
#ifndef CONFIG_KSU_SUSFS_SUS_SU
if (!ksu_is_allow_uid(current_uid().val)) {
return 0;
}
#endif
if (unlikely(!filename_user)) {
return 0;
}
#ifdef CONFIG_KSU_SUSFS_SUS_SU
char path[sizeof(su)] = {0};
#else
char path[sizeof(su) + 1];
memset(path, 0, sizeof(path));
#endif
// Remove this later!! we use syscall hook, so this will never happen!!!!!
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) && 0
// it becomes a `struct filename *` after 5.18
@@ -116,8 +161,12 @@ int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
int *__never_use_flags)
{
struct filename *filename;
const char sh[] = KSUD_PATH;
const char su[] = SU_PATH;
#ifndef CONFIG_KSU_KPROBES_HOOK
if (!ksu_sucompat_non_kp) {
return 0;
}
#endif
if (unlikely(!filename_ptr))
return 0;
@@ -130,13 +179,15 @@ int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
if (likely(memcmp(filename->name, su, sizeof(su))))
return 0;
#ifndef CONFIG_KSU_SUSFS_SUS_SU
if (!ksu_is_allow_uid(current_uid().val))
return 0;
#endif
pr_info("do_execveat_common su found\n");
memcpy((void *)filename->name, sh, sizeof(sh));
memcpy((void *)filename->name, ksud_path, sizeof(ksud_path));
escape_to_root();
ksu_escape_to_root();
return 0;
}
@@ -145,14 +196,23 @@ int ksu_handle_execve_sucompat(int *fd, const char __user **filename_user,
void *__never_use_argv, void *__never_use_envp,
int *__never_use_flags)
{
const char su[] = SU_PATH;
#ifdef CONFIG_KSU_SUSFS_SUS_SU
char path[sizeof(su)] = {0};
#else
char path[sizeof(su) + 1];
#endif
#ifndef CONFIG_KSU_KPROBES_HOOK
if (!ksu_sucompat_non_kp) {
return 0;
}
#endif
if (unlikely(!filename_user))
return 0;
memset(path, 0, sizeof(path));
ksu_strncpy_from_user_nofault(path, *filename_user, sizeof(path));
ksu_strncpy_from_user_retry(path, *filename_user, sizeof(path));
if (likely(memcmp(path, su, sizeof(su))))
return 0;
@@ -163,13 +223,19 @@ int ksu_handle_execve_sucompat(int *fd, const char __user **filename_user,
pr_info("sys_execve su found\n");
*filename_user = ksud_user_path();
escape_to_root();
ksu_escape_to_root();
return 0;
}
int ksu_handle_devpts(struct inode *inode)
{
#ifndef CONFIG_KSU_KPROBES_HOOK
if (!ksu_sucompat_non_kp) {
return 0;
}
#endif
if (!current->mm) {
return 0;
}
@@ -198,21 +264,9 @@ int ksu_handle_devpts(struct inode *inode)
return 0;
}
#ifdef CONFIG_KPROBES
#ifdef CONFIG_KSU_KPROBES_HOOK
__maybe_unused static int faccessat_handler_pre(struct kprobe *p,
struct pt_regs *regs)
{
int *dfd = (int *)&PT_REGS_PARM1(regs);
const char __user **filename_user = (const char **)&PT_REGS_PARM2(regs);
int *mode = (int *)&PT_REGS_PARM3(regs);
// Both sys_ and do_ is C function
int *flags = (int *)&PT_REGS_CCALL_PARM4(regs);
return ksu_handle_faccessat(dfd, filename_user, mode, flags);
}
static int sys_faccessat_handler_pre(struct kprobe *p, struct pt_regs *regs)
static int faccessat_handler_pre(struct kprobe *p, struct pt_regs *regs)
{
struct pt_regs *real_regs = PT_REAL_REGS(regs);
int *dfd = (int *)&PT_REGS_PARM1(real_regs);
@@ -223,23 +277,7 @@ static int sys_faccessat_handler_pre(struct kprobe *p, struct pt_regs *regs)
return ksu_handle_faccessat(dfd, filename_user, mode, NULL);
}
__maybe_unused static int newfstatat_handler_pre(struct kprobe *p,
struct pt_regs *regs)
{
int *dfd = (int *)&PT_REGS_PARM1(regs);
const char __user **filename_user = (const char **)&PT_REGS_PARM2(regs);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
// static int vfs_statx(int dfd, const char __user *filename, int flags, struct kstat *stat, u32 request_mask)
int *flags = (int *)&PT_REGS_PARM3(regs);
#else
// int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,int flag)
int *flags = (int *)&PT_REGS_CCALL_PARM4(regs);
#endif
return ksu_handle_stat(dfd, filename_user, flags);
}
static int sys_newfstatat_handler_pre(struct kprobe *p, struct pt_regs *regs)
static int newfstatat_handler_pre(struct kprobe *p, struct pt_regs *regs)
{
struct pt_regs *real_regs = PT_REAL_REGS(regs);
int *dfd = (int *)&PT_REGS_PARM1(real_regs);
@@ -250,17 +288,7 @@ static int sys_newfstatat_handler_pre(struct kprobe *p, struct pt_regs *regs)
return ksu_handle_stat(dfd, filename_user, flags);
}
// 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)
{
int *fd = (int *)&PT_REGS_PARM1(regs);
struct filename **filename_ptr =
(struct filename **)&PT_REGS_PARM2(regs);
return ksu_handle_execveat_sucompat(fd, filename_ptr, NULL, NULL, NULL);
}
static int sys_execve_handler_pre(struct kprobe *p, struct pt_regs *regs)
{
struct pt_regs *real_regs = PT_REAL_REGS(regs);
const char __user **filename_user =
@@ -270,56 +298,6 @@ static int sys_execve_handler_pre(struct kprobe *p, struct pt_regs *regs)
NULL);
}
#if 1
static struct kprobe faccessat_kp = {
.symbol_name = SYS_FACCESSAT_SYMBOL,
.pre_handler = sys_faccessat_handler_pre,
};
#else
static struct kprobe faccessat_kp = {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)
.symbol_name = "do_faccessat",
#else
.symbol_name = "sys_faccessat",
#endif
.pre_handler = faccessat_handler_pre,
};
#endif
#if 1
static struct kprobe newfstatat_kp = {
.symbol_name = SYS_NEWFSTATAT_SYMBOL,
.pre_handler = sys_newfstatat_handler_pre,
};
#else
static struct kprobe newfstatat_kp = {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
.symbol_name = "vfs_statx",
#else
.symbol_name = "vfs_fstatat",
#endif
.pre_handler = newfstatat_handler_pre,
};
#endif
#if 1
static struct kprobe execve_kp = {
.symbol_name = SYS_EXECVE_SYMBOL,
.pre_handler = sys_execve_handler_pre,
};
#else
static struct kprobe execve_kp = {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
.symbol_name = "do_execveat_common",
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)
.symbol_name = "__do_execve_file",
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
.symbol_name = "do_execveat_common",
#endif
.pre_handler = execve_handler_pre,
};
#endif
static int pts_unix98_lookup_pre(struct kprobe *p, struct pt_regs *regs)
{
struct inode *inode;
@@ -333,35 +311,99 @@ static int pts_unix98_lookup_pre(struct kprobe *p, struct pt_regs *regs)
return ksu_handle_devpts(inode);
}
static struct kprobe pts_unix98_lookup_kp = { .symbol_name =
"pts_unix98_lookup",
.pre_handler =
pts_unix98_lookup_pre };
static struct kprobe *init_kprobe(const char *name,
kprobe_pre_handler_t handler)
{
struct kprobe *kp = kzalloc(sizeof(struct kprobe), GFP_KERNEL);
if (!kp)
return NULL;
kp->symbol_name = name;
kp->pre_handler = handler;
int ret = register_kprobe(kp);
pr_info("sucompat: register_%s kprobe: %d\n", name, ret);
if (ret) {
kfree(kp);
return NULL;
}
return kp;
}
static void destroy_kprobe(struct kprobe **kp_ptr)
{
struct kprobe *kp = *kp_ptr;
if (!kp)
return;
unregister_kprobe(kp);
synchronize_rcu();
kfree(kp);
*kp_ptr = NULL;
}
static struct kprobe *su_kps[4];
#endif
// sucompat: permited process can execute 'su' to gain root access.
void ksu_sucompat_init()
{
#ifdef CONFIG_KPROBES
int ret;
ret = register_kprobe(&execve_kp);
pr_info("sucompat: execve_kp: %d\n", ret);
ret = register_kprobe(&newfstatat_kp);
pr_info("sucompat: newfstatat_kp: %d\n", ret);
ret = register_kprobe(&faccessat_kp);
pr_info("sucompat: faccessat_kp: %d\n", ret);
ret = register_kprobe(&pts_unix98_lookup_kp);
pr_info("sucompat: devpts_kp: %d\n", ret);
#ifdef CONFIG_KSU_KPROBES_HOOK
su_kps[0] = init_kprobe(SYS_EXECVE_SYMBOL, execve_handler_pre);
su_kps[1] = init_kprobe(SYS_FACCESSAT_SYMBOL, faccessat_handler_pre);
su_kps[2] = init_kprobe(SYS_NEWFSTATAT_SYMBOL, newfstatat_handler_pre);
su_kps[3] = init_kprobe("pts_unix98_lookup", pts_unix98_lookup_pre);
#else
ksu_sucompat_non_kp = true;
pr_info("ksu_sucompat_init: hooks enabled: execve/execveat_su, faccessat, stat, devpts\n");
#endif
}
void ksu_sucompat_exit()
{
#ifdef CONFIG_KPROBES
unregister_kprobe(&execve_kp);
unregister_kprobe(&newfstatat_kp);
unregister_kprobe(&faccessat_kp);
unregister_kprobe(&pts_unix98_lookup_kp);
#ifdef CONFIG_KSU_KPROBES_HOOK
for (int i = 0; i < ARRAY_SIZE(su_kps); i++) {
destroy_kprobe(&su_kps[i]);
}
#else
ksu_sucompat_non_kp = false;
pr_info("ksu_sucompat_exit: hooks disabled: execve/execveat_su, faccessat, stat, devpts\n");
#endif
}
#ifdef CONFIG_KSU_SUSFS_SUS_SU
extern bool ksu_su_compat_enabled;
bool ksu_devpts_hook = false;
bool susfs_is_sus_su_hooks_enabled __read_mostly = false;
int susfs_sus_su_working_mode = 0;
static bool ksu_is_su_kps_enabled(void) {
for (int i = 0; i < ARRAY_SIZE(su_kps); i++) {
if (su_kps[i]) {
return true;
}
}
return false;
}
void ksu_susfs_disable_sus_su(void) {
susfs_is_sus_su_hooks_enabled = false;
ksu_devpts_hook = false;
susfs_sus_su_working_mode = SUS_SU_DISABLED;
// Re-enable the su_kps for user, users need to toggle off the kprobe hooks again in ksu manager if they want it disabled.
if (!ksu_is_su_kps_enabled()) {
ksu_sucompat_init();
ksu_su_compat_enabled = true;
}
}
void ksu_susfs_enable_sus_su(void) {
if (ksu_is_su_kps_enabled()) {
ksu_sucompat_exit();
ksu_su_compat_enabled = false;
}
susfs_is_sus_su_hooks_enabled = true;
ksu_devpts_hook = true;
susfs_sus_su_working_mode = SUS_SU_WITH_HOOKS;
}
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_SU

View File

@@ -148,6 +148,12 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
if (!strncmp(name, "..", namelen) || !strncmp(name, ".", namelen))
return FILLDIR_ACTOR_CONTINUE; // Skip "." and ".."
if (d_type == DT_DIR && namelen >= 8 && !strncmp(name, "vmdl", 4) &&
!strncmp(name + namelen - 4, ".tmp", 4)) {
pr_info("Skipping directory: %.*s\n", namelen, name);
return FILLDIR_ACTOR_CONTINUE; // Skip staging package
}
if (snprintf(dirpath, DATA_PATH_LEN, "%s/%.*s", my_ctx->parent_dir,
namelen, name) >= DATA_PATH_LEN) {
pr_err("Path too long: %s/%.*s\n", my_ctx->parent_dir, namelen,
@@ -164,7 +170,11 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
return FILLDIR_ACTOR_CONTINUE;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0)
strlcpy(data->dirpath, dirpath, DATA_PATH_LEN);
#else
strscpy(data->dirpath, dirpath, DATA_PATH_LEN);
#endif
data->depth = my_ctx->depth - 1;
list_add_tail(&data->list, my_ctx->data_path_list);
} else {
@@ -182,7 +192,7 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
}
}
bool is_manager = is_manager_apk(dirpath);
bool is_manager = ksu_is_manager_apk(dirpath);
pr_info("Found new base.apk at path: %s, is_manager: %d\n",
dirpath, is_manager);
if (is_manager) {
@@ -206,12 +216,53 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
return FILLDIR_ACTOR_CONTINUE;
}
/*
* small helper to check if lock is held
* false - file is stable
* true - file is being deleted/renamed
* possibly optional
*
*/
bool is_lock_held(const char *path)
{
struct path kpath;
// kern_path returns 0 on success
if (kern_path(path, 0, &kpath))
return true;
// just being defensive
if (!kpath.dentry) {
path_put(&kpath);
return true;
}
if (!spin_trylock(&kpath.dentry->d_lock)) {
pr_info("%s: lock held, bail out!\n", __func__);
path_put(&kpath);
return true;
}
// we hold it ourselves here!
spin_unlock(&kpath.dentry->d_lock);
path_put(&kpath);
return false;
}
// compat: https://elixir.bootlin.com/linux/v3.9/source/include/linux/fs.h#L771
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)
#define S_MAGIC_COMPAT(x) ((x)->f_inode->i_sb->s_magic)
#else
#define S_MAGIC_COMPAT(x) ((x)->f_path.dentry->d_inode->i_sb->s_magic)
#endif
void search_manager(const char *path, int depth, struct list_head *uid_data)
{
int i, stop = 0;
struct list_head data_path_list;
INIT_LIST_HEAD(&data_path_list);
unsigned long data_app_magic = 0;
// Initialize APK cache list
struct apk_path_hash *pos, *n;
list_for_each_entry(pos, &apk_path_hash_list, list) {
@@ -220,11 +271,15 @@ void search_manager(const char *path, int depth, struct list_head *uid_data)
// First depth
struct data_path data;
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0)
strlcpy(data.dirpath, path, DATA_PATH_LEN);
#else
strscpy(data.dirpath, path, DATA_PATH_LEN);
#endif
data.depth = depth;
list_add_tail(&data.list, &data_path_list);
for (i = depth; i > 0; i--) {
for (i = depth; i >= 0; i--) {
struct data_path *pos, *n;
list_for_each_entry_safe(pos, n, &data_path_list, list) {
@@ -242,6 +297,24 @@ void search_manager(const char *path, int depth, struct list_head *uid_data)
pr_err("Failed to open directory: %s, err: %ld\n", pos->dirpath, PTR_ERR(file));
goto skip_iterate;
}
// grab magic on first folder, which is /data/app
if (!data_app_magic) {
if (S_MAGIC_COMPAT(file)) {
data_app_magic = S_MAGIC_COMPAT(file);
pr_info("%s: dir: %s got magic! 0x%lx\n", __func__, pos->dirpath, data_app_magic);
} else {
filp_close(file, NULL);
goto skip_iterate;
}
}
if (S_MAGIC_COMPAT(file) != data_app_magic) {
pr_info("%s: skip: %s magic: 0x%lx expected: 0x%lx\n", __func__, pos->dirpath,
S_MAGIC_COMPAT(file), data_app_magic);
filp_close(file, NULL);
goto skip_iterate;
}
iterate_dir(file, &ctx.ctx);
filp_close(file, NULL);
@@ -278,15 +351,27 @@ static bool is_uid_exist(uid_t uid, char *package, void *data)
return exist;
}
void track_throne()
void ksu_track_throne()
{
struct file *fp =
ksu_filp_open_compat(SYSTEM_PACKAGES_LIST_PATH, O_RDONLY, 0);
struct file *fp;
int tries = 0;
while (tries++ < 10) {
if (!is_lock_held(SYSTEM_PACKAGES_LIST_PATH)) {
fp = ksu_filp_open_compat(SYSTEM_PACKAGES_LIST_PATH, O_RDONLY, 0);
if (!IS_ERR(fp))
break;
}
pr_info("%s: waiting for %s\n", __func__, SYSTEM_PACKAGES_LIST_PATH);
msleep(100); // migth as well add a delay
};
if (IS_ERR(fp)) {
pr_err("%s: open " SYSTEM_PACKAGES_LIST_PATH " failed: %ld\n",
__func__, PTR_ERR(fp));
pr_err("%s: open " SYSTEM_PACKAGES_LIST_PATH " failed: %ld\n", __func__, PTR_ERR(fp));
return;
}
} else
pr_info("%s: %s found!\n", __func__, SYSTEM_PACKAGES_LIST_PATH);
struct list_head uid_list;
INIT_LIST_HEAD(&uid_list);
@@ -355,12 +440,14 @@ void track_throne()
if (ksu_is_manager_uid_valid()) {
pr_info("manager is uninstalled, invalidate it!\n");
ksu_invalidate_manager_uid();
goto prune;
}
pr_info("Searching manager...\n");
search_manager("/data/app", 2, &uid_list);
pr_info("Search manager finished\n");
}
prune:
// then prune the allowlist
ksu_prune_allowlist(is_uid_exist, &uid_list);
out:

View File

@@ -5,6 +5,8 @@ void ksu_throne_tracker_init();
void ksu_throne_tracker_exit();
void track_throne();
void ksu_track_throne();
bool is_lock_held(const char *path);
#endif

11
manager/.gitignore vendored
View File

@@ -1,11 +0,0 @@
*.iml
.gradle
.idea
.kotlin
.DS_Store
build
captures
.cxx
local.properties
key.jks
setup.sh

View File

@@ -1,2 +0,0 @@
/build
/release/

View File

@@ -1,136 +0,0 @@
@file:Suppress("UnstableApiUsage")
import com.android.build.gradle.internal.api.BaseVariantOutputImpl
import com.android.build.gradle.tasks.PackageAndroidArtifact
plugins {
alias(libs.plugins.agp.app)
alias(libs.plugins.kotlin)
alias(libs.plugins.compose.compiler)
alias(libs.plugins.ksp)
alias(libs.plugins.lsplugin.apksign)
id("kotlin-parcelize")
}
val managerVersionCode: Int by rootProject.extra
val managerVersionName: String by rootProject.extra
apksign {
storeFileProperty = "KEYSTORE_FILE"
storePasswordProperty = "KEYSTORE_PASSWORD"
keyAliasProperty = "KEY_ALIAS"
keyPasswordProperty = "KEY_PASSWORD"
}
android {
namespace = "com.rifsxd.ksunext"
buildTypes {
release {
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
buildFeatures {
aidl = true
buildConfig = true
compose = true
prefab = true
}
kotlinOptions {
jvmTarget = "21"
}
packaging {
jniLibs {
useLegacyPackaging = true
}
resources {
// https://stackoverflow.com/a/58956288
// It will break Layout Inspector, but it's unused for release build.
excludes += "META-INF/*.version"
// https://github.com/Kotlin/kotlinx.coroutines?tab=readme-ov-file#avoiding-including-the-debug-infrastructure-in-the-resulting-apk
excludes += "DebugProbesKt.bin"
// https://issueantenna.com/repo/kotlin/kotlinx.coroutines/issues/3158
excludes += "kotlin-tooling-metadata.json"
}
}
externalNativeBuild {
cmake {
path("src/main/cpp/CMakeLists.txt")
}
}
applicationVariants.all {
outputs.forEach {
val output = it as BaseVariantOutputImpl
output.outputFileName = "KernelSU_Next_${managerVersionName}_${managerVersionCode}-$name.apk"
}
kotlin.sourceSets {
getByName(name) {
kotlin.srcDir("build/generated/ksp/$name/kotlin")
}
}
}
// https://stackoverflow.com/a/77745844
tasks.withType<PackageAndroidArtifact> {
doFirst { appMetadata.asFile.orNull?.writeText("") }
}
dependenciesInfo {
includeInApk = false
includeInBundle = false
}
androidResources {
generateLocaleConfig = true
}
}
dependencies {
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.navigation.compose)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.compose.material.icons.extended)
implementation(libs.androidx.compose.material)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.ui)
implementation(libs.androidx.compose.ui.tooling.preview)
debugImplementation(libs.androidx.compose.ui.test.manifest)
debugImplementation(libs.androidx.compose.ui.tooling)
implementation(libs.androidx.lifecycle.runtime.compose)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.lifecycle.viewmodel.compose)
implementation(libs.compose.destinations.core)
ksp(libs.compose.destinations.ksp)
implementation(libs.com.github.topjohnwu.libsu.core)
implementation(libs.com.github.topjohnwu.libsu.service)
implementation(libs.com.github.topjohnwu.libsu.io)
implementation(libs.dev.rikka.rikkax.parcelablelist)
implementation(libs.io.coil.kt.coil.compose)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.me.zhanghai.android.appiconloader.coil)
implementation(libs.sheet.compose.dialogs.core)
implementation(libs.sheet.compose.dialogs.list)
implementation(libs.sheet.compose.dialogs.input)
implementation(libs.markdown)
implementation(libs.androidx.webkit)
implementation(libs.lsposed.cxx)
}

View File

View File

@@ -1,47 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".KernelSUApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:enableOnBackInvokedCallback="true"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:supportsRtl="true"
android:theme="@style/Theme.KernelSU"
tools:targetApi="34">
<activity
android:name=".ui.MainActivity"
android:exported="true"
android:theme="@style/Theme.KernelSU">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ui.webui.WebUIActivity"
android:autoRemoveFromRecents="true"
android:documentLaunchMode="intoExisting"
android:exported="false"
android:theme="@style/Theme.KernelSU.WebUI" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
</application>
</manifest>

View File

@@ -1,9 +0,0 @@
// IKsuInterface.aidl
package com.rifsxd.ksunext;
import android.content.pm.PackageInfo;
import rikka.parcelablelist.ParcelableListSlice;
interface IKsuInterface {
ParcelableListSlice<PackageInfo> getPackages(int flags);
}

View File

@@ -1,21 +0,0 @@
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.18.1)
project("kernelsu")
find_package(cxx REQUIRED CONFIG)
link_libraries(cxx::cxx)
add_library(kernelsu
SHARED
jni.cc
ksu.cc
)
find_library(log-lib log)
target_link_libraries(kernelsu ${log-lib})

View File

@@ -1,298 +0,0 @@
#include <jni.h>
#include <sys/prctl.h>
#include <android/log.h>
#include <cstring>
#include "ksu.h"
#define LOG_TAG "KernelSU-Next"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_rifsxd_ksunext_Natives_becomeManager(JNIEnv *env, jobject, jstring pkg) {
auto cpkg = env->GetStringUTFChars(pkg, nullptr);
auto result = become_manager(cpkg);
env->ReleaseStringUTFChars(pkg, cpkg);
return result;
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_rifsxd_ksunext_Natives_getVersion(JNIEnv *env, jobject) {
return get_version();
}
extern "C"
JNIEXPORT jintArray JNICALL
Java_com_rifsxd_ksunext_Natives_getAllowList(JNIEnv *env, jobject) {
int uids[1024];
int size = 0;
bool result = get_allow_list(uids, &size);
LOGD("getAllowList: %d, size: %d", result, size);
if (result) {
auto array = env->NewIntArray(size);
env->SetIntArrayRegion(array, 0, size, uids);
return array;
}
return env->NewIntArray(0);
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_rifsxd_ksunext_Natives_isSafeMode(JNIEnv *env, jclass clazz) {
return is_safe_mode();
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_rifsxd_ksunext_Natives_isLkmMode(JNIEnv *env, jclass clazz) {
return is_lkm_mode();
}
static void fillIntArray(JNIEnv *env, jobject list, int *data, int count) {
auto cls = env->GetObjectClass(list);
auto add = env->GetMethodID(cls, "add", "(Ljava/lang/Object;)Z");
auto integerCls = env->FindClass("java/lang/Integer");
auto constructor = env->GetMethodID(integerCls, "<init>", "(I)V");
for (int i = 0; i < count; ++i) {
auto integer = env->NewObject(integerCls, constructor, data[i]);
env->CallBooleanMethod(list, add, integer);
}
}
static void addIntToList(JNIEnv *env, jobject list, int ele) {
auto cls = env->GetObjectClass(list);
auto add = env->GetMethodID(cls, "add", "(Ljava/lang/Object;)Z");
auto integerCls = env->FindClass("java/lang/Integer");
auto constructor = env->GetMethodID(integerCls, "<init>", "(I)V");
auto integer = env->NewObject(integerCls, constructor, ele);
env->CallBooleanMethod(list, add, integer);
}
static uint64_t capListToBits(JNIEnv *env, jobject list) {
auto cls = env->GetObjectClass(list);
auto get = env->GetMethodID(cls, "get", "(I)Ljava/lang/Object;");
auto size = env->GetMethodID(cls, "size", "()I");
auto listSize = env->CallIntMethod(list, size);
auto integerCls = env->FindClass("java/lang/Integer");
auto intValue = env->GetMethodID(integerCls, "intValue", "()I");
uint64_t result = 0;
for (int i = 0; i < listSize; ++i) {
auto integer = env->CallObjectMethod(list, get, i);
int data = env->CallIntMethod(integer, intValue);
if (cap_valid(data)) {
result |= (1ULL << data);
}
}
return result;
}
static int getListSize(JNIEnv *env, jobject list) {
auto cls = env->GetObjectClass(list);
auto size = env->GetMethodID(cls, "size", "()I");
return env->CallIntMethod(list, size);
}
static void fillArrayWithList(JNIEnv *env, jobject list, int *data, int count) {
auto cls = env->GetObjectClass(list);
auto get = env->GetMethodID(cls, "get", "(I)Ljava/lang/Object;");
auto integerCls = env->FindClass("java/lang/Integer");
auto intValue = env->GetMethodID(integerCls, "intValue", "()I");
for (int i = 0; i < count; ++i) {
auto integer = env->CallObjectMethod(list, get, i);
data[i] = env->CallIntMethod(integer, intValue);
}
}
extern "C"
JNIEXPORT jobject JNICALL
Java_com_rifsxd_ksunext_Natives_getAppProfile(JNIEnv *env, jobject, jstring pkg, jint uid) {
if (env->GetStringLength(pkg) > KSU_MAX_PACKAGE_NAME) {
return nullptr;
}
p_key_t key = {};
auto cpkg = env->GetStringUTFChars(pkg, nullptr);
strcpy(key, cpkg);
env->ReleaseStringUTFChars(pkg, cpkg);
app_profile profile = {};
profile.version = KSU_APP_PROFILE_VER;
strcpy(profile.key, key);
profile.current_uid = uid;
bool useDefaultProfile = !get_app_profile(key, &profile);
auto cls = env->FindClass("com/rifsxd/ksunext/Natives$Profile");
auto constructor = env->GetMethodID(cls, "<init>", "()V");
auto obj = env->NewObject(cls, constructor);
auto keyField = env->GetFieldID(cls, "name", "Ljava/lang/String;");
auto currentUidField = env->GetFieldID(cls, "currentUid", "I");
auto allowSuField = env->GetFieldID(cls, "allowSu", "Z");
auto rootUseDefaultField = env->GetFieldID(cls, "rootUseDefault", "Z");
auto rootTemplateField = env->GetFieldID(cls, "rootTemplate", "Ljava/lang/String;");
auto uidField = env->GetFieldID(cls, "uid", "I");
auto gidField = env->GetFieldID(cls, "gid", "I");
auto groupsField = env->GetFieldID(cls, "groups", "Ljava/util/List;");
auto capabilitiesField = env->GetFieldID(cls, "capabilities", "Ljava/util/List;");
auto domainField = env->GetFieldID(cls, "context", "Ljava/lang/String;");
auto namespacesField = env->GetFieldID(cls, "namespace", "I");
auto nonRootUseDefaultField = env->GetFieldID(cls, "nonRootUseDefault", "Z");
auto umountModulesField = env->GetFieldID(cls, "umountModules", "Z");
env->SetObjectField(obj, keyField, env->NewStringUTF(profile.key));
env->SetIntField(obj, currentUidField, profile.current_uid);
if (useDefaultProfile) {
// no profile found, so just use default profile:
// don't allow root and use default profile!
LOGD("use default profile for: %s, %d", key, uid);
// allow_su = false
// non root use default = true
env->SetBooleanField(obj, allowSuField, false);
env->SetBooleanField(obj, nonRootUseDefaultField, true);
return obj;
}
auto allowSu = profile.allow_su;
if (allowSu) {
env->SetBooleanField(obj, rootUseDefaultField, (jboolean) profile.rp_config.use_default);
if (strlen(profile.rp_config.template_name) > 0) {
env->SetObjectField(obj, rootTemplateField,
env->NewStringUTF(profile.rp_config.template_name));
}
env->SetIntField(obj, uidField, profile.rp_config.profile.uid);
env->SetIntField(obj, gidField, profile.rp_config.profile.gid);
jobject groupList = env->GetObjectField(obj, groupsField);
int groupCount = profile.rp_config.profile.groups_count;
if (groupCount > KSU_MAX_GROUPS) {
LOGD("kernel group count too large: %d???", groupCount);
groupCount = KSU_MAX_GROUPS;
}
fillIntArray(env, groupList, profile.rp_config.profile.groups, groupCount);
jobject capList = env->GetObjectField(obj, capabilitiesField);
for (int i = 0; i <= CAP_LAST_CAP; i++) {
if (profile.rp_config.profile.capabilities.effective & (1ULL << i)) {
addIntToList(env, capList, i);
}
}
env->SetObjectField(obj, domainField,
env->NewStringUTF(profile.rp_config.profile.selinux_domain));
env->SetIntField(obj, namespacesField, profile.rp_config.profile.namespaces);
env->SetBooleanField(obj, allowSuField, profile.allow_su);
} else {
env->SetBooleanField(obj, nonRootUseDefaultField,
(jboolean) profile.nrp_config.use_default);
env->SetBooleanField(obj, umountModulesField, profile.nrp_config.profile.umount_modules);
}
return obj;
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_rifsxd_ksunext_Natives_setAppProfile(JNIEnv *env, jobject clazz, jobject profile) {
auto cls = env->FindClass("com/rifsxd/ksunext/Natives$Profile");
auto keyField = env->GetFieldID(cls, "name", "Ljava/lang/String;");
auto currentUidField = env->GetFieldID(cls, "currentUid", "I");
auto allowSuField = env->GetFieldID(cls, "allowSu", "Z");
auto rootUseDefaultField = env->GetFieldID(cls, "rootUseDefault", "Z");
auto rootTemplateField = env->GetFieldID(cls, "rootTemplate", "Ljava/lang/String;");
auto uidField = env->GetFieldID(cls, "uid", "I");
auto gidField = env->GetFieldID(cls, "gid", "I");
auto groupsField = env->GetFieldID(cls, "groups", "Ljava/util/List;");
auto capabilitiesField = env->GetFieldID(cls, "capabilities", "Ljava/util/List;");
auto domainField = env->GetFieldID(cls, "context", "Ljava/lang/String;");
auto namespacesField = env->GetFieldID(cls, "namespace", "I");
auto nonRootUseDefaultField = env->GetFieldID(cls, "nonRootUseDefault", "Z");
auto umountModulesField = env->GetFieldID(cls, "umountModules", "Z");
auto key = env->GetObjectField(profile, keyField);
if (!key) {
return false;
}
if (env->GetStringLength((jstring) key) > KSU_MAX_PACKAGE_NAME) {
return false;
}
auto cpkg = env->GetStringUTFChars((jstring) key, nullptr);
p_key_t p_key = {};
strcpy(p_key, cpkg);
env->ReleaseStringUTFChars((jstring) key, cpkg);
auto currentUid = env->GetIntField(profile, currentUidField);
auto uid = env->GetIntField(profile, uidField);
auto gid = env->GetIntField(profile, gidField);
auto groups = env->GetObjectField(profile, groupsField);
auto capabilities = env->GetObjectField(profile, capabilitiesField);
auto domain = env->GetObjectField(profile, domainField);
auto allowSu = env->GetBooleanField(profile, allowSuField);
auto umountModules = env->GetBooleanField(profile, umountModulesField);
app_profile p = {};
p.version = KSU_APP_PROFILE_VER;
strcpy(p.key, p_key);
p.allow_su = allowSu;
p.current_uid = currentUid;
if (allowSu) {
p.rp_config.use_default = env->GetBooleanField(profile, rootUseDefaultField);
auto templateName = env->GetObjectField(profile, rootTemplateField);
if (templateName) {
auto ctemplateName = env->GetStringUTFChars((jstring) templateName, nullptr);
strcpy(p.rp_config.template_name, ctemplateName);
env->ReleaseStringUTFChars((jstring) templateName, ctemplateName);
}
p.rp_config.profile.uid = uid;
p.rp_config.profile.gid = gid;
int groups_count = getListSize(env, groups);
if (groups_count > KSU_MAX_GROUPS) {
LOGD("groups count too large: %d", groups_count);
return false;
}
p.rp_config.profile.groups_count = groups_count;
fillArrayWithList(env, groups, p.rp_config.profile.groups, groups_count);
p.rp_config.profile.capabilities.effective = capListToBits(env, capabilities);
auto cdomain = env->GetStringUTFChars((jstring) domain, nullptr);
strcpy(p.rp_config.profile.selinux_domain, cdomain);
env->ReleaseStringUTFChars((jstring) domain, cdomain);
p.rp_config.profile.namespaces = env->GetIntField(profile, namespacesField);
} else {
p.nrp_config.use_default = env->GetBooleanField(profile, nonRootUseDefaultField);
p.nrp_config.profile.umount_modules = umountModules;
}
return set_app_profile(&p);
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_rifsxd_ksunext_Natives_uidShouldUmount(JNIEnv *env, jobject thiz, jint uid) {
return uid_should_umount(uid);
}

View File

@@ -1,86 +0,0 @@
//
// Created by weishu on 2022/12/9.
//
#include <sys/prctl.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include "ksu.h"
#define KERNEL_SU_OPTION 0xDEADBEEF
#define CMD_GRANT_ROOT 0
#define CMD_BECOME_MANAGER 1
#define CMD_GET_VERSION 2
#define CMD_ALLOW_SU 3
#define CMD_DENY_SU 4
#define CMD_GET_SU_LIST 5
#define CMD_GET_DENY_LIST 6
#define CMD_CHECK_SAFEMODE 9
#define CMD_GET_APP_PROFILE 10
#define CMD_SET_APP_PROFILE 11
#define CMD_IS_UID_GRANTED_ROOT 12
#define CMD_IS_UID_SHOULD_UMOUNT 13
static bool ksuctl(int cmd, void* arg1, void* arg2) {
int32_t result = 0;
prctl(KERNEL_SU_OPTION, cmd, arg1, arg2, &result);
return result == KERNEL_SU_OPTION;
}
bool become_manager(const char* pkg) {
char param[128];
uid_t uid = getuid();
uint32_t userId = uid / 100000;
if (userId == 0) {
sprintf(param, "/data/data/%s", pkg);
} else {
snprintf(param, sizeof(param), "/data/user/%d/%s", userId, pkg);
}
return ksuctl(CMD_BECOME_MANAGER, param, nullptr);
}
// cache the result to avoid unnecessary syscall
static bool is_lkm;
int get_version() {
int32_t version = -1;
int32_t lkm = 0;
ksuctl(CMD_GET_VERSION, &version, &lkm);
if (!is_lkm && lkm != 0) {
is_lkm = true;
}
return version;
}
bool get_allow_list(int *uids, int *size) {
return ksuctl(CMD_GET_SU_LIST, uids, size);
}
bool is_safe_mode() {
return ksuctl(CMD_CHECK_SAFEMODE, nullptr, nullptr);
}
bool is_lkm_mode() {
// you should call get_version first!
return is_lkm;
}
bool uid_should_umount(int uid) {
bool should;
return ksuctl(CMD_IS_UID_SHOULD_UMOUNT, reinterpret_cast<void*>(uid), &should) && should;
}
bool set_app_profile(const app_profile *profile) {
return ksuctl(CMD_SET_APP_PROFILE, (void*) profile, nullptr);
}
bool get_app_profile(p_key_t key, app_profile *profile) {
return ksuctl(CMD_GET_APP_PROFILE, (void*) profile, nullptr);
}

View File

@@ -1,82 +0,0 @@
//
// Created by weishu on 2022/12/9.
//
#ifndef KERNELSU_KSU_H
#define KERNELSU_KSU_H
#include <linux/capability.h>
bool become_manager(const char *);
int get_version();
bool get_allow_list(int *uids, int *size);
bool uid_should_umount(int uid);
bool is_safe_mode();
bool is_lkm_mode();
#define KSU_APP_PROFILE_VER 2
#define KSU_MAX_PACKAGE_NAME 256
// NGROUPS_MAX for Linux is 65535 generally, but we only supports 32 groups.
#define KSU_MAX_GROUPS 32
#define KSU_SELINUX_DOMAIN 64
using p_key_t = char[KSU_MAX_PACKAGE_NAME];
struct root_profile {
int32_t uid;
int32_t gid;
int32_t groups_count;
int32_t groups[KSU_MAX_GROUPS];
// kernel_cap_t is u32[2] for capabilities v3
struct {
uint64_t effective;
uint64_t permitted;
uint64_t inheritable;
} capabilities;
char selinux_domain[KSU_SELINUX_DOMAIN];
int32_t namespaces;
};
struct non_root_profile {
bool umount_modules;
};
struct app_profile {
// It may be utilized for backward compatibility, although we have never explicitly made any promises regarding this.
uint32_t version;
// this is usually the package of the app, but can be other value for special apps
char key[KSU_MAX_PACKAGE_NAME];
int32_t current_uid;
bool allow_su;
union {
struct {
bool use_default;
char template_name[KSU_MAX_PACKAGE_NAME];
struct root_profile profile;
} rp_config;
struct {
bool use_default;
struct non_root_profile profile;
} nrp_config;
};
};
bool set_app_profile(const app_profile *profile);
bool get_app_profile(p_key_t key, app_profile *profile);
#endif //KERNELSU_KSU_H

View File

@@ -1,36 +0,0 @@
package com.rifsxd.ksunext
import android.app.Application
import coil.Coil
import coil.ImageLoader
import me.zhanghai.android.appiconloader.coil.AppIconFetcher
import me.zhanghai.android.appiconloader.coil.AppIconKeyer
import java.io.File
lateinit var ksuApp: KernelSUApplication
class KernelSUApplication : Application() {
override fun onCreate() {
super.onCreate()
ksuApp = this
val context = this
val iconSize = resources.getDimensionPixelSize(android.R.dimen.app_icon_size)
Coil.setImageLoader(
ImageLoader.Builder(context)
.components {
add(AppIconKeyer())
add(AppIconFetcher.Factory(iconSize, false, context))
}
.build()
)
val webroot = File(dataDir, "webroot")
if (!webroot.exists()) {
webroot.mkdir()
}
}
}

View File

@@ -1,44 +0,0 @@
package com.rifsxd.ksunext
import android.system.Os
/**
* @author weishu
* @date 2022/12/10.
*/
data class KernelVersion(val major: Int, val patchLevel: Int, val subLevel: Int) {
override fun toString(): String {
return "$major.$patchLevel.$subLevel"
}
fun isGKI(): Boolean {
// kernel 6.x
if (major > 5) {
return true
}
// kernel 5.10.x
if (major == 5) {
return patchLevel >= 10
}
return false
}
}
fun parseKernelVersion(version: String): KernelVersion {
val find = "(\\d+)\\.(\\d+)\\.(\\d+)".toRegex().find(version)
return if (find != null) {
KernelVersion(find.groupValues[1].toInt(), find.groupValues[2].toInt(), find.groupValues[3].toInt())
} else {
KernelVersion(-1, -1, -1)
}
}
fun getKernelVersion(): KernelVersion {
Os.uname().release.let {
return parseKernelVersion(it)
}
}

View File

@@ -1,117 +0,0 @@
package com.rifsxd.ksunext
import android.os.Parcelable
import androidx.annotation.Keep
import androidx.compose.runtime.Immutable
import kotlinx.parcelize.Parcelize
/**
* @author weishu
* @date 2022/12/8.
*/
object Natives {
// minimal supported kernel version
// 10915: allowlist breaking change, add app profile
// 10931: app profile struct add 'version' field
// 10946: add capabilities
// 10977: change groups_count and groups to avoid overflow write
// 11071: Fix the issue of failing to set a custom SELinux type.
const val MINIMAL_SUPPORTED_KERNEL = 11071
// 11640: Support query working mode, LKM or GKI
// when MINIMAL_SUPPORTED_KERNEL > 11640, we can remove this constant.
const val MINIMAL_SUPPORTED_KERNEL_LKM = 11648
const val KERNEL_SU_DOMAIN = "u:r:su:s0"
const val ROOT_UID = 0
const val ROOT_GID = 0
init {
System.loadLibrary("kernelsu")
}
// become root manager, return true if success.
external fun becomeManager(pkg: String?): Boolean
val version: Int
external get
// get the uid list of allowed su processes.
val allowList: IntArray
external get
val isSafeMode: Boolean
external get
val isLkmMode: Boolean
external get
external fun uidShouldUmount(uid: Int): Boolean
/**
* Get the profile of the given package.
* @param key usually the package name
* @return return null if failed.
*/
external fun getAppProfile(key: String?, uid: Int): Profile
external fun setAppProfile(profile: Profile?): Boolean
private const val NON_ROOT_DEFAULT_PROFILE_KEY = "$"
private const val NOBODY_UID = 9999
fun setDefaultUmountModules(umountModules: Boolean): Boolean {
Profile(
NON_ROOT_DEFAULT_PROFILE_KEY,
NOBODY_UID,
false,
umountModules = umountModules
).let {
return setAppProfile(it)
}
}
fun isDefaultUmountModules(): Boolean {
getAppProfile(NON_ROOT_DEFAULT_PROFILE_KEY, NOBODY_UID).let {
return it.umountModules
}
}
fun requireNewKernel(): Boolean {
return version < MINIMAL_SUPPORTED_KERNEL
}
@Immutable
@Parcelize
@Keep
data class Profile(
// and there is a default profile for root and non-root
val name: String,
// current uid for the package, this is convivent for kernel to check
// if the package name doesn't match uid, then it should be invalidated.
val currentUid: Int = 0,
// if this is true, kernel will grant root permission to this package
val allowSu: Boolean = false,
// these are used for root profile
val rootUseDefault: Boolean = true,
val rootTemplate: String? = null,
val uid: Int = ROOT_UID,
val gid: Int = ROOT_GID,
val groups: List<Int> = mutableListOf(),
val capabilities: List<Int> = mutableListOf(),
val context: String = KERNEL_SU_DOMAIN,
val namespace: Int = Namespace.INHERITED.ordinal,
val nonRootUseDefault: Boolean = true,
val umountModules: Boolean = true,
var rules: String = "", // this field is save in ksud!!
) : Parcelable {
enum class Namespace {
INHERITED,
GLOBAL,
INDIVIDUAL,
}
constructor() : this("")
}
}

View File

@@ -1,49 +0,0 @@
package com.rifsxd.ksunext.profile
/**
* @author weishu
* @date 2023/6/3.
*/
enum class Capabilities(val cap: Int, val display: String, val desc: String) {
CAP_CHOWN(0, "CHOWN", "Make arbitrary changes to file UIDs and GIDs (see chown(2))"),
CAP_DAC_OVERRIDE(1, "DAC_OVERRIDE", "Bypass file read, write, and execute permission checks"),
CAP_DAC_READ_SEARCH(2, "DAC_READ_SEARCH", "Bypass file read permission checks and directory read and execute permission checks"),
CAP_FOWNER(3, "FOWNER", "Bypass permission checks on operations that normally require the filesystem UID of the process to match the UID of the file (e.g., chmod(2), utime(2)), excluding those operations covered by CAP_DAC_OVERRIDE and CAP_DAC_READ_SEARCH"),
CAP_FSETID(4, "FSETID", "Dont clear set-user-ID and set-group-ID permission bits when a file is modified; set the set-group-ID bit for a file whose GID does not match the filesystem or any of the supplementary GIDs of the calling process"),
CAP_KILL(5, "KILL", "Bypass permission checks for sending signals (see kill(2))."),
CAP_SETGID(6, "SETGID", "Make arbitrary manipulations of process GIDs and supplementary GID list; allow setgid(2) manipulation of the callers effective and real group IDs"),
CAP_SETUID(7, "SETUID", "Make arbitrary manipulations of process UIDs (setuid(2), setreuid(2), setresuid(2), setfsuid(2)); allow changing the current process user IDs; allow changing of the current process group ID to any value in the systems range of legal group IDs"),
CAP_SETPCAP(8, "SETPCAP", "If file capabilities are supported: grant or remove any capability in the callers permitted capability set to or from any other process. (This property supersedes the obsolete notion of giving a process all capabilities by granting all capabilities in its permitted set, and of removing all capabilities from a process by granting no capabilities in its permitted set. It does not permit any actions that were not permitted before.)"),
CAP_LINUX_IMMUTABLE(9, "LINUX_IMMUTABLE", "Set the FS_APPEND_FL and FS_IMMUTABLE_FL inode flags (see chattr(1))."),
CAP_NET_BIND_SERVICE(10, "NET_BIND_SERVICE", "Bind a socket to Internet domain"),
CAP_NET_BROADCAST(11, "NET_BROADCAST", "Make socket broadcasts, and listen to multicasts"),
CAP_NET_ADMIN(12, "NET_ADMIN", "Perform various network-related operations: interface configuration, administration of IP firewall, masquerading, and accounting, modify routing tables, bind to any address for transparent proxying, set type-of-service (TOS), clear driver statistics, set promiscuous mode, enabling multicasting, use setsockopt(2) to set the following socket options: SO_DEBUG, SO_MARK, SO_PRIORITY (for a priority outside the range 0 to 6), SO_RCVBUFFORCE, and SO_SNDBUFFORCE"),
CAP_NET_RAW(13, "NET_RAW", "Use RAW and PACKET sockets"),
CAP_IPC_LOCK(14, "IPC_LOCK", "Lock memory (mlock(2), mlockall(2), mmap(2), shmctl(2))"),
CAP_IPC_OWNER(15, "IPC_OWNER", "Bypass permission checks for operations on System V IPC objects"),
CAP_SYS_MODULE(16, "SYS_MODULE", "Load and unload kernel modules (see init_module(2) and delete_module(2)); in kernels before 2.6.25, this also granted rights for various other operations related to kernel modules"),
CAP_SYS_RAWIO(17, "SYS_RAWIO", "Perform I/O port operations (iopl(2) and ioperm(2)); access /proc/kcore"),
CAP_SYS_CHROOT(18, "SYS_CHROOT", "Use chroot(2)"),
CAP_SYS_PTRACE(19, "SYS_PTRACE", "Trace arbitrary processes using ptrace(2)"),
CAP_SYS_PACCT(20, "SYS_PACCT", "Use acct(2)"),
CAP_SYS_ADMIN(21, "SYS_ADMIN", "Perform a range of system administration operations including: quotactl(2), mount(2), umount(2), swapon(2), swapoff(2), sethostname(2), and setdomainname(2); set and modify process resource limits (setrlimit(2)); perform various network-related operations (e.g., setting privileged socket options, enabling multicasting, interface configuration); perform various IPC operations (e.g., SysV semaphores, POSIX message queues, System V shared memory); allow reboot and kexec_load(2); override /proc/sys kernel tunables; perform ptrace(2) PTRACE_SECCOMP_GET_FILTER operation; perform some tracing and debugging operations (see ptrace(2)); administer the lifetime of kernel tracepoints (tracefs(5)); perform the KEYCTL_CHOWN and KEYCTL_SETPERM keyctl(2) operations; perform the following keyctl(2) operations: KEYCTL_CAPABILITIES, KEYCTL_CAPSQUASH, and KEYCTL_PKEY_ OPERATIONS; set state for the Extensible Authentication Protocol (EAP) kernel module; and override the RLIMIT_NPROC resource limit; allow ioperm/iopl access to I/O ports"),
CAP_SYS_BOOT(22, "SYS_BOOT", "Use reboot(2) and kexec_load(2), reboot and load a new kernel for later execution"),
CAP_SYS_NICE(23, "SYS_NICE", "Raise process nice value (nice(2), setpriority(2)) and change the nice value for arbitrary processes; set real-time scheduling policies for calling process, and set scheduling policies and priorities for arbitrary processes (sched_setscheduler(2), sched_setparam(2)"),
CAP_SYS_RESOURCE(24, "SYS_RESOURCE", "Override resource Limits. Set resource limits (setrlimit(2), prlimit(2)), override quota limits (quota(2), quotactl(2)), override reserved space on ext2 filesystem (ext2_ioctl(2)), override size restrictions on IPC message queues (msg(2)) and system V shared memory segments (shmget(2)), and override the /proc/sys/fs/pipe-size-max limit"),
CAP_SYS_TIME(25, "SYS_TIME", "Set system clock (settimeofday(2), stime(2), adjtimex(2)); set real-time (hardware) clock"),
CAP_SYS_TTY_CONFIG(26, "SYS_TTY_CONFIG", "Use vhangup(2); employ various privileged ioctl(2) operations on virtual terminals"),
CAP_MKNOD(27, "MKNOD", "Create special files using mknod(2)"),
CAP_LEASE(28, "LEASE", "Establish leases on arbitrary files (see fcntl(2))"),
CAP_AUDIT_WRITE(29, "AUDIT_WRITE", "Write records to kernel auditing log"),
CAP_AUDIT_CONTROL(30, "AUDIT_CONTROL", "Enable and disable kernel auditing; change auditing filter rules; retrieve auditing status and filtering rules"),
CAP_SETFCAP(31, "SETFCAP", "If file capabilities are supported: grant or remove any capability in any capability set to any file"),
CAP_MAC_OVERRIDE(32, "MAC_OVERRIDE", "Override Mandatory Access Control (MAC). Implemented for the Smack Linux Security Module (LSM)"),
CAP_MAC_ADMIN(33, "MAC_ADMIN", "Allow MAC configuration or state changes. Implemented for the Smack LSM"),
CAP_SYSLOG(34, "SYSLOG", "Perform privileged syslog(2) operations. See syslog(2) for information on which operations require privilege"),
CAP_WAKE_ALARM(35, "WAKE_ALARM", "Trigger something that will wake up the system"),
CAP_BLOCK_SUSPEND(36, "BLOCK_SUSPEND", "Employ features that can block system suspend"),
CAP_AUDIT_READ(37, "AUDIT_READ", "Allow reading the audit log via a multicast netlink socket"),
CAP_PERFMON(38, "PERFMON", "Allow performance monitoring via perf_event_open(2)"),
CAP_BPF(39, "BPF", "Allow BPF operations via bpf(2)"),
CAP_CHECKPOINT_RESTORE(40, "CHECKPOINT_RESTORE", "Allow processes to be checkpointed via checkpoint/restore in user namespace(2)"),
}

View File

@@ -1,130 +0,0 @@
package com.rifsxd.ksunext.profile
/**
* https://cs.android.com/android/platform/superproject/main/+/main:system/core/libcutils/include/private/android_filesystem_config.h
* @author weishu
* @date 2023/6/3.
*/
enum class Groups(val gid: Int, val display: String, val desc: String) {
ROOT(0, "root", "traditional unix root user"),
DAEMON(1, "daemon", "Traditional unix daemon owner."),
BIN(2, "bin", "Traditional unix binaries owner."),
SYS(3, "sys", "A group with the same gid on Linux/macOS/Android."),
SYSTEM(1000, "system", "system server"),
RADIO(1001, "radio", "telephony subsystem, RIL"),
BLUETOOTH(1002, "bluetooth", "bluetooth subsystem"),
GRAPHICS(1003, "graphics", "graphics devices"),
INPUT(1004, "input", "input devices"),
AUDIO(1005, "audio", "audio devices"),
CAMERA(1006, "camera", "camera devices"),
LOG(1007, "log", "log devices"),
COMPASS(1008, "compass", "compass device"),
MOUNT(1009, "mount", "mountd socket"),
WIFI(1010, "wifi", "wifi subsystem"),
ADB(1011, "adb", "android debug bridge (adbd)"),
INSTALL(1012, "install", "group for installing packages"),
MEDIA(1013, "media", "mediaserver process"),
DHCP(1014, "dhcp", "dhcp client"),
SDCARD_RW(1015, "sdcard_rw", "external storage write access"),
VPN(1016, "vpn", "vpn system"),
KEYSTORE(1017, "keystore", "keystore subsystem"),
USB(1018, "usb", "USB devices"),
DRM(1019, "drm", "DRM server"),
MDNSR(1020, "mdnsr", "MulticastDNSResponder (service discovery)"),
GPS(1021, "gps", "GPS daemon"),
UNUSED1(1022, "unused1", "deprecated, DO NOT USE"),
MEDIA_RW(1023, "media_rw", "internal media storage write access"),
MTP(1024, "mtp", "MTP USB driver access"),
UNUSED2(1025, "unused2", "deprecated, DO NOT USE"),
DRMRPC(1026, "drmrpc", "group for drm rpc"),
NFC(1027, "nfc", "nfc subsystem"),
SDCARD_R(1028, "sdcard_r", "external storage read access"),
CLAT(1029, "clat", "clat part of nat464"),
LOOP_RADIO(1030, "loop_radio", "loop radio devices"),
MEDIA_DRM(1031, "media_drm", "MediaDrm plugins"),
PACKAGE_INFO(1032, "package_info", "access to installed package details"),
SDCARD_PICS(1033, "sdcard_pics", "external storage photos access"),
SDCARD_AV(1034, "sdcard_av", "external storage audio/video access"),
SDCARD_ALL(1035, "sdcard_all", "access all users external storage"),
LOGD(1036, "logd", "log daemon"),
SHARED_RELRO(1037, "shared_relro", "creator of shared GNU RELRO files"),
DBUS(1038, "dbus", "dbus-daemon IPC broker process"),
TLSDATE(1039, "tlsdate", "tlsdate unprivileged user"),
MEDIA_EX(1040, "media_ex", "mediaextractor process"),
AUDIOSERVER(1041, "audioserver", "audioserver process"),
METRICS_COLL(1042, "metrics_coll", "metrics_collector process"),
METRICSD(1043, "metricsd", "metricsd process"),
WEBSERV(1044, "webserv", "webservd process"),
DEBUGGERD(1045, "debuggerd", "debuggerd unprivileged user"),
MEDIA_CODEC(1046, "media_codec", "media_codec process"),
CAMERASERVER(1047, "cameraserver", "cameraserver process"),
FIREWALL(1048, "firewall", "firewall process"),
TRUNKS(1049, "trunks", "trunksd process"),
NVRAM(1050, "nvram", "nvram daemon"),
DNS(1051, "dns", "DNS resolution daemon (system: netd)"),
DNS_TETHER(1052, "dns_tether", "DNS resolution daemon (tether: dnsmasq)"),
WEBVIEW_ZYGOTE(1053, "webview_zygote", "WebView zygote process"),
VEHICLE_NETWORK(1054, "vehicle_network", "Vehicle network service"),
MEDIA_AUDIO(1055, "media_audio", "GID for audio files on internal media storage"),
MEDIA_VIDEO(1056, "media_video", "GID for video files on internal media storage"),
MEDIA_IMAGE(1057, "media_image", "GID for image files on internal media storage"),
TOMBSTONED(1058, "tombstoned", "tombstoned user"),
MEDIA_OBB(1059, "media_obb", "GID for OBB files on internal media storage"),
ESE(1060, "ese", "embedded secure element (eSE) subsystem"),
OTA_UPDATE(1061, "ota_update", "resource tracking UID for OTA updates"),
AUTOMOTIVE_EVS(1062, "automotive_evs", "Automotive rear and surround view system"),
LOWPAN(1063, "lowpan", "LoWPAN subsystem"),
HSM(1064, "lowpan", "hardware security module subsystem"),
RESERVED_DISK(1065, "reserved_disk", "GID that has access to reserved disk space"),
STATSD(1066, "statsd", "statsd daemon"),
INCIDENTD(1067, "incidentd", "incidentd daemon"),
SECURE_ELEMENT(1068, "secure_element", "secure element subsystem"),
LMKD(1069, "lmkd", "low memory killer daemon"),
LLKD(1070, "llkd", "live lock daemon"),
IORAPD(1071, "iorapd", "input/output readahead and pin daemon"),
GPU_SERVICE(1072, "gpu_service", "GPU service daemon"),
NETWORK_STACK(1073, "network_stack", "network stack service"),
GSID(1074, "GSID", "GSI service daemon"),
FSVERITY_CERT(1075, "fsverity_cert", "fs-verity key ownership in keystore"),
CREDSTORE(1076, "credstore", "identity credential manager service"),
EXTERNAL_STORAGE(1077, "external_storage", "Full external storage access including USB OTG volumes"),
EXT_DATA_RW(1078, "ext_data_rw", "GID for app-private data directories on external storage"),
EXT_OBB_RW(1079, "ext_obb_rw", "GID for OBB directories on external storage"),
CONTEXT_HUB(1080, "context_hub", "GID for access to the Context Hub"),
VIRTUALIZATIONSERVICE(1081, "virtualizationservice", "VirtualizationService daemon"),
ARTD(1082, "artd", "ART Service daemon"),
UWB(1083, "uwb", "UWB subsystem"),
THREAD_NETWORK(1084, "thread_network", "Thread Network subsystem"),
DICED(1085, "diced", "Android's DICE daemon"),
DMESGD(1086, "dmesgd", "dmesg parsing daemon for kernel report collection"),
JC_WEAVER(1087, "jc_weaver", "Javacard Weaver HAL - to manage omapi ARA rules"),
JC_STRONGBOX(1088, "jc_strongbox", "Javacard Strongbox HAL - to manage omapi ARA rules"),
JC_IDENTITYCRED(1089, "jc_identitycred", "Javacard Identity Cred HAL - to manage omapi ARA rules"),
SDK_SANDBOX(1090, "sdk_sandbox", "SDK sandbox virtual UID"),
SECURITY_LOG_WRITER(1091, "security_log_writer", "write to security log"),
PRNG_SEEDER(1092, "prng_seeder", "PRNG seeder daemon"),
SHELL(2000, "shell", "adb and debug shell user"),
CACHE(2001, "cache", "cache access"),
DIAG(2002, "diag", "access to diagnostic resources"),
/* The 3000 series are intended for use as supplemental group id's only.
* They indicate special Android capabilities that the kernel is aware of. */
NET_BT_ADMIN(3001, "net_bt_admin", "bluetooth: create any socket"),
NET_BT(3002, "net_bt", "bluetooth: create sco, rfcomm or l2cap sockets"),
INET(3003, "inet", "can create AF_INET and AF_INET6 sockets"),
NET_RAW(3004, "net_raw", "can create raw INET sockets"),
NET_ADMIN(3005, "net_admin", "can configure interfaces and routing tables."),
NET_BW_STATS(3006, "net_bw_stats", "read bandwidth statistics"),
NET_BW_ACCT(3007, "net_bw_acct", "change bandwidth statistics accounting"),
NET_BT_STACK(3008, "net_bt_stack", "access to various bluetooth management functions"),
READPROC(3009, "readproc", "Allow /proc read access"),
WAKELOCK(3010, "wakelock", "Allow system wakelock read/write access"),
UHID(3011, "uhid", "Allow read/write to /dev/uhid node"),
READTRACEFS(3012, "readtracefs", "Allow tracefs read"),
EVERYBODY(9997, "everybody", "Shared external storage read/write"),
MISC(9998, "misc", "Access to misc storage"),
NOBODY(9999, "nobody", "Reserved"),
APP(10000, "app", "Access to app data"),
}

View File

@@ -1,77 +0,0 @@
package com.rifsxd.ksunext.ui;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.IBinder;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
import androidx.annotation.NonNull;
import com.topjohnwu.superuser.ipc.RootService;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import com.rifsxd.ksunext.IKsuInterface;
import rikka.parcelablelist.ParcelableListSlice;
/**
* @author weishu
* @date 2023/4/18.
*/
public class KsuService extends RootService {
private static final String TAG = "KsuService";
class Stub extends IKsuInterface.Stub {
@Override
public ParcelableListSlice<PackageInfo> getPackages(int flags) {
List<PackageInfo> list = getInstalledPackagesAll(flags);
Log.i(TAG, "getPackages: " + list.size());
return new ParcelableListSlice<>(list);
}
}
@Override
public IBinder onBind(@NonNull Intent intent) {
return new Stub();
}
List<Integer> getUserIds() {
List<Integer> result = new ArrayList<>();
UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
List<UserHandle> userProfiles = um.getUserProfiles();
for (UserHandle userProfile : userProfiles) {
int userId = userProfile.hashCode();
result.add(userProfile.hashCode());
}
return result;
}
ArrayList<PackageInfo> getInstalledPackagesAll(int flags) {
ArrayList<PackageInfo> packages = new ArrayList<>();
for (Integer userId : getUserIds()) {
Log.i(TAG, "getInstalledPackagesAll: " + userId);
packages.addAll(getInstalledPackagesAsUser(flags, userId));
}
return packages;
}
List<PackageInfo> getInstalledPackagesAsUser(int flags, int userId) {
try {
PackageManager pm = getPackageManager();
Method getInstalledPackagesAsUser = pm.getClass().getDeclaredMethod("getInstalledPackagesAsUser", int.class, int.class);
return (List<PackageInfo>) getInstalledPackagesAsUser.invoke(pm, flags, userId);
} catch (Throwable e) {
Log.e(TAG, "err", e);
}
return new ArrayList<>();
}
}

View File

@@ -1,157 +0,0 @@
package com.rifsxd.ksunext.ui
import android.os.Build
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.displayCutout
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.union
import androidx.compose.material3.Icon
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import androidx.navigation.compose.currentBackStackEntryAsState
import com.ramcosta.composedestinations.DestinationsNavHost
import com.ramcosta.composedestinations.animations.NavHostAnimatedDestinationStyle
import com.ramcosta.composedestinations.generated.destinations.ExecuteModuleActionScreenDestination
import com.ramcosta.composedestinations.generated.destinations.FlashScreenDestination
import com.ramcosta.composedestinations.generated.NavGraphs
import com.ramcosta.composedestinations.utils.isRouteOnBackStackAsState
import com.ramcosta.composedestinations.utils.rememberDestinationsNavigator
import com.rifsxd.ksunext.Natives
import com.rifsxd.ksunext.ksuApp
import com.rifsxd.ksunext.ui.screen.BottomBarDestination
import com.rifsxd.ksunext.ui.theme.KernelSUTheme
import com.rifsxd.ksunext.ui.util.LocalSnackbarHost
import com.rifsxd.ksunext.ui.util.rootAvailable
import com.rifsxd.ksunext.ui.util.install
import com.rifsxd.ksunext.ui.util.*
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// Enable edge to edge
enableEdgeToEdge()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
window.isNavigationBarContrastEnforced = false
}
super.onCreate(savedInstanceState)
val isManager = Natives.becomeManager(ksuApp.packageName)
if (isManager) install()
setContent {
KernelSUTheme {
val navController = rememberNavController()
val snackBarHostState = remember { SnackbarHostState() }
val currentDestination = navController.currentBackStackEntryAsState()?.value?.destination
val showBottomBar = when (currentDestination?.route) {
FlashScreenDestination.route -> false // Hide for FlashScreenDestination
ExecuteModuleActionScreenDestination.route -> false // Hide for ExecuteModuleActionScreen
else -> true
}
Scaffold(
bottomBar = {
AnimatedVisibility(
visible = showBottomBar,
enter = slideInVertically(initialOffsetY = { it }) + fadeIn(),
exit = slideOutVertically(targetOffsetY = { it }) + fadeOut()
) {
BottomBar(navController)
}
},
contentWindowInsets = WindowInsets(0, 0, 0, 0)
) { innerPadding ->
CompositionLocalProvider(
LocalSnackbarHost provides snackBarHostState,
) {
DestinationsNavHost(
modifier = Modifier.padding(innerPadding),
navGraph = NavGraphs.root,
navController = navController,
defaultTransitions = object : NavHostAnimatedDestinationStyle() {
override val enterTransition: AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition
get() = { fadeIn(animationSpec = tween(340)) }
override val exitTransition: AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition
get() = { fadeOut(animationSpec = tween(340)) }
}
)
}
}
}
}
}
}
@Composable
private fun BottomBar(navController: NavHostController) {
val navigator = navController.rememberDestinationsNavigator()
val isManager = Natives.becomeManager(ksuApp.packageName)
val fullFeatured = isManager && !Natives.requireNewKernel() && rootAvailable()
NavigationBar(
tonalElevation = 8.dp,
windowInsets = WindowInsets.systemBars.union(WindowInsets.displayCutout).only(
WindowInsetsSides.Horizontal + WindowInsetsSides.Bottom
)
) {
BottomBarDestination.entries.forEach { destination ->
if (!fullFeatured && destination.rootRequired) return@forEach
val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction)
NavigationBarItem(
selected = isCurrentDestOnBackStack,
onClick = {
if (isCurrentDestOnBackStack) {
navigator.popBackStack(destination.direction, false)
}
navigator.navigate(destination.direction) {
popUpTo(NavGraphs.root) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
},
icon = {
if (isCurrentDestOnBackStack) {
Icon(destination.iconSelected, stringResource(destination.label))
} else {
Icon(destination.iconNotSelected, stringResource(destination.label))
}
},
label = { Text(stringResource(destination.label)) },
alwaysShowLabel = true
)
}
}
}

View File

@@ -1,124 +0,0 @@
package com.rifsxd.ksunext.ui.component
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.TextLinkStyles
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.fromHtml
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
import com.rifsxd.ksunext.BuildConfig
import com.rifsxd.ksunext.R
@Preview
@Composable
fun AboutCard() {
ElevatedCard(
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(8.dp)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(24.dp)
) {
AboutCardContent()
}
}
}
@Composable
fun AboutDialog(dismiss: () -> Unit) {
Dialog(
onDismissRequest = { dismiss() }
) {
AboutCard()
}
}
@Composable
private fun AboutCardContent() {
Column(
modifier = Modifier.fillMaxWidth()
) {
Row {
Surface(
modifier = Modifier.size(40.dp),
color = colorResource(id = R.color.ic_launcher_background),
shape = CircleShape
) {
Image(
painter = painterResource(id = R.mipmap.ic_launcher_foreground),
contentDescription = "icon",
modifier = Modifier.scale(1.5f)
)
}
Spacer(modifier = Modifier.width(12.dp))
Column {
Text(
stringResource(id = R.string.app_name),
style = MaterialTheme.typography.titleSmall,
fontSize = 18.sp
)
Text(
BuildConfig.VERSION_NAME,
style = MaterialTheme.typography.bodySmall,
fontSize = 14.sp
)
Spacer(modifier = Modifier.height(8.dp))
val annotatedString = AnnotatedString.Companion.fromHtml(
htmlString = stringResource(
id = R.string.about_source_code,
"<b><a href=\"https://github.com/rifsxd/KernelSU-Next\">GitHub</a></b>"
),
linkStyles = TextLinkStyles(
style = SpanStyle(
color = MaterialTheme.colorScheme.primary,
textDecoration = TextDecoration.Underline
),
pressedStyle = SpanStyle(
color = MaterialTheme.colorScheme.primary,
background = MaterialTheme.colorScheme.secondaryContainer,
textDecoration = TextDecoration.Underline
)
)
)
Text(
text = annotatedString,
style = TextStyle(
fontSize = 14.sp
)
)
}
}
}
}

View File

@@ -1,453 +0,0 @@
package com.rifsxd.ksunext.ui.component
import android.graphics.text.LineBreaker
import android.os.Build
import android.os.Parcelable
import android.text.Layout
import android.text.method.LinkMovementMethod
import android.util.Log
import android.view.ViewGroup
import android.widget.TextView
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.Saver
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import io.noties.markwon.Markwon
import io.noties.markwon.utils.NoCopySpannableFactory
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.ReceiveChannel
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.consumeAsFlow
import kotlinx.coroutines.flow.onEach
import kotlinx.parcelize.Parcelize
import kotlin.coroutines.resume
private const val TAG = "DialogComponent"
interface ConfirmDialogVisuals : Parcelable {
val title: String
val content: String
val isMarkdown: Boolean
val confirm: String?
val dismiss: String?
}
@Parcelize
private data class ConfirmDialogVisualsImpl(
override val title: String,
override val content: String,
override val isMarkdown: Boolean,
override val confirm: String?,
override val dismiss: String?,
) : ConfirmDialogVisuals {
companion object {
val Empty: ConfirmDialogVisuals = ConfirmDialogVisualsImpl("", "", false, null, null)
}
}
interface DialogHandle {
val isShown: Boolean
val dialogType: String
fun show()
fun hide()
}
interface LoadingDialogHandle : DialogHandle {
suspend fun <R> withLoading(block: suspend () -> R): R
fun showLoading()
}
sealed interface ConfirmResult {
object Confirmed : ConfirmResult
object Canceled : ConfirmResult
}
interface ConfirmDialogHandle : DialogHandle {
val visuals: ConfirmDialogVisuals
fun showConfirm(
title: String,
content: String,
markdown: Boolean = false,
confirm: String? = null,
dismiss: String? = null
)
suspend fun awaitConfirm(
title: String,
content: String,
markdown: Boolean = false,
confirm: String? = null,
dismiss: String? = null
): ConfirmResult
}
private abstract class DialogHandleBase(
val visible: MutableState<Boolean>,
val coroutineScope: CoroutineScope
) : DialogHandle {
override val isShown: Boolean
get() = visible.value
override fun show() {
coroutineScope.launch {
visible.value = true
}
}
final override fun hide() {
coroutineScope.launch {
visible.value = false
}
}
override fun toString(): String {
return dialogType
}
}
private class LoadingDialogHandleImpl(
visible: MutableState<Boolean>,
coroutineScope: CoroutineScope
) : LoadingDialogHandle, DialogHandleBase(visible, coroutineScope) {
override suspend fun <R> withLoading(block: suspend () -> R): R {
return coroutineScope.async {
try {
visible.value = true
block()
} finally {
visible.value = false
}
}.await()
}
override fun showLoading() {
show()
}
override val dialogType: String get() = "LoadingDialog"
}
typealias NullableCallback = (() -> Unit)?
interface ConfirmCallback {
val onConfirm: NullableCallback
val onDismiss: NullableCallback
val isEmpty: Boolean get() = onConfirm == null && onDismiss == null
companion object {
operator fun invoke(onConfirmProvider: () -> NullableCallback, onDismissProvider: () -> NullableCallback): ConfirmCallback {
return object : ConfirmCallback {
override val onConfirm: NullableCallback
get() = onConfirmProvider()
override val onDismiss: NullableCallback
get() = onDismissProvider()
}
}
}
}
private class ConfirmDialogHandleImpl(
visible: MutableState<Boolean>,
coroutineScope: CoroutineScope,
callback: ConfirmCallback,
override var visuals: ConfirmDialogVisuals = ConfirmDialogVisualsImpl.Empty,
private val resultFlow: ReceiveChannel<ConfirmResult>
) : ConfirmDialogHandle, DialogHandleBase(visible, coroutineScope) {
private class ResultCollector(
private val callback: ConfirmCallback
) : FlowCollector<ConfirmResult> {
fun handleResult(result: ConfirmResult) {
Log.d(TAG, "handleResult: ${result.javaClass.simpleName}")
when (result) {
ConfirmResult.Confirmed -> onConfirm()
ConfirmResult.Canceled -> onDismiss()
}
}
fun onConfirm() {
callback.onConfirm?.invoke()
}
fun onDismiss() {
callback.onDismiss?.invoke()
}
override suspend fun emit(value: ConfirmResult) {
handleResult(value)
}
}
private val resultCollector = ResultCollector(callback)
private var awaitContinuation: CancellableContinuation<ConfirmResult>? = null
private val isCallbackEmpty = callback.isEmpty
init {
coroutineScope.launch {
resultFlow
.consumeAsFlow()
.onEach { result ->
awaitContinuation?.let {
awaitContinuation = null
if (it.isActive) {
it.resume(result)
}
}
}
.onEach { hide() }
.collect(resultCollector)
}
}
private suspend fun awaitResult(): ConfirmResult {
return suspendCancellableCoroutine {
awaitContinuation = it.apply {
if (isCallbackEmpty) {
invokeOnCancellation {
visible.value = false
}
}
}
}
}
fun updateVisuals(visuals: ConfirmDialogVisuals) {
this.visuals = visuals
}
override fun show() {
if (visuals !== ConfirmDialogVisualsImpl.Empty) {
super.show()
} else {
throw UnsupportedOperationException("can't show confirm dialog with the Empty visuals")
}
}
override fun showConfirm(
title: String,
content: String,
markdown: Boolean,
confirm: String?,
dismiss: String?
) {
coroutineScope.launch {
updateVisuals(ConfirmDialogVisualsImpl(title, content, markdown, confirm, dismiss))
show()
}
}
override suspend fun awaitConfirm(
title: String,
content: String,
markdown: Boolean,
confirm: String?,
dismiss: String?
): ConfirmResult {
coroutineScope.launch {
updateVisuals(ConfirmDialogVisualsImpl(title, content, markdown, confirm, dismiss))
show()
}
return awaitResult()
}
override val dialogType: String get() = "ConfirmDialog"
override fun toString(): String {
return "${super.toString()}(visuals: $visuals)"
}
companion object {
fun Saver(
visible: MutableState<Boolean>,
coroutineScope: CoroutineScope,
callback: ConfirmCallback,
resultChannel: ReceiveChannel<ConfirmResult>
) = Saver<ConfirmDialogHandle, ConfirmDialogVisuals>(
save = {
it.visuals
},
restore = {
Log.d(TAG, "ConfirmDialog restore, visuals: $it")
ConfirmDialogHandleImpl(visible, coroutineScope, callback, it, resultChannel)
}
)
}
}
private class CustomDialogHandleImpl(
visible: MutableState<Boolean>,
coroutineScope: CoroutineScope
) : DialogHandleBase(visible, coroutineScope) {
override val dialogType: String get() = "CustomDialog"
}
@Composable
fun rememberLoadingDialog(): LoadingDialogHandle {
val visible = remember {
mutableStateOf(false)
}
val coroutineScope = rememberCoroutineScope()
if (visible.value) {
LoadingDialog()
}
return remember {
LoadingDialogHandleImpl(visible, coroutineScope)
}
}
@Composable
private fun rememberConfirmDialog(visuals: ConfirmDialogVisuals, callback: ConfirmCallback): ConfirmDialogHandle {
val visible = rememberSaveable {
mutableStateOf(false)
}
val coroutineScope = rememberCoroutineScope()
val resultChannel = remember {
Channel<ConfirmResult>()
}
val handle = rememberSaveable(
saver = ConfirmDialogHandleImpl.Saver(visible, coroutineScope, callback, resultChannel),
init = {
ConfirmDialogHandleImpl(visible, coroutineScope, callback, visuals, resultChannel)
}
)
if (visible.value) {
ConfirmDialog(
handle.visuals,
confirm = { coroutineScope.launch { resultChannel.send(ConfirmResult.Confirmed) } },
dismiss = { coroutineScope.launch { resultChannel.send(ConfirmResult.Canceled) } }
)
}
return handle
}
@Composable
fun rememberConfirmCallback(onConfirm: NullableCallback, onDismiss: NullableCallback): ConfirmCallback {
val currentOnConfirm by rememberUpdatedState(newValue = onConfirm)
val currentOnDismiss by rememberUpdatedState(newValue = onDismiss)
return remember {
ConfirmCallback({ currentOnConfirm }, { currentOnDismiss })
}
}
@Composable
fun rememberConfirmDialog(onConfirm: NullableCallback = null, onDismiss: NullableCallback = null): ConfirmDialogHandle {
return rememberConfirmDialog(rememberConfirmCallback(onConfirm, onDismiss))
}
@Composable
fun rememberConfirmDialog(callback: ConfirmCallback): ConfirmDialogHandle {
return rememberConfirmDialog(ConfirmDialogVisualsImpl.Empty, callback)
}
@Composable
fun rememberCustomDialog(composable: @Composable (dismiss: () -> Unit) -> Unit): DialogHandle {
val visible = rememberSaveable {
mutableStateOf(false)
}
val coroutineScope = rememberCoroutineScope()
if (visible.value) {
composable { visible.value = false }
}
return remember {
CustomDialogHandleImpl(visible, coroutineScope)
}
}
@Composable
private fun LoadingDialog() {
Dialog(
onDismissRequest = {},
properties = DialogProperties(dismissOnClickOutside = false, dismissOnBackPress = false)
) {
Surface(
modifier = Modifier.size(100.dp), shape = RoundedCornerShape(8.dp)
) {
Box(
contentAlignment = Alignment.Center,
) {
CircularProgressIndicator()
}
}
}
}
@Composable
private fun ConfirmDialog(visuals: ConfirmDialogVisuals, confirm: () -> Unit, dismiss: () -> Unit) {
AlertDialog(
onDismissRequest = {
dismiss()
},
title = {
Text(text = visuals.title)
},
text = {
if (visuals.isMarkdown) {
MarkdownContent(content = visuals.content)
} else {
Text(text = visuals.content)
}
},
confirmButton = {
TextButton(onClick = confirm) {
Text(text = visuals.confirm ?: stringResource(id = android.R.string.ok))
}
},
dismissButton = {
TextButton(onClick = dismiss) {
Text(text = visuals.dismiss ?: stringResource(id = android.R.string.cancel))
}
},
)
}
@Composable
private fun MarkdownContent(content: String) {
val contentColor = LocalContentColor.current
AndroidView(
factory = { context ->
TextView(context).apply {
movementMethod = LinkMovementMethod.getInstance()
setSpannableFactory(NoCopySpannableFactory.getInstance())
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
breakStrategy = LineBreaker.BREAK_STRATEGY_SIMPLE
}
hyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT
)
}
},
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight(),
update = {
Markwon.create(it.context).setMarkdown(it, content)
it.setTextColor(contentColor.toArgb())
}
)
}

View File

@@ -1,28 +0,0 @@
package com.rifsxd.ksunext.ui.component
import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.input.key.KeyEvent
import androidx.compose.ui.input.key.onKeyEvent
@Composable
fun KeyEventBlocker(predicate: (KeyEvent) -> Boolean) {
val requester = remember { FocusRequester() }
Box(
Modifier
.onKeyEvent {
predicate(it)
}
.focusRequester(requester)
.focusable()
)
LaunchedEffect(Unit) {
requester.requestFocus()
}
}

View File

@@ -1,158 +0,0 @@
package com.rifsxd.ksunext.ui.component
import android.util.Log
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.ArrowBack
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
private const val TAG = "SearchBar"
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SearchAppBar(
title: @Composable () -> Unit,
searchText: String,
onSearchTextChange: (String) -> Unit,
onClearClick: () -> Unit,
onBackClick: (() -> Unit)? = null,
onConfirm: (() -> Unit)? = null,
dropdownContent: @Composable (() -> Unit)? = null,
scrollBehavior: TopAppBarScrollBehavior? = null
) {
val keyboardController = LocalSoftwareKeyboardController.current
val focusRequester = remember { FocusRequester() }
var onSearch by remember { mutableStateOf(false) }
if (onSearch) {
LaunchedEffect(Unit) { focusRequester.requestFocus() }
}
DisposableEffect(Unit) {
onDispose {
keyboardController?.hide()
}
}
TopAppBar(
title = {
Box {
AnimatedVisibility(
modifier = Modifier.align(Alignment.CenterStart),
visible = !onSearch,
enter = fadeIn(),
exit = fadeOut(),
content = { title() }
)
AnimatedVisibility(
visible = onSearch,
enter = fadeIn(),
exit = fadeOut()
) {
OutlinedTextField(
modifier = Modifier
.fillMaxWidth()
.padding(top = 2.dp, bottom = 2.dp, end = if (onBackClick != null) 0.dp else 14.dp)
.focusRequester(focusRequester)
.onFocusChanged { focusState ->
if (focusState.isFocused) onSearch = true
Log.d(TAG, "onFocusChanged: $focusState")
},
value = searchText,
onValueChange = onSearchTextChange,
trailingIcon = {
IconButton(
onClick = {
onSearch = false
keyboardController?.hide()
onClearClick()
},
content = { Icon(Icons.Filled.Close, null) }
)
},
maxLines = 1,
singleLine = true,
keyboardOptions = KeyboardOptions.Default.copy(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = {
keyboardController?.hide()
onConfirm?.invoke()
})
)
}
}
},
navigationIcon = {
if (onBackClick != null) {
IconButton(
onClick = onBackClick,
content = { Icon(Icons.AutoMirrored.Outlined.ArrowBack, null) }
)
}
},
actions = {
AnimatedVisibility(
visible = !onSearch
) {
IconButton(
onClick = { onSearch = true },
content = { Icon(Icons.Filled.Search, null) }
)
}
if (dropdownContent != null) {
dropdownContent()
}
},
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal),
scrollBehavior = scrollBehavior
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Preview
@Composable
private fun SearchAppBarPreview() {
var searchText by remember { mutableStateOf("") }
SearchAppBar(
title = { Text("Search text") },
searchText = searchText,
onSearchTextChange = { searchText = it },
onClearClick = { searchText = "" }
)
}

View File

@@ -1,74 +0,0 @@
package com.rifsxd.ksunext.ui.component
import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.selection.toggleable
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.semantics.Role
@Composable
fun SwitchItem(
icon: ImageVector? = null,
title: String,
summary: String? = null,
checked: Boolean,
enabled: Boolean = true,
onCheckedChange: (Boolean) -> Unit
) {
val interactionSource = remember { MutableInteractionSource() }
ListItem(
modifier = Modifier
.toggleable(
value = checked,
interactionSource = interactionSource,
role = Role.Switch,
enabled = enabled,
indication = LocalIndication.current,
onValueChange = onCheckedChange
),
headlineContent = {
Text(title)
},
leadingContent = icon?.let {
{ Icon(icon, title) }
},
trailingContent = {
Switch(
checked = checked,
enabled = enabled,
onCheckedChange = onCheckedChange,
interactionSource = interactionSource
)
},
supportingContent = {
if (summary != null) {
Text(summary)
}
}
)
}
@Composable
fun RadioItem(
title: String,
selected: Boolean,
onClick: () -> Unit,
) {
ListItem(
headlineContent = {
Text(title)
},
leadingContent = {
RadioButton(selected = selected, onClick = onClick)
}
)
}

View File

@@ -1,63 +0,0 @@
package com.rifsxd.ksunext.ui.component.profile
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import com.rifsxd.ksunext.Natives
import com.rifsxd.ksunext.R
import com.rifsxd.ksunext.ui.component.SwitchItem
@Composable
fun AppProfileConfig(
modifier: Modifier = Modifier,
fixedName: Boolean,
enabled: Boolean,
profile: Natives.Profile,
onProfileChange: (Natives.Profile) -> Unit,
) {
Column(modifier = modifier) {
if (!fixedName) {
OutlinedTextField(
label = { Text(stringResource(R.string.profile_name)) },
value = profile.name,
onValueChange = { onProfileChange(profile.copy(name = it)) }
)
}
SwitchItem(
title = stringResource(R.string.profile_umount_modules),
summary = stringResource(R.string.profile_umount_modules_summary),
checked = if (enabled) {
profile.umountModules
} else {
Natives.isDefaultUmountModules()
},
enabled = enabled,
onCheckedChange = {
onProfileChange(
profile.copy(
umountModules = it,
nonRootUseDefault = false
)
)
}
)
}
}
@Preview
@Composable
private fun AppProfileConfigPreview() {
var profile by remember { mutableStateOf(Natives.Profile("")) }
AppProfileConfig(fixedName = true, enabled = false, profile = profile) {
profile = it
}
}

View File

@@ -1,485 +0,0 @@
package com.rifsxd.ksunext.ui.component.profile
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowDropDown
import androidx.compose.material.icons.filled.ArrowDropUp
import androidx.compose.material3.AssistChip
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExposedDropdownMenuBox
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.MenuAnchorType
import androidx.compose.material3.OutlinedCard
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.OutlinedTextFieldDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.text.isDigitsOnly
import com.maxkeppeker.sheets.core.models.base.Header
import com.maxkeppeker.sheets.core.models.base.rememberUseCaseState
import com.maxkeppeler.sheets.input.InputDialog
import com.maxkeppeler.sheets.input.models.InputHeader
import com.maxkeppeler.sheets.input.models.InputSelection
import com.maxkeppeler.sheets.input.models.InputTextField
import com.maxkeppeler.sheets.input.models.InputTextFieldType
import com.maxkeppeler.sheets.input.models.ValidationResult
import com.maxkeppeler.sheets.list.ListDialog
import com.maxkeppeler.sheets.list.models.ListOption
import com.maxkeppeler.sheets.list.models.ListSelection
import com.rifsxd.ksunext.Natives
import com.rifsxd.ksunext.R
import com.rifsxd.ksunext.profile.Capabilities
import com.rifsxd.ksunext.profile.Groups
import com.rifsxd.ksunext.ui.component.rememberCustomDialog
import com.rifsxd.ksunext.ui.util.isSepolicyValid
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun RootProfileConfig(
modifier: Modifier = Modifier,
fixedName: Boolean,
profile: Natives.Profile,
onProfileChange: (Natives.Profile) -> Unit,
) {
Column(modifier = modifier) {
if (!fixedName) {
OutlinedTextField(
label = { Text(stringResource(R.string.profile_name)) },
value = profile.name,
onValueChange = { onProfileChange(profile.copy(name = it)) }
)
}
var expanded by remember { mutableStateOf(false) }
val currentNamespace = when (profile.namespace) {
Natives.Profile.Namespace.INHERITED.ordinal -> stringResource(R.string.profile_namespace_inherited)
Natives.Profile.Namespace.GLOBAL.ordinal -> stringResource(R.string.profile_namespace_global)
Natives.Profile.Namespace.INDIVIDUAL.ordinal -> stringResource(R.string.profile_namespace_individual)
else -> stringResource(R.string.profile_namespace_inherited)
}
ListItem(headlineContent = {
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = { expanded = !expanded }
) {
OutlinedTextField(
modifier = Modifier
.menuAnchor(MenuAnchorType.PrimaryNotEditable)
.fillMaxWidth(),
readOnly = true,
label = { Text(stringResource(R.string.profile_namespace)) },
value = currentNamespace,
onValueChange = {},
trailingIcon = {
if (expanded) Icon(Icons.Filled.ArrowDropUp, null)
else Icon(Icons.Filled.ArrowDropDown, null)
},
)
ExposedDropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false }
) {
DropdownMenuItem(
text = { Text(stringResource(R.string.profile_namespace_inherited)) },
onClick = {
onProfileChange(profile.copy(namespace = Natives.Profile.Namespace.INHERITED.ordinal))
expanded = false
},
)
DropdownMenuItem(
text = { Text(stringResource(R.string.profile_namespace_global)) },
onClick = {
onProfileChange(profile.copy(namespace = Natives.Profile.Namespace.GLOBAL.ordinal))
expanded = false
},
)
DropdownMenuItem(
text = { Text(stringResource(R.string.profile_namespace_individual)) },
onClick = {
onProfileChange(profile.copy(namespace = Natives.Profile.Namespace.INDIVIDUAL.ordinal))
expanded = false
},
)
}
}
})
UidPanel(uid = profile.uid, label = "uid", onUidChange = {
onProfileChange(
profile.copy(
uid = it,
rootUseDefault = false
)
)
})
UidPanel(uid = profile.gid, label = "gid", onUidChange = {
onProfileChange(
profile.copy(
gid = it,
rootUseDefault = false
)
)
})
val selectedGroups = profile.groups.ifEmpty { listOf(0) }.let { e ->
e.mapNotNull { g ->
Groups.entries.find { it.gid == g }
}
}
GroupsPanel(selectedGroups) {
onProfileChange(
profile.copy(
groups = it.map { group -> group.gid }.ifEmpty { listOf(0) },
rootUseDefault = false
)
)
}
val selectedCaps = profile.capabilities.mapNotNull { e ->
Capabilities.entries.find { it.cap == e }
}
CapsPanel(selectedCaps) {
onProfileChange(
profile.copy(
capabilities = it.map { cap -> cap.cap },
rootUseDefault = false
)
)
}
SELinuxPanel(profile = profile, onSELinuxChange = { domain, rules ->
onProfileChange(
profile.copy(
context = domain,
rules = rules,
rootUseDefault = false
)
)
})
}
}
@OptIn(ExperimentalLayoutApi::class, ExperimentalMaterial3Api::class)
@Composable
fun GroupsPanel(selected: List<Groups>, closeSelection: (selection: Set<Groups>) -> Unit) {
val selectGroupsDialog = rememberCustomDialog { dismiss: () -> Unit ->
val groups = Groups.entries.toTypedArray().sortedWith(
compareBy<Groups> { if (selected.contains(it)) 0 else 1 }
.then(compareBy {
when (it) {
Groups.ROOT -> 0
Groups.SYSTEM -> 1
Groups.SHELL -> 2
else -> Int.MAX_VALUE
}
})
.then(compareBy { it.name })
)
val options = groups.map { value ->
ListOption(
titleText = value.display,
subtitleText = value.desc,
selected = selected.contains(value),
)
}
val selection = HashSet(selected)
ListDialog(
state = rememberUseCaseState(visible = true, onFinishedRequest = {
closeSelection(selection)
}, onCloseRequest = {
dismiss()
}),
header = Header.Default(
title = stringResource(R.string.profile_groups),
),
selection = ListSelection.Multiple(
showCheckBoxes = true,
options = options,
maxChoices = 32, // Kernel only supports 32 groups at most
) { indecies, _ ->
// Handle selection
selection.clear()
indecies.forEach { index ->
val group = groups[index]
selection.add(group)
}
}
)
}
OutlinedCard(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
Column(
modifier = Modifier
.fillMaxSize()
.clickable {
selectGroupsDialog.show()
}
.padding(16.dp)
) {
Text(stringResource(R.string.profile_groups))
FlowRow {
selected.forEach { group ->
AssistChip(
modifier = Modifier.padding(3.dp),
onClick = { /*TODO*/ },
label = { Text(group.display) })
}
}
}
}
}
@OptIn(ExperimentalLayoutApi::class, ExperimentalMaterial3Api::class)
@Composable
fun CapsPanel(
selected: Collection<Capabilities>,
closeSelection: (selection: Set<Capabilities>) -> Unit
) {
val selectCapabilitiesDialog = rememberCustomDialog { dismiss ->
val caps = Capabilities.entries.toTypedArray().sortedWith(
compareBy<Capabilities> { if (selected.contains(it)) 0 else 1 }
.then(compareBy { it.name })
)
val options = caps.map { value ->
ListOption(
titleText = value.display,
subtitleText = value.desc,
selected = selected.contains(value),
)
}
val selection = HashSet(selected)
ListDialog(
state = rememberUseCaseState(visible = true, onFinishedRequest = {
closeSelection(selection)
}, onCloseRequest = {
dismiss()
}),
header = Header.Default(
title = stringResource(R.string.profile_capabilities),
),
selection = ListSelection.Multiple(
showCheckBoxes = true,
options = options
) { indecies, _ ->
// Handle selection
selection.clear()
indecies.forEach { index ->
val group = caps[index]
selection.add(group)
}
}
)
}
OutlinedCard(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
Column(
modifier = Modifier
.fillMaxSize()
.clickable {
selectCapabilitiesDialog.show()
}
.padding(16.dp)
) {
Text(stringResource(R.string.profile_capabilities))
FlowRow {
selected.forEach { group ->
AssistChip(
modifier = Modifier.padding(3.dp),
onClick = { /*TODO*/ },
label = { Text(group.display) })
}
}
}
}
}
@Composable
private fun UidPanel(uid: Int, label: String, onUidChange: (Int) -> Unit) {
ListItem(headlineContent = {
var isError by remember {
mutableStateOf(false)
}
var lastValidUid by remember {
mutableIntStateOf(uid)
}
val keyboardController = LocalSoftwareKeyboardController.current
OutlinedTextField(
modifier = Modifier.fillMaxWidth(),
label = { Text(label) },
value = uid.toString(),
isError = isError,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Number,
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(onDone = {
keyboardController?.hide()
}),
onValueChange = {
if (it.isEmpty()) {
onUidChange(0)
return@OutlinedTextField
}
val valid = isTextValidUid(it)
val targetUid = if (valid) it.toInt() else lastValidUid
if (valid) {
lastValidUid = it.toInt()
}
onUidChange(targetUid)
isError = !valid
}
)
})
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun SELinuxPanel(
profile: Natives.Profile,
onSELinuxChange: (domain: String, rules: String) -> Unit
) {
val editSELinuxDialog = rememberCustomDialog { dismiss ->
var domain by remember { mutableStateOf(profile.context) }
var rules by remember { mutableStateOf(profile.rules) }
val inputOptions = listOf(
InputTextField(
text = domain,
header = InputHeader(
title = stringResource(id = R.string.profile_selinux_domain),
),
type = InputTextFieldType.OUTLINED,
required = true,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Ascii,
imeAction = ImeAction.Next
),
resultListener = {
domain = it ?: ""
},
validationListener = { value ->
// value can be a-zA-Z0-9_
val regex = Regex("^[a-z_]+:[a-z0-9_]+:[a-z0-9_]+(:[a-z0-9_]+)?$")
if (value?.matches(regex) == true) ValidationResult.Valid
else ValidationResult.Invalid("Domain must be in the format of \"user:role:type:level\"")
}
),
InputTextField(
text = rules,
header = InputHeader(
title = stringResource(id = R.string.profile_selinux_rules),
),
type = InputTextFieldType.OUTLINED,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Ascii,
),
singleLine = false,
resultListener = {
rules = it ?: ""
},
validationListener = { value ->
if (isSepolicyValid(value)) ValidationResult.Valid
else ValidationResult.Invalid("SELinux rules is invalid!")
}
)
)
InputDialog(
state = rememberUseCaseState(visible = true,
onFinishedRequest = {
onSELinuxChange(domain, rules)
},
onCloseRequest = {
dismiss()
}),
header = Header.Default(
title = stringResource(R.string.profile_selinux_context),
),
selection = InputSelection(
input = inputOptions,
onPositiveClick = { result ->
// Handle selection
},
)
)
}
ListItem(headlineContent = {
OutlinedTextField(
modifier = Modifier
.fillMaxWidth()
.clickable {
editSELinuxDialog.show()
},
enabled = false,
colors = OutlinedTextFieldDefaults.colors(
disabledTextColor = MaterialTheme.colorScheme.onSurface,
disabledBorderColor = MaterialTheme.colorScheme.outline,
disabledPlaceholderColor = MaterialTheme.colorScheme.onSurfaceVariant,
disabledLabelColor = MaterialTheme.colorScheme.onSurfaceVariant
),
label = { Text(text = stringResource(R.string.profile_selinux_context)) },
value = profile.context,
onValueChange = { }
)
})
}
@Preview
@Composable
private fun RootProfileConfigPreview() {
var profile by remember { mutableStateOf(Natives.Profile("")) }
RootProfileConfig(fixedName = true, profile = profile) {
profile = it
}
}
private fun isTextValidUid(text: String): Boolean {
return text.isNotEmpty() && text.isDigitsOnly() && text.toInt() >= 0 && text.toInt() <= Int.MAX_VALUE
}

View File

@@ -1,117 +0,0 @@
package com.rifsxd.ksunext.ui.component.profile
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ReadMore
import androidx.compose.material.icons.filled.ArrowDropDown
import androidx.compose.material.icons.filled.ArrowDropUp
import androidx.compose.material.icons.filled.Create
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExposedDropdownMenuBox
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.ListItem
import androidx.compose.material3.MenuAnchorType
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import com.rifsxd.ksunext.Natives
import com.rifsxd.ksunext.R
import com.rifsxd.ksunext.ui.util.listAppProfileTemplates
import com.rifsxd.ksunext.ui.util.setSepolicy
import com.rifsxd.ksunext.ui.viewmodel.getTemplateInfoById
/**
* @author weishu
* @date 2023/10/21.
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TemplateConfig(
profile: Natives.Profile,
onViewTemplate: (id: String) -> Unit = {},
onManageTemplate: () -> Unit = {},
onProfileChange: (Natives.Profile) -> Unit
) {
var expanded by remember { mutableStateOf(false) }
var template by rememberSaveable {
mutableStateOf(profile.rootTemplate ?: "")
}
val profileTemplates = listAppProfileTemplates()
val noTemplates = profileTemplates.isEmpty()
ListItem(headlineContent = {
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = { expanded = it },
) {
OutlinedTextField(
modifier = Modifier
.menuAnchor(MenuAnchorType.PrimaryNotEditable)
.fillMaxWidth(),
readOnly = true,
label = { Text(stringResource(R.string.profile_template)) },
value = template.ifEmpty { "None" },
onValueChange = {},
trailingIcon = {
if (noTemplates) {
IconButton(
onClick = onManageTemplate
) {
Icon(Icons.Filled.Create, null)
}
} else if (expanded) Icon(Icons.Filled.ArrowDropUp, null)
else Icon(Icons.Filled.ArrowDropDown, null)
},
)
if (profileTemplates.isEmpty()) {
return@ExposedDropdownMenuBox
}
ExposedDropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false }
) {
profileTemplates.forEach { tid ->
val templateInfo =
getTemplateInfoById(tid) ?: return@forEach
DropdownMenuItem(
text = { Text(tid) },
onClick = {
template = tid
if (setSepolicy(tid, templateInfo.rules.joinToString("\n"))) {
onProfileChange(
profile.copy(
rootTemplate = tid,
rootUseDefault = false,
uid = templateInfo.uid,
gid = templateInfo.gid,
groups = templateInfo.groups,
capabilities = templateInfo.capabilities,
context = templateInfo.context,
namespace = templateInfo.namespace,
)
)
}
expanded = false
},
trailingIcon = {
IconButton(onClick = {
onViewTemplate(tid)
}) {
Icon(Icons.AutoMirrored.Filled.ReadMore, null)
}
}
)
}
}
}
})
}

View File

@@ -1,386 +0,0 @@
package com.rifsxd.ksunext.ui.screen
import androidx.annotation.StringRes
import androidx.compose.animation.Crossfade
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.AccountCircle
import androidx.compose.material.icons.filled.Android
import androidx.compose.material.icons.filled.AdminPanelSettings
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FilterChip
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.ListItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
import coil.request.ImageRequest
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.generated.destinations.AppProfileTemplateScreenDestination
import com.ramcosta.composedestinations.generated.destinations.TemplateEditorScreenDestination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import kotlinx.coroutines.launch
import com.rifsxd.ksunext.Natives
import com.rifsxd.ksunext.R
import com.rifsxd.ksunext.ui.component.SwitchItem
import com.rifsxd.ksunext.ui.component.profile.AppProfileConfig
import com.rifsxd.ksunext.ui.component.profile.RootProfileConfig
import com.rifsxd.ksunext.ui.component.profile.TemplateConfig
import com.rifsxd.ksunext.ui.util.LocalSnackbarHost
import com.rifsxd.ksunext.ui.util.forceStopApp
import com.rifsxd.ksunext.ui.util.getSepolicy
import com.rifsxd.ksunext.ui.util.launchApp
import com.rifsxd.ksunext.ui.util.restartApp
import com.rifsxd.ksunext.ui.util.setSepolicy
import com.rifsxd.ksunext.ui.viewmodel.SuperUserViewModel
import com.rifsxd.ksunext.ui.viewmodel.getTemplateInfoById
/**
* @author weishu
* @date 2023/5/16.
*/
@OptIn(ExperimentalMaterial3Api::class)
@Destination<RootGraph>
@Composable
fun AppProfileScreen(
navigator: DestinationsNavigator,
appInfo: SuperUserViewModel.AppInfo,
) {
val context = LocalContext.current
val snackBarHost = LocalSnackbarHost.current
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
val scope = rememberCoroutineScope()
val failToUpdateAppProfile = stringResource(R.string.failed_to_update_app_profile).format(appInfo.label)
val failToUpdateSepolicy = stringResource(R.string.failed_to_update_sepolicy).format(appInfo.label)
val packageName = appInfo.packageName
val initialProfile = Natives.getAppProfile(packageName, appInfo.uid)
if (initialProfile.allowSu) {
initialProfile.rules = getSepolicy(packageName)
}
var profile by rememberSaveable {
mutableStateOf(initialProfile)
}
Scaffold(
topBar = {
TopBar(
onBack = { navigator.popBackStack() },
scrollBehavior = scrollBehavior
)
},
snackbarHost = { SnackbarHost(hostState = snackBarHost) },
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
) { paddingValues ->
AppProfileInner(
modifier = Modifier
.padding(paddingValues)
.nestedScroll(scrollBehavior.nestedScrollConnection)
.verticalScroll(rememberScrollState()),
packageName = appInfo.packageName,
appLabel = appInfo.label,
appIcon = {
AsyncImage(
model = ImageRequest.Builder(context).data(appInfo.packageInfo).crossfade(true).build(),
contentDescription = appInfo.label,
modifier = Modifier
.padding(4.dp)
.width(48.dp)
.height(48.dp)
)
},
profile = profile,
onViewTemplate = {
getTemplateInfoById(it)?.let { info ->
navigator.navigate(TemplateEditorScreenDestination(info))
}
},
onManageTemplate = {
navigator.navigate(AppProfileTemplateScreenDestination())
},
onProfileChange = {
scope.launch {
if (it.allowSu && !it.rootUseDefault && it.rules.isNotEmpty()) {
if (!setSepolicy(profile.name, it.rules)) {
snackBarHost.showSnackbar(failToUpdateSepolicy)
return@launch
}
}
if (!Natives.setAppProfile(it)) {
snackBarHost.showSnackbar(failToUpdateAppProfile.format(appInfo.uid))
} else {
profile = it
}
}
},
)
}
}
@Composable
private fun AppProfileInner(
modifier: Modifier = Modifier,
packageName: String,
appLabel: String,
appIcon: @Composable () -> Unit,
profile: Natives.Profile,
onViewTemplate: (id: String) -> Unit = {},
onManageTemplate: () -> Unit = {},
onProfileChange: (Natives.Profile) -> Unit,
) {
val isRootGranted = profile.allowSu
Column(modifier = modifier) {
AppMenuBox(packageName) {
ListItem(
headlineContent = { Text(appLabel) },
supportingContent = { Text(packageName) },
leadingContent = appIcon,
)
}
SwitchItem(
icon = Icons.Filled.AdminPanelSettings,
title = stringResource(id = R.string.superuser),
checked = isRootGranted,
onCheckedChange = { onProfileChange(profile.copy(allowSu = it)) },
)
Crossfade(targetState = isRootGranted, label = "") { current ->
Column(
modifier = Modifier.padding(bottom = 6.dp + 48.dp + 6.dp /* SnackBar height */)
) {
if (current) {
val initialMode = if (profile.rootUseDefault) {
Mode.Default
} else if (profile.rootTemplate != null) {
Mode.Template
} else {
Mode.Custom
}
var mode by rememberSaveable {
mutableStateOf(initialMode)
}
ProfileBox(mode, true) {
// template mode shouldn't change profile here!
if (it == Mode.Default || it == Mode.Custom) {
onProfileChange(profile.copy(rootUseDefault = it == Mode.Default))
}
mode = it
}
Crossfade(targetState = mode, label = "") { currentMode ->
if (currentMode == Mode.Template) {
TemplateConfig(
profile = profile,
onViewTemplate = onViewTemplate,
onManageTemplate = onManageTemplate,
onProfileChange = onProfileChange
)
} else if (mode == Mode.Custom) {
RootProfileConfig(
fixedName = true,
profile = profile,
onProfileChange = onProfileChange
)
}
}
} else {
val mode = if (profile.nonRootUseDefault) Mode.Default else Mode.Custom
ProfileBox(mode, false) {
onProfileChange(profile.copy(nonRootUseDefault = (it == Mode.Default)))
}
Crossfade(targetState = mode, label = "") { currentMode ->
val modifyEnabled = currentMode == Mode.Custom
AppProfileConfig(
fixedName = true,
profile = profile,
enabled = modifyEnabled,
onProfileChange = onProfileChange
)
}
}
}
}
}
}
private enum class Mode(@StringRes private val res: Int) {
Default(R.string.profile_default), Template(R.string.profile_template), Custom(R.string.profile_custom);
val text: String
@Composable get() = stringResource(res)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun TopBar(
onBack: () -> Unit,
scrollBehavior: TopAppBarScrollBehavior? = null
) {
TopAppBar(
title = {
Text(stringResource(R.string.profile))
},
navigationIcon = {
IconButton(
onClick = onBack
) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) }
},
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal),
scrollBehavior = scrollBehavior
)
}
@Composable
private fun ProfileBox(
mode: Mode,
hasTemplate: Boolean,
onModeChange: (Mode) -> Unit,
) {
ListItem(
headlineContent = { Text(stringResource(R.string.profile)) },
supportingContent = { Text(mode.text) },
leadingContent = { Icon(Icons.Filled.AccountCircle, null) },
)
HorizontalDivider(thickness = Dp.Hairline)
ListItem(headlineContent = {
Row(
modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly
) {
FilterChip(
selected = mode == Mode.Default,
label = { Text(stringResource(R.string.profile_default)) },
onClick = { onModeChange(Mode.Default) },
)
if (hasTemplate) {
FilterChip(
selected = mode == Mode.Template,
label = { Text(stringResource(R.string.profile_template)) },
onClick = { onModeChange(Mode.Template) },
)
}
FilterChip(
selected = mode == Mode.Custom,
label = { Text(stringResource(R.string.profile_custom)) },
onClick = { onModeChange(Mode.Custom) },
)
}
})
}
@Composable
private fun AppMenuBox(packageName: String, content: @Composable () -> Unit) {
var expanded by remember { mutableStateOf(false) }
var touchPoint: Offset by remember { mutableStateOf(Offset.Zero) }
val density = LocalDensity.current
BoxWithConstraints(
Modifier
.fillMaxSize()
.pointerInput(Unit) {
detectTapGestures {
touchPoint = it
expanded = true
}
}
) {
content()
val (offsetX, offsetY) = with(density) {
(touchPoint.x.toDp()) to (touchPoint.y.toDp())
}
DropdownMenu(
expanded = expanded,
offset = DpOffset(offsetX, -offsetY),
onDismissRequest = {
expanded = false
},
) {
DropdownMenuItem(
text = { Text(stringResource(id = R.string.launch_app)) },
onClick = {
expanded = false
launchApp(packageName)
},
)
DropdownMenuItem(
text = { Text(stringResource(id = R.string.force_stop_app)) },
onClick = {
expanded = false
forceStopApp(packageName)
},
)
DropdownMenuItem(
text = { Text(stringResource(id = R.string.restart_app)) },
onClick = {
expanded = false
restartApp(packageName)
},
)
}
}
}
@Preview
@Composable
private fun AppProfilePreview() {
var profile by remember { mutableStateOf(Natives.Profile("")) }
AppProfileInner(
packageName = "icu.nullptr.test",
appLabel = "Test",
appIcon = { Icon(Icons.Filled.Android, null) },
profile = profile,
onProfileChange = {
profile = it
},
)
}

View File

@@ -1,26 +0,0 @@
package com.rifsxd.ksunext.ui.screen
import androidx.annotation.StringRes
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.*
import androidx.compose.material.icons.outlined.*
import androidx.compose.ui.graphics.vector.ImageVector
import com.ramcosta.composedestinations.generated.destinations.HomeScreenDestination
import com.ramcosta.composedestinations.generated.destinations.ModuleScreenDestination
import com.ramcosta.composedestinations.generated.destinations.SuperUserScreenDestination
import com.ramcosta.composedestinations.generated.destinations.SettingScreenDestination
import com.ramcosta.composedestinations.spec.DirectionDestinationSpec
import com.rifsxd.ksunext.R
enum class BottomBarDestination(
val direction: DirectionDestinationSpec,
@StringRes val label: Int,
val iconSelected: ImageVector,
val iconNotSelected: ImageVector,
val rootRequired: Boolean,
) {
Home(HomeScreenDestination, R.string.home, Icons.Filled.Home, Icons.Outlined.Home, false),
SuperUser(SuperUserScreenDestination, R.string.superuser, Icons.Filled.AdminPanelSettings, Icons.Outlined.AdminPanelSettings, true),
Module(ModuleScreenDestination, R.string.module, Icons.Filled.Layers, Icons.Outlined.Layers, true),
Settings(SettingScreenDestination, R.string.settings, Icons.Filled.Settings, Icons.Outlined.Settings, false)
}

View File

@@ -1,182 +0,0 @@
package com.rifsxd.ksunext.ui.screen
import android.os.Environment
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.only
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Save
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.key
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import com.rifsxd.ksunext.R
import com.rifsxd.ksunext.ui.component.KeyEventBlocker
import com.rifsxd.ksunext.ui.util.LocalSnackbarHost
import com.rifsxd.ksunext.ui.util.runModuleAction
import java.io.File
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
@Composable
@Destination<RootGraph>
fun ExecuteModuleActionScreen(navigator: DestinationsNavigator, moduleId: String) {
var text by rememberSaveable { mutableStateOf("") }
var tempText: String
val logContent = rememberSaveable { StringBuilder() }
val snackBarHost = LocalSnackbarHost.current
val scope = rememberCoroutineScope()
val scrollState = rememberScrollState()
var actionResult: Boolean
var isActionRunning by rememberSaveable { mutableStateOf(true) }
BackHandler(enabled = isActionRunning) {
// Disable back button if action is running
}
LaunchedEffect(Unit) {
if (text.isNotEmpty()) {
return@LaunchedEffect
}
withContext(Dispatchers.IO) {
runModuleAction(
moduleId = moduleId,
onStdout = {
tempText = "$it\n"
if (tempText.startsWith("")) { // clear command
text = tempText.substring(6)
} else {
text += tempText
}
logContent.append(it).append("\n")
},
onStderr = {
logContent.append(it).append("\n")
}
).let {
actionResult = it
}
}
isActionRunning = false
}
Scaffold(
topBar = {
TopBar(
isActionRunning = isActionRunning,
onBack = {
navigator.popBackStack()
},
onSave = {
if (!isActionRunning) {
scope.launch {
val format = SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.getDefault())
val date = format.format(Date())
val file = File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
"KernelSU_module_action_log_${date}.log"
)
file.writeText(logContent.toString())
snackBarHost.showSnackbar("Log saved to ${file.absolutePath}")
}
}
}
)
},
floatingActionButton = {
if (!isActionRunning) {
ExtendedFloatingActionButton(
text = { Text(text = stringResource(R.string.close)) },
icon = { Icon(Icons.Filled.Close, contentDescription = null) },
onClick = {
navigator.popBackStack()
}
)
}
},
contentWindowInsets = WindowInsets.safeDrawing,
snackbarHost = { SnackbarHost(snackBarHost) }
) { innerPadding ->
KeyEventBlocker {
it.key == Key.VolumeDown || it.key == Key.VolumeUp
}
Column(
modifier = Modifier
.fillMaxSize(1f)
.padding(innerPadding)
.verticalScroll(scrollState),
) {
LaunchedEffect(text) {
scrollState.animateScrollTo(scrollState.maxValue)
}
Text(
modifier = Modifier.padding(8.dp),
text = text,
fontSize = MaterialTheme.typography.bodySmall.fontSize,
fontFamily = FontFamily.Monospace,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
)
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun TopBar(isActionRunning: Boolean, onBack: () -> Unit = {}, onSave: () -> Unit = {}) {
TopAppBar(
title = { Text(stringResource(R.string.action)) },
navigationIcon = {
IconButton(
onClick = onBack,
enabled = !isActionRunning
) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) }
},
actions = {
IconButton(
onClick = onSave,
enabled = !isActionRunning
) {
Icon(
imageVector = Icons.Filled.Save,
contentDescription = stringResource(id = R.string.save_log),
)
}
}
)
}

View File

@@ -1,323 +0,0 @@
package com.rifsxd.ksunext.ui.screen
import android.net.Uri
import android.os.Environment
import android.os.Parcelable
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Save
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.parcelize.Parcelize
import com.rifsxd.ksunext.R
import com.rifsxd.ksunext.ui.component.KeyEventBlocker
import com.rifsxd.ksunext.ui.util.LkmSelection
import com.rifsxd.ksunext.ui.util.LocalSnackbarHost
import com.rifsxd.ksunext.ui.util.flashModule
import com.rifsxd.ksunext.ui.util.installBoot
import com.rifsxd.ksunext.ui.util.reboot
import com.rifsxd.ksunext.ui.util.restoreBoot
import com.rifsxd.ksunext.ui.util.uninstallPermanently
import java.io.File
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
enum class FlashingStatus {
FLASHING,
SUCCESS,
FAILED
}
// Lets you flash modules sequentially when mutiple zipUris are selected
fun flashModulesSequentially(
uris: List<Uri>,
onFinish: (Boolean, Int) -> Unit,
onStdout: (String) -> Unit,
onStderr: (String) -> Unit
) {
val iterator = uris.iterator()
// Start processing from the first module inside a coroutine
CoroutineScope(Dispatchers.IO).launch {
// Define the recursive function within the coroutine
suspend fun processNext() {
if (iterator.hasNext()) {
// Flash the current module
flashModule(iterator.next(), onFinish = { showReboot, code ->
// If successful, continue to the next one
if (code == 0) {
// Recursively call to process the next module
launch {
processNext()
}
} else {
onFinish(showReboot, code) // If failed, finish the process
}
}, onStdout, onStderr)
} else {
// No more modules to process, finish the process
onFinish(true, 0)
}
}
// Start the process
processNext()
}
}
/**
* @author weishu
* @date 2023/1/1.
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@Destination<RootGraph>
fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
var text by rememberSaveable { mutableStateOf("") }
var tempText : String
val logContent = rememberSaveable { StringBuilder() }
var showFloatAction by rememberSaveable { mutableStateOf(false) }
val snackBarHost = LocalSnackbarHost.current
val scope = rememberCoroutineScope()
val scrollState = rememberScrollState()
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
var flashing by rememberSaveable {
mutableStateOf(FlashingStatus.FLASHING)
}
BackHandler(enabled = flashing == FlashingStatus.FLASHING) {
// Disable back button if flashing is running
}
LaunchedEffect(Unit) {
if (text.isNotEmpty()) {
return@LaunchedEffect
}
withContext(Dispatchers.IO) {
flashIt(flashIt, onFinish = { showReboot, code ->
if (code != 0) {
text += "Error: exit code = $code.\nPlease save and check the log.\n"
}
if (showReboot) {
text += "\n\n\n"
showFloatAction = true
}
flashing = if (code == 0) FlashingStatus.SUCCESS else FlashingStatus.FAILED
}, onStdout = {
tempText = "$it\n"
if (tempText.startsWith("")) { // clear command
text = tempText.substring(6)
} else {
text += tempText
}
logContent.append(it).append("\n")
}, onStderr = {
logContent.append(it).append("\n")
})
}
}
Scaffold(
topBar = {
TopBar(
flashing,
onBack = {
navigator.popBackStack()
},
onSave = {
scope.launch {
val format = SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.getDefault())
val date = format.format(Date())
val file = File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
"KernelSU_install_log_${date}.log"
)
file.writeText(logContent.toString())
snackBarHost.showSnackbar("Log saved to ${file.absolutePath}")
}
},
scrollBehavior = scrollBehavior
)
},
floatingActionButton = {
if (showFloatAction) {
// Reboot button (bottom left)
ExtendedFloatingActionButton(
onClick = {
scope.launch {
withContext(Dispatchers.IO) {
reboot()
}
}
},
icon = { Icon(Icons.Filled.Refresh, contentDescription = stringResource(R.string.reboot)) },
text = { Text(text = stringResource(R.string.reboot)) }
)
}
},
contentWindowInsets = WindowInsets.safeDrawing,
snackbarHost = { SnackbarHost(hostState = snackBarHost) }
) { innerPadding ->
KeyEventBlocker {
it.key == Key.VolumeDown || it.key == Key.VolumeUp
}
Column(
modifier = Modifier
.fillMaxSize(1f)
.padding(innerPadding)
.nestedScroll(scrollBehavior.nestedScrollConnection)
.verticalScroll(scrollState),
) {
LaunchedEffect(text) {
scrollState.animateScrollTo(scrollState.maxValue)
}
Text(
modifier = Modifier.padding(8.dp),
text = text,
fontSize = MaterialTheme.typography.bodySmall.fontSize,
fontFamily = FontFamily.Monospace,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
)
}
}
}
@Parcelize
sealed class FlashIt : Parcelable {
data class FlashBoot(val boot: Uri? = null, val lkm: LkmSelection, val ota: Boolean) :
FlashIt()
data class FlashModule(val uri: Uri) : FlashIt()
data class FlashModules(val uris: List<Uri>) : FlashIt()
data object FlashRestore : FlashIt()
data object FlashUninstall : FlashIt()
}
fun flashIt(
flashIt: FlashIt, onFinish: (Boolean, Int) -> Unit,
onStdout: (String) -> Unit,
onStderr: (String) -> Unit
) {
when (flashIt) {
is FlashIt.FlashBoot -> installBoot(
flashIt.boot,
flashIt.lkm,
flashIt.ota,
onFinish,
onStdout,
onStderr
)
is FlashIt.FlashModule -> flashModule(flashIt.uri, onFinish, onStdout, onStderr)
is FlashIt.FlashModules -> {
flashModulesSequentially(flashIt.uris, onFinish, onStdout, onStderr)
}
FlashIt.FlashRestore -> restoreBoot(onFinish, onStdout, onStderr)
FlashIt.FlashUninstall -> uninstallPermanently(onFinish, onStdout, onStderr)
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun TopBar(
status: FlashingStatus,
onBack: () -> Unit = {},
onSave: () -> Unit = {},
scrollBehavior: TopAppBarScrollBehavior? = null
) {
TopAppBar(
title = {
Text(
stringResource(
when (status) {
FlashingStatus.FLASHING -> R.string.flashing
FlashingStatus.SUCCESS -> R.string.flash_success
FlashingStatus.FAILED -> R.string.flash_failed
}
)
)
},
navigationIcon = {
IconButton(
onClick = { if (status != FlashingStatus.FLASHING) onBack() },
enabled = status != FlashingStatus.FLASHING
) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) }
},
actions = {
IconButton(
onClick = { if (status != FlashingStatus.FLASHING) onSave() },
enabled = status != FlashingStatus.FLASHING
) {
Icon(
imageVector = Icons.Filled.Save,
contentDescription = "Localized description"
)
}
},
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal),
scrollBehavior = scrollBehavior
)
}
@Preview
@Composable
fun InstallPreview() {
InstallScreen(EmptyDestinationsNavigator)
}

View File

@@ -1,619 +0,0 @@
package com.rifsxd.ksunext.ui.screen
import android.content.Context
import android.os.Build
import android.os.PowerManager
import android.os.Handler
import android.os.Looper
import android.system.Os
import androidx.annotation.StringRes
import androidx.compose.animation.*
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.*
import androidx.compose.material.icons.filled.*
import androidx.compose.material.icons.outlined.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.content.pm.PackageInfoCompat
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.generated.destinations.InstallScreenDestination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import com.rifsxd.ksunext.*
import com.rifsxd.ksunext.R
import com.rifsxd.ksunext.ui.component.rememberConfirmDialog
import com.rifsxd.ksunext.ui.util.*
import com.rifsxd.ksunext.ui.util.module.LatestVersionInfo
import java.util.*
@OptIn(ExperimentalMaterial3Api::class)
@Destination<RootGraph>(start = true)
@Composable
fun HomeScreen(navigator: DestinationsNavigator) {
val kernelVersion = getKernelVersion()
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
val isManager = Natives.becomeManager(ksuApp.packageName)
val ksuVersion = if (isManager) Natives.version else null
Scaffold(
topBar = {
TopBar(
kernelVersion,
ksuVersion,
onInstallClick = {
navigator.navigate(InstallScreenDestination)
},
scrollBehavior = scrollBehavior
)
},
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
) { innerPadding ->
Column(
modifier = Modifier
.padding(innerPadding)
.nestedScroll(scrollBehavior.nestedScrollConnection)
.verticalScroll(rememberScrollState())
.padding(horizontal = 16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
val lkmMode = ksuVersion?.let {
if (it >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && kernelVersion.isGKI()) Natives.isLkmMode else null
}
StatusCard(kernelVersion, ksuVersion, lkmMode) {
navigator.navigate(InstallScreenDestination)
}
if (isManager && Natives.requireNewKernel()) {
WarningCard(
stringResource(id = R.string.require_kernel_version).format(
ksuVersion, Natives.MINIMAL_SUPPORTED_KERNEL
)
)
}
if (ksuVersion != null && !rootAvailable()) {
WarningCard(
stringResource(id = R.string.grant_root_failed)
)
}
val checkUpdate =
LocalContext.current.getSharedPreferences("settings", Context.MODE_PRIVATE)
.getBoolean("check_update", true)
if (checkUpdate) {
UpdateCard()
}
//NextCard()
InfoCard()
IssueReportCard()
//EXperimentalCard()
Spacer(Modifier)
}
}
}
@Composable
fun UpdateCard() {
val context = LocalContext.current
val latestVersionInfo = LatestVersionInfo()
val newVersion by produceState(initialValue = latestVersionInfo) {
value = withContext(Dispatchers.IO) {
checkNewVersion()
}
}
val currentVersionCode = getManagerVersion(context).second
val newVersionCode = newVersion.versionCode
val newVersionUrl = newVersion.downloadUrl
val changelog = newVersion.changelog
val uriHandler = LocalUriHandler.current
val title = stringResource(id = R.string.module_changelog)
val updateText = stringResource(id = R.string.module_update)
AnimatedVisibility(
visible = newVersionCode > currentVersionCode,
enter = fadeIn() + expandVertically(),
exit = shrinkVertically() + fadeOut()
) {
val updateDialog = rememberConfirmDialog(onConfirm = { uriHandler.openUri(newVersionUrl) })
WarningCard(
message = stringResource(id = R.string.new_version_available).format(newVersionCode),
MaterialTheme.colorScheme.outlineVariant
) {
if (changelog.isEmpty()) {
uriHandler.openUri(newVersionUrl)
} else {
updateDialog.showConfirm(
title = title,
content = changelog,
markdown = true,
confirm = updateText
)
}
}
}
}
@Composable
fun RebootDropdownItem(@StringRes id: Int, reason: String = "") {
DropdownMenuItem(text = {
Text(stringResource(id))
}, onClick = {
reboot(reason)
})
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun TopBar(
kernelVersion: KernelVersion,
ksuVersion: Int?,
onInstallClick: () -> Unit,
scrollBehavior: TopAppBarScrollBehavior? = null
) {
TopAppBar(
title = { Text(stringResource(R.string.app_name)) },
actions = {
if (kernelVersion.isGKI()) {
IconButton(onClick = onInstallClick) {
Icon(
imageVector = Icons.Filled.Archive,
contentDescription = stringResource(id = R.string.install)
)
}
}
if (ksuVersion != null) {
var showDropdown by remember { mutableStateOf(false) }
IconButton(onClick = {
showDropdown = true
}) {
Icon(
imageVector = Icons.Filled.Refresh,
contentDescription = stringResource(id = R.string.reboot)
)
DropdownMenu(expanded = showDropdown, onDismissRequest = {
showDropdown = false
}) {
RebootDropdownItem(id = R.string.reboot)
val pm = LocalContext.current.getSystemService(Context.POWER_SERVICE) as PowerManager?
@Suppress("DEPRECATION")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && pm?.isRebootingUserspaceSupported == true) {
RebootDropdownItem(id = R.string.reboot_userspace, reason = "userspace")
}
RebootDropdownItem(id = R.string.reboot_recovery, reason = "recovery")
RebootDropdownItem(id = R.string.reboot_bootloader, reason = "bootloader")
RebootDropdownItem(id = R.string.reboot_download, reason = "download")
RebootDropdownItem(id = R.string.reboot_edl, reason = "edl")
}
}
}
},
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal),
scrollBehavior = scrollBehavior
)
}
@Composable
fun getSeasonalIcon(): ImageVector {
val month = Calendar.getInstance().get(Calendar.MONTH) // 0-11 for January-December
return when (month) {
Calendar.DECEMBER, Calendar.JANUARY, Calendar.FEBRUARY -> Icons.Filled.AcUnit // Winter
Calendar.MARCH, Calendar.APRIL, Calendar.MAY -> Icons.Filled.Spa // Spring
Calendar.JUNE, Calendar.JULY, Calendar.AUGUST -> Icons.Filled.WbSunny // Summer
Calendar.SEPTEMBER, Calendar.OCTOBER, Calendar.NOVEMBER -> Icons.Filled.Forest // Fall
else -> Icons.Filled.Whatshot // Fallback icon
}
}
@Composable
private fun StatusCard(
kernelVersion: KernelVersion,
ksuVersion: Int?,
lkmMode: Boolean?,
onClickInstall: () -> Unit = {}
) {
ElevatedCard(
colors = CardDefaults.elevatedCardColors(containerColor = run {
if (ksuVersion != null) MaterialTheme.colorScheme.secondaryContainer
else MaterialTheme.colorScheme.errorContainer
})
) {
Row(modifier = Modifier
.fillMaxWidth()
.clickable {
if (kernelVersion.isGKI()) {
onClickInstall()
}
}
.padding(24.dp), verticalAlignment = Alignment.CenterVertically) {
when {
ksuVersion != null -> {
val safeMode = when {
Natives.isSafeMode -> " [${stringResource(id = R.string.safe_mode)}]"
else -> ""
}
val workingMode = when (lkmMode) {
null -> " <LTS>"
true -> " <LKM>"
else -> " <GKI>"
}
val workingText =
"${stringResource(id = R.string.home_working)}$workingMode$safeMode"
Icon(
getSeasonalIcon(), // Use dynamic seasonal icon
contentDescription = stringResource(R.string.home_working)
)
Column(Modifier.padding(start = 20.dp)) {
Text(
text = workingText,
style = MaterialTheme.typography.titleMedium
)
Spacer(Modifier.height(4.dp))
Text(
text = stringResource(R.string.home_working_version, ksuVersion),
style = MaterialTheme.typography.bodyMedium
)
Spacer(Modifier.height(4.dp))
Text(
text = stringResource(
R.string.home_superuser_count, getSuperuserCount()
), style = MaterialTheme.typography.bodyMedium
)
Spacer(Modifier.height(4.dp))
Text(
text = stringResource(R.string.home_module_count, getModuleCount()),
style = MaterialTheme.typography.bodyMedium
)
Spacer(Modifier.height(4.dp))
val suSFS = getSuSFS()
if (suSFS == "Supported") {
Text(
text = stringResource(R.string.home_susfs, getSuSFS()),
style = MaterialTheme.typography.bodyMedium
)
}
}
}
kernelVersion.isGKI() -> {
Icon(Icons.Filled.AutoFixHigh, stringResource(R.string.home_not_installed))
Column(Modifier.padding(start = 20.dp)) {
Text(
text = stringResource(R.string.home_not_installed),
style = MaterialTheme.typography.titleMedium
)
Spacer(Modifier.height(4.dp))
Text(
text = stringResource(R.string.home_click_to_install),
style = MaterialTheme.typography.bodyMedium
)
}
}
else -> {
Icon(Icons.Filled.Dangerous, stringResource(R.string.home_failure))
Column(Modifier.padding(start = 20.dp)) {
Text(
text = stringResource(R.string.home_failure),
style = MaterialTheme.typography.titleMedium
)
Spacer(Modifier.height(4.dp))
Text(
text = stringResource(R.string.home_failure_tip),
style = MaterialTheme.typography.bodyMedium
)
}
}
}
}
}
}
@Composable
fun WarningCard(
message: String, color: Color = MaterialTheme.colorScheme.error, onClick: (() -> Unit)? = null
) {
ElevatedCard(
colors = CardDefaults.elevatedCardColors(
containerColor = color
)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.then(onClick?.let { Modifier.clickable { it() } } ?: Modifier)
.padding(24.dp)
) {
Text(
text = message, style = MaterialTheme.typography.bodyMedium
)
}
}
}
@Composable
private fun InfoCard() {
val context = LocalContext.current
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
var useOverlayFs by rememberSaveable {
mutableStateOf(prefs.getBoolean("use_overlay_fs", false))
}
val isManager = Natives.becomeManager(ksuApp.packageName)
val ksuVersion = if (isManager) Natives.version else null
LaunchedEffect(Unit) {
useOverlayFs = prefs.getBoolean("use_overlay_fs", false)
}
ElevatedCard {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(start = 24.dp, top = 24.dp, end = 24.dp, bottom = 16.dp)
) {
val contents = StringBuilder()
val uname = Os.uname()
@Composable
fun InfoCardItem(label: String, content: String, icon: Any? = null) {
Row(verticalAlignment = Alignment.CenterVertically) {
if (icon != null) {
when (icon) {
is ImageVector -> Icon(
imageVector = icon,
contentDescription = null,
modifier = Modifier.padding(end = 20.dp)
)
is Painter -> Icon(
painter = icon,
contentDescription = null,
modifier = Modifier.padding(end = 20.dp)
)
}
}
Column {
Text(
text = label,
style = MaterialTheme.typography.bodyLarge
)
Text(
text = content,
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.padding(top = 4.dp)
)
}
}
}
InfoCardItem(
label = stringResource(R.string.home_kernel),
content = uname.release,
icon = painterResource(R.drawable.ic_linux),
)
Spacer(Modifier.height(16.dp))
InfoCardItem(
label = stringResource(R.string.home_android),
content = "${Build.VERSION.RELEASE} (${Build.VERSION.SDK_INT})",
icon = Icons.Filled.Android,
)
Spacer(Modifier.height(16.dp))
val managerVersion = getManagerVersion(context)
InfoCardItem(
label = stringResource(R.string.home_manager_version),
content = "${managerVersion.first} (${managerVersion.second})",
icon = painterResource(R.drawable.ic_ksu_next),
)
Spacer(Modifier.height(16.dp))
InfoCardItem(
label = stringResource(R.string.home_selinux_status),
content = getSELinuxStatus(),
icon = Icons.Filled.Security,
)
Spacer(Modifier.height(16.dp))
InfoCardItem(
label = stringResource(R.string.home_module_mount),
content = when {
ksuVersion == null -> stringResource(R.string.unavailable)
useOverlayFs -> stringResource(R.string.home_overlayfs_mount)
else -> stringResource(R.string.home_magic_mount)
},
icon = Icons.Filled.SettingsSuggest,
)
Spacer(Modifier.height(16.dp))
val isSUS_SU = getSuSFSFeatures() == "CONFIG_KSU_SUSFS_SUS_SU"
val suSFS = getSuSFS()
if (suSFS == "Supported") {
val susSUMode = if (isSUS_SU) "| SuS SU mode: ${susfsSUS_SU_Mode()}" else ""
InfoCardItem(
label = stringResource(R.string.home_susfs_version),
content = "${getSuSFSVersion()} (${getSuSFSVariant()}) $susSUMode",
icon = painterResource(R.drawable.ic_sus),
)
}
}
}
}
@Composable
fun NextCard() {
val uriHandler = LocalUriHandler.current
val url = stringResource(R.string.home_next_kernelsu_repo)
ElevatedCard {
Row(modifier = Modifier
.fillMaxWidth()
.clickable {
uriHandler.openUri(url)
}
.padding(24.dp), verticalAlignment = Alignment.CenterVertically) {
Column {
Text(
text = stringResource(R.string.home_next_kernelsu),
style = MaterialTheme.typography.titleSmall
)
Spacer(Modifier.height(4.dp))
Text(
text = stringResource(R.string.home_next_kernelsu_body),
style = MaterialTheme.typography.bodyMedium
)
}
}
}
}
@Composable
fun EXperimentalCard() {
/*val uriHandler = LocalUriHandler.current
val url = stringResource(R.string.home_experimental_kernelsu_repo)
*/
ElevatedCard {
Row(modifier = Modifier
.fillMaxWidth()
/*.clickable {
uriHandler.openUri(url)
}
*/
.padding(24.dp), verticalAlignment = Alignment.CenterVertically) {
Column {
Text(
text = stringResource(R.string.home_experimental_kernelsu),
style = MaterialTheme.typography.titleSmall
)
Spacer(Modifier.height(4.dp))
Text(
text = stringResource(R.string.home_experimental_kernelsu_body),
style = MaterialTheme.typography.bodyMedium
)
Spacer(Modifier.height(4.dp))
Text(
text = stringResource(R.string.home_experimental_kernelsu_body_point_1),
style = MaterialTheme.typography.bodyMedium
)
Spacer(Modifier.height(2.dp))
Text(
text = stringResource(R.string.home_experimental_kernelsu_body_point_2),
style = MaterialTheme.typography.bodyMedium
)
Spacer(Modifier.height(2.dp))
Text(
text = stringResource(R.string.home_experimental_kernelsu_body_point_3),
style = MaterialTheme.typography.bodyMedium
)
}
}
}
}
@Composable
fun IssueReportCard() {
val uriHandler = LocalUriHandler.current
val githubIssueUrl = stringResource(R.string.issue_report_github_link)
val telegramUrl = stringResource(R.string.issue_report_telegram_link)
ElevatedCard {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(24.dp),
verticalAlignment = Alignment.CenterVertically
) {
Column(modifier = Modifier.weight(1f)) {
Text(
text = stringResource(R.string.issue_report_title),
style = MaterialTheme.typography.titleSmall
)
Spacer(Modifier.height(4.dp))
Text(
text = stringResource(R.string.issue_report_body),
style = MaterialTheme.typography.bodyMedium
)
Spacer(Modifier.height(4.dp))
Text(
text = stringResource(R.string.issue_report_body_2),
style = MaterialTheme.typography.bodyMedium
)
}
Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) {
IconButton(onClick = { uriHandler.openUri(githubIssueUrl) }) {
Icon(
painter = painterResource(R.drawable.ic_github),
contentDescription = stringResource(R.string.issue_report_github),
)
}
IconButton(onClick = { uriHandler.openUri(telegramUrl) }) {
Icon(
painter = painterResource(R.drawable.ic_telegram),
contentDescription = stringResource(R.string.issue_report_telegram),
)
}
}
}
}
}
fun getManagerVersion(context: Context): Pair<String, Long> {
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)!!
val versionCode = PackageInfoCompat.getLongVersionCode(packageInfo)
return Pair(packageInfo.versionName!!, versionCode)
}
@Preview
@Composable
private fun StatusCardPreview() {
Column {
StatusCard(KernelVersion(5, 10, 101), 1, null)
StatusCard(KernelVersion(5, 10, 101), 20000, true)
StatusCard(KernelVersion(5, 10, 101), null, true)
StatusCard(KernelVersion(4, 10, 101), null, false)
}
}
@Preview
@Composable
private fun WarningCardPreview() {
Column {
WarningCard(message = "Warning message")
WarningCard(
message = "Warning message ",
MaterialTheme.colorScheme.outlineVariant,
onClick = {})
}
}

View File

@@ -1,361 +0,0 @@
package com.rifsxd.ksunext.ui.screen
import android.app.Activity
import android.content.Intent
import android.net.Uri
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.StringRes
import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.selection.toggleable
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.FileUpload
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.maxkeppeker.sheets.core.models.base.Header
import com.maxkeppeker.sheets.core.models.base.rememberUseCaseState
import com.maxkeppeler.sheets.list.ListDialog
import com.maxkeppeler.sheets.list.models.ListOption
import com.maxkeppeler.sheets.list.models.ListSelection
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.generated.destinations.FlashScreenDestination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
import com.rifsxd.ksunext.R
import com.rifsxd.ksunext.ui.component.DialogHandle
import com.rifsxd.ksunext.ui.component.rememberConfirmDialog
import com.rifsxd.ksunext.ui.component.rememberCustomDialog
import com.rifsxd.ksunext.ui.util.LkmSelection
import com.rifsxd.ksunext.ui.util.getCurrentKmi
import com.rifsxd.ksunext.ui.util.getSupportedKmis
import com.rifsxd.ksunext.ui.util.isAbDevice
import com.rifsxd.ksunext.ui.util.isInitBoot
import com.rifsxd.ksunext.ui.util.rootAvailable
/**
* @author weishu
* @date 2024/3/12.
*/
@OptIn(ExperimentalMaterial3Api::class)
@Destination<RootGraph>
@Composable
fun InstallScreen(navigator: DestinationsNavigator) {
var installMethod by remember {
mutableStateOf<InstallMethod?>(null)
}
var lkmSelection by remember {
mutableStateOf<LkmSelection>(LkmSelection.KmiNone)
}
val onInstall = {
installMethod?.let { method ->
val flashIt = FlashIt.FlashBoot(
boot = if (method is InstallMethod.SelectFile) method.uri else null,
lkm = lkmSelection,
ota = method is InstallMethod.DirectInstallToInactiveSlot
)
navigator.navigate(FlashScreenDestination(flashIt))
}
}
val currentKmi by produceState(initialValue = "") { value = getCurrentKmi() }
val selectKmiDialog = rememberSelectKmiDialog { kmi ->
kmi?.let {
lkmSelection = LkmSelection.KmiString(it)
onInstall()
}
}
val onClickNext = {
if (lkmSelection == LkmSelection.KmiNone && currentKmi.isBlank()) {
// no lkm file selected and cannot get current kmi
selectKmiDialog.show()
} else {
onInstall()
}
}
val selectLkmLauncher =
rememberLauncherForActivityResult(contract = ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode == Activity.RESULT_OK) {
it.data?.data?.let { uri ->
lkmSelection = LkmSelection.LkmUri(uri)
}
}
}
val onLkmUpload = {
selectLkmLauncher.launch(Intent(Intent.ACTION_GET_CONTENT).apply {
type = "application/octet-stream"
})
}
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
Scaffold(
topBar = {
TopBar(
onBack = { navigator.popBackStack() },
onLkmUpload = onLkmUpload,
scrollBehavior = scrollBehavior
)
},
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
) { innerPadding ->
Column(
modifier = Modifier
.padding(innerPadding)
.nestedScroll(scrollBehavior.nestedScrollConnection)
.verticalScroll(rememberScrollState())
) {
SelectInstallMethod { method ->
installMethod = method
}
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
(lkmSelection as? LkmSelection.LkmUri)?.let {
Text(
stringResource(
id = R.string.selected_lkm,
it.uri.lastPathSegment ?: "(file)"
)
)
}
Button(modifier = Modifier.fillMaxWidth(),
enabled = installMethod != null,
onClick = {
onClickNext()
}) {
Text(
stringResource(id = R.string.install_next),
fontSize = MaterialTheme.typography.bodyMedium.fontSize
)
}
}
}
}
}
sealed class InstallMethod {
data class SelectFile(
val uri: Uri? = null,
@StringRes override val label: Int = R.string.select_file,
override val summary: String?
) : InstallMethod()
data object DirectInstall : InstallMethod() {
override val label: Int
get() = R.string.direct_install
}
data object DirectInstallToInactiveSlot : InstallMethod() {
override val label: Int
get() = R.string.install_inactive_slot
}
abstract val label: Int
open val summary: String? = null
}
@Composable
private fun SelectInstallMethod(onSelected: (InstallMethod) -> Unit = {}) {
val rootAvailable = rootAvailable()
val isAbDevice = isAbDevice()
val selectFileTip = stringResource(
id = R.string.select_file_tip, if (isInitBoot()) "init_boot" else "boot"
)
val radioOptions =
mutableListOf<InstallMethod>(InstallMethod.SelectFile(summary = selectFileTip))
if (rootAvailable) {
radioOptions.add(InstallMethod.DirectInstall)
if (isAbDevice) {
radioOptions.add(InstallMethod.DirectInstallToInactiveSlot)
}
}
var selectedOption by remember { mutableStateOf<InstallMethod?>(null) }
val selectImageLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult()
) {
if (it.resultCode == Activity.RESULT_OK) {
it.data?.data?.let { uri ->
val option = InstallMethod.SelectFile(uri, summary = selectFileTip)
selectedOption = option
onSelected(option)
}
}
}
val confirmDialog = rememberConfirmDialog(onConfirm = {
selectedOption = InstallMethod.DirectInstallToInactiveSlot
onSelected(InstallMethod.DirectInstallToInactiveSlot)
}, onDismiss = null)
val dialogTitle = stringResource(id = android.R.string.dialog_alert_title)
val dialogContent = stringResource(id = R.string.install_inactive_slot_warning)
val onClick = { option: InstallMethod ->
when (option) {
is InstallMethod.SelectFile -> {
selectImageLauncher.launch(Intent(Intent.ACTION_GET_CONTENT).apply {
type = "application/octet-stream"
})
}
is InstallMethod.DirectInstall -> {
selectedOption = option
onSelected(option)
}
is InstallMethod.DirectInstallToInactiveSlot -> {
confirmDialog.showConfirm(dialogTitle, dialogContent)
}
}
}
Column {
radioOptions.forEach { option ->
val interactionSource = remember { MutableInteractionSource() }
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.toggleable(
value = option.javaClass == selectedOption?.javaClass,
onValueChange = {
onClick(option)
},
role = Role.RadioButton,
indication = LocalIndication.current,
interactionSource = interactionSource
)
) {
RadioButton(
selected = option.javaClass == selectedOption?.javaClass,
onClick = {
onClick(option)
},
interactionSource = interactionSource
)
Column(
modifier = Modifier.padding(vertical = 12.dp)
) {
Text(
text = stringResource(id = option.label),
fontSize = MaterialTheme.typography.titleMedium.fontSize,
fontFamily = MaterialTheme.typography.titleMedium.fontFamily,
fontStyle = MaterialTheme.typography.titleMedium.fontStyle
)
option.summary?.let {
Text(
text = it,
fontSize = MaterialTheme.typography.bodySmall.fontSize,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
fontStyle = MaterialTheme.typography.bodySmall.fontStyle
)
}
}
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun rememberSelectKmiDialog(onSelected: (String?) -> Unit): DialogHandle {
return rememberCustomDialog { dismiss ->
val supportedKmi by produceState(initialValue = emptyList<String>()) {
value = getSupportedKmis()
}
val options = supportedKmi.map { value ->
ListOption(
titleText = value
)
}
var selection by remember { mutableStateOf<String?>(null) }
ListDialog(state = rememberUseCaseState(visible = true, onFinishedRequest = {
onSelected(selection)
}, onCloseRequest = {
dismiss()
}), header = Header.Default(
title = stringResource(R.string.select_kmi),
), selection = ListSelection.Single(
showRadioButtons = true,
options = options,
) { _, option ->
selection = option.titleText
})
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun TopBar(
onBack: () -> Unit = {},
onLkmUpload: () -> Unit = {},
scrollBehavior: TopAppBarScrollBehavior? = null
) {
TopAppBar(
title = { Text(stringResource(R.string.install)) }, navigationIcon = {
IconButton(
onClick = onBack
) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) }
}, actions = {
IconButton(onClick = onLkmUpload) {
Icon(Icons.Filled.FileUpload, contentDescription = null)
}
},
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal),
scrollBehavior = scrollBehavior
)
}
@Composable
@Preview
fun SelectInstallPreview() {
InstallScreen(EmptyDestinationsNavigator)
}

View File

@@ -1,861 +0,0 @@
package com.rifsxd.ksunext.ui.screen
import android.app.Activity.RESULT_OK
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.util.Log
import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.selection.toggleable
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.Wysiwyg
import androidx.compose.material.icons.filled.*
import androidx.compose.material.icons.outlined.*
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Checkbox
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FilledTonalButton
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.SnackbarResult
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.generated.destinations.ExecuteModuleActionScreenDestination
import com.ramcosta.composedestinations.generated.destinations.FlashScreenDestination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import com.rifsxd.ksunext.Natives
import com.rifsxd.ksunext.R
import com.rifsxd.ksunext.ui.component.ConfirmResult
import com.rifsxd.ksunext.ui.component.rememberConfirmDialog
import com.rifsxd.ksunext.ui.component.rememberLoadingDialog
import com.rifsxd.ksunext.ui.component.SearchAppBar
import com.rifsxd.ksunext.ui.util.*
import com.rifsxd.ksunext.ui.util.DownloadListener
import com.rifsxd.ksunext.ui.util.LocalSnackbarHost
import com.rifsxd.ksunext.ui.util.download
import com.rifsxd.ksunext.ui.util.hasMagisk
import com.rifsxd.ksunext.ui.util.reboot
import com.rifsxd.ksunext.ui.util.toggleModule
import com.rifsxd.ksunext.ui.util.uninstallModule
import com.rifsxd.ksunext.ui.util.restoreModule
import com.rifsxd.ksunext.ui.viewmodel.ModuleViewModel
import com.rifsxd.ksunext.ui.webui.WebUIActivity
import okhttp3.OkHttpClient
@OptIn(ExperimentalMaterial3Api::class)
@Destination<RootGraph>
@Composable
fun ModuleScreen(navigator: DestinationsNavigator) {
val viewModel = viewModel<ModuleViewModel>()
val context = LocalContext.current
val snackBarHost = LocalSnackbarHost.current
val scope = rememberCoroutineScope()
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
LaunchedEffect(Unit) {
if (viewModel.moduleList.isEmpty() || viewModel.isNeedRefresh) {
viewModel.sortAToZ = prefs.getBoolean("module_sort_a_to_z", true)
viewModel.sortZToA = prefs.getBoolean("module_sort_z_to_a", false)
viewModel.fetchModuleList()
}
}
val isSafeMode = Natives.isSafeMode
val hasMagisk = hasMagisk()
val hideInstallButton = isSafeMode || hasMagisk
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
var zipUri by remember { mutableStateOf<Uri?>(null) }
var zipUris by remember { mutableStateOf<List<Uri>>(emptyList()) }
var showConfirmDialog by remember { mutableStateOf(false) }
val webUILauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult()
) { viewModel.fetchModuleList() }
Scaffold(
topBar = {
SearchAppBar(
title = { Text(stringResource(R.string.module)) },
searchText = viewModel.search,
onSearchTextChange = { viewModel.search = it },
onClearClick = { viewModel.search = "" },
dropdownContent = {
var showDropdown by remember { mutableStateOf(false) }
IconButton(
onClick = { showDropdown = true },
) {
Icon(
imageVector = Icons.Filled.MoreVert,
contentDescription = stringResource(id = R.string.settings)
)
DropdownMenu(
expanded = showDropdown,
onDismissRequest = {
showDropdown = false
}
) {
DropdownMenuItem(
text = {
Text(stringResource(R.string.module_sort_a_to_z))
},
trailingIcon = {
Checkbox(checked = viewModel.sortAToZ, onCheckedChange = null)
},
onClick = {
viewModel.sortAToZ = !viewModel.sortAToZ
viewModel.sortZToA = false
prefs.edit()
.putBoolean("module_sort_a_to_z", viewModel.sortAToZ)
.putBoolean("module_sort_z_to_a", false)
.apply()
scope.launch {
viewModel.fetchModuleList()
}
}
)
DropdownMenuItem(
text = {
Text(stringResource(R.string.module_sort_z_to_a))
},
trailingIcon = {
Checkbox(checked = viewModel.sortZToA, onCheckedChange = null)
},
onClick = {
viewModel.sortZToA = !viewModel.sortZToA
viewModel.sortAToZ = false
prefs.edit()
.putBoolean("module_sort_z_to_a", viewModel.sortZToA)
.putBoolean("module_sort_a_to_z", false)
.apply()
scope.launch {
viewModel.fetchModuleList()
}
}
)
}
}
},
scrollBehavior = scrollBehavior
)
},
floatingActionButton = {
if (!hideInstallButton) {
val moduleInstall = stringResource(id = R.string.module_install)
val selectZipLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode != RESULT_OK) {
return@rememberLauncherForActivityResult
}
val data = result.data ?: return@rememberLauncherForActivityResult
val clipData = data.clipData
val uris = mutableListOf<Uri>()
if (clipData != null) {
for (i in 0 until clipData.itemCount) {
clipData.getItemAt(i)?.uri?.let { uris.add(it) }
}
} else {
data.data?.let { uris.add(it) }
}
zipUris = uris
showConfirmDialog = uris.isNotEmpty()
}
ExtendedFloatingActionButton(
onClick = {
// Select the zip files to install
val intent = Intent(Intent.ACTION_GET_CONTENT).apply {
type = "application/zip"
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
}
selectZipLauncher.launch(intent)
},
icon = { Icon(Icons.Filled.Add, moduleInstall) },
text = { Text(text = moduleInstall) },
)
}
},
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal),
snackbarHost = { SnackbarHost(hostState = snackBarHost) }
) { innerPadding ->
// Confirmation dialog
if (showConfirmDialog && zipUris.isNotEmpty()) {
val moduleNames = zipUris.joinToString("\n") { getFileName(context, it) }
AlertDialog(
onDismissRequest = { showConfirmDialog = false },
confirmButton = {
TextButton(onClick = {
showConfirmDialog = false
navigator.navigate(FlashScreenDestination(FlashIt.FlashModules(zipUris)))
viewModel.markNeedRefresh()
}) {
Text(stringResource(R.string.confirm))
}
},
dismissButton = {
TextButton(onClick = { showConfirmDialog = false }) {
Text(stringResource(android.R.string.cancel))
}
},
title = { Text(stringResource(R.string.module)) },
text = {
Text(
stringResource(R.string.module_install_prompt_with_name, moduleNames)
)
}
)
}
when {
hasMagisk -> {
Box(
modifier = Modifier
.fillMaxSize()
.padding(24.dp),
contentAlignment = Alignment.Center
) {
Text(
stringResource(R.string.module_magisk_conflict),
textAlign = TextAlign.Center,
)
}
}
else -> {
ModuleList(
navigator,
viewModel = viewModel,
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
boxModifier = Modifier.padding(innerPadding),
onInstallModule = {
navigator.navigate(FlashScreenDestination(FlashIt.FlashModule(it)))
},
onClickModule = { id, name, hasWebUi ->
if (hasWebUi) {
webUILauncher.launch(
Intent(context, WebUIActivity::class.java)
.setData(Uri.parse("kernelsu://webui/$id"))
.putExtra("id", id)
.putExtra("name", name)
)
}
},
context = context,
snackBarHost = snackBarHost
)
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun ModuleList(
navigator: DestinationsNavigator,
viewModel: ModuleViewModel,
modifier: Modifier = Modifier,
boxModifier: Modifier = Modifier,
onInstallModule: (Uri) -> Unit,
onClickModule: (id: String, name: String, hasWebUi: Boolean) -> Unit,
context: Context,
snackBarHost: SnackbarHostState
) {
val failedEnable = stringResource(R.string.module_failed_to_enable)
val failedDisable = stringResource(R.string.module_failed_to_disable)
val failedUninstall = stringResource(R.string.module_uninstall_failed)
val failedRestore = stringResource(R.string.module_restore_failed)
val successUninstall = stringResource(R.string.module_uninstall_success)
val successRestore = stringResource(R.string.module_restore_success)
val reboot = stringResource(R.string.reboot)
val rebootToApply = stringResource(R.string.reboot_to_apply)
val moduleStr = stringResource(R.string.module)
val uninstall = stringResource(R.string.uninstall)
val restore = stringResource(R.string.restore)
val cancel = stringResource(android.R.string.cancel)
val moduleUninstallConfirm = stringResource(R.string.module_uninstall_confirm)
val moduleRestoreConfirm = stringResource(R.string.module_restore_confirm)
val updateText = stringResource(R.string.module_update)
val changelogText = stringResource(R.string.module_changelog)
val downloadingText = stringResource(R.string.module_downloading)
val startDownloadingText = stringResource(R.string.module_start_downloading)
val fetchChangeLogFailed = stringResource(R.string.module_changelog_failed)
val loadingDialog = rememberLoadingDialog()
val confirmDialog = rememberConfirmDialog()
suspend fun onModuleUpdate(
module: ModuleViewModel.ModuleInfo,
changelogUrl: String,
downloadUrl: String,
fileName: String
) {
val changelogResult = loadingDialog.withLoading {
withContext(Dispatchers.IO) {
runCatching {
OkHttpClient().newCall(
okhttp3.Request.Builder().url(changelogUrl).build()
).execute().body!!.string()
}
}
}
val showToast: suspend (String) -> Unit = { msg ->
withContext(Dispatchers.Main) {
Toast.makeText(
context,
msg,
Toast.LENGTH_SHORT
).show()
}
}
val changelog = changelogResult.getOrElse {
showToast(fetchChangeLogFailed.format(it.message))
return
}.ifBlank {
showToast(fetchChangeLogFailed.format(module.name))
return
}
// changelog is not empty, show it and wait for confirm
val confirmResult = confirmDialog.awaitConfirm(
changelogText,
content = changelog,
markdown = true,
confirm = updateText,
)
if (confirmResult != ConfirmResult.Confirmed) {
return
}
showToast(startDownloadingText.format(module.name))
val downloading = downloadingText.format(module.name)
withContext(Dispatchers.IO) {
download(
context,
downloadUrl,
fileName,
downloading,
onDownloaded = onInstallModule,
onDownloading = {
launch(Dispatchers.Main) {
Toast.makeText(context, downloading, Toast.LENGTH_SHORT).show()
}
}
)
}
}
suspend fun onModuleUninstall(module: ModuleViewModel.ModuleInfo) {
val confirmResult = confirmDialog.awaitConfirm(
moduleStr,
content = moduleUninstallConfirm.format(module.name),
confirm = uninstall,
dismiss = cancel
)
if (confirmResult != ConfirmResult.Confirmed) {
return
}
val success = loadingDialog.withLoading {
withContext(Dispatchers.IO) {
uninstallModule(module.dirId)
}
}
if (success) {
viewModel.fetchModuleList()
}
val message = if (success) {
successUninstall.format(module.name)
} else {
failedUninstall.format(module.name)
}
val actionLabel = if (success) {
reboot
} else {
null
}
val result = snackBarHost.showSnackbar(
message = message,
actionLabel = actionLabel,
duration = SnackbarDuration.Long
)
if (result == SnackbarResult.ActionPerformed) {
reboot()
}
}
suspend fun onModuleRestore(module: ModuleViewModel.ModuleInfo) {
val confirmResult = confirmDialog.awaitConfirm(
moduleStr,
content = moduleRestoreConfirm.format(module.name),
confirm = restore,
dismiss = cancel
)
if (confirmResult != ConfirmResult.Confirmed) {
return
}
val success = loadingDialog.withLoading {
withContext(Dispatchers.IO) {
restoreModule(module.dirId)
}
}
if (success) {
viewModel.fetchModuleList()
}
val message = if (success) {
successRestore.format(module.name)
} else {
failedRestore.format(module.name)
}
}
PullToRefreshBox(
modifier = boxModifier,
onRefresh = {
viewModel.fetchModuleList()
},
isRefreshing = viewModel.isRefreshing
) {
LazyColumn(
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(16.dp),
contentPadding = remember {
PaddingValues(
start = 16.dp,
top = 16.dp,
end = 16.dp,
bottom = 16.dp + 56.dp + 16.dp + 48.dp + 6.dp /* Scaffold Fab Spacing + Fab container height + SnackBar height */
)
},
) {
when {
!viewModel.isOverlayAvailable -> {
item {
Box(
modifier = Modifier.fillParentMaxSize(),
contentAlignment = Alignment.Center
) {
Text(
stringResource(R.string.module_overlay_fs_not_available),
textAlign = TextAlign.Center
)
}
}
}
viewModel.moduleList.isEmpty() -> {
item {
Box(
modifier = Modifier.fillParentMaxSize(),
contentAlignment = Alignment.Center
) {
Text(
stringResource(R.string.module_empty),
textAlign = TextAlign.Center
)
}
}
}
else -> {
items(viewModel.moduleList) { module ->
val scope = rememberCoroutineScope()
val updatedModule by produceState(initialValue = Triple("", "", "")) {
scope.launch(Dispatchers.IO) {
value = viewModel.checkUpdate(module)
}
}
ModuleItem(
navigator = navigator,
module = module,
updateUrl = updatedModule.first,
onUninstall = {
scope.launch { onModuleUninstall(module) }
},
onRestore = {
scope.launch { onModuleRestore(module) }
},
onCheckChanged = {
scope.launch {
val success = loadingDialog.withLoading {
withContext(Dispatchers.IO) {
toggleModule(module.dirId, !module.enabled)
}
}
if (success) {
viewModel.fetchModuleList()
val result = snackBarHost.showSnackbar(
message = rebootToApply,
actionLabel = reboot,
duration = SnackbarDuration.Long
)
if (result == SnackbarResult.ActionPerformed) {
reboot()
}
} else {
val message = if (module.enabled) failedDisable else failedEnable
snackBarHost.showSnackbar(message.format(module.name))
}
}
},
onUpdate = {
scope.launch {
onModuleUpdate(
module,
updatedModule.third,
updatedModule.first,
"${module.name}-${updatedModule.second}.zip"
)
}
},
onClick = {
onClickModule(it.dirId, it.name, it.hasWebUi)
}
)
// fix last item shadow incomplete in LazyColumn
Spacer(Modifier.height(1.dp))
}
}
}
}
DownloadListener(context, onInstallModule)
}
}
@Composable
fun ModuleItem(
navigator: DestinationsNavigator,
module: ModuleViewModel.ModuleInfo,
updateUrl: String,
onUninstall: (ModuleViewModel.ModuleInfo) -> Unit,
onRestore: (ModuleViewModel.ModuleInfo) -> Unit,
onCheckChanged: (Boolean) -> Unit,
onUpdate: (ModuleViewModel.ModuleInfo) -> Unit,
onClick: (ModuleViewModel.ModuleInfo) -> Unit
) {
ElevatedCard(
modifier = Modifier.fillMaxWidth()
) {
val textDecoration = if (!module.remove) null else TextDecoration.LineThrough
val interactionSource = remember { MutableInteractionSource() }
val indication = LocalIndication.current
val viewModel = viewModel<ModuleViewModel>()
Column(
modifier = Modifier
.run {
if (module.hasWebUi) {
toggleable(
value = module.enabled,
interactionSource = interactionSource,
role = Role.Button,
indication = indication,
onValueChange = { onClick(module) }
)
} else {
this
}
}
.padding(22.dp, 18.dp, 22.dp, 12.dp)
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
) {
val moduleVersion = stringResource(id = R.string.module_version)
val moduleAuthor = stringResource(id = R.string.module_author)
Column(
modifier = Modifier.fillMaxWidth(0.8f)
) {
Text(
text = module.name,
fontSize = MaterialTheme.typography.titleMedium.fontSize,
fontWeight = FontWeight.SemiBold,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
fontFamily = MaterialTheme.typography.titleMedium.fontFamily,
textDecoration = textDecoration,
)
Text(
text = "$moduleVersion: ${module.version}",
fontSize = MaterialTheme.typography.bodySmall.fontSize,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
textDecoration = textDecoration
)
Text(
text = "$moduleAuthor: ${module.author}",
fontSize = MaterialTheme.typography.bodySmall.fontSize,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
textDecoration = textDecoration
)
}
Spacer(modifier = Modifier.weight(1f))
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.End,
) {
Switch(
enabled = !module.update,
checked = module.enabled,
onCheckedChange = onCheckChanged,
interactionSource = if (!module.hasWebUi) interactionSource else null
)
}
}
Spacer(modifier = Modifier.height(12.dp))
Text(
text = module.description,
fontSize = MaterialTheme.typography.bodySmall.fontSize,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
fontWeight = MaterialTheme.typography.bodySmall.fontWeight,
overflow = TextOverflow.Ellipsis,
maxLines = 4,
textDecoration = textDecoration
)
Spacer(modifier = Modifier.height(16.dp))
HorizontalDivider(thickness = Dp.Hairline)
Spacer(modifier = Modifier.height(4.dp))
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
if (module.hasActionScript) {
FilledTonalButton(
modifier = Modifier.defaultMinSize(52.dp, 32.dp),
onClick = {
navigator.navigate(ExecuteModuleActionScreenDestination(module.dirId))
viewModel.markNeedRefresh()
},
contentPadding = ButtonDefaults.TextButtonContentPadding
) {
Icon(
modifier = Modifier.size(20.dp),
imageVector = Icons.Outlined.PlayArrow,
contentDescription = null
)
if (!module.hasWebUi && updateUrl.isEmpty()) {
Text(
modifier = Modifier.padding(start = 7.dp),
text = stringResource(R.string.action),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize
)
}
}
Spacer(modifier = Modifier.weight(0.1f, true))
}
if (module.hasWebUi) {
FilledTonalButton(
modifier = Modifier.defaultMinSize(52.dp, 32.dp),
onClick = { onClick(module) },
interactionSource = interactionSource,
contentPadding = ButtonDefaults.TextButtonContentPadding
) {
Icon(
modifier = Modifier.size(20.dp),
imageVector = Icons.AutoMirrored.Outlined.Wysiwyg,
contentDescription = null
)
if (!module.hasActionScript && updateUrl.isEmpty()) {
Text(
modifier = Modifier.padding(start = 7.dp),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize,
text = stringResource(R.string.open)
)
}
}
}
Spacer(modifier = Modifier.weight(1f, true))
if (updateUrl.isNotEmpty()) {
Button(
modifier = Modifier.defaultMinSize(52.dp, 32.dp),
onClick = { onUpdate(module) },
shape = ButtonDefaults.textShape,
contentPadding = ButtonDefaults.TextButtonContentPadding
) {
Icon(
modifier = Modifier.size(20.dp),
imageVector = Icons.Outlined.Download,
contentDescription = null
)
if (!module.hasActionScript || !module.hasWebUi) {
Text(
modifier = Modifier.padding(start = 7.dp),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize,
text = stringResource(R.string.module_update)
)
}
}
Spacer(modifier = Modifier.weight(0.1f, true))
}
if (module.remove) {
FilledTonalButton(
modifier = Modifier.defaultMinSize(52.dp, 32.dp),
onClick = { onRestore(module) },
contentPadding = ButtonDefaults.TextButtonContentPadding
) {
Icon(
modifier = Modifier.size(20.dp),
imageVector = Icons.Outlined.Restore,
contentDescription = null
)
if (!module.hasActionScript && !module.hasWebUi && updateUrl.isEmpty()) {
Text(
modifier = Modifier.padding(start = 7.dp),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize,
text = stringResource(R.string.restore)
)
}
}
} else {
FilledTonalButton(
modifier = Modifier.defaultMinSize(52.dp, 32.dp),
enabled = true,
onClick = { onUninstall(module) },
contentPadding = ButtonDefaults.TextButtonContentPadding
) {
Icon(
modifier = Modifier.size(20.dp),
imageVector = Icons.Outlined.Delete,
contentDescription = null
)
if (!module.hasActionScript && !module.hasWebUi && updateUrl.isEmpty()) {
Text(
modifier = Modifier.padding(start = 7.dp),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize,
text = stringResource(R.string.uninstall)
)
}
}
}
}
}
}
}
@Preview
@Composable
fun ModuleItemPreview() {
val module = ModuleViewModel.ModuleInfo(
id = "id",
name = "name",
version = "version",
versionCode = 1,
author = "author",
description = "I am a test module and i do nothing but show a very long description",
enabled = true,
update = true,
remove = false,
updateJson = "",
hasWebUi = false,
hasActionScript = false,
dirId = "dirId"
)
ModuleItem(EmptyDestinationsNavigator, module, "", {}, {}, {}, {}, {})
}

View File

@@ -1,637 +0,0 @@
package com.rifsxd.ksunext.ui.screen
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.Undo
import androidx.compose.material.icons.filled.*
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.ListItem
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.Text
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.LineHeightStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.content.FileProvider
import com.maxkeppeker.sheets.core.models.base.Header
import com.maxkeppeker.sheets.core.models.base.IconSource
import com.maxkeppeker.sheets.core.models.base.rememberUseCaseState
import com.maxkeppeler.sheets.list.ListDialog
import com.maxkeppeler.sheets.list.models.ListOption
import com.maxkeppeler.sheets.list.models.ListSelection
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.generated.destinations.AppProfileTemplateScreenDestination
import com.ramcosta.composedestinations.generated.destinations.FlashScreenDestination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import com.rifsxd.ksunext.BuildConfig
import com.rifsxd.ksunext.Natives
import com.rifsxd.ksunext.ksuApp
import com.rifsxd.ksunext.R
import com.rifsxd.ksunext.ui.component.AboutDialog
import com.rifsxd.ksunext.ui.component.ConfirmResult
import com.rifsxd.ksunext.ui.component.DialogHandle
import com.rifsxd.ksunext.ui.component.SwitchItem
import com.rifsxd.ksunext.ui.component.rememberConfirmDialog
import com.rifsxd.ksunext.ui.component.rememberCustomDialog
import com.rifsxd.ksunext.ui.component.rememberLoadingDialog
import com.rifsxd.ksunext.ui.util.LocalSnackbarHost
import com.rifsxd.ksunext.ui.util.getBugreportFile
import com.rifsxd.ksunext.ui.util.*
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
/**
* @author weishu
* @date 2023/1/1.
*/
@OptIn(ExperimentalMaterial3Api::class)
@Destination<RootGraph>
@Composable
fun SettingScreen(navigator: DestinationsNavigator) {
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
val snackBarHost = LocalSnackbarHost.current
val isManager = Natives.becomeManager(ksuApp.packageName)
val ksuVersion = if (isManager) Natives.version else null
Scaffold(
topBar = {
TopBar(
scrollBehavior = scrollBehavior
)
},
snackbarHost = { SnackbarHost(snackBarHost) },
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
) { paddingValues ->
val aboutDialog = rememberCustomDialog {
AboutDialog(it)
}
val loadingDialog = rememberLoadingDialog()
val shrinkDialog = rememberConfirmDialog()
val restoreDialog = rememberConfirmDialog()
val backupDialog = rememberConfirmDialog()
Column(
modifier = Modifier
.padding(paddingValues)
.nestedScroll(scrollBehavior.nestedScrollConnection)
.verticalScroll(rememberScrollState())
) {
val context = LocalContext.current
val scope = rememberCoroutineScope()
val exportBugreportLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.CreateDocument("application/gzip")
) { uri: Uri? ->
if (uri == null) return@rememberLauncherForActivityResult
scope.launch(Dispatchers.IO) {
loadingDialog.show()
context.contentResolver.openOutputStream(uri)?.use { output ->
getBugreportFile(context).inputStream().use {
it.copyTo(output)
}
}
loadingDialog.hide()
snackBarHost.showSnackbar(context.getString(R.string.log_saved))
}
}
val profileTemplate = stringResource(id = R.string.settings_profile_template)
if (ksuVersion != null) {
ListItem(
leadingContent = { Icon(Icons.Filled.Fence, profileTemplate) },
headlineContent = { Text(profileTemplate) },
supportingContent = { Text(stringResource(id = R.string.settings_profile_template_summary)) },
modifier = Modifier.clickable {
navigator.navigate(AppProfileTemplateScreenDestination)
}
)
}
var umountChecked by rememberSaveable {
mutableStateOf(Natives.isDefaultUmountModules())
}
if (ksuVersion != null) {
SwitchItem(
icon = Icons.Filled.RemoveModerator,
title = stringResource(id = R.string.settings_umount_modules_default),
summary = stringResource(id = R.string.settings_umount_modules_default_summary),
checked = umountChecked
) {
if (Natives.setDefaultUmountModules(it)) {
umountChecked = it
}
}
}
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
val suSFS = getSuSFS()
val isSUS_SU = getSuSFSFeatures()
if (suSFS == "Supported") {
if (isSUS_SU == "CONFIG_KSU_SUSFS_SUS_SU") {
var isEnabled by rememberSaveable {
mutableStateOf(susfsSUS_SU_Mode() == "2")
}
LaunchedEffect(Unit) {
isEnabled = susfsSUS_SU_Mode() == "2"
}
SwitchItem(
icon = Icons.Filled.VisibilityOff,
title = stringResource(id = R.string.settings_susfs_toggle),
summary = stringResource(id = R.string.settings_susfs_toggle_summary),
checked = isEnabled
) {
if (it) {
susfsSUS_SU_2()
} else {
susfsSUS_SU_0()
}
prefs.edit().putBoolean("enable_sus_su", it).apply()
isEnabled = it
}
}
}
val hasShownWarning = rememberSaveable { mutableStateOf(prefs.getBoolean("has_shown_warning", false)) }
var useOverlayFs by rememberSaveable {
mutableStateOf(
prefs.getBoolean("use_overlay_fs", false)
)
}
val isManager = Natives.becomeManager(ksuApp.packageName)
var showRebootDialog by remember { mutableStateOf(false) }
var showWarningDialog by remember { mutableStateOf(false) }
if (ksuVersion != null) {
SwitchItem(
icon = Icons.Filled.Build,
title = stringResource(id = R.string.use_overlay_fs),
summary = stringResource(id = R.string.use_overlay_fs_summary),
checked = useOverlayFs
) {
if (!hasShownWarning.value) {
showWarningDialog = true
}
}
}
if (showWarningDialog) {
AlertDialog(
onDismissRequest = { showWarningDialog = false },
title = { Text(stringResource(R.string.warning)) },
text = { Text(stringResource(R.string.warning_message)) },
confirmButton = {
TextButton(onClick = {
showWarningDialog = false
prefs.edit().putBoolean("use_overlay_fs", !useOverlayFs).apply()
useOverlayFs = !useOverlayFs
if (useOverlayFs) {
moduleBackup()
} else {
moduleMigration()
}
if (isManager) install()
showRebootDialog = true
}) {
Text(stringResource(R.string.proceed))
}
},
dismissButton = {
TextButton(onClick = { showWarningDialog = false }) {
Text(stringResource(R.string.cancel))
}
}
)
}
if (showRebootDialog) {
AlertDialog(
onDismissRequest = { showRebootDialog = false },
title = { Text(stringResource(R.string.reboot_required)) },
text = { Text(stringResource(R.string.reboot_message)) },
confirmButton = {
TextButton(onClick = {
showRebootDialog = false
reboot()
}) {
Text(stringResource(R.string.reboot))
}
},
dismissButton = {
TextButton(onClick = { showRebootDialog = false }) {
Text(stringResource(R.string.later))
}
}
)
}
var checkUpdate by rememberSaveable {
mutableStateOf(
prefs.getBoolean("check_update", true)
)
}
SwitchItem(
icon = Icons.Filled.Update,
title = stringResource(id = R.string.settings_check_update),
summary = stringResource(id = R.string.settings_check_update_summary),
checked = checkUpdate
) {
prefs.edit().putBoolean("check_update", it).apply()
checkUpdate = it
}
var enableWebDebugging by rememberSaveable {
mutableStateOf(
prefs.getBoolean("enable_web_debugging", false)
)
}
SwitchItem(
icon = Icons.Filled.DeveloperMode,
title = stringResource(id = R.string.enable_web_debugging),
summary = stringResource(id = R.string.enable_web_debugging_summary),
checked = enableWebDebugging
) {
prefs.edit().putBoolean("enable_web_debugging", it).apply()
enableWebDebugging = it
}
var showBottomsheet by remember { mutableStateOf(false) }
ListItem(
leadingContent = {
Icon(
Icons.Filled.BugReport,
stringResource(id = R.string.export_log)
)
},
headlineContent = { Text(stringResource(id = R.string.export_log)) },
modifier = Modifier.clickable {
showBottomsheet = true
}
)
if (showBottomsheet) {
ModalBottomSheet(
onDismissRequest = { showBottomsheet = false },
content = {
Row(
modifier = Modifier
.padding(10.dp)
.align(Alignment.CenterHorizontally)
) {
Box {
Column(
modifier = Modifier
.padding(16.dp)
.clickable {
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH_mm")
val current = LocalDateTime.now().format(formatter)
exportBugreportLauncher.launch("KernelSU_bugreport_${current}.tar.gz")
showBottomsheet = false
}
) {
Icon(
Icons.Filled.Save,
contentDescription = null,
modifier = Modifier.align(Alignment.CenterHorizontally)
)
Text(
text = stringResource(id = R.string.save_log),
modifier = Modifier.padding(top = 16.dp),
textAlign = TextAlign.Center.also {
LineHeightStyle(
alignment = LineHeightStyle.Alignment.Center,
trim = LineHeightStyle.Trim.None
)
}
)
}
}
Box {
Column(
modifier = Modifier
.padding(16.dp)
.clickable {
scope.launch {
val bugreport = loadingDialog.withLoading {
withContext(Dispatchers.IO) {
getBugreportFile(context)
}
}
val uri: Uri =
FileProvider.getUriForFile(
context,
"${BuildConfig.APPLICATION_ID}.fileprovider",
bugreport
)
val shareIntent = Intent(Intent.ACTION_SEND).apply {
putExtra(Intent.EXTRA_STREAM, uri)
setDataAndType(uri, "application/gzip")
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
context.startActivity(
Intent.createChooser(
shareIntent,
context.getString(R.string.send_log)
)
)
}
}
) {
Icon(
Icons.Filled.Share,
contentDescription = null,
modifier = Modifier.align(Alignment.CenterHorizontally)
)
Text(
text = stringResource(id = R.string.send_log),
modifier = Modifier.padding(top = 16.dp),
textAlign = TextAlign.Center.also {
LineHeightStyle(
alignment = LineHeightStyle.Alignment.Center,
trim = LineHeightStyle.Trim.None
)
}
)
}
}
}
}
)
}
if (ksuVersion != null) {
val moduleBackup = stringResource(id = R.string.module_backup)
val backupMessage = stringResource(id = R.string.module_backup_message)
ListItem(
leadingContent = {
Icon(
Icons.Filled.Backup,
moduleBackup
)
},
headlineContent = { Text(moduleBackup) },
modifier = Modifier.clickable {
scope.launch {
val result = backupDialog.awaitConfirm(title = moduleBackup, content = backupMessage)
if (result == ConfirmResult.Confirmed) {
loadingDialog.withLoading {
moduleBackup()
}
}
}
}
)
}
if (ksuVersion != null) {
val moduleRestore = stringResource(id = R.string.module_restore)
val restoreMessage = stringResource(id = R.string.module_restore_message)
ListItem(
leadingContent = {
Icon(
Icons.Filled.Restore,
moduleRestore
)
},
headlineContent = { Text(moduleRestore) },
modifier = Modifier.clickable {
scope.launch {
val result = restoreDialog.awaitConfirm(title = moduleRestore, content = restoreMessage)
if (result == ConfirmResult.Confirmed) {
loadingDialog.withLoading {
moduleRestore()
showRebootDialog = true
}
}
}
}
)
}
if (useOverlayFs) {
val shrink = stringResource(id = R.string.shrink_sparse_image)
val shrinkMessage = stringResource(id = R.string.shrink_sparse_image_message)
ListItem(
leadingContent = {
Icon(
Icons.Filled.Compress,
shrink
)
},
headlineContent = { Text(shrink) },
modifier = Modifier.clickable {
scope.launch {
val result = shrinkDialog.awaitConfirm(title = shrink, content = shrinkMessage)
if (result == ConfirmResult.Confirmed) {
loadingDialog.withLoading {
shrinkModules()
}
}
}
}
)
}
val lkmMode = Natives.version >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && Natives.isLkmMode
if (lkmMode) {
UninstallItem(navigator) {
loadingDialog.withLoading(it)
}
}
val about = stringResource(id = R.string.about)
ListItem(
leadingContent = {
Icon(
Icons.Filled.ContactPage,
about
)
},
headlineContent = { Text(about) },
modifier = Modifier.clickable {
aboutDialog.show()
}
)
}
}
}
@Composable
fun UninstallItem(
navigator: DestinationsNavigator,
withLoading: suspend (suspend () -> Unit) -> Unit
) {
val context = LocalContext.current
val scope = rememberCoroutineScope()
val uninstallConfirmDialog = rememberConfirmDialog()
val showTodo = {
Toast.makeText(context, "TODO", Toast.LENGTH_SHORT).show()
}
val uninstallDialog = rememberUninstallDialog { uninstallType ->
scope.launch {
val result = uninstallConfirmDialog.awaitConfirm(
title = context.getString(uninstallType.title),
content = context.getString(uninstallType.message)
)
if (result == ConfirmResult.Confirmed) {
withLoading {
when (uninstallType) {
UninstallType.TEMPORARY -> showTodo()
UninstallType.PERMANENT -> navigator.navigate(
FlashScreenDestination(FlashIt.FlashUninstall)
)
UninstallType.RESTORE_STOCK_IMAGE -> navigator.navigate(
FlashScreenDestination(FlashIt.FlashRestore)
)
UninstallType.NONE -> Unit
}
}
}
}
}
val uninstall = stringResource(id = R.string.settings_uninstall)
ListItem(
leadingContent = {
Icon(
Icons.Filled.Delete,
uninstall
)
},
headlineContent = { Text(uninstall) },
modifier = Modifier.clickable {
uninstallDialog.show()
}
)
}
enum class UninstallType(val title: Int, val message: Int, val icon: ImageVector) {
TEMPORARY(
R.string.settings_uninstall_temporary,
R.string.settings_uninstall_temporary_message,
Icons.Filled.Delete
),
PERMANENT(
R.string.settings_uninstall_permanent,
R.string.settings_uninstall_permanent_message,
Icons.Filled.DeleteForever
),
RESTORE_STOCK_IMAGE(
R.string.settings_restore_stock_image,
R.string.settings_restore_stock_image_message,
Icons.AutoMirrored.Filled.Undo
),
NONE(0, 0, Icons.Filled.Delete)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun rememberUninstallDialog(onSelected: (UninstallType) -> Unit): DialogHandle {
return rememberCustomDialog { dismiss ->
val options = listOf(
// UninstallType.TEMPORARY,
UninstallType.PERMANENT,
UninstallType.RESTORE_STOCK_IMAGE
)
val listOptions = options.map {
ListOption(
titleText = stringResource(it.title),
subtitleText = if (it.message != 0) stringResource(it.message) else null,
icon = IconSource(it.icon)
)
}
var selection = UninstallType.NONE
ListDialog(state = rememberUseCaseState(visible = true, onFinishedRequest = {
if (selection != UninstallType.NONE) {
onSelected(selection)
}
}, onCloseRequest = {
dismiss()
}), header = Header.Default(
title = stringResource(R.string.settings_uninstall),
), selection = ListSelection.Single(
showRadioButtons = false,
options = listOptions,
) { index, _ ->
selection = options[index]
})
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun TopBar(
scrollBehavior: TopAppBarScrollBehavior? = null
) {
TopAppBar(
title = { Text(stringResource(R.string.settings)) },
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal),
scrollBehavior = scrollBehavior
)
}
@Preview
@Composable
private fun SettingsPreview() {
SettingScreen(EmptyDestinationsNavigator)
}

View File

@@ -1,200 +0,0 @@
package com.rifsxd.ksunext.ui.screen
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material3.*
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import coil.compose.AsyncImage
import coil.request.ImageRequest
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.generated.destinations.AppProfileScreenDestination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import kotlinx.coroutines.launch
import com.rifsxd.ksunext.Natives
import com.rifsxd.ksunext.R
import com.rifsxd.ksunext.ui.component.SearchAppBar
import com.rifsxd.ksunext.ui.viewmodel.SuperUserViewModel
@OptIn(ExperimentalMaterialApi::class, ExperimentalMaterial3Api::class)
@Destination<RootGraph>
@Composable
fun SuperUserScreen(navigator: DestinationsNavigator) {
val viewModel = viewModel<SuperUserViewModel>()
val scope = rememberCoroutineScope()
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
val listState = rememberLazyListState()
LaunchedEffect(key1 = navigator) {
viewModel.search = ""
if (viewModel.appList.isEmpty()) {
viewModel.fetchAppList()
}
}
LaunchedEffect(viewModel.search) {
if (viewModel.search.isEmpty()) {
listState.scrollToItem(0)
}
}
LaunchedEffect(Unit) {
if (viewModel.refreshOnReturn) {
viewModel.fetchAppList()
viewModel.refreshOnReturn = false
}
}
Scaffold(
topBar = {
SearchAppBar(
title = { Text(stringResource(R.string.superuser)) },
searchText = viewModel.search,
onSearchTextChange = { viewModel.search = it },
onClearClick = { viewModel.search = "" },
dropdownContent = {
var showDropdown by remember { mutableStateOf(false) }
IconButton(
onClick = { showDropdown = true },
) {
Icon(
imageVector = Icons.Filled.MoreVert,
contentDescription = stringResource(id = R.string.settings)
)
DropdownMenu(expanded = showDropdown, onDismissRequest = {
showDropdown = false
}) {
DropdownMenuItem(text = {
Text(stringResource(R.string.refresh))
}, onClick = {
scope.launch {
viewModel.fetchAppList()
}
showDropdown = false
})
DropdownMenuItem(text = {
Text(
if (viewModel.showSystemApps) {
stringResource(R.string.hide_system_apps)
} else {
stringResource(R.string.show_system_apps)
}
)
}, onClick = {
viewModel.showSystemApps = !viewModel.showSystemApps
showDropdown = false
})
}
}
},
scrollBehavior = scrollBehavior
)
},
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
) { innerPadding ->
PullToRefreshBox(
modifier = Modifier.padding(innerPadding),
onRefresh = {
scope.launch { viewModel.fetchAppList() }
},
isRefreshing = viewModel.isRefreshing
) {
LazyColumn(
state = listState,
modifier = Modifier
.fillMaxSize()
.nestedScroll(scrollBehavior.nestedScrollConnection)
) {
items(viewModel.appList, key = { it.packageName + it.uid }) { app ->
AppItem(app) {
viewModel.refreshOnReturn = true
navigator.navigate(AppProfileScreenDestination(app))
}
}
}
}
}
}
@OptIn(ExperimentalLayoutApi::class)
@Composable
private fun AppItem(
app: SuperUserViewModel.AppInfo,
onClickListener: () -> Unit,
) {
ListItem(
modifier = Modifier.clickable(onClick = onClickListener),
headlineContent = { Text(app.label) },
supportingContent = {
Column {
Text(app.packageName)
FlowRow {
if (app.allowSu) {
LabelText(label = "ROOT")
} else {
if (Natives.uidShouldUmount(app.uid)) {
LabelText(label = "UMOUNT")
}
}
if (app.hasCustomProfile) {
LabelText(label = "CUSTOM")
}
}
}
},
leadingContent = {
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data(app.packageInfo)
.crossfade(true)
.build(),
contentDescription = app.label,
modifier = Modifier
.padding(4.dp)
.width(48.dp)
.height(48.dp)
)
},
)
}
@Composable
fun LabelText(label: String) {
Box(
modifier = Modifier
.padding(top = 4.dp, end = 4.dp)
.background(
Color.Black,
shape = RoundedCornerShape(4.dp)
)
) {
Text(
text = label,
modifier = Modifier.padding(vertical = 2.dp, horizontal = 5.dp),
style = TextStyle(
fontSize = 8.sp,
color = Color.White,
)
)
}
}

View File

@@ -1,268 +0,0 @@
package com.rifsxd.ksunext.ui.screen
import android.widget.Toast
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.ImportExport
import androidx.compose.material.icons.filled.Sync
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.generated.destinations.TemplateEditorScreenDestination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.result.ResultRecipient
import com.ramcosta.composedestinations.result.getOr
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import com.rifsxd.ksunext.R
import com.rifsxd.ksunext.ui.viewmodel.TemplateViewModel
/**
* @author weishu
* @date 2023/10/20.
*/
@OptIn(ExperimentalMaterialApi::class, ExperimentalMaterial3Api::class)
@Destination<RootGraph>
@Composable
fun AppProfileTemplateScreen(
navigator: DestinationsNavigator,
resultRecipient: ResultRecipient<TemplateEditorScreenDestination, Boolean>
) {
val viewModel = viewModel<TemplateViewModel>()
val scope = rememberCoroutineScope()
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
LaunchedEffect(Unit) {
if (viewModel.templateList.isEmpty()) {
viewModel.fetchTemplates()
}
}
// handle result from TemplateEditorScreen, refresh if needed
resultRecipient.onNavResult { result ->
if (result.getOr { false }) {
scope.launch { viewModel.fetchTemplates() }
}
}
Scaffold(
topBar = {
val clipboardManager = LocalClipboardManager.current
val context = LocalContext.current
val showToast = fun(msg: String) {
scope.launch(Dispatchers.Main) {
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
}
}
TopBar(
onBack = { navigator.popBackStack() },
onSync = {
scope.launch { viewModel.fetchTemplates(true) }
},
onImport = {
clipboardManager.getText()?.text?.let {
if (it.isEmpty()) {
showToast(context.getString(R.string.app_profile_template_import_empty))
return@let
}
scope.launch {
viewModel.importTemplates(
it, {
showToast(context.getString(R.string.app_profile_template_import_success))
viewModel.fetchTemplates(false)
},
showToast
)
}
}
},
onExport = {
scope.launch {
viewModel.exportTemplates(
{
showToast(context.getString(R.string.app_profile_template_export_empty))
}
) {
clipboardManager.setText(AnnotatedString(it))
}
}
},
scrollBehavior = scrollBehavior
)
},
floatingActionButton = {
ExtendedFloatingActionButton(
onClick = {
navigator.navigate(
TemplateEditorScreenDestination(
TemplateViewModel.TemplateInfo(),
false
)
)
},
icon = { Icon(Icons.Filled.Add, null) },
text = { Text(stringResource(id = R.string.app_profile_template_create)) },
)
},
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
) { innerPadding ->
PullToRefreshBox(
modifier = Modifier.padding(innerPadding),
isRefreshing = viewModel.isRefreshing,
onRefresh = {
scope.launch { viewModel.fetchTemplates() }
}
) {
LazyColumn(
modifier = Modifier
.fillMaxSize()
.nestedScroll(scrollBehavior.nestedScrollConnection),
contentPadding = remember {
PaddingValues(bottom = 16.dp + 56.dp + 16.dp /* Scaffold Fab Spacing + Fab container height */)
}
) {
items(viewModel.templateList, key = { it.id }) { app ->
TemplateItem(navigator, app)
}
}
}
}
}
@OptIn(ExperimentalLayoutApi::class)
@Composable
private fun TemplateItem(
navigator: DestinationsNavigator,
template: TemplateViewModel.TemplateInfo
) {
ListItem(
modifier = Modifier
.clickable {
navigator.navigate(TemplateEditorScreenDestination(template, !template.local))
},
headlineContent = { Text(template.name) },
supportingContent = {
Column {
Text(
text = "${template.id}${if (template.author.isEmpty()) "" else "@${template.author}"}",
style = MaterialTheme.typography.bodySmall,
fontSize = MaterialTheme.typography.bodySmall.fontSize,
)
Text(template.description)
FlowRow {
LabelText(label = "UID: ${template.uid}")
LabelText(label = "GID: ${template.gid}")
LabelText(label = template.context)
if (template.local) {
LabelText(label = "local")
} else {
LabelText(label = "remote")
}
}
}
},
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun TopBar(
onBack: () -> Unit,
onSync: () -> Unit = {},
onImport: () -> Unit = {},
onExport: () -> Unit = {},
scrollBehavior: TopAppBarScrollBehavior? = null
) {
TopAppBar(
title = {
Text(stringResource(R.string.settings_profile_template))
},
navigationIcon = {
IconButton(
onClick = onBack
) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) }
},
actions = {
IconButton(onClick = onSync) {
Icon(
Icons.Filled.Sync,
contentDescription = stringResource(id = R.string.app_profile_template_sync)
)
}
var showDropdown by remember { mutableStateOf(false) }
IconButton(onClick = {
showDropdown = true
}) {
Icon(
imageVector = Icons.Filled.ImportExport,
contentDescription = stringResource(id = R.string.app_profile_import_export)
)
DropdownMenu(expanded = showDropdown, onDismissRequest = {
showDropdown = false
}) {
DropdownMenuItem(text = {
Text(stringResource(id = R.string.app_profile_import_from_clipboard))
}, onClick = {
onImport()
showDropdown = false
})
DropdownMenuItem(text = {
Text(stringResource(id = R.string.app_profile_export_to_clipboard))
}, onClick = {
onExport()
showDropdown = false
})
}
}
},
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal),
scrollBehavior = scrollBehavior
)
}

View File

@@ -1,339 +0,0 @@
package com.rifsxd.ksunext.ui.screen
import android.widget.Toast
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.DeleteForever
import androidx.compose.material.icons.filled.Save
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.input.pointer.pointerInteropFilter
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.result.ResultBackNavigator
import com.rifsxd.ksunext.Natives
import com.rifsxd.ksunext.R
import com.rifsxd.ksunext.ui.component.profile.RootProfileConfig
import com.rifsxd.ksunext.ui.util.deleteAppProfileTemplate
import com.rifsxd.ksunext.ui.util.getAppProfileTemplate
import com.rifsxd.ksunext.ui.util.setAppProfileTemplate
import com.rifsxd.ksunext.ui.viewmodel.TemplateViewModel
import com.rifsxd.ksunext.ui.viewmodel.toJSON
/**
* @author weishu
* @date 2023/10/20.
*/
@OptIn(ExperimentalComposeUiApi::class, ExperimentalMaterial3Api::class)
@Destination<RootGraph>
@Composable
fun TemplateEditorScreen(
navigator: ResultBackNavigator<Boolean>,
initialTemplate: TemplateViewModel.TemplateInfo,
readOnly: Boolean = true,
) {
val isCreation = initialTemplate.id.isBlank()
val autoSave = !isCreation
var template by rememberSaveable {
mutableStateOf(initialTemplate)
}
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
BackHandler {
navigator.navigateBack(result = !readOnly)
}
Scaffold(
topBar = {
val author =
if (initialTemplate.author.isNotEmpty()) "@${initialTemplate.author}" else ""
val readOnlyHint = if (readOnly) {
" - ${stringResource(id = R.string.app_profile_template_readonly)}"
} else {
""
}
val titleSummary = "${initialTemplate.id}$author$readOnlyHint"
val saveTemplateFailed = stringResource(id = R.string.app_profile_template_save_failed)
val context = LocalContext.current
TopBar(
title = if (isCreation) {
stringResource(R.string.app_profile_template_create)
} else if (readOnly) {
stringResource(R.string.app_profile_template_view)
} else {
stringResource(R.string.app_profile_template_edit)
},
readOnly = readOnly,
summary = titleSummary,
onBack = { navigator.navigateBack(result = !readOnly) },
onDelete = {
if (deleteAppProfileTemplate(template.id)) {
navigator.navigateBack(result = true)
}
},
onSave = {
if (saveTemplate(template, isCreation)) {
navigator.navigateBack(result = true)
} else {
Toast.makeText(context, saveTemplateFailed, Toast.LENGTH_SHORT).show()
}
},
scrollBehavior = scrollBehavior
)
},
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
) { innerPadding ->
Column(
modifier = Modifier
.padding(innerPadding)
.nestedScroll(scrollBehavior.nestedScrollConnection)
.verticalScroll(rememberScrollState())
.pointerInteropFilter {
// disable click and ripple if readOnly
readOnly
}
) {
if (isCreation) {
var errorHint by remember {
mutableStateOf("")
}
val idConflictError = stringResource(id = R.string.app_profile_template_id_exist)
val idInvalidError = stringResource(id = R.string.app_profile_template_id_invalid)
TextEdit(
label = stringResource(id = R.string.app_profile_template_id),
text = template.id,
errorHint = errorHint,
isError = errorHint.isNotEmpty()
) { value ->
errorHint = if (isTemplateExist(value)) {
idConflictError
} else if (!isValidTemplateId(value)) {
idInvalidError
} else {
""
}
template = template.copy(id = value)
}
}
TextEdit(
label = stringResource(id = R.string.app_profile_template_name),
text = template.name
) { value ->
template.copy(name = value).run {
if (autoSave) {
if (!saveTemplate(this)) {
// failed
return@run
}
}
template = this
}
}
TextEdit(
label = stringResource(id = R.string.app_profile_template_description),
text = template.description
) { value ->
template.copy(description = value).run {
if (autoSave) {
if (!saveTemplate(this)) {
// failed
return@run
}
}
template = this
}
}
RootProfileConfig(fixedName = true,
profile = toNativeProfile(template),
onProfileChange = {
template.copy(
uid = it.uid,
gid = it.gid,
groups = it.groups,
capabilities = it.capabilities,
context = it.context,
namespace = it.namespace,
rules = it.rules.split("\n")
).run {
if (autoSave) {
if (!saveTemplate(this)) {
// failed
return@run
}
}
template = this
}
})
}
}
}
fun toNativeProfile(templateInfo: TemplateViewModel.TemplateInfo): Natives.Profile {
return Natives.Profile().copy(rootTemplate = templateInfo.id,
uid = templateInfo.uid,
gid = templateInfo.gid,
groups = templateInfo.groups,
capabilities = templateInfo.capabilities,
context = templateInfo.context,
namespace = templateInfo.namespace,
rules = templateInfo.rules.joinToString("\n").ifBlank { "" })
}
fun isTemplateValid(template: TemplateViewModel.TemplateInfo): Boolean {
if (template.id.isBlank()) {
return false
}
if (!isValidTemplateId(template.id)) {
return false
}
return true
}
fun saveTemplate(template: TemplateViewModel.TemplateInfo, isCreation: Boolean = false): Boolean {
if (!isTemplateValid(template)) {
return false
}
if (isCreation && isTemplateExist(template.id)) {
return false
}
val json = template.toJSON()
json.put("local", true)
return setAppProfileTemplate(template.id, json.toString())
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun TopBar(
title: String,
readOnly: Boolean,
summary: String = "",
onBack: () -> Unit,
onDelete: () -> Unit = {},
onSave: () -> Unit = {},
scrollBehavior: TopAppBarScrollBehavior? = null
) {
TopAppBar(
title = {
Column {
Text(title)
if (summary.isNotBlank()) {
Text(
text = summary,
style = MaterialTheme.typography.bodyMedium,
)
}
}
}, navigationIcon = {
IconButton(
onClick = onBack
) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) }
}, actions = {
if (readOnly) {
return@TopAppBar
}
IconButton(onClick = onDelete) {
Icon(
Icons.Filled.DeleteForever,
contentDescription = stringResource(id = R.string.app_profile_template_delete)
)
}
IconButton(onClick = onSave) {
Icon(
imageVector = Icons.Filled.Save,
contentDescription = stringResource(id = R.string.app_profile_template_save)
)
}
},
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal),
scrollBehavior = scrollBehavior
)
}
@Composable
private fun TextEdit(
label: String,
text: String,
errorHint: String = "",
isError: Boolean = false,
onValueChange: (String) -> Unit = {}
) {
ListItem(headlineContent = {
val keyboardController = LocalSoftwareKeyboardController.current
OutlinedTextField(
value = text,
modifier = Modifier.fillMaxWidth(),
label = { Text(label) },
suffix = {
if (errorHint.isNotBlank()) {
Text(
text = if (isError) errorHint else "",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.error
)
}
},
isError = isError,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Ascii, imeAction = ImeAction.Next
),
keyboardActions = KeyboardActions(onDone = {
keyboardController?.hide()
}),
onValueChange = onValueChange
)
})
}
private fun isValidTemplateId(id: String): Boolean {
return Regex("""^([A-Za-z][A-Za-z\d_]*\.)*[A-Za-z][A-Za-z\d_]*$""").matches(id)
}
private fun isTemplateExist(id: String): Boolean {
return getAppProfileTemplate(id).isNotBlank()
}

View File

@@ -1,10 +0,0 @@
package com.rifsxd.ksunext.ui.theme
import androidx.compose.ui.graphics.Color
val YELLOW = Color(0xFFeed502)
val YELLOW_LIGHT = Color(0xFFffff52)
val SECONDARY_LIGHT = Color(0xffa9817f)
val YELLOW_DARK = Color(0xFFb7a400)
val SECONDARY_DARK = Color(0xFF4c2b2b)

View File

@@ -1,46 +0,0 @@
package com.rifsxd.ksunext.ui.theme
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
private val DarkColorScheme = darkColorScheme(
primary = YELLOW,
secondary = YELLOW_DARK,
tertiary = SECONDARY_DARK
)
private val LightColorScheme = lightColorScheme(
primary = YELLOW,
secondary = YELLOW_LIGHT,
tertiary = SECONDARY_LIGHT
)
@Composable
fun KernelSUTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
// Dynamic color is available on Android 12+
dynamicColor: Boolean = true,
content: @Composable () -> Unit
) {
val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
MaterialTheme(
colorScheme = colorScheme,
typography = Typography,
content = content
)
}

View File

@@ -1,33 +0,0 @@
package com.rifsxd.ksunext.ui.theme
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
// Set of Material typography styles to start with
val Typography = androidx.compose.material3.Typography(
bodyLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.5.sp
)
/* Other default text styles to override
titleLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 22.sp,
lineHeight = 28.sp,
letterSpacing = 0.sp
),
labelSmall = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Medium,
fontSize = 11.sp,
lineHeight = 16.sp,
letterSpacing = 0.5.sp
)
*/
)

Some files were not shown because too many files have changed in this diff Show More