691 Commits

Author SHA1 Message Date
Tools-app
aaf27a3db8 chore(ksud): make cargo clippy happy
Signed-off-by: Tools-app <localhost.hutao@gmail.com>
2025-11-30 13:39:52 +08:00
Tools-app
b9d8da3415 fix(ksud): fix print sth. is usize
Signed-off-by: Tools-app <localhost.hutao@gmail.com>
2025-11-30 13:39:52 +08:00
Tools-app
f8a3a3aaf2 feat(ksud): add get susfs version/status/features for ksud susfs
Signed-off-by: Tools-app <localhost.hutao@gmail.com>
2025-11-30 13:39:52 +08:00
Wang Han
ed7b41545a ksud: Remove warning for non-tty std 2025-11-30 13:39:52 +08:00
Saksham
9e65012c99 Clean unused
Some checks failed
Crowdin Action / synchronize-with-crowdin (push) Has been cancelled
2025-11-30 11:06:38 +05:30
Saksham
91ede12d23 clean unused 2025-11-30 11:05:51 +05:30
MorStar
cd12337f2a Update README with SukiSU module mounting note
Added note about SukiSU's module mounting delegation.
2025-11-29 19:04:18 +08:00
Wang Han
2baaecc7f0 kernel: Remove unreachable vfs_statx handling 2025-11-26 17:15:08 +08:00
5ec1cff
ad5042b66e ksud: refine boot patch, add --out-name arg to boot-patch and boot-restore command (#2982) 2025-11-24 11:33:12 +08:00
ShirkNeko
2e067fa5d1 kernel: Avoid duplicating the built in uninstall path adder with the path manager. 2025-11-24 11:32:19 +08:00
ShirkNeko
2c1beac1ca manager: Updated the susfs binary file
- made the umount manager publicly
available

- and removed the “try umount” functionality

- susfs interface and fixed path issues (on Android 16).
2025-11-23 23:51:40 +08:00
Saksham
84be28708e fix declarations 2025-11-23 19:01:57 +05:30
Saksham
6242c6ca8b fix: script 2025-11-23 18:43:07 +05:30
Saksham
ca5e93f221 add: bot: 2025-11-23 18:34:19 +05:30
Wang Han
e382a83895 kernel: Unmount all isolated process which forks from zygote
Kernel has few information about which isolated process belongs to which
application, so there is actually no good choice if we don't implement a
userspace daemon. One choice is to access cmdline memory from kernel,
but cmdline is __user, and it is likely to trigger detections. Before we
have more good ideas, use this.
2025-11-23 19:18:11 +08:00
ShirkNeko
2bc727bfbd manager: Deprecated AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT, the leftover add_sus_mount cli and umount_for_zygote_system_process
Reason:
 - AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT is also causing a bit more performance overheads and still it cannot catch all the sus mounts in all situations. Actually it can easily be done in boot-completed.sh, and it should be more accurate, see module templates for more details.

- Official KernelSU also allows ksud to add custom path to try_umount list as well, users can use their own way to add only the desired sus mounts to try_umount list, but remember to disable susfs ADD_TRY_UMOUNT in kernel if users want to use the official one.

- There are less use cases for umount_for_zygote_system_process, and sometimes enabling this may cause bootloop with some modules enabled, instead user can use busybox nsenter to umount the sus mounts for specific process later by themmselves.
2025-11-22 22:55:42 +08:00
Ylarod
8bdde66eaf ksud: fmt 2025-11-22 17:41:26 +08:00
Wang Han
0582a7554c ksud: Set KSU_MODULE only for module script (#2971) 2025-11-22 17:41:17 +08:00
Ylarod
48016fac7b ksud: config set support read from stdin, and less restriction 2025-11-22 17:40:59 +08:00
Ylarod
823a3f9767 ksud: larger config value size limit, update docs 2025-11-22 17:16:16 +08:00
Tools-app
56a028d60d Fix compile on x86_64
Co-authored-by: weishu <twsxtd@gmail.com>
Signed-off-by: Tools-app <localhost.hutao@gmail.com>
2025-11-22 09:23:23 +08:00
生于生时 亡于亡刻
d0e8faea77 chore(ksud): enable clippy::all, clippy::pedantic && make clippy happy (#617)
* Revert "chore(ksud): bump ksud's deps (#585)"
* Because it may cause compilation errors.

This reverts commit c8020b2066.

* chore(ksud): remove unused Result

Signed-off-by: Tools-app <localhost.hutao@gmail.com>

* chore(ksud): enable clippy::all, clippy::pedantic && make clippy happy

https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or

https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args

https://rust-lang.github.io/rust-clippy/master/index.html#used_underscore_items

https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_for_method_calls

https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pub_crate
...
and use some #![allow(...)] or #[allow(...)]

Signed-off-by: Tools-app <localhost.hutao@gmail.com>

---------

Signed-off-by: Tools-app <localhost.hutao@gmail.com>
2025-11-22 06:09:45 +08:00
AlexLiuDev233
a772a0f82d manager: support meta module (#616) 2025-11-21 21:54:01 +05:30
AlexLiuDev233
de6dc65a56 refactor: use SuFile get Zygisk Implement (#615) 2025-11-21 23:52:16 +08:00
weishu
c81e0c6c0f meta-overlayfs: Moved to module repo 2025-11-21 14:03:36 +08:00
Wang Han
f87e705e2f ksud: Use regex to validate module id (#2968)
https://github.com/tiann/KernelSU/blob/main/website/docs/guide/module.md?plain=1#L106
2025-11-21 13:10:24 +08:00
weishu
078ffdb5e1 metaovl: Fix incorrect permission, Add updateJson and changelog 2025-11-21 11:13:29 +08:00
Ylarod
5a6ab43ea4 add module config, migrate managedFeatures (#2965)
Co-authored-by: YuKongA <70465933+YuKongA@users.noreply.github.com>
2025-11-20 22:17:33 +08:00
ShirkNeko
de6b2794b7 manager: Fixed the module list retrieval to the correct format 2025-11-20 21:38:22 +08:00
ShirkNeko
c574f39ae3 kernel/manager: No longer need to add unmounting for default mount points 2025-11-20 21:38:21 +08:00
ShirkNeko
954ecd9644 support metamodule, remove built-in overlayfs mount
Co-authored-by: weishu <twsxtd@gmail.com>
Co-authored-by: YuKongA <70465933+YuKongA@users.noreply.github.com>
Co-authored-by: Ylarod <me@ylarod.cn>
2025-11-20 21:38:01 +08:00
ShirkNeko
8250c0ecc2 Reapply "kernel: expose umount list to ioctl interface #2950"
This reverts commit 088996da9b.
2025-11-20 20:07:59 +08:00
ShirkNeko
cc78812f50 manager: Rework 2025-11-20 20:07:35 +08:00
ShirkNeko
088996da9b Revert "kernel: expose umount list to ioctl interface #2950"
This reverts commit 029ae8d389.
2025-11-20 18:48:59 +08:00
ShirkNeko
52a3a04b11 manager: Remove obsolete susfs configuration entries 2025-11-20 17:14:09 +08:00
ShirkNeko
f290653088 ci: Fix omitted checks 2025-11-20 14:40:38 +08:00
ShirkNeko
33c498078f ci :Skip the disguised manager build for the MIUIX branch 2025-11-20 14:29:18 +08:00
ShirkNeko
fb0eea2994 ci: Add the MIUIX branch build 2025-11-19 18:48:05 +08:00
ShirkNeko
2ea748dac1 manager: add inset support to webui (#2952)
ref:
https://github.com/MMRLApp/WebUI-X-Portable/blob/master/webui/src/main/kotlin/com/dergoogler/mmrl/webui/model/Insets.kt

Co-Authored-By: Der_Googler
<54764558+dergoogler@users.noreply.github.com>
Signed-off-by: KOWX712 <leecc0503@gmail.com>

---------

Co-authored-by: KOWX712 <leecc0503@gmail.com>
Co-authored-by: Der_Googler <54764558+dergoogler@users.noreply.github.com>
Co-authored-by: Light_summer <93428659+lightsummer233@users.noreply.github.com>
2025-11-19 14:23:49 +08:00
ShirkNeko
429874b4d6 manager: fix webui package manager
Co-authored-by: KOWX712 <leecc0503@gmail.com>
Co-authored-by: YuKongA <70465933+YuKongA@users.noreply.github.com>
2025-11-19 13:13:11 +08:00
ShirkNeko
cd86589ad3 manager: Fixed an error caused by the line count identifier being omitted in the Umount Path Manager. 2025-11-18 13:49:21 +08:00
ShirkNeko
22cb7596a7 ksud: fmt & fix build 2025-11-18 12:44:27 +08:00
backslashxx
029ae8d389 kernel: expose umount list to ioctl interface (#2950)
This idea is borrowed from simonpunk's susfs4ksu.
What we see here is that, yeah well, lets just have userspace send us
what it
wants unmounted, this is better than hardcoding everything.

This also solves that issue where MNT_DETACH fails, as long as we send
unmountables in proper order.

A small anti-duplicate mechanism is also added.

While in-kernel umount is a bit worse than zygisk-provider-based ones,
this can still
serve as a healthy alternative.

---------

- Remove duplicate checks

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
Co-authored-by: weishu <twsxtd@gmail.com>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-11-18 12:36:42 +08:00
Wang Han
58c8289890 kernel/ksud: Fix KSU_IOCTL_NUKE_EXT4_SYSFS definition 2025-11-18 12:17:00 +08:00
weishu
94fa1e360a ksud: Add cli interface for nuke_ext4_sysfs 2025-11-18 12:15:49 +08:00
weishu
1d1ce396d3 kernel: Add nuke_ext4_sysfs interface 2025-11-18 12:12:06 +08:00
ShirkNeko
99d58c8cfd manager: Only display the option to use LKM files when the kernel version is greater than 5.10 2025-11-18 00:34:19 +08:00
ShirkNeko
ad2a23f55e manager: Move certain settings to the Advanced Settings section. 2025-11-17 12:37:53 +08:00
ShirkNeko
f48d2e6cac manger: fmt code 2025-11-17 12:20:45 +08:00
ShirkNeko
d45676f059 manager: bump susfs assets 2025-11-17 11:46:32 +08:00
AlexLiuDev233
0439a00f1d manager: increase appGroup performance & add appGroup status notice 2025-11-16 23:02:15 +08:00
ShirkNeko
cbcaa07fd5 manager: Set up in real time using the correct method 2025-11-16 17:19:48 +08:00
ShirkNeko
c4d8c49e5c kernel/manager/ksud: Add switch functionality to sulog
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-11-16 16:53:55 +08:00
生于生时 亡于亡刻
c8020b2066 chore(ksud): bump ksud's deps (#585)
Name                                              Project            Compat   Latest   Kind         Platform
----                                              -------            ------   ------   ----         --------
addr2line->gimli                                  0.31.1             Removed  Removed  Normal       ---
ahash->cfg-if                                     1.0.0              Removed  Removed  Normal       ---
ahash->once_cell                                  1.21.3             Removed  Removed  Normal       cfg(not(all(target_arch = "arm", target_os = "none")))
ahash->version_check                              0.9.5              Removed  Removed  Build        ---
ahash->zerocopy                                   0.8.25             Removed  Removed  Normal       ---
android_logger                                    0.14.1             ---      0.15.1   Normal       cfg(target_os = "android")
android_logger->env_filter                        0.1.3              0.1.4    0.1.4    Normal       ---
android_logger->log                               0.4.27             0.4.28   0.4.28   Normal       ---
android_system_properties->libc                   0.2.172            0.2.177  0.2.177  Normal       ---
anstream->anstyle                                 1.0.10             1.0.13   1.0.13   Normal       ---
anstream->anstyle-parse                           0.2.6              0.2.7    0.2.7    Normal       ---
anstream->anstyle-query                           1.1.2              1.1.5    1.1.5    Normal       ---
anstream->anstyle-wincon                          3.0.7              3.0.11   3.0.11   Normal       cfg(windows)
anstream->colorchoice                             1.0.3              1.0.4    1.0.4    Normal       ---
anstream->is_terminal_polyfill                    1.70.1             1.70.2   1.70.2   Normal       ---
anstyle-query->windows-sys                        0.59.0             0.61.2   0.61.2   Normal       cfg(windows)
anstyle-wincon->anstyle                           1.0.10             1.0.13   1.0.13   Normal       ---
anstyle-wincon->once_cell                         1.21.3             Removed  Removed  Normal       cfg(windows)
anstyle-wincon->windows-sys                       0.59.0             0.61.2   0.61.2   Normal       cfg(windows)
anyhow                                            1.0.98             1.0.100  1.0.100  Normal       ---
arbitrary->derive_arbitrary                       1.4.1              1.4.2    1.4.2    Normal       ---
async-trait->proc-macro2                          1.0.95             1.0.103  1.0.103  Normal       ---
async-trait->quote                                1.0.40             1.0.42   1.0.42   Normal       ---
async-trait->syn                                  2.0.101            2.0.110  2.0.110  Normal       ---
backtrace->addr2line                              0.24.2             Removed  Removed  Normal       cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))
backtrace->cfg-if                                 1.0.0              Removed  Removed  Normal       ---
backtrace->libc                                   0.2.172            Removed  Removed  Normal       cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))
backtrace->miniz_oxide                            0.8.8              Removed  Removed  Normal       cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))
backtrace->object                                 0.36.7             Removed  Removed  Normal       cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))
backtrace->rustc-demangle                         0.1.24             Removed  Removed  Normal       ---
backtrace->windows-targets                        0.52.6             Removed  Removed  Normal       cfg(any(windows, target_os = "cygwin"))
cc->shlex                                         1.3.0              ---      Removed  Normal       ---
chrono                                            0.4.41             0.4.42   0.4.42   Normal       ---
chrono->android-tzdata                            0.1.1              Removed  Removed  Normal       cfg(target_os = "android")
chrono->iana-time-zone                            0.1.63             0.1.64   0.1.64   Normal       cfg(unix)
chrono->js-sys                                    0.3.77             0.3.82   0.3.82   Normal       cfg(all(target_arch = "wasm32", not(any(target_os = "emscripten", target_os = "wasi"))))
chrono->wasm-bindgen                              0.2.100            0.2.105  0.2.105  Normal       cfg(all(target_arch = "wasm32", not(any(target_os = "emscripten", target_os = "wasi"))))
chrono->windows-link                              0.1.3              0.2.1    0.2.1    Normal       cfg(windows)
clap                                              4.5.38             4.5.51   4.5.51   Normal       ---
clap->clap_builder                                4.5.38             4.5.51   4.5.51   Normal       ---
clap->clap_derive                                 4.5.32             4.5.49   4.5.49   Normal       ---
clap_builder->anstream                            0.6.18             0.6.21   0.6.21   Normal       ---
clap_builder->anstyle                             1.0.10             1.0.13   1.0.13   Normal       ---
clap_builder->clap_lex                            0.7.4              0.7.6    0.7.6    Normal       ---
clap_derive->proc-macro2                          1.0.95             1.0.103  1.0.103  Normal       ---
clap_derive->quote                                1.0.40             1.0.42   1.0.42   Normal       ---
clap_derive->syn                                  2.0.101            2.0.110  2.0.110  Normal       ---
const_format                                      0.2.34             0.2.35   0.2.35   Normal       ---
const_format_proc_macros->proc-macro2             1.0.95             1.0.103  1.0.103  Normal       ---
const_format_proc_macros->quote                   1.0.40             1.0.42   1.0.42   Normal       ---
core2->memchr                                     2.7.4              2.7.6    2.7.6    Normal       ---
cpufeatures->libc                                 0.2.172            0.2.177  0.2.177  Normal       aarch64-linux-android
crc->crc-catalog                                  2.4.0              ---      Removed  Normal       ---
crc32fast->cfg-if                                 1.0.0              1.0.4    1.0.4    Normal       ---
crossbeam-channel->crossbeam-utils                0.8.21             ---      Removed  Normal       ---
crypto-common->typenum                            1.18.0             1.19.0   1.19.0   Normal       ---
deranged->powerfmt                                0.2.0              ---      Removed  Normal       ---
derive-new->proc-macro2                           1.0.95             1.0.103  1.0.103  Normal       ---
derive-new->quote                                 1.0.40             1.0.42   1.0.42   Normal       ---
derive-new->syn                                   2.0.101            2.0.110  2.0.110  Normal       ---
derive_arbitrary->proc-macro2                     1.0.95             1.0.103  1.0.103  Normal       ---
derive_arbitrary->quote                           1.0.40             1.0.42   1.0.42   Normal       ---
derive_arbitrary->syn                             2.0.101            2.0.110  2.0.110  Normal       ---
digest->crypto-common                             0.1.6              0.1.7    0.1.7    Normal       ---
encoding_rs->cfg-if                               1.0.0              1.0.4    1.0.4    Normal       ---
env_filter->log                                   0.4.27             0.4.28   0.4.28   Normal       ---
env_logger->env_filter                            0.1.3              0.1.4    0.1.4    Normal       ---
env_logger->log                                   0.4.27             0.4.28   0.4.28   Normal       ---
errno->libc                                       0.2.172            0.2.177  0.2.177  Normal       cfg(target_os = "hermit")
errno->windows-sys                                0.59.0             0.61.2   0.61.2   Normal       cfg(windows)
errno-dragonfly->cc                               1.2.22             1.2.46   1.2.46   Build        ---
errno-dragonfly->libc                             0.2.172            0.2.177  0.2.177  Normal       ---
extattr->libc                                     0.2.172            0.2.177  0.2.177  Normal       ---
filetime->cfg-if                                  1.0.0              1.0.4    Removed  Normal       ---
filetime->libc                                    0.2.172            0.2.177  Removed  Normal       cfg(unix)
filetime->libredox                                0.1.9              0.1.10   Removed  Normal       cfg(target_os = "redox")
filetime->windows-sys                             0.60.2             ---      Removed  Normal       cfg(windows)
flate2->crc32fast                                 1.4.2              1.5.0    1.5.0    Normal       ---
flate2->miniz_oxide                               0.8.8              0.8.9    0.8.9    Normal       ---
fsevent-sys->libc                                 0.2.172            0.2.177  0.2.177  Normal       ---
generic-array->typenum                            1.18.0             1.19.0   1.19.0   Normal       ---
getopts                                           0.2.21             0.2.24   0.2.24   Normal       ---
getopts->unicode-width                            0.1.14             0.2.2    0.2.2    Normal       ---
getrandom->cfg-if                                 1.0.0              1.0.4    1.0.4    Normal       ---
getrandom->libc                                   0.2.172            0.2.177  0.2.177  Normal       cfg(all(any(target_os = "linux", target_os = "android"), not(any(all(target_os = "linux", target_env = ""), getrandom_backend = "custom", getrandom_backend = "linux_raw", getrandom_backend = "rdrand", getrandom_backend = "rndr"))))
getrandom->r-efi                                  5.2.0              5.3.0    5.3.0    Normal       cfg(all(target_os = "uefi", getrandom_backend = "efi_rng"))
getrandom->wasi                                   0.14.2+wasi-0.2.4  Removed  Removed  Normal       cfg(all(target_arch = "wasm32", target_os = "wasi", target_env = "p2"))
hashbrown->ahash                                  0.8.12             Removed  Removed  Normal       ---
iana-time-zone->js-sys                            0.3.77             0.3.82   0.3.82   Normal       cfg(all(target_arch = "wasm32", target_os = "unknown"))
iana-time-zone->log                               0.4.27             0.4.28   0.4.28   Normal       cfg(all(target_arch = "wasm32", target_os = "unknown"))
iana-time-zone->wasm-bindgen                      0.2.100            0.2.105  0.2.105  Normal       cfg(all(target_arch = "wasm32", target_os = "unknown"))
iana-time-zone->windows-core                      0.61.0             0.62.2   0.62.2   Normal       cfg(target_os = "windows")
iana-time-zone-haiku->cc                          1.2.22             1.2.46   1.2.46   Build        ---
include-flate->include-flate-codegen              0.2.0              0.3.1    0.3.1    Normal       ---
include-flate->lazy_static                        1.5.0              Removed  Removed  Normal       ---
include-flate->libflate                           2.1.0              2.2.1    2.2.1    Normal       ---
include-flate-codegen->libflate                   2.1.0              2.2.1    2.2.1    Normal       ---
include-flate-codegen->proc-macro2                1.0.95             1.0.103  1.0.103  Normal       ---
include-flate-codegen->quote                      1.0.40             1.0.42   1.0.42   Normal       ---
include-flate-codegen->syn                        2.0.101            2.0.110  2.0.110  Normal       ---
indexmap->hashbrown                               0.15.2             0.16.0   0.16.0   Normal       ---
inotify->bitflags                                 1.3.2              ---      2.10.0   Normal       ---
inotify->libc                                     0.2.172            0.2.177  0.2.177  Normal       ---
inotify-sys->libc                                 0.2.172            0.2.177  0.2.177  Normal       ---
is_executable                                     1.0.4              1.0.5    1.0.5    Normal       ---
is_executable->winapi                             0.3.9              Removed  Removed  Normal       cfg(target_os = "windows")
java-properties->regex-lite                       0.1.6              0.1.8    0.1.8    Normal       ---
js-sys->wasm-bindgen                              0.2.100            0.2.105  0.2.105  Normal       ---
jwalk->rayon                                      1.10.0             1.11.0   1.11.0   Normal       ---
kqueue->libc                                      0.2.172            0.2.177  0.2.177  Normal       ---
kqueue-sys->libc                                  0.2.172            0.2.177  0.2.177  Normal       ---
libc                                              0.2.172            0.2.177  0.2.177  Normal       ---
libflate->crc32fast                               1.4.2              1.5.0    1.5.0    Normal       ---
libflate->dary_heap                               0.3.7              0.3.8    0.3.8    Normal       ---
libflate->libflate_lz77                           2.1.0              2.2.0    2.2.0    Normal       ---
libflate_lz77->hashbrown                          0.14.5             0.16.0   0.16.0   Normal       ---
libredox->bitflags                                2.8.0              2.10.0   Removed  Normal       ---
libredox->libc                                    0.2.172            0.2.177  Removed  Normal       ---
libredox->redox_syscall                           0.5.17             0.5.18   Removed  Normal       ---
log                                               0.4.27             0.4.28   0.4.28   Normal       ---
lzma-rs->byteorder                                1.5.0              ---      Removed  Normal       ---
lzma-rs->crc                                      3.3.0              ---      Removed  Normal       ---
lzma-sys->cc                                      1.2.22             1.2.46   1.2.46   Build        ---
lzma-sys->cc                                      1.2.22             1.2.46   Removed  Build        ---
lzma-sys->libc                                    0.2.172            0.2.177  0.2.177  Normal       ---
lzma-sys->libc                                    0.2.172            0.2.177  Removed  Normal       ---
lzma-sys->pkg-config                              0.3.32             ---      Removed  Build        ---
miniz_oxide->adler2                               2.0.0              2.0.1    2.0.1    Normal       ---
miniz_oxide->adler2                               2.0.0              Removed  Removed  Normal       ---
mio->libc                                         0.2.172            0.2.177  0.2.177  Normal       cfg(target_os = "wasi")
mio->log                                          0.4.27             0.4.28   0.4.28   Normal       ---
mio->windows-sys                                  0.48.0             ---      0.61.2   Normal       cfg(windows)
nom->memchr                                       2.7.4              2.7.6    2.7.6    Normal       ---
notify                                            6.1.1              ---      8.2.0    Normal       ---
notify->bitflags                                  2.8.0              2.10.0   2.10.0   Normal       cfg(target_os = "macos")
notify->crossbeam-channel                         0.5.15             ---      Removed  Normal       ---
notify->filetime                                  0.2.26             ---      Removed  Normal       ---
notify->inotify                                   0.9.6              ---      0.11.0   Normal       cfg(any(target_os = "linux", target_os = "android"))
notify->libc                                      0.2.172            0.2.177  0.2.177  Normal       ---
notify->log                                       0.4.27             0.4.28   0.4.28   Normal       ---
notify->mio                                       0.8.11             ---      1.1.0    Normal       cfg(any(target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", target_os = "dragonflybsd"))
notify->windows-sys                               0.48.0             ---      0.60.2   Normal       cfg(windows)
num-traits->autocfg                               1.4.0              1.5.0    1.5.0    Build        ---
object->memchr                                    2.7.4              Removed  Removed  Normal       ---
proc-macro2->unicode-ident                        1.0.18             1.0.22   1.0.22   Normal       ---
proc-macro2->unicode-ident                        1.0.18             1.0.22   Removed  Normal       ---
proc-macro2->unicode-ident                        1.0.18             Removed  Removed  Normal       ---
quote->proc-macro2                                1.0.95             1.0.103  1.0.103  Normal       ---
quote->proc-macro2                                1.0.95             1.0.103  Removed  Normal       ---
quote->proc-macro2                                1.0.95             Removed  Removed  Normal       ---
rayon->rayon-core                                 1.12.1             1.13.0   1.13.0   Normal       ---
redox_syscall->bitflags                           2.8.0              2.10.0   Removed  Normal       ---
regex-lite                                        0.1.6              0.1.8    0.1.8    Normal       ---
rust-embed                                        8.7.2              8.9.0    8.9.0    Normal       ---
rust-embed->include-flate                         0.3.0              0.3.1    0.3.1    Normal       ---
rust-embed->rust-embed-impl                       8.7.2              8.9.0    8.9.0    Normal       ---
rust-embed->rust-embed-utils                      8.7.2              8.9.0    8.9.0    Normal       ---
rust-embed-impl->proc-macro2                      1.0.95             1.0.103  1.0.103  Normal       ---
rust-embed-impl->quote                            1.0.40             1.0.42   1.0.42   Normal       ---
rust-embed-impl->rust-embed-utils                 8.7.2              8.9.0    8.9.0    Normal       ---
rust-embed-impl->syn                              2.0.101            2.0.110  2.0.110  Normal       ---
rustix                                            0.38.34            1.1.2    1.1.2    Normal       cfg(any(target_os = "android", target_os = "linux"))
rustix->bitflags                                  2.8.0              2.10.0   2.10.0   Normal       ---
rustix->errno                                     0.3.10             0.3.14   0.3.14   Development  ---
rustix->itoa                                      1.0.15             Removed  Removed  Normal       ---
rustix->libc                                      0.2.172            0.2.177  0.2.177  Development  ---
rustix->linux-raw-sys                             0.4.15             0.11.0   0.11.0   Normal       cfg(all(any(target_os = "android", target_os = "linux"), any(rustix_use_libc, miri, not(all(target_os = "linux", target_endian = "little", any(target_arch = "arm", all(target_arch = "aarch64", target_pointer_width = "64"), target_arch = "riscv64", all(rustix_use_experimental_asm, target_arch = "powerpc64"), all(rustix_use_experimental_asm, target_arch = "mips"), all(rustix_use_experimental_asm, target_arch = "mips32r6"), all(rustix_use_experimental_asm, target_arch = "mips64"), all(rustix_use_experimental_asm, target_arch = "mips64r6"), target_arch = "x86", all(target_arch = "x86_64", target_pointer_width = "64")))))))
rustix->linux-raw-sys                             0.9.4              0.11.0   0.11.0   Normal       cfg(all(any(target_os = "android", target_os = "linux"), any(rustix_use_libc, miri, not(all(target_os = "linux", any(target_endian = "little", any(target_arch = "s390x", target_arch = "powerpc")), any(target_arch = "arm", all(target_arch = "aarch64", target_pointer_width = "64"), target_arch = "riscv64", all(rustix_use_experimental_asm, target_arch = "powerpc"), all(rustix_use_experimental_asm, target_arch = "powerpc64"), all(rustix_use_experimental_asm, target_arch = "s390x"), all(rustix_use_experimental_asm, target_arch = "mips"), all(rustix_use_experimental_asm, target_arch = "mips32r6"), all(rustix_use_experimental_asm, target_arch = "mips64"), all(rustix_use_experimental_asm, target_arch = "mips64r6"), target_arch = "x86", all(target_arch = "x86_64", target_pointer_width = "64")))))))
rustix->once_cell                                 1.21.3             Removed  Removed  Normal       cfg(any(target_os = "android", target_os = "linux"))
rustix->windows-sys                               0.52.0             0.61.2   0.61.2   Normal       cfg(windows)
rustix->windows-sys                               0.59.0             0.61.2   0.61.2   Normal       cfg(windows)
same-file->winapi-util                            0.1.9              0.1.11   0.1.11   Normal       cfg(windows)
serde                                             1.0.219            1.0.228  1.0.228  Normal       ---
serde->serde_derive                               1.0.219            1.0.228  1.0.228  Normal       ---
serde->serde_derive                               1.0.219            1.0.228  Removed  Normal       ---
serde_derive->proc-macro2                         1.0.95             1.0.103  1.0.103  Normal       ---
serde_derive->proc-macro2                         1.0.95             1.0.103  Removed  Normal       ---
serde_derive->quote                               1.0.40             1.0.42   1.0.42   Normal       ---
serde_derive->quote                               1.0.40             1.0.42   Removed  Normal       ---
serde_derive->syn                                 2.0.101            2.0.110  2.0.110  Normal       ---
serde_derive->syn                                 2.0.101            2.0.110  Removed  Normal       ---
serde_json                                        1.0.140            1.0.145  1.0.145  Normal       ---
serde_json->memchr                                2.7.4              2.7.6    2.7.6    Normal       ---
serde_json->serde                                 1.0.219            1.0.228  1.0.228  Normal       ---
sha1->cfg-if                                      1.0.0              1.0.4    1.0.4    Normal       ---
sha2->cfg-if                                      1.0.0              1.0.4    1.0.4    Normal       ---
sha256->async-trait                               0.1.88             0.1.89   0.1.89   Normal       ---
sha256->bytes                                     1.10.1             1.11.0   1.11.0   Normal       ---
sha256->tokio                                     1.45.0             1.48.0   1.48.0   Normal       ---
syn->proc-macro2                                  1.0.95             1.0.103  1.0.103  Normal       ---
syn->proc-macro2                                  1.0.95             1.0.103  Removed  Normal       ---
syn->proc-macro2                                  1.0.95             Removed  Removed  Normal       ---
syn->quote                                        1.0.40             1.0.42   1.0.42   Normal       ---
syn->quote                                        1.0.40             1.0.42   Removed  Normal       ---
syn->quote                                        1.0.40             Removed  Removed  Normal       ---
syn->unicode-ident                                1.0.18             1.0.22   1.0.22   Normal       ---
syn->unicode-ident                                1.0.18             1.0.22   Removed  Normal       ---
syn->unicode-ident                                1.0.18             Removed  Removed  Normal       ---
tempfile                                          3.20.0             3.23.0   3.23.0   Normal       ---
tempfile->getrandom                               0.3.3              0.3.4    0.3.4    Normal       cfg(any(unix, windows, target_os = "wasi"))
tempfile->rustix                                  1.0.7              1.1.2    1.1.2    Normal       cfg(any(unix, target_os = "wasi"))
tempfile->windows-sys                             0.59.0             0.61.2   0.61.2   Normal       cfg(windows)
time->deranged                                    0.4.0              0.5.5    0.5.5    Normal       ---
time->deranged                                    0.4.0              0.5.5    Removed  Normal       ---
time->num-conv                                    0.1.0              ---      Removed  Normal       ---
time->powerfmt                                    0.2.0              ---      Removed  Normal       ---
time->serde                                       1.0.219            1.0.228  1.0.228  Normal       ---
time->serde                                       1.0.219            1.0.228  Removed  Normal       ---
time->time-core                                   0.1.4              0.1.6    0.1.6    Normal       ---
time->time-core                                   0.1.4              0.1.6    Removed  Normal       ---
tokio->backtrace                                  0.3.75             Removed  Removed  Normal       cfg(tokio_taskdump)
tokio->bytes                                      1.10.1             1.11.0   1.11.0   Normal       ---
walkdir->winapi-util                              0.1.9              0.1.11   0.1.11   Normal       cfg(windows)
wasi->wit-bindgen-rt                              0.39.0             Removed  Removed  Normal       ---
wasm-bindgen->cfg-if                              1.0.0              1.0.4    1.0.4    Normal       ---
wasm-bindgen->rustversion                         1.0.20             1.0.22   1.0.22   Normal       ---
wasm-bindgen->wasm-bindgen-macro                  0.2.100            0.2.105  0.2.105  Normal       ---
wasm-bindgen-backend->bumpalo                     3.17.0             Removed  Removed  Normal       ---
wasm-bindgen-backend->log                         0.4.27             Removed  Removed  Normal       ---
wasm-bindgen-backend->proc-macro2                 1.0.95             Removed  Removed  Normal       ---
wasm-bindgen-backend->quote                       1.0.40             Removed  Removed  Normal       ---
wasm-bindgen-backend->syn                         2.0.101            Removed  Removed  Normal       ---
wasm-bindgen-backend->wasm-bindgen-shared         0.2.100            Removed  Removed  Normal       ---
wasm-bindgen-macro->quote                         1.0.40             1.0.42   1.0.42   Normal       ---
wasm-bindgen-macro->wasm-bindgen-macro-support    0.2.100            0.2.105  0.2.105  Normal       ---
wasm-bindgen-macro-support->proc-macro2           1.0.95             1.0.103  1.0.103  Normal       ---
wasm-bindgen-macro-support->quote                 1.0.40             1.0.42   1.0.42   Normal       ---
wasm-bindgen-macro-support->syn                   2.0.101            2.0.110  2.0.110  Normal       ---
wasm-bindgen-macro-support->wasm-bindgen-backend  0.2.100            Removed  Removed  Normal       ---
wasm-bindgen-macro-support->wasm-bindgen-shared   0.2.100            0.2.105  0.2.105  Normal       ---
wasm-bindgen-shared->unicode-ident                1.0.18             1.0.22   1.0.22   Normal       ---
wasm-bindgen-shared->unicode-ident                1.0.18             Removed  Removed  Normal       ---
which                                             7.0.3              ---      8.0.0    Normal       ---
which->either                                     1.15.0             ---      Removed  Normal       ---
which->rustix                                     1.0.7              1.1.2    1.1.2    Normal       cfg(any(unix, target_os = "wasi", target_os = "redox"))
winapi->winapi-i686-pc-windows-gnu                0.4.0              Removed  Removed  Normal       i686-pc-windows-gnu
winapi->winapi-x86_64-pc-windows-gnu              0.4.0              Removed  Removed  Normal       x86_64-pc-windows-gnu
winapi-util->windows-sys                          0.59.0             0.61.2   0.61.2   Normal       cfg(windows)
windows-core->windows-implement                   0.60.0             0.60.2   0.60.2   Normal       ---
windows-core->windows-interface                   0.59.1             0.59.3   0.59.3   Normal       ---
windows-core->windows-link                        0.1.3              0.2.1    0.2.1    Normal       ---
windows-core->windows-result                      0.3.2              0.4.1    0.4.1    Normal       ---
windows-core->windows-strings                     0.4.0              0.5.1    0.5.1    Normal       ---
windows-implement->proc-macro2                    1.0.95             1.0.103  1.0.103  Normal       ---
windows-implement->quote                          1.0.40             1.0.42   1.0.42   Normal       ---
windows-implement->syn                            2.0.101            2.0.110  2.0.110  Normal       ---
windows-interface->proc-macro2                    1.0.95             1.0.103  1.0.103  Normal       ---
windows-interface->quote                          1.0.40             1.0.42   1.0.42   Normal       ---
windows-interface->syn                            2.0.101            2.0.110  2.0.110  Normal       ---
windows-result->windows-link                      0.1.3              0.2.1    0.2.1    Normal       ---
windows-strings->windows-link                     0.1.3              0.2.1    0.2.1    Normal       ---
windows-sys->windows-targets                      0.48.5             ---      0.53.5   Normal       ---
windows-sys->windows-targets                      0.48.5             ---      Removed  Normal       ---
windows-sys->windows-targets                      0.52.6             Removed  Removed  Normal       ---
windows-sys->windows-targets                      0.53.3             0.53.5   Removed  Normal       ---
windows-targets->windows-link                     0.1.3              0.2.1    Removed  Normal       cfg(windows_raw_dylib)
windows-targets->windows_aarch64_gnullvm          0.48.5             ---      0.53.1   Normal       aarch64-pc-windows-gnullvm
windows-targets->windows_aarch64_gnullvm          0.48.5             ---      Removed  Normal       aarch64-pc-windows-gnullvm
windows-targets->windows_aarch64_gnullvm          0.52.6             Removed  Removed  Normal       aarch64-pc-windows-gnullvm
windows-targets->windows_aarch64_gnullvm          0.53.0             0.53.1   Removed  Normal       aarch64-pc-windows-gnullvm
windows-targets->windows_aarch64_msvc             0.48.5             ---      0.53.1   Normal       cfg(all(target_arch = "aarch64", target_env = "msvc", not(windows_raw_dylib)))
windows-targets->windows_aarch64_msvc             0.48.5             ---      Removed  Normal       cfg(all(target_arch = "aarch64", target_env = "msvc", not(windows_raw_dylib)))
windows-targets->windows_aarch64_msvc             0.52.6             Removed  Removed  Normal       cfg(all(target_arch = "aarch64", target_env = "msvc", not(windows_raw_dylib)))
windows-targets->windows_aarch64_msvc             0.53.0             0.53.1   Removed  Normal       cfg(all(target_arch = "aarch64", target_env = "msvc", not(windows_raw_dylib)))
windows-targets->windows_i686_gnu                 0.48.5             ---      0.53.1   Normal       cfg(all(target_arch = "x86", target_env = "gnu", not(windows_raw_dylib)))
windows-targets->windows_i686_gnu                 0.48.5             ---      Removed  Normal       cfg(all(target_arch = "x86", target_env = "gnu", not(windows_raw_dylib)))
windows-targets->windows_i686_gnu                 0.52.6             Removed  Removed  Normal       cfg(all(target_arch = "x86", target_env = "gnu", not(target_abi = "llvm"), not(windows_raw_dylib)))
windows-targets->windows_i686_gnu                 0.53.0             0.53.1   Removed  Normal       cfg(all(target_arch = "x86", target_env = "gnu", not(target_abi = "llvm"), not(windows_raw_dylib)))
windows-targets->windows_i686_gnullvm             0.52.6             Removed  Removed  Normal       i686-pc-windows-gnullvm
windows-targets->windows_i686_gnullvm             0.53.0             0.53.1   Removed  Normal       i686-pc-windows-gnullvm
windows-targets->windows_i686_msvc                0.48.5             ---      0.53.1   Normal       cfg(all(target_arch = "x86", target_env = "msvc", not(windows_raw_dylib)))
windows-targets->windows_i686_msvc                0.48.5             ---      Removed  Normal       cfg(all(target_arch = "x86", target_env = "msvc", not(windows_raw_dylib)))
windows-targets->windows_i686_msvc                0.52.6             Removed  Removed  Normal       cfg(all(target_arch = "x86", target_env = "msvc", not(windows_raw_dylib)))
windows-targets->windows_i686_msvc                0.53.0             0.53.1   Removed  Normal       cfg(all(target_arch = "x86", target_env = "msvc", not(windows_raw_dylib)))
windows-targets->windows_x86_64_gnu               0.48.5             ---      0.53.1   Normal       cfg(all(target_arch = "x86_64", target_env = "gnu", not(target_abi = "llvm"), not(windows_raw_dylib)))
windows-targets->windows_x86_64_gnu               0.48.5             ---      Removed  Normal       cfg(all(target_arch = "x86_64", target_env = "gnu", not(target_abi = "llvm"), not(windows_raw_dylib)))
windows-targets->windows_x86_64_gnu               0.52.6             Removed  Removed  Normal       cfg(all(target_arch = "x86_64", target_env = "gnu", not(target_abi = "llvm"), not(windows_raw_dylib)))
windows-targets->windows_x86_64_gnu               0.53.0             0.53.1   Removed  Normal       cfg(all(target_arch = "x86_64", target_env = "gnu", not(target_abi = "llvm"), not(windows_raw_dylib)))
windows-targets->windows_x86_64_gnullvm           0.48.5             ---      0.53.1   Normal       x86_64-pc-windows-gnullvm
windows-targets->windows_x86_64_gnullvm           0.48.5             ---      Removed  Normal       x86_64-pc-windows-gnullvm
windows-targets->windows_x86_64_gnullvm           0.52.6             Removed  Removed  Normal       x86_64-pc-windows-gnullvm
windows-targets->windows_x86_64_gnullvm           0.53.0             0.53.1   Removed  Normal       x86_64-pc-windows-gnullvm
windows-targets->windows_x86_64_msvc              0.48.5             ---      0.53.1   Normal       cfg(all(target_arch = "x86_64", target_env = "msvc", not(windows_raw_dylib)))
windows-targets->windows_x86_64_msvc              0.48.5             ---      Removed  Normal       cfg(all(target_arch = "x86_64", target_env = "msvc", not(windows_raw_dylib)))
windows-targets->windows_x86_64_msvc              0.52.6             Removed  Removed  Normal       cfg(all(any(target_arch = "x86_64", target_arch = "arm64ec"), target_env = "msvc", not(windows_raw_dylib)))
windows-targets->windows_x86_64_msvc              0.53.0             0.53.1   Removed  Normal       cfg(all(any(target_arch = "x86_64", target_arch = "arm64ec"), target_env = "msvc", not(windows_raw_dylib)))
wit-bindgen-rt->bitflags                          2.8.0              Removed  Removed  Normal       ---
xz2->lzma-sys                                     0.1.20             ---      Removed  Normal       ---
zerocopy->zerocopy-derive                         0.8.25             Removed  Removed  Normal       ---
zerocopy-derive->proc-macro2                      1.0.95             Removed  Removed  Normal       ---
zerocopy-derive->quote                            1.0.40             Removed  Removed  Normal       ---
zerocopy-derive->syn                              2.0.101            Removed  Removed  Normal       ---
zip                                               3.0.0              ---      6.0.0    Normal       ---
zip->arbitrary                                    1.4.1              1.4.2    1.4.2    Normal       cfg(fuzzing)
zip->crc32fast                                    1.4.2              1.5.0    1.5.0    Normal       ---
zip->deflate64                                    0.1.9              0.1.10   0.1.10   Normal       ---
zip->deflate64                                    0.1.9              0.1.10   Removed  Normal       ---
zip->flate2                                       1.1.1              1.1.5    1.1.5    Normal       ---
zip->indexmap                                     2.9.0              2.12.0   2.12.0   Normal       ---
zip->lzma-rs                                      0.3.0              ---      Removed  Normal       ---
zip->memchr                                       2.7.4              2.7.6    2.7.6    Normal       ---
zip->time                                         0.3.41             0.3.44   0.3.44   Normal       ---
zip->time                                         0.3.41             0.3.44   Removed  Normal       ---
zip->xz2                                          0.1.7              ---      Removed  Normal       ---
zip->zopfli                                       0.8.2              0.8.3    0.8.3    Normal       ---
zopfli->bumpalo                                   3.17.0             3.19.0   3.19.0   Normal       ---
zopfli->crc32fast                                 1.4.2              1.5.0    1.5.0    Normal       ---
zopfli->log                                       0.4.27             0.4.28   0.4.28   Normal       ---

Signed-off-by: Tools-app <localhost.hutao@gmail.com>
2025-11-16 15:47:11 +08:00
ShirkNeko
8442ebcb7a kernel: Optimise multi manager scanning logic 2025-11-16 15:35:26 +08:00
Wang Han
25fbc22f66 kernel: Replace kmalloc() usages with kzalloc() (#2939)
This ensures we won't use uninitialized pointers for task work.
2025-11-16 15:24:49 +08:00
ShirkNeko
a4a9df3a25 kernel: fmt 2025-11-16 14:29:10 +08:00
ShirkNeko
19a67fb76c mamager: fix the crash of Superuser in multi-user environments 2025-11-16 14:03:06 +08:00
AlexLiuDev233
3a2d55237d manager: make group shows like upstream & add some animation to SuperUser menu i18n file pick from upstream
Co-authored-by: YuKongA <70465933+YuKongA@users.noreply.github.com>
2025-11-16 13:34:26 +08:00
生于生时 亡于亡刻
98e617f1bd refactor(ksud): refactor ksud's kpm
- remove useless code
- ignore create dir all return
- when kpm file delete failed, return Error
2025-11-16 07:11:16 +08:00
AlexLiuDev233
d84a88f059 manager: disable webuix exitConfirm 2025-11-16 00:58:32 +08:00
ShirkNeko
ae7b4dcbed manager: fix MarkdownContent scrollBehavior
Co-authored-by: AlexLiuDev233 <wzylin11@outlook.com>
2025-11-16 00:02:29 +08:00
ShirkNeko
684a5d1ccd manager: display the same UID as a group
Co-authored-by: YuKongA <70465933+YuKongA@users.noreply.github.com>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-11-15 23:44:38 +08:00
Tools-app
35b02e3c73 ci: remove cache for ksud
Because it no truth save

Signed-off-by: Tools-app <localhost.hutao@gmail.com>
2025-11-15 19:57:40 +08:00
5ec1cff
db6a59ec4e kernel: file_wrapper: copy mode of original inode
Bionic uses fstat to determine whether an fd is a tty and set proper
buffering flags, so we also need to set the wrapper file's inode mode to
the original inode mode.

see:
https://cs.android.com/android/platform/superproject/main/+/main:bionic/libc/upstream-openbsd/lib/libc/stdio/makebuf.c;l=61-95;drc=9a4b68e20d617b2cb3355071521f16e8c3d538df
2025-11-15 19:54:16 +08:00
ShirkNeko
46846dce91 kernel: Utilise the existing try_umount to avoid repackaging 2025-11-15 19:29:12 +08:00
Tools-app
cd21af6728 ci: fix shared-key not find (ksud)
Signed-off-by: Tools-app <localhost.hutao@gmail.com>
2025-11-15 18:56:19 +08:00
生于生时 亡于亡刻
92a483d222 ksud: Optimise ksud (#576)
* opt: Optimize printing for result isn't successful
- print chain && backtrace to stderr

Signed-off-by: Tools-app <localhost.hutao@gmail.com>

* ci(ksud): add CARGO_TERM_COLOR for build

Signed-off-by: Tools-app <localhost.hutao@gmail.com>

* fix(ksud): fix uninstall package name is `me.weishu.kernelsu`

Signed-off-by: Tools-app <localhost.hutao@gmail.com>

* fix(ksud): Reverted to a private function for get_kernel_version

Signed-off-by: Tools-app <localhost.hutao@gmail.com>

* chore: format code for magic_mount.rs

Signed-off-by: Tools-app <localhost.hutao@gmail.com>

* fix: fix rustfmt

Signed-off-by: Tools-app <localhost.hutao@gmail.com>

* feat: Move the statement to the correct place && remove allow dead_code

Signed-off-by: Tools-app <localhost.hutao@gmail.com>

---------

Signed-off-by: Tools-app <localhost.hutao@gmail.com>
2025-11-15 18:25:17 +08:00
5ec1cff
04ca981e4d kernel: no need to remark process on post-fs-data and boot-completed
- Remark on post-fs-data may unmark zygote unexpectedly, and there is no
necessity to remark on these stages, so simply remove them.
2025-11-15 17:27:48 +08:00
ShirkNeko
83209a5259 ci: Fixed build information 2025-11-15 12:47:11 +08:00
YC酱luyancib
3cfc6d6a31 Manager/CI: Add spoofed manager build (#570)
* manager: add script for randomizing pkg name

Signed-off-by: rsuntk <rsuntk@yukiprjkt.my.id>
Co-Authored-By: YC酱luyancib <luyancib@qq.com>

* manager: Update randomizer to avoid bug

Revert "manager: Update randomizer to avoid bug"

This reverts commit af9205e70a11db3e3d43bb34de880bbd6b4185b5.

manager: Update randomizer to avoid bug

* mamager: Update randomizer to fix error
fixed
> Task :app:compileReleaseAidl FAILED
ERROR: /home/runner/work/SukiSU-Ultra/SukiSU-Ultra/manager/app/src/main/aidl/org/knifhr/zako/IKsuInterface.aidl:7.1-10: IKsuInterface should be declared in a file called com/sukisu/zako/IKsuInterface.aidl

* manager:clean randomizer

* ci:add spoofed manager build with matrix

* 更新 build-manager.yml

* 更新 build-manager.yml

* fix

* Revert "更新 build-manager.yml"

This reverts commit da80e3f13a.

* ksubot: make MESSAGE_THREAD_ID optional

---------

Signed-off-by: rsuntk <rsuntk@yukiprjkt.my.id>
Co-authored-by: rifsxd <rifat.44.azad.rifs@gmail.com>
Co-authored-by: 5ec1cff <ewtqyqyewtqyqy@gmail.com>
2025-11-15 10:58:10 +08:00
Wang Han
01ac06c3fd kernel: Prune allowlist only after boot completed
For unknown reason, packages.list is not reliable during boot for oplus
devices, so we have to disable pruning and re-run pruning after boot.
2025-11-15 10:54:19 +08:00
ShirkNeko
906c4bdb01 manager: bump susfs version to 2.0.0
- Remove versions below susfs 2.0.0 that are no longer supported.
2025-11-14 21:53:17 +08:00
weishu
c17d7b38eb ci: fix android16-6.12 gki build (#2931) 2025-11-14 19:02:48 +08:00
KOWX712
fa57ccccf4 manager: introduce webui package manager api (#2928)
this is a squash of:

* manager: introduce app package info API for webui-next
(KernelSU-Next/KernelSU-Next@58167a4)

* manager: sort a-z order for webui-next list packages api
(KernelSU-Next/KernelSU-Next@4a9733c)

* manager: implement getPackagesIcons and cacheAllPackageIcons api to
webui-next (KernelSU-Next/KernelSU-Next@a361fa3)

* manager/webui: let getPackagesIcons generate icon and store in cache
as well when called (KernelSU-Next/KernelSU-Next@6afa86d)

* POC: load icon app via ksu://icon/[packageName] (KernelSU-Next#674)
(KernelSU-Next/KernelSU-Next@bc9927b)

* manager: refine webui package manager (KOWX712/KernelSU@0400c42)

Co-Authored-By: Rifat Azad <33044977+rifsxd@users.noreply.github.com>
Co-Authored-By: Fahrez256Bit
<167403685+fahrez256@users.noreply.github.com>
Signed-off-by: KOWX712 <leecc0503@gmail.com>

---------

Signed-off-by: KOWX712 <leecc0503@gmail.com>
Co-authored-by: Rifat Azad <33044977+rifsxd@users.noreply.github.com>
Co-authored-by: Fahrez256Bit <167403685+fahrez256@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-14 19:02:21 +08:00
ShirkNeko
7e7713ee4a kernel/sulog: Optimise the sulog log format 2025-11-14 12:55:57 +08:00
ShirkNeko
7afcdb3059 kernel: Optimise sulog to prevent deadlocks caused by global lock contexts. 2025-11-14 12:29:55 +08:00
ShirkNeko
5df821ed41 kernel: Resolved potential deadlock issues arising from operations not being performed within locks. 2025-11-14 11:55:06 +08:00
YuKongA
12fc2e6d5e userspace: remove vendor_boot selection logic
- Only patch it when user actively selects vendor_boot.
2025-11-13 20:36:44 +08:00
5ec1cff
9f869090d2 kernel: refine syscall_hook_manager
- Don't unmark process when setuid if syscall tracepoint is in use
- Remark process when app profile updated
- Ensure zygote is marked on first boot
2025-11-13 20:09:32 +08:00
ShirkNeko
bb8b991110 kernel: restart enable sulog for LKM 2025-11-13 17:46:08 +08:00
ShirkNeko
10548f9243 kernel: fix build 2025-11-13 17:06:27 +08:00
weishu
96d33e62bb kernel: fix zygote mark on first boot (#2924) 2025-11-13 16:31:26 +08:00
ShirkNeko
7be8c15b85 kernel: Remove redundant ksu_handle_inode_permission hooks, calling only for manual_su 2025-11-13 15:02:20 +08:00
ShirkNeko
14bb6afd0b New Crowdin updates (#568)
* New translations strings.xml (Russian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Indonesian)

* New translations strings.xml (Chinese Traditional, Hong Kong)
2025-11-13 13:23:31 +08:00
ShirkNeko
54dad4ceb2 assets: bump KPM version to 0.12.2 2025-11-12 18:52:22 +08:00
ShirkNeko
a60395ba35 manager: install: do not always recommended to select boot partition if not rooted
Co-authored-by: YuKongA <70465933+YuKongA@users.noreply.github.com>
2025-11-12 18:04:49 +08:00
5ec1cff
095385f814 kernel: fix wrong show_fdinfo impl
Signed-off-by: Wang Han <416810799@qq.com>
2025-11-12 13:25:20 +08:00
ShirkNeko
7e595e1730 kernel: Public ksu_handle_sys_reboot
- clean code
2025-11-11 16:49:09 +08:00
Wang Han
ded31c2043 kernel: Fix task flag marking for root and shell UID
Signed-off-by: Wang Han <416810799@qq.com>
Co-authored-by: 5ec1cff <56485584+5ec1cff@users.noreply.github.com>
2025-11-11 16:26:37 +08:00
ShirkNeko
a7f840d811 manager: fix template status display issue (#2910)
manager: 修复模板状态显示问题 (#2910)

修复当 app 设置过模板后再使用自定义配置,离开页面后再次打开,管理器显示应用使用的是模板而不是自定义配置的问题

- bump AGP version

Co-authored-by: u9521 <63995396+u9521@users.noreply.github.com>
2025-11-11 16:00:54 +08:00
Ylarod
05cca26075 ci: move workflow_dispatch to versioned ci workflow
Signed-off-by: Faris <rissu.ntk@gmail.com>
2025-11-11 15:40:09 +08:00
ShirkNeko
5ce6c210c4 manager: install: add choose partition support
manager: fix KsuCli cmd

userspace: reuse choose_boot_device

- manager: simplify find boot image

Co-authored-by: weishu <twsxtd@gmail.com>
Co-authored-by: YuKongA <70465933+YuKongA@users.noreply.github.com>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-11-11 15:16:11 +08:00
ShirkNeko
8f49898155 kernel: Use task work to install fd
There are many fd related functions that can sleep, so we have no choice
but move operations to task work. Also close fd when copy_to_user fails.

Co-authored-by: Wang Han <416810799@qq.com>
2025-11-11 01:10:36 +08:00
ShirkNeko
fd3a22360a kernel: Clean code build 2025-11-09 23:18:48 +08:00
Wang Han
ef36a36e9a kernel: Don't save allowlist on module exit
This is not needed and may trigger UAF as work is async.
2025-11-09 23:14:13 +08:00
ShirkNeko
7a1a08064b manager: After flashing anykernel3, release ksud. 2025-11-09 21:26:08 +08:00
AlexLiuDev233
36862d6175 manager: if manager incompatible with current kernel, don't save ksud (#2895)
I think we should'nt install kernelsu's userspace when manager
incompatible with current kernel
this maybe cause a lot of bug, for example, when user install 2.x
kernelsu manager, but not update
his kernel to 2.x, ksud will return "kernel version 0", because ksud
incompatible with old supercall impl
2025-11-09 21:14:40 +08:00
ShirkNeko
cda7e4c6c0 Clean up kernel code (#2898)
1) Fix memory leak of callback head in allowlist.c
2) Remove duplicated logic and incorrect log in kernel_umount.c
3) Prevent sleep in kprobe context in ksud.c
4) Remove useless is_unsupported_uid, use euid for security enhance,
   add FIXME in setuid_hook.c
5) Remove useless fd argument for execve hook, fix incorrent pointer
   usage in syscall_hook_manager.c and sucompat.c
6) Use correct errno in supercalls.c

---------

Co-authored-by: Ylarod <me@ylarod.cn>
2025-11-09 19:20:30 +08:00
ShirkNeko
0b63cc445c kernel: Expose the ksu_handle_sys_read hook 2025-11-09 18:11:30 +08:00
ShirkNeko
2433ced81a kernel: Rollback disable_seccomp
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
Co-authored-by: Faris <rissu.ntk@gmail.com>
2025-11-09 17:00:43 +08:00
ShirkNeko
1f04f13e44 kernel: Remove redundant checks 2025-11-09 16:41:54 +08:00
ShirkNeko
184467c691 kernel: Undo some changes 2025-11-09 16:09:59 +08:00
ShirkNeko
05ed1a3714 fix build 2025-11-09 14:17:27 +08:00
ShirkNeko
163531fcd2 kernel: Simplify state management logic 2025-11-09 14:07:40 +08:00
ShirkNeko
049956aaa9 Fixes only hook in LKM mode __NR_newfstatat ,__NR_faccessat ,__NR_execve system calls 2025-11-09 12:16:23 +08:00
ShirkNeko
6530d06710 kernel: clean build 2025-11-09 04:12:11 +08:00
ShirkNeko
88135d8363 Attempt to refactor and migrate inode_permission, bprm_check_security, and task_alloc entirely to syscall_hook_manager 2025-11-09 02:52:46 +08:00
ShirkNeko
548258f922 kernel: Rewrite the kernel source code (#554)
* clean unused header

* on_module_mounted in ksud.c

* refact: use app_profile

* unified hook manager

* add zygote to hook target

* move reboot hook to supercall.c

* refactor: kernel_umount setuid_hook

* update mark rules, add init mark tracker

* remove reboot from check_syscall_fastpath

* update setuid_hook, remove uneeded sucompat enable

* log freely

* kernel: Migrate kprobe hook configuration items

* kernel: fix build

* cli: add ksud debug mark

* Fix rustfmt warning

---------

Co-authored-by: Ylarod <me@ylarod.cn>
Co-authored-by: Wang Han <416810799@qq.com>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-11-09 01:14:26 +08:00
weishu
46b9f5fb4b kernel: fix put_task if alloc failed. 2025-11-08 21:44:04 +08:00
ShirkNeko
413e9ab8a9 kernel: Resolved compatibility issues with su when using manual hooks 2025-11-08 20:52:29 +08:00
ShirkNeko
c3644da85b assets: Bump KPM version to 0.12.1 2025-11-08 20:05:59 +08:00
生于生时 亡于亡刻
7b4b5b431f fix: fix ksud install error (#550)
Signed-off-by: Tools-app <localhost.hutao@gmail.com>
2025-11-08 17:31:58 +05:30
ShirkNeko
7479c0b81b kernel: Fix build 2025-11-08 19:54:20 +08:00
ShirkNeko
0381d12be2 kernel: Resolve implicit declaration conflicts 2025-11-08 19:47:03 +08:00
Wang Han
4425c88d5a Fix missing unlock on error path 2025-11-08 19:41:11 +08:00
weishu
7828c5c107 kernel: fix save allowlist 2025-11-08 19:40:16 +08:00
ShirkNeko
76046c84cd kernel: remove unused kernel_compat
Co-authored-by: weishu <twsxtd@gmail.com>
2025-11-08 19:39:41 +08:00
weishu
623dd15cbf kernel: Use real_parent to avoid interference from ptrace. 2025-11-08 19:30:55 +08:00
ShirkNeko
ab13ed5c16 kernel: remove unused wrapper for
Co-authored-by: weishu <twsxtd@gmail.com>
2025-11-08 19:30:44 +08:00
weishu
e171ca15cb kernel: remove ksu_compat_{open,read,write} because we're in the right context now
Co-authored-by: weishu <twsxtd@gmail.com>
2025-11-08 19:28:25 +08:00
ShirkNeko
4fc369a059 kernel: remove workqueue for allowlist
Co-authored-by: weishu <twsxtd@gmail.com>
2025-11-08 19:18:20 +08:00
ShirkNeko
18ad2afadb Reworking fdwrapper
Co-authored-by: 5ec1cff <ewtqyqyewtqyqy@gmail.com>
Co-authored-by: 5ec1cff <56485584+5ec1cff@users.noreply.github.com>
Co-authored-by: Ylarod <me@ylarod.cn>
2025-11-08 19:03:14 +08:00
ShirkNeko
3badbcd4bc assets: Bump KPM version to 0.13.0 2025-11-08 18:38:53 +08:00
technotic
1b5b235bd9 add include for crc32.h in sulog.h (for dedup_calc_hash) (#548)
Co-authored-by: technotic <pixie@technotic.us>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-11-08 18:12:38 +08:00
AlexLiuDev233
fdf5e7104e refactor: kpm: memory management migrate to sukisu side (#539)
* refactor: kpm: memory management migrate to sukisu side

* fix: build warning in some gki2 device

fix stack frame size warning (maybe) in gki2 device, specialy in ShirkNeko's device

* chore: use pr_info instead of printk

* feat: check the validity of pointers sent from user space
Sometimes, ksud or other root processes might request a kpm ioctl,
but data incorrectly, such as invalid pointer,
which cause the kernel to crash.

If the request is made by ksud at boot time, the situation is even worse,
as it can cause the system to enter the boot loop.

Therefore, I believe we need to check pointer integrity in kernel space to fix this problem.

---------

Co-authored-by: Saksham <typeflu@gmail.com>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-11-08 18:11:29 +08:00
生于生时 亡于亡刻
ed6b2e0a8e opt: Optimize the kpm && uid_scanner (#549)
* opt: Optimize the structure of kpm.rs

Signed-off-by: Tools-app <localhost.hutao@gmail.com>

* opt: Optimize the uid_scanner startup logic in userspace && code style

Signed-off-by: Tools-app <localhost.hutao@gmail.com>

* opt: rename kpm's ioctl

Signed-off-by: Tools-app <localhost.hutao@gmail.com>

* opt: rename ksucalls::KsuKpmCmd's arg2..arg5

using
```rust
pub struct KsuKpmCmd {
    pub control_code: u64,
    pub arg1: u64,
    pub arg2: u64,
    pub result_code: u64,
}
```
This makes it easier to distinguish parameters.

Signed-off-by: Tools-app <localhost.hutao@gmail.com>

---------

Signed-off-by: Tools-app <localhost.hutao@gmail.com>
2025-11-08 13:43:32 +05:30
AlexLiuDev233
704f7cba32 kernel: core_hook: disable seccomp in 5.10.2- for allowed uids (#545)
* kernel: core_hook: disable seccomp in 5.10.2- for allowed uids

we dont have those new fancy things upstream has
lets just do original thing where we disable seccomp

* Update kernel/core_hook.c

* fmt

---------

Co-authored-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
Co-authored-by: Saksham <saksham.mac@icloud.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-08 12:46:25 +08:00
ShirkNeko
860bdce295 ksud :fmt 2025-11-08 12:41:03 +08:00
生于生时 亡于亡刻
d8a8ef6458 fix: fix self exe path error && opt: Optimize ensure_dir_exists processing (#541)
* fix: fix self exe path error

* opt: Optimize ensure_dir_exists processing

---------

Signed-off-by: Tools-app <localhost.hutao@gmail.com>
2025-11-08 12:34:22 +08:00
ShirkNeko
d37a78ea2d fix build & cleanup 2025-11-08 11:48:35 +08:00
Ylarod
6c9bf69718 fix build 2025-11-08 11:37:07 +08:00
Ylarod
776bcc4d5d rename to proxy_file 2025-11-08 11:36:15 +08:00
ShirkNeko
bf5cb885b5 kernel: remove devpts hook 2025-11-08 11:28:23 +08:00
Wang Han
a533a490bd Use force_sig(SIGKILL) to kill process 2025-11-08 01:34:44 +08:00
Shadichy
c6d9f76c7b kernel: Refactor selinux/selinux.c (#2881)
Signed-off-by: shadichy <shadichy@blisslabs.org>
Co-authored-by: Wang Han <416810799@qq.com>
2025-11-08 01:34:23 +08:00
Wang Han
66032391af Switch kretprobe to heap (#2880)
Co-authored-by: Ylarod <me@ylarod.cn>
2025-11-07 18:39:53 +08:00
Wang Han
da0e16bd26 Replace mutex with spinlock for tracepoint registration (#2882) 2025-11-07 18:37:12 +08:00
ShirkNeko
53d763cdf9 manager: Implement editable and removable mount points for LKM 2025-11-07 15:37:04 +08:00
ShirkNeko
9ebddde0d5 kernel: Avoid calling umount whilst holding a spinlock. 2025-11-07 14:23:58 +08:00
ShirkNeko
03a164ebb7 kernel: By default, MNT_DETACH is used as the value for the mount point. 2025-11-07 13:37:09 +08:00
ShirkNeko
4769065cfc ksud: Implementing editable, removable mount points 2025-11-07 13:15:07 +08:00
ShirkNeko
9b209765c4 kernel: Implementing editable, removable mount points 2025-11-07 12:16:42 +08:00
ShirkNeko
d7c101e244 kernel: Fix compilation 2025-11-07 11:33:02 +08:00
Ylarod
a32f89403b ci: update build 2025-11-07 11:12:21 +08:00
ShirkNeko
2cd673d776 manager: fix where the option displays "Temporary enable" after device reboot
Co-authored-by: YuKongA <70465933+YuKongA@users.noreply.github.com>
2025-11-07 11:08:27 +08:00
Ylarod
14fea6f8a3 build: remove -Wno-implicit-function-declaration 2025-11-07 11:02:48 +08:00
ShirkNeko
02f1aec6e9 ksud: Fix clippy 2025-11-07 00:11:02 +08:00
5ec1cff
826661dffb feature: add devpts fd wrapper (#21)
This feature is intended to resolve devpts problem.
2025-11-06 23:56:53 +08:00
ShirkNeko
f86c71efc5 Compilation fix 2025-11-06 23:26:55 +08:00
Ylarod
06018a2f03 revert: still using workqueue for allowlist 2025-11-06 23:05:29 +08:00
Ylarod
a2193841d5 skip init_features in safe mode 2025-11-06 23:03:43 +08:00
Ylarod
1324a7f54e fix: enhanced security register 2025-11-06 23:02:27 +08:00
Ylarod
5df9431a22 kill pgrp in enhanced security 2025-11-06 23:01:59 +08:00
Ylarod
e54989e51a add mutex for sucompat mark 2025-11-06 23:01:45 +08:00
Ylarod
cf50be122e fix: sucompat (#2874)
Co-authored-by: Wang Han <416810799@qq.com>
2025-11-06 23:01:28 +08:00
ShirkNeko
7f9048724f fix 2025-11-06 22:57:13 +08:00
ShirkNeko
3dde6d9a25 manager: some ui changes
* Steeing: add enhanced security dropdown
* Settings: allow change module update check
* Settings: allow always enable/disable feat
* misc: update all deps

---------

Co-authored-by: weishu <twsxtd@gmail.com>
Co-authored-by: Ylarod <me@ylarod.cn>
Co-authored-by: YuKongA <70465933+YuKongA@users.noreply.github.com>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-11-06 22:54:43 +08:00
ShirkNeko
132e9ef8ed kernel: Resolve compilation issues 2025-11-06 13:48:26 +08:00
ShirkNeko
e6436b340c kernel: clean headers
Co-authored-by: weishu <twsxtd@gmail.com>
2025-11-06 13:08:01 +08:00
weishu
9cdf98782d kernel: Set the tracepoint flag in a tracepoint manner 2025-11-06 13:02:13 +08:00
Ylarod
dece57cacf feature: add enhanced security (#2873) 2025-11-06 12:59:09 +08:00
ShirkNeko
3f07ea29ae manager: remove outdated lkm condition
Co-authored-by: weishu <twsxtd@gmail.com>
2025-11-06 12:58:44 +08:00
weishu
c8e103062a kernel: remove unused workqueue 2025-11-06 12:56:00 +08:00
Ylarod
91312effba fix sepolicy patch hint (#2872) 2025-11-06 12:53:09 +08:00
Ylarod
fd60cda3b3 fix: mark tif (#2871) 2025-11-06 12:52:52 +08:00
ShirkNeko
5323a500dd kernel: use sys_enter tracepoint for sucompat (#533)
* use sys_enter tracepoint for sucompat

* update sucompat rules

* clean tif mark

* mark tif after load allow list

* clear all tif first, then mark target

* Fix shell su

* allow when escape

* fix bugs

* kernel: Resolve logical inconsistencies

---------

Co-authored-by: Ylarod <me@ylarod.cn>
Co-authored-by: weishu <twsxtd@gmail.com>
2025-11-06 12:45:37 +08:00
ShirkNeko
0ce7bc2627 kernel: Migrate manual_su to ioctl 2025-11-06 02:52:14 +08:00
libingxuan
c9c62b25d2 support mainline kernel (#2869) 2025-11-05 23:00:42 +08:00
ShirkNeko
f8904b1b02 kernel: Resolved permission verification issue 2025-11-05 19:04:51 +08:00
ShirkNeko
89ce65e8ba Use a more appropriate minor version number 2025-11-05 16:41:30 +08:00
ShirkNeko
994fdfddf2 kernel: Use CONFIG_KSU_MANUAL_SU to protect MANUAL_SU 2025-11-05 16:17:54 +08:00
ShirkNeko
557e7f8153 bump KSU_VERSION_API to 4.0.0 2025-11-05 16:07:23 +08:00
backslashxx
9e9bb685f0 kernel: supercall: allow escalation on ioctl interface (#2862)
Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-11-05 15:52:00 +08:00
Wang Han
99bec0e439 Fix legacy prctl check condition (#2864) 2025-11-05 15:47:03 +08:00
ShirkNeko
0400b94674 v2.0.0 2025-11-05 15:43:10 +08:00
ShirkNeko
247f7d4aee Kernel: Enable processes with corresponding UIDs to utilise netlink, and optimise netlink functionality 2025-11-05 15:41:14 +08:00
ShirkNeko
088ce97697 kernel: Remove prctl; use netlink communication to control manual_su 2025-11-05 03:53:54 +08:00
ShirkNeko
c0a86544d8 kernel: Remove macro definitions, pass variables using ccflags -y, and reapply manual su protection.
kernel: stop printing useless message unless its ddk environment
* In-tree build show empty KDIR

-- KDIR:
-- MDIR: /home/runner/work/KernelSU-Test/KernelSU-Test/kernel_414/KernelSU/kernel
  AR      drivers/iommu/built-in.o
  CC      drivers/input/misc/uinput.o
-- KernelSU version: 12329
-- KernelSU: CONFIG_KSU_MANUAL_HOOK
-- Supported KernelSU Manager(s): tiann, rsuntk, 5ec1cff
  CC      drivers/kernelsu/ksu.o
  AR      drivers/input/joystick/built-in.o
  CC      drivers/hid/hid-roccat-pyra.o

Co-authored-by: Faris <rissu.ntk@gmail.com>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-11-05 02:18:38 +08:00
weishu
47bd84f3d1 kernel: init/exit umount feature 2025-11-04 22:29:55 +08:00
Ylarod
06e714b4e7 ksubot: add branch, happy 2k 2025-11-04 22:26:40 +08:00
weishu
1439e486a1 kernel: rework umount with task_work 2025-11-04 21:57:10 +08:00
ShirkNeko
801bcb0e1f Revert "Implement workqueue for unmounting" 2025-11-04 21:55:00 +08:00
Ylarod
54b5fb5fdb ignore user settings 2025-11-04 21:29:19 +08:00
Ylarod
1cc9fce2c6 rename to managedFeatures 2025-11-04 21:29:11 +08:00
ShirkNeko
46fefc299c kernel: Remove CONFIG_KSU_MANUAL_SU protection 2025-11-04 21:28:39 +08:00
ShirkNeko
23cc0ceff1 Revert "ci: bump ddk to 20251104, fix android16-6.12 lkm"
This reverts commit 257f0ca6de.
2025-11-04 21:08:24 +08:00
ShirkNeko
4a610af452 manager: Fixed warning card status error
- Reuse your own DDK
2025-11-04 20:30:04 +08:00
backslashxx
8177afa81e kernel: core_hook: provide a better reboot handler (#523)
* Revert "feat: try manual reboot hook (#521)"

This reverts commit 1853d9decf.

* kernel: core_hook: provide a better reboot handler

I propose that you pass cmd and arg as reference.
this is so we can have much more extendable use of that pointer

kernel: core_hook: provide sys_reboot handler
- 2e2727d56c

kernel: kp_ksud: add sys_reboot kp hook
- 03285886b0

I'm proposing passing arg as reference to arg pointer and also pass int cmd
we can use it to pass numbers atleast.
for advanced usage, we can use it as a delimiter so we can pass a pointer to array.

example pass a char *array[] which decays to a char ** and then use cmd as the number of array members.
we can pass the pointer of the first member of the array and use cmd as the delimiter (count) of members.

for simpler usecase, heres some that I added.

kernel: core_hook: expose  umount list on sys_reboot interface
- 352de41e4b

kernel: core_hook: expose nuke_ext4_sysfs to sys_reboot interface
- 83fc684ccb

ksud: add cmd for add-try-umount, wipe-umount-list and nuke-ext4-sysfs
- a4eab4b8c3

more usage demos
https://github.com/backslashxx/lkm_template/tree/write-pointer-on-pointer
https://github.com/backslashxx/lkm_template/tree/pointer-reuse

I actually proposed sys_reboot upstream because of this pointer that is very usable.

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

---------

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-11-04 19:51:40 +08:00
ShirkNeko
3588282b43 ci: build dev manager
Co-authored-by: Ylarod <me@ylarod.cn>
2025-11-04 19:49:08 +08:00
ShirkNeko
257f0ca6de ci: bump ddk to 20251104, fix android16-6.12 lkm
-kernel: Using macros to control manual su operations

Co-authored-by: Ylarod <me@ylarod.cn>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-11-04 19:44:43 +08:00
ShirkNeko
c863ff6f49 ci: Attempting once more to build the LKM using the DDK 2025-11-04 19:28:13 +08:00
ShirkNeko
e99a14290f manager: fix logical confusion 2025-11-04 12:22:49 +08:00
backslashxx
18e60ededa Reapply: "kernel: Allow to use in Private Space" (#2857)
rebase of
0576495b4b

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
Co-authored-by: weishu <twsxtd@gmail.com>
2025-11-04 11:17:46 +08:00
ShirkNeko
22e4b69231 manager: When the version is less than 13490, enable safe mode. 2025-11-04 11:16:42 +08:00
AlexLiuDev233
1853d9decf feat: try manual reboot hook (#521)
* feat: try manual reboot hook

* refactor: move ksu_handle_reboot to supercalls.c for ShirkNeko

---------
2025-11-04 01:08:49 +08:00
ShirkNeko
d286f49e11 [skip ci]kernel: Migrating KPM to ioctl 2025-11-04 00:52:13 +08:00
ShirkNeko
7103779a11 ksud: Migrating KPM to ioctl
- Fix compatibility manager issues with legacy kernels

Co-authored-by: AlexLiuDev233 <wzylin11@outlook.com>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-11-04 00:35:26 +08:00
ShirkNeko
4350d309da manager: Implement version restrictions for certain features 2025-11-03 14:59:12 +08:00
ShirkNeko
7051b22536 manager: Provide backward compatibility for legacy kernels 2025-11-03 14:32:16 +08:00
ShirkNeko
e0bce04e79 ksud: clippy happy & fmt 2025-11-03 12:24:36 +08:00
ShirkNeko
c75b041c40 kernel: Reset KERNEL_SU_OPTION to 0xDEADBEEF 2025-11-03 12:12:08 +08:00
ShirkNeko
d2a3f0fcad manager: fix suggest boot partition if we've root.
Co-authored-by: weishu <twsxtd@gmail.com>
2025-11-03 12:10:49 +08:00
ShirkNeko
696c3059b6 manager: fix legacy get version
Co-authored-by: weishu <twsxtd@gmail.com>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-11-03 12:09:00 +08:00
Ylarod
ab8e966b7f add check_managed_features to installer.sh 2025-11-03 11:48:03 +08:00
Ylarod
7ece40bb2c ksud: add managed_feature 2025-11-03 11:47:39 +08:00
ShirkNeko
d1aa6c8beb manager: improve local LKM selection
Co-authored-by: YuKongA <70465933+YuKongA@users.noreply.github.com>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-11-03 11:39:42 +08:00
Ylarod
bfed2d700a add legacy get_version & Full get_version
Co-authored-by: Ylarod <me@ylarod.cn>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-11-03 11:16:55 +08:00
ShirkNeko
59339b806a Revert "ci: use ddk for faster ci, manual gki image build"
This reverts commit 33d1f18395.
2025-11-03 03:49:56 +08:00
ShirkNeko
2433d64b6b Revert "ci: Attempting to resolve the issue with DDK compilation being unavailable"
This reverts commit a622657092.
2025-11-03 03:39:46 +08:00
ShirkNeko
a622657092 ci: Attempting to resolve the issue with DDK compilation being unavailable 2025-11-03 00:57:29 +08:00
Ylarod
b4e682148a kernel: remove dynamic alloc in feature 2025-11-03 00:41:27 +08:00
Ylarod
02474a5953 update embed ksuinit to v2 2025-11-02 23:49:46 +08:00
Ylarod
450dbf14fc kernel: disable setuid debug log 2025-11-02 23:49:40 +08:00
Ylarod
d89eab2c34 use cap_task_fix_setuid hook to avoid inline issue 2025-11-02 22:04:28 +08:00
ShirkNeko
a6b86a4f99 ci: skip dup lkm build
- Fixed and added build 6.12

- Repair construction

Co-authored-by: Ylarod <me@ylarod.cn>
2025-11-02 21:53:53 +08:00
ShirkNeko
33d1f18395 ci: use ddk for faster ci, manual gki image build
Co-authored-by: Ylarod <me@ylarod.cn>
2025-11-02 20:54:58 +08:00
Ylarod
8ebe60ca04 update ioctl macro (#2850) 2025-11-02 20:15:55 +08:00
ShirkNeko
980613c6a9 ksud: fmt 2025-11-02 20:07:35 +08:00
ShirkNeko
47bcc956a3 fix lot (#518)
* refact: use feature subsystem

* use 64bit feature

* fix

* add fixme

* add feature max to get_info

* use 32bit feature id

* allow root to get/set feature

* more clean perm_check functions

* fix

* add feature command to ksud

kernel: do not expose perm checker

* fix security_task_fix_setuid_handler_pre

* add android16-6.12 ci

* manager: add kernel_umount switch

Co-authored-by: YuKongA <70465933+YuKongA@users.noreply.github.com>

* manager: Reinstate the LKM selection function

* kernel: add name and print command value

- Optimise sulog log display

Co-authored-by: Ylarod <me@ylarod.cn>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>

* fix

* ksud: clippy

---------

Co-authored-by: Ylarod <me@ylarod.cn>
Co-authored-by: YuKongA <70465933+YuKongA@users.noreply.github.com>
Co-authored-by: weishu <twsxtd@gmail.com>
2025-11-02 20:01:24 +08:00
ꑄℭѧᝰ.ᐟ
00de4e1c64 Update Vietnamese Translation (#515)
* Update Vietnamese Translation

* Fix typo strings
2025-11-02 18:42:34 +08:00
Ylarod
97ec718fea switch ns umount 2025-11-02 12:23:23 +08:00
Wang Han
5c96f951b5 Implement workqueue for unmounting
umount schedules, so it cannot be used in kprobe context.
2025-11-02 12:21:00 +08:00
Ylarod
7e446efac4 back to kprobe setuid hook 2025-11-02 12:17:21 +08:00
ShirkNeko
c06d694ebc kernel: When CONFIG_KSU = m, disable sulog 2025-11-02 03:09:55 +08:00
ShirkNeko
bd0b07cba9 kernel: Add sulog records for supercalls 2025-11-02 03:04:35 +08:00
ShirkNeko
e54339cf4e Compilation fixed; defaults to fallback using packages.list 2025-11-02 01:31:41 +08:00
ShirkNeko
320e08b8fb new supercall impl (#511)
* refactor: replace throne tracker with ksud token

* use snprintf

* refactor: new supercall impl

- Import the sukisu command

* disable seccomp for supercall users

* kernel: fmt clear

* kernel: Enable macro protection for sulog

- Only enabled on kernel versions greater than 5.10.245

* kernel: Refactor kprobe hooks and implement LSM hooks for improved security handling

* debug mode

* kernel: Add functionality to generate and validate authentication tokens for cmd_su

* kernel: Simplified manual SU command processing for code

* kernel: replace renameat hook with fsnotify

* Revert "refactor: replace throne tracker with ksud token"

This reverts commit aa2cbbf9cd.

* kernel: fix compile

* kernel: fix compile below 6.0

* Fix compile err; Add become_manager

* kernel: install fd for manager automaticlly

- extend to import the corresponding command

* manager: new supercall impl

* temp changes for ksud

* ksud: fix compile

* fix wrong opcode

* kernel: fix compile

* kernel: Fixed hook type and KPM status retrieval errors

* kernel: Fixed potential null pointer issue with current->mm in kernel version 5.10

When calling get_full_comm() within system call hooks, current->mm may be null (prctl). A fallback mechanism for current->comm must be added beforehand to prevent null pointer dereferences when accessing mm->arg_start/arg_end.

Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>

* ksud: fix cargo check

* manager: Fixed an issue where the KSUD release and user-mode scanning switch failed to function correctly.

- kernel: fix spin lock mutual

kernel: Fixed potential null pointer issue with current->mm in kernel version 5.10

When calling get_full_comm() within system call hooks, current->mm may be null (prctl). A fallback mechanism for current->comm must be added beforehand to prevent null pointer dereferences when accessing mm->arg_start/arg_end.

kernel: try introduce like susfs's method to fix prctl delay

* seccomp: allow reboot

* use u32

* update clang-format

* 4 spaces save the world

* ksud: Fix build on macOS

* manager: bump minimal supported kernel.

- When get_hook_type is empty, display “Unknown”.


* Fix ksud build (#2841)

* try fix ksud

* fix for macos

* remove any

* Fix ksud build, take 3

* try fix allowlist

* bring lsm hook back

* fix: a lot again

* Fix ksud build, take 4 (#2846)

Remove init_driver_fd function for non-linux/android targets

* manager: Return to the native method via KSUd installation

* Merge with susfs-mian format

---------

Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
Co-authored-by: Ylarod <me@ylarod.cn>
Co-authored-by: weishu <twsxtd@gmail.com>
Co-authored-by: AlexLiuDev233 <wzylin11@outlook.com>
Co-authored-by: Wang Han <416810799@qq.com>
2025-11-01 23:30:30 +08:00
NkBe
0da8ecb071 enjoy: 專門為MiUI桌面卸載添加了提示,提升使用者體驗 (#502) 2025-10-30 14:50:13 +08:00
NkBe
cc54abd273 strings: Update zh-rTW (#501) 2025-10-30 14:49:57 +08:00
ShirkNeko
ee781cf959 kernel: Fixed potential null pointer issue with current->mm in kernel version 5.10
When calling get_full_comm() within system call hooks, current->mm may be null (prctl). A fallback mechanism for current->comm must be added beforehand to prevent null pointer dereferences when accessing mm->arg_start/arg_end.

Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-10-27 22:02:12 +08:00
ShirkNeko
a21b18c5de kernel: Simplified manual SU command processing for code 2025-10-27 16:02:04 +08:00
ShirkNeko
1644f22c98 manager: Restore the colour scheme on the sulog page 2025-10-27 12:31:26 +08:00
由崎黑板
7a338b1b43 Revert "Disable Samsung Activation Verify to solve -45(2000) error during activation on China Mainland Samsung devices (#446)" (#492)
This reverts commit 7ef9230d66.
2025-10-26 22:22:11 +08:00
ShirkNeko
324dc0844f kernel: Greenlight the new prctl command 2025-10-26 20:43:51 +08:00
ShirkNeko
f7fe0cf748 kernel: Add functionality to generate and validate authentication tokens for cmd_su 2025-10-26 19:58:16 +08:00
ShirkNeko
bf1a45963b kernel: try introduce like susfs's method to fix prctl delay
Co-authored-by: AlexLiuDev233 <wzylin11@outlook.com>
2025-10-25 18:35:53 +08:00
ShirkNeko
64ee09fd12 kernel: Enable macro protection for sulog
- Only enabled on kernel versions greater than 5.10.245
2025-10-25 00:45:43 +08:00
ShirkNeko
b9a84a15bc manager: Remove sulog file selection 2025-10-24 21:55:32 +08:00
ShirkNeko
6a1e1d788b kernel: sulog: Simplify code using vfs_truncate 2025-10-23 22:16:06 +08:00
ShirkNeko
4b86989bf9 kernel: Restore the sequence of sulog logs 2025-10-23 21:48:55 +08:00
ShirkNeko
d3f8c128da kernel: Add a UID blacklist feature to restrict the operational permissions of specific users 2025-10-23 02:08:45 +08:00
ShirkNeko
bbb2748494 kernel: Adjust the command processing sequence 2025-10-22 23:54:55 +08:00
ShirkNeko
b9e6246d65 manager: Avoid page crashes caused by excessive data. 2025-10-22 23:53:05 +08:00
ShirkNeko
7bf13fbfca manager: Add an option to exclude the current application and certain system calls from the log viewer. 2025-10-22 22:42:26 +08:00
ShirkNeko
e9ee2304d3 kernel: Extend sulog to also record system call logs 2025-10-22 20:56:46 +08:00
ShirkNeko
f7b4b4b82d kernel: Optimized log timestamp processing and added manual refresh functionality. 2025-10-22 18:42:50 +08:00
ShirkNeko
15b9c4dbbf manager: Add the sulog log viewer interface and functionality 2025-10-22 18:19:16 +08:00
ShirkNeko
3b966c536b Kernel: Implement sulog for enhanced logging of SU attempts and permissions 2025-10-22 17:21:25 +08:00
ShirkNeko
b5e5be2572 Revert: ksud, kernel: Pick some upstream changes and remove unused functions
* Upstream commit:
f130f7572f

Signed-off-by: Faris <rsuntk@yukiprjkt.my.id>
2025-10-22 00:09:56 +08:00
ShirkNeko
253df1ea47 New translations strings.xml (Vietnamese) (#484) 2025-10-21 16:40:43 +08:00
ShirkNeko
134684a139 Kernel(Makefile): Add KSU_SRC to set path correctly #483
try Fix version define for 6.12 Kernel

Co-authored-by: YC酱luyancib <luyancib@qq.com>
2025-10-19 19:23:18 +08:00
ShirkNeko
9c07fa6889 ksud: Fixed compilation errors 2025-10-19 19:00:47 +08:00
Sultan Alsawaf
c3f66e15e9 kernel: Fix kernel panics caused by thread info flag corruption
Signed-off-by: Sultan Alsawaf <sultan@kerneltoast.com>
2025-10-19 18:44:15 +08:00
Faris
b6e2fa383a ksud: fix compilation and remove unused imports
Signed-off-by: Faris <rsuntk@yukiprjkt.my.id>
2025-10-19 18:44:07 +08:00
Ylarod
61f85a029e ksud, kernel: Pick some upstream changes and remove unused functions
* Upstream commit:
f130f7572f

Signed-off-by: Faris <rsuntk@yukiprjkt.my.id>
2025-10-19 18:41:30 +08:00
5ec1cff
b1564b77a2 ksud: refine mount
- `magic_mount` now takes the tmp_path from its argument
- `.notmpfs` and `.nomount` now behave the same

skip:
ksud: cache tmp path (74ce44de21963fddc83897846eed28eca89d78aa)

Co-authored-by: shatyuka <shatyuka@qq.com>
Signed-off-by: Faris <rsuntk@yukiprjkt.my.id>
2025-10-19 18:39:57 +08:00
Vayruz Rafli
cc0a3590ce docs: Fix little typo on tracepoint hook guide (#482) 2025-10-19 13:00:58 +08:00
PKQYPKJ
e793219c2b manager: Remove unnecessary translations (#478)
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-10-18 22:43:54 +08:00
ShirkNeko
776a753206 manager: Rewrite UI state management 2025-10-18 22:37:17 +08:00
ShirkNeko
7b6470cc79 manager: Fixed sus tab mapping error 2025-10-18 17:40:23 +08:00
ShirkNeko
eb5fdbbf3f manager: SuSFS: Add SUS_MAP feature configuration item 2025-10-18 15:09:02 +08:00
ShirkNeko
8db55f56a9 manager: Reuse the aidi reflection to retrieve the list of applications 2025-10-17 01:59:56 +08:00
ShirkNeko
62635879e0 manager: Add multiple activity declarations for the backup icon close #469 2025-10-16 23:43:18 +08:00
ShirkNeko
86634aac3d Manager: Increase the loading priority of ksud
- This will resolve data loading errors that occur upon first launch.
2025-10-16 22:51:38 +08:00
ShirkNeko
af25f8d49e manager: Optimize Language Settings
- Do not update language configurations by refreshing activities; instead, introduce consistent language configurations from kernelsu-next.

Co-authored-by: rifsxd <rifat.44.azad.rifs@gmail.com>
2025-10-16 22:37:52 +08:00
Wang Han
cd78c2693a Don't write newline character to cgroup node (#2804)
This prevents su hang on oplus devices, maybe related to bad kernel
hooks.
2025-10-16 12:28:36 +08:00
ShirkNeko
8ff9fab414 manager: Fixed an issue where ksud failed to release properly during the first installation. 2025-10-15 14:15:13 +08:00
ShirkNeko
b8eebcda5a kernel: Bump susfs binary version to 1.5.12
- Removed functionally coupled versions 1.5.10-1.5.11

- Removed `statusMagicMount` status retrieval

- Use `getSuSFSFeatures` to replace `CMD_GET_SUSFS_FEATURE_STATUS` for obtaining SUSFS status.
2025-10-13 17:40:33 +08:00
ShirkNeko
85291de02a manager: Restructure the file directory to keep it clean 2025-10-12 18:58:02 +08:00
Cynthia
cb7abc88dd strings: full Indonesian translation (values-ind/strings.xml) (#464) 2025-10-12 15:50:29 +08:00
James Sparrow
918e7ae0b7 [skip ci]Update Vietnamese Translation (#462) 2025-10-12 15:50:05 +08:00
生于生时 亡于亡刻
0a804ba170 feat: Optimize some codes (ksud) (#465)
* chore: make cargo clippy happy

Signed-off-by: Tools-app <localhost.hutao@gmail.com>

* chore: Optimize import
-  Format as a standard import

Signed-off-by: Tools-app <localhost.hutao@gmail.com>

---------

Signed-off-by: Tools-app <localhost.hutao@gmail.com>
2025-10-12 15:48:24 +08:00
ShirkNeko
4c512dc7ff manager: Add detailed information about the module / anykernel3 compressed package from sharing and direct flashing
- Treat certain XP module APK files as modules for processing
2025-10-11 17:49:36 +08:00
ShirkNeko
fcb7c3e99d manager: Avoid repeated flashing caused by unconditionally clearing the Anykernel3 flashing status. 2025-10-10 23:56:03 +08:00
Prslc
b827360ac6 docs: Sync TRACEPOINT HOOK v1.1 (#456)
- Replace trace_ksu_trace_execveat_sucompat_hook with trace_ksu_trace_execveat_hook to align with v1.1 changes
  The new hook now passes argv/envp and a flags argument, adding support for 32-on-64 environments.
- Remove the devpts hook section from both English and Chinese guides
  The devpts (pty.c) hook example was deprecated in v1.1 and is no longer required.

Link: f1f7c61aee

Signed-off-by: Prslc <prslc113@gmail.com>
2025-10-10 00:39:15 +08:00
ShirkNeko
ca7b53370e manager: Enhanced External Selection Sharing Single/Batch Module Installation
- Reduce the delay exit time in seconds
2025-10-08 19:16:30 +08:00
ShirkNeko
230ca54d63 manager: Expand the option to directly open the file and flash the anykernel3 kernel package 2025-10-08 18:23:53 +08:00
ShirkNeko
2f43ad4f76 manager: add support for opening zip file and directly flash module
- refine zip intent method

- use MMRL method to handle zip, fix failed to open zip from Chrome

Co-Authored-By: Der_Googler <54764558+dergoogler@users.noreply.github.com>
Co-authored-by: rifsxd <rifat.44.azad.rifs@gmail.com>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-10-08 16:11:55 +08:00
ShirkNeko
9c1ff635e3 Kernel: Add support for 6.12
Filtered from tiann/KernelSU #2793

Co-authored-by: libingxuan <84086386+aaaaaaaa-815@users.noreply.github.com>
2025-10-08 15:00:04 +08:00
rsuntk
ef97f0e4d9 kernel: make apk_sign_key as a typedef instead
Style preference.

Signed-off-by: rsuntk <rsuntk@yukiprjkt.my.id>
2025-10-08 14:50:50 +08:00
ShirkNeko
2e394903cc kernel: Simplified Logic 2025-10-08 14:46:58 +08:00
unknow-tech
7978cbafa5 Add support for 6.13 (#454)
Fiz issue https://github.com/SukiSU-Ultra/SukiSU-Ultra/issues/364

cdd30ebb1b
2025-10-08 14:46:50 +08:00
rsuntk
c89a3dbcd9 kernel: add guard for avoiding LKM being builded on Linux 6.8+
* Due to numerous changes on LSM (Linux Security Module) in Linux 6.8+
* This is temporary guard until a working solution exist.

Signed-off-by: rsuntk <rsuntk@yukiprjkt.my.id>
2025-10-08 14:46:00 +08:00
Huy Minh
13c7912320 kernel: add initial 6.8+/6.14 kernel support
* This is a squashed of un-merged pull requests of Official KernelSU
* LKM support are not available.
* Require this additional patch to avoid kernel panic because of "Too many LSMs registered":
7042991a5c

* Un-merged pull requests of Official KernelSU:
https://github.com/tiann/KernelSU/pull/1785
https://github.com/tiann/KernelSU/pull/2662

* This commit probably not 100% completed.

Signed-off-by: rsuntk <rsuntk@yukiprjkt.my.id>
2025-10-08 14:45:36 +08:00
saitama-droid
abbe385382 kernel: core_hook: add config guard for manual SU escalation (#453)
Wrap manual SU escalation handling in CONFIG_KSU_MANUAL_SU
conditional compilation to allow builds without this functionality.

This affects:
- CMD_SU_ESCALATION_REQUEST
- CMD_ADD_PENDING_ROOT

When CONFIG_KSU_MANUAL_SU is disabled, these prctl commands
will not be compiled into the kernel.
2025-10-08 14:33:17 +08:00
Saksham
0b80137f17 Bump to latest stable ndk
Ref:https://developer.android.com/ndk/downloads#stable-downloads
2025-10-07 11:27:09 +05:30
ShirkNeko
c4ff89c13d manager: Add pull-to-refresh functionality 2025-10-07 01:29:00 +08:00
rifsxd
ce3a7ec189 kernel: handle throned UID change if manager is reinstall or changed
drop old UID and throne the new one when the manager is reinstalled or changed

- Add dynamic manager lock

Co-authored-by: rifsxd <rifat.44.azad.rifs@gmail.com>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-10-07 00:08:30 +08:00
ShirkNeko
2bb789212a New translations strings.xml (Vietnamese) (#449) 2025-10-06 23:15:30 +08:00
由崎黑板
7ef9230d66 Disable Samsung Activation Verify to solve -45(2000) error during activation on China Mainland Samsung devices (#446) 2025-10-06 23:02:54 +08:00
ShirkNeko
fbaa69f3fb manager: Raise the minimum version requirement to 3.1.8 close #448 2025-10-06 22:50:24 +08:00
ShirkNeko
e78ee720b5 ksud: fmt 2025-10-06 22:44:09 +08:00
ShirkNeko
04b603394a ksud: Fixed inconsistent parameter passing in kpm_prctl 2025-10-06 22:02:59 +08:00
ShirkNeko
c9c7a5f4e3 manager: Update Repository Naming 2025-10-06 21:08:23 +08:00
ShirkNeko
044b4a2f9c manager: Simplify kpm management by migrating to the ksud side. 2025-10-06 20:53:18 +08:00
ShirkNeko
59cd8d1c3b kernel: core_hook: harden prctl handler
detection is done by comparing a 0xDEADBEEF call to a non-0xDEADBEEF one.
which yeah, you will see that the non-0xDEADBEEF one returns early.

yes I know this causes delays for all prctl calls, as we straight up check uid,
but this keeps the delay consistent, which is what we want.

another is that we only should only perform this recrowning logic for multiuser

- temp fix for cimb octo's prctl abuse

Co-authored-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-10-06 00:19:37 +08:00
ShirkNeko
36617bf0a1 kernel: For cmd_su, bypass the susfs_is_current_proc_umounted check only for system processes. 2025-10-05 20:08:51 +08:00
unknow-tech
5b49054055 Merge pull request #445 from unknow-tech/patch-1
Fix wrong function
2025-10-05 00:37:59 +08:00
NkBe
a17a220745 manager: Update zh-rTW strings (#439)
* manager: Update zh-rTW strings

* Update strings.xml

* Update strings.xml
2025-10-04 20:52:12 +05:30
YC酱luyancib
0729066a6f manager: add susfs 1.5.11 binary (#444) 2025-10-04 18:19:15 +05:30
ShirkNeko
d4dcf610c9 kernel: Fixed disable_seccomp compatibility issues 2025-10-01 00:16:35 +08:00
ShirkNeko
78e0dc6da2 kernel: Add CONFIG_KSU_MANUAL_SU configuration
- Use random passphrase protection for manual su functionality
2025-09-30 23:29:29 +08:00
ShirkNeko
a9a10466b3 Kernel: Enhanced temporary record UID functionality and elevated privileges 2025-09-30 23:27:02 +08:00
ShirkNeko
65d5d6a494 kernel: Add the ability to manually elevate privileges for programs using prctl by specifying UID or PID. 2025-09-30 23:26:28 +08:00
ShirkNeko
e552163d9e Revert "manager: Removed SUSFS_UMOUNT_FOR_ZYGOTE_ISO_SERVICE which are no longer used in susfs 1.5.10."
This reverts commit 475b3998a1.

- bump susfs version 1.5.10
2025-09-30 23:08:34 +08:00
ShirkNeko
c950705044 Manager: fmt
- Optimized homepage refresh logic and removed the caching mechanism
2025-09-29 17:17:19 +08:00
Rifat Azad
9e7aabf3f7 userspace/su: add ndk compatible su from kernelnosu
Co-authored-by: nampud <nampud@users.noreply.github.com>
2025-09-28 00:35:26 +08:00
ShirkNeko
a20a89da03 kernel: Revert partial changes 2025-09-27 23:04:14 +08:00
ShirkNeko
9551ca4fe8 kernel: fmt ,optimization Log 2025-09-27 21:12:02 +08:00
ShirkNeko
a2431d50ce kernel: Enhance the user space scanning functionality 2025-09-27 19:47:22 +08:00
ShirkNeko
8b74f7d466 manager: Redesign zygisk to ensure display accuracy 2025-09-26 23:28:27 +08:00
ShirkNeko
b5d9607e8e manager: Switch to matching mode to match the zygisk module
- bump dependencies
2025-09-26 20:14:27 +08:00
ShirkNeko
475b3998a1 manager: Removed SUSFS_UMOUNT_FOR_ZYGOTE_ISO_SERVICE and SUSFS_RUN_UMOUNT_FOR_CURRENT_MNT_NS, which are no longer used in susfs 1.5.10.
- bump susfs version 1.5.10
2025-09-25 21:57:31 +08:00
ShirkNeko
23ed4384e6 Revert "Unmount isolated process which forks from zygote unconditionally (#2747)"
This reverts commit 695e749e3e.
2025-09-25 16:13:07 +08:00
ShirkNeko
0af1ab2845 bump LKM build version 2025-09-24 22:45:12 +08:00
ShirkNeko
c664aa66af bump KSU_VERSION_API to 3.2.0 2025-09-24 22:34:47 +08:00
ShirkNeko
7a449345d1 kernel: fmt 2025-09-24 22:32:58 +08:00
Saksham
fa48b2fdaa feat: update to stable vitepress 2025-09-24 19:53:52 +05:30
ShirkNeko
f1f7c61aee kernel: Bump tracepoint_hooks to version v1.1
Remove `devpts_hook` and `execveat_hook` from `tracepoint_hooks`
2025-09-24 22:18:14 +08:00
ShirkNeko
ccc5cb74bf kernel: core_hook: intercept devpts via security_inode_permission LSM
`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.

EDIT: define devpts super magic if its undefined
- yeah I aint gonna include a conditional include of a header just for this
- while we can just fully remove the macro and inline, readability loss is bad

Co-authored-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-09-24 22:17:12 +08:00
Cloud_Yun
75fe8c9b6a kpm: remove incorrect "<" to fix compilation error (#418)
i'm so sorry

Signed-off-by: Cloud_Yun <1770669041@qq.com>
2025-09-24 21:48:03 +09:00
ShirkNeko
a12c78d213 Revert "kernel: throne_tracker: offload to kthread tiann #2632"
This reverts commit d5d2bb35d2.
2025-09-24 16:25:47 +08:00
backslashxx
6c145179d4 pullout envp 2025-09-24 16:17:38 +08:00
backslashxx
ac05038e64 move debug back up 2025-09-24 16:17:12 +08:00
ShirkNeko
d5d2bb35d2 kernel: throne_tracker: offload to kthread tiann #2632
Run throne_tracker() in kthread instead of blocking the caller.
Prevents full lockup during installation and removing the manager.

By default, first run remains synchronous for compatibility purposes
(FDE, FBEv1, FBEv2)

Features:
- looks and waits for manager UID in /data/system/packages.list
- run track_throne() in a kthread after the first synchronous run
- prevent duplicate thread creation with a single-instance check
- spinlock-on-d_lock based polling adressing possible race conditions.

Race conditions adressed
- single instance kthread lock, smp_mb()
- track_throne_function, packages.list, spinlock-on-d_lock based polling
- is_manager_apk, apk, spinlock-on-d_lock based polling

This is a squash of:
https://github.com/tiann/KernelSU/pull/2632

Original skeleton based on:
`kernelsu: move throne_tracker() to kthread`
`kernelsu: check locking before accessing files and dirs during searching manager`
`kernelsu: look for manager UID in /data/system/packages.list, not /data/system/packages.list.tmp`
0b05e927...8783badd

Co-Authored-By: backslashxx <118538522+backslashxx@users.noreply.github.com>
Co-Authored-By: Yaroslav Zviezda <10716792+acroreiser@users.noreply.github.com>
Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-09-24 01:51:28 +08:00
ShirkNeko
cb01bf428d kernel: Simplify and remove user_arg_ptr ksu_handle_execveat_ksud
- Migrate `ksu_handle_execveat` to sucompat
2025-09-24 01:27:04 +08:00
ShirkNeko
7146210192 kernel: sys_execve bprm simplified
Co-authored-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-09-23 23:58:41 +08:00
ShirkNeko
528df754a5 manager: bump dependencies 2025-09-23 22:54:15 +08:00
ShirkNeko
8a14f64964 kernel: sys_execve_kp remains the preferred choice for the first registration. 2025-09-23 21:22:34 +08:00
ShirkNeko
bf4e12ce80 ksud: Modified KPM to use the prctl system call instead of external execution. 2025-09-23 20:37:40 +08:00
ShirkNeko
5497c0004d Revert "ksud: Only start the monitor and load the module when KPM is enabled"
This reverts commit 3ed1d9aebc.
2025-09-23 18:40:58 +08:00
ShirkNeko
32baf8d9b0 ksud: Rename the output LKM patch file 2025-09-23 17:22:07 +08:00
ShirkNeko
763ce7e86c kernel ksud: Attempt registration with bprm_check_kp first. If it fails, fall back to sys_execve_kp.
Co-authored-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-09-23 17:20:48 +08:00
5ec1cff
3a8ecf1253 ksud: magic_mount: make mount points read only
Signed-off-by: rsuntk <rsuntk@yukiprjkt.my.id>
2025-09-23 00:54:44 +08:00
Wang Han
7026c340b0 ksud: Update zip-extensions and set needed features for zip (#2592)
zip-extensions does not export time and deflate64 features now.
2025-09-23 00:54:30 +08:00
ShirkNeko
6dc803702b ksud: create our own new ramdisk when no compatible ramdisk found
Co-authored-by: rifsxd <rifat.44.azad.rifs@gmail.com>
2025-09-23 00:48:15 +08:00
backslashxx
c64d196a10 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-09-22 23:01:38 +08:00
backslashxx
c690d9c02c ksud: migrate ksud execution to security_bprm_check (tiann#2653)
This migrates ksud execution decision-making to bprm_check_security.
This requires passing proper argv and envp to a modified _ksud handler
aptly named 'ksu_handle_bprm_ksud'.

Introduces:
int ksu_handle_bprm_ksud(const char *filename, const char *argv1,
const char *envp, size_t envp_len)

which is adapted from:
int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
struct user_arg_ptr *argv,
struct user_arg_ptr *envp,
int *flags)

ksu_handle_bprm_ksud handles all the decision making, it decides when it is
time to apply_kernelsu_rules depending if it sees "second_stage".

For LSM hook, turns out we can pull out argv and envp from mm_struct.
The code in here explains itself on how to do it.

whole blob exists on arg_start to arg_end, so we just pull it out and grab next
array after the first null terminator.

as for envp, we pass the pointer then hunt for it when needed

My reasoning on adding a fallback on usercopy is that on some devices a fault
happens, and it copies garbled data. On my creation of this, I actually had to lock
that _nofault copy on a spinlock as a way to mimic preempt_disable/enable without
actually doing it. As per user reports, no failed _nofault copies anyway but we
have-to-have a fallback for resilience.

References:
- old version1 6efcd8193e
- old version2 37d5938e66
- bad usercopy #21

This now provides a small helper function, ksu_copy_from_user_retry, which explains
itself. First we attempt a _nofault copy, if that fails, we try plain.

With that, It also provides an inlined copy_from_user_nofault for < 5.8.

While using strncpy_from_user_nofault was considered, this wont do, this will
only copy up to the first \0.

devlog:
16e5dce9e7...16c1f5f521
28642e60d7...728de0c571

References:
https://elixir.bootlin.com/linux/v4.14.1/source/include/linux/mm_types.h#L429
https://elixir.bootlin.com/linux/v4.14.1/source/include/linux/lsm_hooks.h

Stale: https://github.com/tiann/KernelSU/pull/2653

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-09-22 23:01:38 +08:00
ShirkNeko
452fe3d508 uid_sanner: Ensure the /data/misc/user_uid/ directory is set to 777 permissions to prevent read/write issues. 2025-09-20 00:27:48 +08:00
ShirkNeko
e27d461eb0 manager: Reworking the cleanup functionality for the runtime environment
Fix the uid_scanner library filename in the build script
2025-09-19 23:02:38 +08:00
ShirkNeko
a77faa1fe2 Manager: Added functionality to clean up the user-mode scanning environment after execution
fmt ksud
2025-09-19 22:04:14 +08:00
ShirkNeko
9a9623f578 kernel: Use /data/user_de/ for rollback instead of packages.list
manager: Fix path and permission issues
2025-09-19 21:21:10 +08:00
ShirkNeko
cc1c66bb6f Add UID scanner functionality and related infrastructure
- Introduced a new module `uid_scanner` in userspace for managing UID scanning.
- Created a new GitHub Actions workflow for building the `user_scanner`.
- Implemented kernel communication in `throne_comm.c` and `throne_comm.h` to handle user space updates and rescan requests.
- Developed the `uid_scanner` daemon in C to scan user directories and manage UID whitelists.
- Added configuration management for the UID scanner with support for multiple users and auto-scanning.
- Implemented logging and error handling throughout the UID scanning process.
- Created necessary build files for the `user_scanner` JNI integration.
- Added a `.gitignore` file to exclude build artifacts.
2025-09-19 21:01:01 +08:00
Wang Han
695e749e3e Unmount isolated process which forks from zygote unconditionally (#2747)
Rethink about this patch, isolated process which directly forks from
zygote is just like normal app, so there is no reason apps won't crash
but Isolated process will. Also zygote reopens fd before actually fork,
so it should be fine.

This reverts commit 2a1741de96a789957555053cf5a397cbef1eb3e4.
2025-09-17 20:01:38 +08:00
生于生时 亡于亡刻
84c85ebe3c feat: Optimize ksud compilation products (#394)
Signed-off-by: Tools-app <localhost.hutao@gmail.com>
2025-09-17 20:01:27 +08:00
Cloud_Yun
ed7dc01fb2 kpm: fix compilation errors (#396)
Sorry, I made another mistake

Signed-off-by: Cloud_Yun <1770669041@qq.com>
2025-09-17 20:01:12 +08:00
Cloud_Yun
7d475e642f kpm: 改进可读性 (#392)
* kpm: improving readability
Honestly, this format is really messy

Signed-off-by: Cloud_Yun <1770669041@qq.com>

* kpm: fix missing int label
my bad (((

Signed-off-by: Cloud_Yun <1770669041@qq.com>

---------

Signed-off-by: Cloud_Yun <1770669041@qq.com>
2025-09-17 20:01:05 +08:00
ShirkNeko
cead5b03f4 Revert "manager: Optimized import, optimized all libsu shell calls, and fixed WebUI memory leaks #369
This reverts commit c3533861f2.
2025-09-17 20:00:51 +08:00
ShirkNeko
0c578e4518 [skip ci]: Reapply "manager: Optimized import, optimized all libsu shell calls, and fixed WebUI memory leaks Partial modification (#369)"
This reverts commit 37368fb41c.
2025-09-17 20:00:39 +08:00
NkBe
fad6420405 manager: Update zh-rTW strings (#388)
* manager: Update zh-rTW strings

* Setup default_signature
2025-09-12 14:12:05 +08:00
ShirkNeko
415555aef8 kernel: Add the real UID by parsing the UID from the /data/user_de/0/[app] directory fix #356]
Prioritize retrieving the application UID from /data/user_de. If this fails, fall back to retrieving it from packages.list.

Fix unstable application UID acquisition

Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-09-12 14:02:00 +08:00
ShirkNeko
f3e9033054 manager: Supplement the missing patch file format 2025-09-11 20:29:33 +08:00
由崎黑板
192323ad5c Add support for more kernel image name in KPM patcher (#386) 2025-09-11 20:18:02 +08:00
Cloud_Yun
6973ce6a1f manager: More standard working mode display (#384)
Actually, the working mode should be displayed here,
rather than the kernel type
This misled many people, leading them to misunderstand
the meaning of GKI

Signed-off-by: Cloud_Yun <1770669041@qq.com>
2025-09-10 22:32:58 +08:00
ShirkNeko
e8852223c4 manager: Optimize the overall layout of KPM patches 2025-09-10 22:05:30 +08:00
OukaroMF
42601b232c docs(zh): relocate SukiSU.svg to correct directory (#382)
- Move logo from docs/zh/guide/ to docs/zh/
- Remove obsolete path reference
- Standardize asset placement for localization

Co-authored-by: OukaroMF <OukaroMF@users.noreply.github.com>
2025-09-10 20:01:39 +08:00
ShirkNeko
cd8b6ab382 Manager: Added KPM patching functionality support. close #372
- Integrated KPM patching logic into KernelFlash and display KPM patching status.
- Updated Install to support KPM patching options.
- Implemented local and remote downloads for KPM tools.

Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-09-10 19:54:33 +08:00
ShirkNeko
3ed1d9aebc ksud: Only start the monitor and load the module when KPM is enabled
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
Co-authored-by: mihoy3rd <159522651+mihoy3rd@users.noreply.github.com>
2025-09-10 14:56:23 +08:00
ShirkNeko
d83fc2aec6 New Crowdin updates (#379)
* New translations strings.xml (Japanese)

* New translations strings.xml (Russian)
2025-09-09 14:31:49 +08:00
Saksham
098583f058 Delete Website/.github directory 2025-09-07 20:53:11 +05:30
NkBe
2521226745 docs: Update SukiSU logo (#381)
* docs: Add mini SukiSU logo/icon files

320x256 更符合大多项目使用标准

Co-Authored-By: OukaroMF <107784230+oukaromf@users.noreply.github.com>

* docs: Update project icon

Co-Authored-By: OukaroMF <107784230+oukaromf@users.noreply.github.com>

---------

Co-authored-by: OukaroMF <107784230+oukaromf@users.noreply.github.com>
2025-09-07 19:43:03 +05:30
ShirkNeko
942e5070f5 Manager: bump the agp version and ksp version. 2025-09-07 19:11:36 +08:00
Re*Index. (ot_inc)
6726828e1d Fix Japanese (#378)
* Fix Japanese

* Update strings.xml

* Update strings.xml

* Update strings.xml
2025-09-07 16:18:04 +08:00
ShirkNeko
4418ebadc4 Merge branch 'main' of https://github.com/SukiSU-Ultra/SukiSU-Ultra 2025-09-07 16:16:49 +08:00
ShirkNeko
37368fb41c Revert "manager: Optimized import, optimized all libsu shell calls, and fixed WebUI memory leaks Partial modification (#369)"
This reverts commit c3533861f2.

Resolved delayed access to globally mounted storage spaces

Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-09-07 16:15:57 +08:00
OukaroMF
1e5db5d6bf docs: Add SukiSU logo/icon files (#377)
- Add SukiSU.svg to docs directory
- Add SukiSU.svg to docs/zh/guide directory
- These SVG files appear to be branding assets for the project
- Add SukiSU.svg to Website/docs/public directory
- This logo file will be used for website branding
- Maintains consistency with other SukiSU branding assets
2025-09-07 15:58:29 +08:00
ShirkNeko
067ced4a8c kernel: Reworking Dynamic Manager Index Configuration 2025-09-06 15:25:03 +08:00
nobody202222
41d21e994c fix 'for' loop problem (#376)
fix ‘for’ loop initial declarations are only allowed in c99 or c11 mode
2025-09-05 21:52:41 +08:00
TypeFlu
596dab1db8 refer links to sukisu-ultra 2025-09-04 15:26:46 +05:30
TypeFlu
71c0424512 Merge commit '49190feab6268d64bbb16e332f53d2a66f387d14' as 'Website' 2025-09-04 15:07:40 +05:30
TypeFlu
49190feab6 Squashed 'Website/' content from commit 820a8fc4
git-subtree-dir: Website
git-subtree-split: 820a8fc4c609fa2281312a6a75491add1c280711
2025-09-04 15:07:40 +05:30
rsuntk
9b37ec4a84 kernel: stop intercepting devpts inode permission via LSM
* Somehow, it just does not work properly. (sometimes)

Signed-off-by: rsuntk <rsuntk@yukiprjkt.my.id>
2025-09-04 16:25:27 +08:00
Wang Han
12f54b115c manager: Strip JNI debug logs on release build (#2732)
Add conditional logging to jni.c for debug builds.
2025-09-02 15:01:50 +08:00
ShirkNeko
5586f9ce30 manager: Optimize build configurations
bump Gradle version and dep
2025-09-01 16:25:25 +08:00
ShirkNeko
0789632efc New translations strings.xml (Vietnamese) (#370) 2025-09-01 15:17:17 +08:00
梦璃酱
c3533861f2 manager: Optimized import, optimized all libsu shell calls, and fixed WebUI memory leaks (#369)
* manager: simply optimize

* manager: optimize webui functions

* manager: detect selinux using libsu:io

* manager: optimize webui functions

* manager: use the default shell

* manager: optimize import

* manager: optimize shell builder

* manager: fix memory leaks

* manager: optimize magisk detection

* manager: use libsu

* manager: optimize webui

---------

Co-authored-by: 白彩恋 <shiro@oom-wg.dev>
2025-09-01 15:04:58 +08:00
dabao1955
662a2b1237 kernel: Removs extra strip for hook choice (#361)
* kernel: Removs extra strip for hook choice 

extra changes for #353

* kernel: Fix Makefile
2025-08-28 10:18:11 +08:00
rsuntk
436071a3f1 ksud: fix some warnings
warning: hiding a lifetime that's elided elsewhere is confusing
  --> src/sepolicy.rs:22:30
   |
22 | fn parse_bracket_objs(input: &str) -> IResult<&str, SeObject> {
   |                              ^^^^             ----  -------- the same lifetime is hidden here
   |                              |                |
   |                              |                the same lifetime is elided here
   |                              the lifetime is elided here

Signed-off-by: rsuntk <rsuntk@yukiprjkt.my.id>
2025-08-25 21:30:39 +08:00
ShirkNeko
ea602be270 kernel: Remove the ksu_ prefix from the dynamic manager signature. 2025-08-25 20:16:51 +08:00
ShirkNeko
8c8f344161 manager: Clean code & bump AGP version 2025-08-25 17:28:51 +08:00
WenHao2130
1af8a87876 workflows: Drop deploy-website.yml
Signed-off-by: WenHao2130 <wenhao2130@outlook.com>
2025-08-24 13:22:12 +08:00
WenHao2130
6640b5b7b6 website: Kill website
* It has been separated into SukiSU-Ultra/Website

Signed-off-by: WenHao2130 <wenhao2130@outlook.com>
2025-08-24 13:15:55 +08:00
ShirkNeko
b8b75349e0 kernel: Bump KSU_VERSION_API to 3.1.9 2025-08-24 11:45:08 +08:00
dabao1955
3f3e520641 kernel: Remove unnecessary strip in CONFIG_KSU_TRACEPOINT_HOOK check (#353)
The 'strip' function is redundant when checking Kconfig variables, as
values from CONFIG options (like CONFIG_KSU_TRACEPOINT_HOOK) are already
trimmed and do not contain leading/trailing whitespace.

Simplify the condition for better readability and maintainability:
  - Remove unnecessary $(strip ...)
  - Add consistent spacing around the comma

This change aligns with kernel Makefile conventions and improves code clarity
without altering behavior.

Signed-off-by: dabao1955 <dabao1955@163.com>
2025-08-24 11:41:18 +08:00
OukaroMF
21aa58f1ee docs: EN: add simple translation for tracepoint-hook docs (#352)
* add EN translation for tracepoint-hook

* add EN translation for tracepoint-hook
2025-08-24 11:38:04 +08:00
ShirkNeko
da164ebeed kernel: Modified dynamic signature All files have been renamed to the correct names: Dynamic Manager 2025-08-24 11:00:17 +08:00
YC酱luyancib
35ae324df5 docs: zh: Introduce tracepoint hook documents (#350)
* docs: Introduce tracepoint hook documents

Still working in progress...
Only zh-cn.

* fix broken link

* format

* 更新 tracepoint-hook.md

* format

* 更新 tracepoint-hook.md

* docs: zh: fmt

Signed-off-by: WenHao2130 <wenhao2130@outlook.com>

---------

Signed-off-by: WenHao2130 <wenhao2130@outlook.com>
Co-authored-by: WenHao2130 <wenhao2130@outlook.com>
2025-08-24 00:06:13 +08:00
rsuntk
fdda1f4ec0 ksud: strip resetprop
* Upstream resetprop is intentionally not stripped.

Signed-off-by: rsuntk <rsuntk@yukiprjkt.my.id>
2025-08-23 17:03:31 +08:00
愛莉希雅
770ed1fdf2 manager: Updated Chinese Traditional 2025-08-20 20:55:35 +08:00
ShirkNeko
106c10d6f8 Kernel: Improved permission tracking logic when dynamic signature manager existence checks are enabled
- Fixed a panic issue caused by repeated scans in certain cases where dynamic signatures were not enabled

Revert: setup.sh: cleanup symlink & config logic (#338)
2025-08-19 18:16:09 +08:00
Juno Bủh
f10de68deb Fix typo strings (#339)
It's annoying that some parts have dot at the end of sentences and some don't. So I think it's better to remove all dot at the end of sentences to make it more consistent and easier to read
2025-08-18 17:06:15 +08:00
noctyra
44db32e8de setup.sh: cleanup symlink & config logic (#338)
- Avoid creating nested symlink (KernelSU/kernel/kernel) when running setup multiple times
- Cleanup in Kconfig only removes the correct line
- Makefile/Kconfig updates only applied once with clearer logs
2025-08-18 17:05:51 +08:00
ShirkNeko
3ced30b427 kernel: refactor APK signature verification functions for clarity and efficiency 2025-08-17 23:10:51 +08:00
ShirkNeko
624a8d9f86 kernel: selinux: dontaudit untrusted_app su dir { getattr }
* Following the advice that was given by member in rksu group, by replacing ALL to untrusted_app.

$ /system/bin/stat /proc/1
Result:
08-15 14:57:54.370 20062 20062 W stat    : type=1400 audit(0.0:9564): avc:  denied  { getattr } for  path="/proc/1" dev="proc" ino=12308 scontext=u:r:untrusted_app_27:s0:c27,c258,c512,c768 tcontext=u:r:init:s0 tclass=dir permissive=0 app=com.termux
(issue
438bd5f#commitcomment-163785768)

Test: Checker pass.

* Any issue? Let me know.

Tested-by: rsuntk <rsuntk@yukiprjkt.my.id>
Co-authored-by: rsuntk <rsuntk@yukiprjkt.my.id>
2025-08-16 12:42:19 +08:00
NkBe
16007f5892 [skip ci]manger: Fix translate module signature verification string (#332)
* manger: Fix translate module signature verification string

Revised the 'module_signature_verification_summary' string in multiple languages to clarify that forced signature verification applies to all ARM architectures, not just arm64-v8a. This improves accuracy and consistency across translations.

* manger: Update Traditional Chinese (Taiwan)

* manger: Update Traditional Chinese (Cantonese)
2025-08-16 12:34:50 +08:00
ShirkNeko
6bb83fdb07 kernel: Add KSU_MANUAL_HOOK configuration for manual KernelSU syscall hooking 2025-08-15 23:00:11 +08:00
ShirkNeko
ec6991f98b kernel: refactor apply_kernelsu_rules to use mutex for synchronization 2025-08-15 11:00:34 +08:00
Tashfin Shakeer Rhythm
f6337e2d52 kernel: selinux: rules: Micro-optimize get_policydb() and fix illegal RCU lock usage in handle_sepolicy() (#2695)
Signed-off-by: Tashfin Shakeer Rhythm <tashfinshakeerrhythm@gmail.com>
2025-08-15 10:33:05 +08:00
ShirkNeko
6b2bf23946 [skip ci]kernel: Add support for ksu_devpts_hook handling in ksu tracepoints 2025-08-15 10:32:23 +08:00
ShirkNeko
dbc662486b Fix correct hook type acquisition 2025-08-14 23:18:21 +08:00
ShirkNeko
e96194c7ff manager: Add hook type info 2025-08-14 22:59:37 +08:00
ShirkNeko
49b01aad74 kernel: Introducing Tracepoint Hook Type Support
Tracepoint is a predefined hook point in the kernel, compared to Kprobe,
it is more stable and has lower performance overhead, although compatibility
is relatively poor, it is still worth trying

By the way, we have also included the config definitions related to hook types
in Kconfig, to enhance cleanliness

Improve and merge types that do not require hooks

Introducing the hook type prctl

These patches is based on https://github.com/backslashxx/KernelSU/issues/5

Co-authored-by: Cloud_Yun <1770669041@qq.com>
Co-authored-by: Prslc <prslc113@gmail.com>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>

Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-08-14 22:17:02 +08:00
ShirkNeko
656a23a250 New Crowdin updates (#329)
* New translations strings.xml (Japanese)

* New translations strings.xml (Russian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Indonesian)

* New translations strings.xml (Chinese Traditional, Hong Kong)
2025-08-14 17:26:03 +08:00
ShirkNeko
11a628f536 manager: Update zakosign binary with support for arm32 architecture 2025-08-14 13:07:58 +08:00
ShirkNeko
57fcf86579 Updating zakosign binary script builds 2025-08-12 19:37:27 +08:00
ShirkNeko
ecb2dae743 manager: Fix anomaly in displaying system app functions due to status refresh issue. 2025-08-12 13:45:27 +08:00
ShirkNeko
75e0cd05a9 manager: Add recognition for app paths add uid hide 2025-08-12 13:25:36 +08:00
WenHao2130
1eb0f19ca6 manager: strings: fmt
Signed-off-by: WenHao2130 <wenhao2130@outlook.com>
2025-08-12 00:16:52 +08:00
NkBe
a7ee0423a3 manager: Updated Chinese Traditional (#325)
Signed-off-by: WenHao2130 <wenhao2130@outlook.com>
2025-08-12 00:13:21 +08:00
rsuntk
355e1c648a kernel: selinux: dontaudit * su dir getattr
* Likely a detection point for newer android.

* I am not sure about this, but a module try to address this: https://github.com/aviraxp/ZN-AuditPatch

* Need more testing.

Suggested-by: fatalcoder524 <11532648+fatalcoder524@users.noreply.github.com>
Tested-by: rsuntk <rsuntk@yukiprjkt.my.id>
Signed-off-by: rsuntk <rsuntk@yukiprjkt.my.id>
2025-08-11 17:18:01 +08:00
ShirkNeko
3cde3e1659 manger: simplify and Using array splitting to compare full version numbers 2025-08-10 19:19:40 +08:00
rsuntk
8dcc3f7c46 ksud: bump resetprop from Magisk v30.2
* Related pr:
https://github.com/tiann/KernelSU/pull/2700

rsuntk: Drop x86_64 bin, build our own arm bin.

Signed-off-by: rsuntk <rsuntk@yukiprjkt.my.id>
2025-08-10 18:32:39 +08:00
5ec1cff
a041b90891 ksud: make clippy happy (#2683)
e1be06240d/clippy_lints/src/format_args.rs (L168)
2025-08-10 17:59:12 +08:00
ShirkNeko
c1c648e34d [skip ci]ksud: support vendor_boot patching for some odd devices (#2650)
This will add support to patch vendor_boot with LKM for devices which
have their init ramdisk inside of vendor_boot and not boot/init_boot.

---------

Co-authored-by: Rifat Azad <rifat.44.azad.rifs@gmail.com>
Co-authored-by: 5ec1cff <ewtqyqyewtqyqy@gmail.com>
Co-authored-by: 5ec1cff <56485584+5ec1cff@users.noreply.github.com>
2025-08-10 17:31:43 +08:00
ShirkNeko
0754fc8920 manager: Update susfs binary version
- Add switches and descriptions for new AVC log spoofing in basic settings
2025-08-10 17:17:28 +08:00
NkBe
4d3bae1113 [skip ci]manger: Update Traditional Chinese (Taiwan) (#314) 2025-08-10 15:55:43 +08:00
Prslc
0fdd7d437f kernel(kpm): Fix typo in printk logs (#311)
Signed-off-by: Prslc <prslc113@gmail.com>
2025-08-06 17:02:38 +08:00
ShirkNeko
6e89c81407 manager: Cleaning up the code 2025-08-03 20:05:19 +08:00
ShirkNeko
f8b8c7f671 manager: Update agp and dependency version, improve module signature error return 2025-08-03 19:08:57 +08:00
ShirkNeko
cd4edf97bd manager: Refinement of module signatures again 2025-08-03 18:50:20 +08:00
Juno Bủh
e3f1e49fe1 Update Vietnamese Translation 2025-08-03 12:31:00 +05:30
MiRinChan
abe0dee4da string: Change the description of Signature Verification 2025-08-03 12:30:32 +05:30
MiRinChan
bc3fcec514 strings: Modified the description of resetting the Bootloader lock 2025-08-03 12:30:32 +05:30
ShirkNeko
d225f0bae9 manager: Continue to improve module signatures 2025-08-03 05:39:35 +08:00
ShirkNeko
48d7a13028 manager: add module signature verification
fix site base
2025-08-03 04:34:04 +08:00
ShirkNeko
7e7d2a28af kernel: Clean up the Dynamic Signature Manager related functionality, removing unnecessary rescanning logic 2025-08-02 16:28:52 +08:00
ShirkNeko
acfba3d0f8 kernel: refactoring uses flag bits for exiting instead of cleaning up the workflow 2025-08-02 01:27:02 +08:00
ShirkNeko
bf5a8a8909 kernel: optimize dynamic signature operation, enhance error recovery capability
- Add timeout protection for multi-manager APK verification.
2025-08-01 16:55:13 +08:00
ShirkNeko
7c4d8da7d1 New Crowdin updates (#300)
* New translations strings.xml (Russian)

* New translations strings.xml (Vietnamese)
2025-07-31 01:07:09 +08:00
Juno Bủh
c656d87e42 [skip ci]Update Vietnamese Translation (#302)
* Update Vietnamese Translation

* Update Vietnamese Translation
2025-07-31 01:05:39 +08:00
ShirkNeko
1b7c7fd726 manager: Optimize SuSFS path editing functionality
- Resize thread pool to improve performance
2025-07-31 01:00:49 +08:00
Seyud
ea68183f80 revert: fix: Remove the incorrect display of the KPM version and simplify the checking logic (#299) 2025-07-29 20:26:19 +08:00
Seyud
b1ee07fee1 Improve file existence check and copying methods, optimize command execution logic, and fix KPM version display issue (#298)
* fix: Remove the incorrect display of the KPM version and simplify the checking logic

* refactor: Optimize the command execution logic and simplify the code structure.

* fix: Improve the file existence check and file copying methods.
2025-07-29 15:16:34 +08:00
ShirkNeko
c42b4ffe4b kernel: fix dynamic signature rescan functionality and update related handlers 2025-07-29 11:49:36 +08:00
ShirkNeko
cfd070f33c kernel: Add Hot Update Rescan Manager feature for dynamic signatures 2025-07-29 10:32:15 +08:00
ShirkNeko
3ae1a3b10a kermel: Refactoring and separating dynamic signature-related structures and functions 2025-07-28 22:58:48 +08:00
ShirkNeko
d21f92d817 ksu_susfs: Reduced the binary size by compiling with dynamically linked, and -O3 for speed 2025-07-28 18:07:05 +08:00
ShirkNeko
6bb66e2819 kernel: Updated APK signature support, removed redundant definitions and adjusted indexing
Co-authored-by: rsuntk <rsuntk@yukiprjkt.my.id>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-07-28 17:12:17 +08:00
WenHao2130
115206bcc6 manager: Remove Loading Dialog when enable/disable the module (#291)
Magic Mount is fast enough that there is almost no
need to display a loading animation while waiting
for the backend to finish processing.

Signed-off-by: WenHao2130 <wenhao2130@outlook.com>
2025-07-24 19:43:56 +08:00
ShirkNeko
5ba4f73eeb manager: Update to version 3.1.8 and rename the relevant version checking functions 2025-07-21 21:22:07 +08:00
ShirkNeko
139899d05d [skip ci]manager: Add SUS loop path function 2025-07-21 21:14:09 +08:00
awkoo
d2ab325e18 优化setup.sh (#288) 2025-07-21 20:23:08 +08:00
ShirkNeko
be393ddb7c manager: Updating susfs binaries 2025-07-21 16:28:50 +08:00
WenHao2130
467d6e0838 ksud: Add KSU_SUKISU to env
This will help module authors determine which root implementation the module is running on.

Signed-off-by: WenHao2130 <wenhao2130@outlook.com>
2025-07-20 23:31:29 +08:00
米凛MiRin
46fcf97be3 readme: add chinese translation (#290) 2025-07-20 12:56:03 +05:30
Juno Bủh
72ed1bc4a2 Update Vietnamese Translation (#284) 2025-07-19 17:41:34 +08:00
ShirkNeko
b8544b4f53 manager: Adding a separate status to the update module
fix duplicate installations of update modules due to status confusion. fix #287

Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-07-19 16:59:36 +08:00
Cloud_Yun
60f0a721ce script: Simplify repository cloning logic (#283)
Rather than cloning to SukiSU-Ultra and renaming it KernelSU, it would be better to clone it directly as KernelSU.

Signed-off-by: Cloud_Yun <1770669041@qq.com>
2025-07-17 19:37:31 +09:00
ShirkNeko
c62676d643 New Crowdin updates (#280)
* New translations strings.xml (Japanese)

* New translations strings.xml (Russian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Vietnamese)
2025-07-17 14:32:35 +08:00
米凛MiRin
dd2b2e995a docs: fix wrong infomation (#282)
* docs: fix wrong infomation

* docs: fix wrong infomation
2025-07-17 14:32:20 +08:00
MiRinChan
86456a4d95 README & docs: Revise the README and documentation. Thanks to lama's help. 2025-07-16 17:18:31 +05:30
Prslc
11e9e37f43 manager: fix typo in hide_zygisk_implement string and summary (#279)
Signed-off-by: prslc <prslc113@gmail.com>
2025-07-16 18:16:34 +08:00
Prslc
a8a2aef4b5 manager: Display Zygisk implementation method with rezygisk support (#278)
* manager: Display Zygisk implementation method with rezygisk support

Signed-off-by: prslc <prslc113@gmail.com>

* manager: Fix incorrect display of Zygisk implementation when module is disabled

Signed-off-by: prslc <prslc113@gmail.com>

---------

Signed-off-by: prslc <prslc113@gmail.com>
2025-07-16 15:08:20 +08:00
Prslc
77ac0d70fd [skip ci]manager: Add switch to hide Zygisk implementation status information (#277)
Signed-off-by: prslc <prslc113@gmail.com>
2025-07-16 15:08:08 +08:00
wxxsfxyzm
2a00ef96c2 UPSTREAM: manager: improve predictive back animations
This pull request introduces custom screen transition animations to
enhance the overall user experience during navigation.

The key change is the implementation of a custom slide/fade effect for
navigating from main screens (i.e., screens hosted in the bottom
navigation bar) to detail screens. Transitions between the bottom
navigation bar tabs themselves retain a simple, clean cross-fade effect
to ensure a fast and smooth user interaction.

This PR also addresses the root cause of an issue where custom
animations were being overridden by the navigation library's defaults.

During implementation, it was discovered that custom transition
animations defined in the `defaultTransitions` parameter of the
`DestinationsNavHost` in `MainActivity` were not being applied. Instead,
a default fade-in/fade-out animation was always present.

The root cause was traced to the `compose-destinations` KSP (Kotlin
Symbol Processing) code generator. By default, the generator creates a
`NavGraphSpec` (e.g., `RootNavGraph.kt`) that includes its own
`defaultTransitions` property. This property, defined at compile-time
within the generated graph object, has a higher precedence than the
`defaultTransitions` parameter supplied to the `DestinationsNavHost`
composable at runtime.

As a result, our intended custom animations were being ignored and
overridden by the generated default.

To resolve this precedence issue permanently, this PR adopts the
official configuration method recommended by the `compose-destinations`
library.

- The following KSP argument has been added to the
`app/build.gradle.kts` file:

```kotlin
ksp {
    arg("compose-destinations.defaultTransitions", "none")
}
```

- This argument instructs the code generator to omit the
`defaultTransitions` property from the generated `NavGraphSpec`.

- By removing the higher-priority, generated default, the
`defaultTransitions` parameter on `DestinationsNavHost` now functions as
the effective default, allowing our custom animation logic to execute as
intended.

The new animation logic is conditional and defined within
`MainActivity`. It distinguishes between two primary navigation types:

- Main Screen → Detail Screen:

   - Enter: The new detail screen slides in from the right.

   - Exit: The old main screen slides out to the left while fading out.

- Detail Screen → Main Screen (on Pop):

- Pop Enter: The main screen slides back in from the left while fading
in.

   - Pop Exit: The detail screen slides out to the right.

- Between Bottom Navigation Tabs:

- A simple cross-fade (`fadeIn`/`fadeOut`) is maintained for these
transitions to provide a quick and non-disruptive experience when
switching between primary sections of the app.
2025-07-15 09:02:06 +08:00
YangQi0408
39ee1cc41d kernel: core_hook: add support for KernelNoSU (#270)
reorder ksu_handle_prctl checks a bit to allow non-manager to use CMD 15
this allows us to piggyback a small su to KernelSU's permission system after
disabling kernel sucompat

from:
Relax prctl perm check
- 95125c32f9
Allow prctl only for root or manager or su binary
- fa7af67d94
Refine prctl access check, allow /product/bin/su
- dd466dc1b6
Refine prctl check a little bit more
- e7c5b24efa

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
Co-authored-by: nampud <nampud@users.noreply.github.com>
2025-07-14 15:24:48 +08:00
米凛MiRin
51556d1253 strings: add copyright infomation (#275)
* copyright: Correct copyright owner information

* string: add copyright infomation
2025-07-14 15:21:48 +08:00
米凛MiRin
94df64f234 copyright: Correct copyright owner information (#273) 2025-07-14 00:08:00 +08:00
WenHao2130
02f545b3fb [skip ci] Revert "Redirect the Feature Requests issue template tab (#1788)"
This reverts commit 3695435c3f.

Allow feature requests

Signed-off-by: WenHao2130 <wenhao2130@outlook.com>
2025-07-13 10:50:28 +08:00
ShirkNeko
62c7aac75b Merge branch 'main' of https://github.com/SukiSU-Ultra/SukiSU-Ultra 2025-07-12 11:43:23 +08:00
ShirkNeko
755d454960 manager:Add flag bits to module installations to prevent repeated installations
- Modify the time and location of the susfs self-startup scripts
2025-07-12 11:41:58 +08:00
Marat Budkevich
9717fa0de6 fix(manager): add extraspace after "UID:" for Home screen (#268) 2025-07-11 19:18:03 +08:00
ShirkNeko
bd6eb7fddd manager: Update agp version
- Fix bug caused by SuSFS configuration screen returning too quickly
2025-07-11 10:56:30 +08:00
ShirkNeko
9f706873f2 manager: Fixed susfs binary naming scheme 2025-07-09 18:54:27 +08:00
ShirkNeko
c424d5bab4 kernel: simplified signature verification 2025-07-09 12:12:12 +08:00
WenHao2130
e795387c30 manager: Reformat zh-rCN strings
Change-Id: I9880ac9c4e6f74d30110cccfbd774ddfebf89ac0
Signed-off-by: WenHao2130 <wenhao2130@outlook.com>
2025-07-09 11:07:54 +08:00
ShirkNeko
044dd9471f manager: Refactor the way information is fetched in the home screen to avoid null pointers
- add an auto-refresh cache feature
2025-07-09 01:33:00 +08:00
YangQi0408
213a15cdb6 manager: 显示 Zygisk 实现方式 (#264)
* manager: Add display of Zygisk Implement feature and formatting code

* manager: Change the method of detecting Zygisk Implement
Signed-off-by: YangQi0408 <a123er3643@163.com>
Co-authored-by: WenHao2130 <WenHao2130@outlook.com>
2025-07-08 22:34:34 +08:00
ShirkNeko
a255ea9d56 [skip ci]New Crowdin updates (#263)
* New translations strings.xml (Russian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Vietnamese)
2025-07-07 17:49:24 +08:00
ShirkNeko
6cbe13dafc Assets: Add susfs executable binary v1.5.9 2025-07-06 14:49:54 +08:00
ShirkNeko
fb5c7c2f9d manager: Updated dependency library version
- Add JNI macros to simplify field setup and object creation
2025-07-06 14:44:36 +08:00
ShirkNeko
b8f2d15bd1 manager: Modify the separator for information cards from a semicolon to a vertical line 2025-07-06 00:56:15 +08:00
ShirkNeko
2bd6929d24 manager: Add the ability to get a list of active managers 2025-07-06 00:26:42 +08:00
ShirkNeko
42b883240e kernel: add multi-manager support 2025-07-05 22:27:39 +08:00
ShirkNeko
4840540038 manager: Modify Dynamic Signature Configuration Input Verification
- Allow sizes beginning with 0x
2025-07-05 17:39:24 +08:00
Juno Bủh
7bfb37a11e [skip ci]Update Vietnamese Translation (#257)
* Update Vietnamese Translation

* Update strings.xml

* Update strings.xml
2025-07-05 16:37:48 +08:00
ShirkNeko
dd6d695020 kernel:Add Dynamic Signature Configuration 2025-07-05 16:21:29 +08:00
ShirkNeko
6a60b72e21 manager: Reorganizing the backup and restore functionality of SuSFS configurations
- Add checking for the existence of a data catalog for applications in SUS Path

- Modify the loading and caching mechanism of the application information class to avoid repeated refreshes,Finish loading with SuperUser.
2025-07-04 17:57:54 +08:00
ShirkNeko
ea3a0cf73b manager: Update the name in the webui description to “SukiSU-Ultra” 2025-07-03 21:09:37 +08:00
ShirkNeko
1816d15ce8 manager: Refactor show SuSFS features
- need to update the kernel
2025-07-03 19:25:52 +08:00
ShirkNeko
79c8f7a709 New Crowdin updates (#247)
* New translations strings.xml (Russian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Japanese)

* New translations strings.xml (Turkish)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Russian)

* New translations strings.xml (Vietnamese)
2025-07-03 14:00:45 +08:00
ShirkNeko
b0cc0e6f6d kernel: Update CMD_GET_FULL_VERSION to a new constant value 2025-07-03 00:08:54 +08:00
ShirkNeko
eccc70c0c9 manager: Improve loading and empty state handling in SuperUserScreen 2025-07-03 00:03:59 +08:00
Juno Bủh
fc828ff3aa [skip ci]: Update Vietnamese Translation (#248)
* Update Vietnamese Translation

* Update Vietnamese Translation
2025-07-02 23:34:48 +08:00
ShirkNeko
acb7cfff1b Revert: Rollback some of the changes in "Add option to use WebUI X" and refactor the KsuService
- Solve the problem that SuperUser is not available when opening SU compatibility.
2025-07-02 01:37:37 +08:00
nanLianQing
3729c22dd0 fix: Fix application crashes caused by improper handling of coroutine exceptions (#249) 2025-07-01 23:26:36 +08:00
ShirkNeko
a84cf70730 manager:Fixed the issue of not getting the corresponding app name and icon in SuSFS paths 2025-07-01 20:00:26 +08:00
ShirkNeko
2278fe49d2 manager: Adding optional additions to SUS paths applies functionality corresponding to the package name as well as categorization 2025-07-01 17:29:45 +08:00
ShirkNeko
be14da387e manager: replace Runtime.exec with getRootShell for command execution 2025-07-01 02:48:09 +08:00
ShirkNeko
1fd13d9d8d docs: Updated documentation to introduce SuSFS Configuration Manager and introduction of advanced features 2025-06-30 16:57:56 +08:00
NkBe
4205db6870 [skip ci]Update Traditional Chinese (Taiwan) (#242) 2025-06-30 16:43:32 +08:00
ShirkNeko
70f03081a4 [skip ci]New Crowdin updates (#240)
* New translations strings.xml (Japanese)

* New translations strings.xml (Russian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Indonesian)

* New translations strings.xml (Chinese Traditional, Hong Kong)
2025-06-30 15:51:32 +08:00
Kitty
5ccb779b6a [skip ci] Update Ukrainian translation (#236) 2025-06-30 15:35:34 +08:00
Juno Bủh
b07bc408ce [skip ci] Update Vietnamese Translation (#238)
* Update Vietnamese Translation

* Update Vietnamese Translation

* Update Vietnam
2025-06-30 15:35:12 +08:00
ShirkNeko
7ee1fd63f1 manager: Add Zygote isolation service uninstallation to susfs feature 2025-06-30 15:32:47 +08:00
ShirkNeko
3551441e42 manager: Provides re-editable functionality for all SuSFS path configurations 2025-06-29 20:36:45 +08:00
ShirkNeko
4a1ab76322 manager: Optimize the logical order of Susfs self boot scripts 2025-06-29 19:06:20 +08:00
ShirkNeko
2fedb051b8 manager: Add Hide Bootloader Scripts and Cleanup Tool Residue feature and switch 2025-06-29 17:50:39 +08:00
Juno Bủh
10c35f4baa Update Vietnamese Translation (#229)
* Update Vietnamese Translation

* Update Vietnamese Translation
2025-06-29 12:32:05 +08:00
科家
4f82eda003 manager: Only display slotinformation on AB devices (#233)
还是有人在用 A-Only 分区设备的
2025-06-29 12:31:50 +08:00
Prslc
80f89c0241 [skip ci] manager: Fix unintended LKM dialog when selecting AnyKernel3 install method (#234)
This fixes a logic issue where the KMI selection dialog would still appear
even when the user selected the AnyKernel3 install method.

Signed-off-by: prslc <prslc113@gmail.com>
2025-06-29 12:30:34 +08:00
ShirkNeko
8399f14fad manager: Add SuSFS configuration backup and restore feature
- Optimize susfs self-boot scripts
- Solve some invalid issues where startup duration does not match or is too fast.

Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-06-28 23:19:18 +08:00
YC酱luyancib
c49a66d1af Update Kconfig (#224)
make sure kpm config requrement was enabled
2025-06-28 10:19:53 +05:30
Juno Bủh
d66b390361 Update Vietnamese Translation (#223) 2025-06-27 18:47:02 +08:00
ShirkNeko
9c290a8080 [skip ci]: New Crowdin updates (#222)
* New translations strings.xml (Japanese)

* New translations strings.xml (Russian)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Indonesian)

* New translations strings.xml (Chinese Traditional, Hong Kong)
2025-06-27 18:46:45 +08:00
Saksham Singla
48efc28e8f Update Funding.yml (#221)
* Update FUNDING.yml

* add sukisu donation

---------

Co-authored-by: weishu <twsxtd@gmail.com>
2025-06-27 16:55:22 +08:00
ShirkNeko
634adad15c ksud: fmt 2025-06-27 11:15:19 +08:00
古塵
4532bab230 kernel: refactor CMD_GET_FULL_VERSION to safely initialize version string (#220)
Use strscpy()/strlcpy() to populate the version buffer in CMD_GET_FULL_VERSION
instead of relying on uninitialized memory. This ensures the returned string
is null-terminated and avoids exposing garbage data to user space.

Signed-off-by: schqiushui <orochi9999@gmail.com>
2025-06-27 10:42:38 +08:00
ShirkNeko
d3c9b6e739 ksud: handle errors and non compatible ramdisk
Co-authored-by: rifsxd <rifat.44.azad.rifs@gmail.com>
2025-06-26 14:22:42 +08:00
ShirkNeko
8e4f980db0 ksud: third test properly check if vendor is already patched or not for lkm restoration and also handle magisk patched vendor boot
Co-authored-by: rifsxd <rifat.44.azad.rifs@gmail.com>
2025-06-26 14:15:49 +08:00
ShirkNeko
cfee357ed1 manager: Optimize susfs management,
- solve some problems caused by new versions not taking effect
2025-06-26 14:10:50 +08:00
ShirkNeko
9393459b27 manager: Improvements to susfs functionality status fetch exceptions
- Show false if unable to fetch
2025-06-26 00:24:33 +08:00
ShirkNeko
60af173a7e manager:Optimize the path configuration to automatically configure the corresponding value as long as the self-boot is enabled 2025-06-25 23:39:04 +08:00
NkBe
23e2377f87 [skip ci]Update README.md (#218)
就单纯怎么看怎么怪,所以手欠改一改
2025-06-25 20:13:06 +08:00
NkBe
d45ba31849 manger: fix lkm detection (#217)
* manger: Rollback crowdin Update (Traditional Chinese Taiwan)

* manger: Try to modify the lkm detection

改了下判斷方式,現在只要核心返回的 version_flags最後一位是 1,is_lkm就會被正確地設成 true
2025-06-25 19:26:54 +08:00
Saksham Singla
c5705c2d5d Bump agp and Gradle to latest (#216)
* Bump AGP

* Bump Gradle

* update gradle to 14.2
2025-06-25 19:15:17 +08:00
ShirkNeko
dfae83cf58 New Crowdin updates (#215)
* New translations strings.xml (Russian)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Indonesian)

* New translations strings.xml (Chinese Traditional, Hong Kong)
2025-06-25 16:33:07 +08:00
NkBe
cd5ba3ac3c [skip ci] manger: Update Traditional Chinese (Taiwan) (#214) 2025-06-25 16:26:24 +08:00
ShirkNeko
2c2698f6bc kernel: Rewrite kernle version code management
Co-authored-by: lamadaemon <i@lama.icu>
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-06-24 23:16:16 +08:00
NkBe
f57fe79c5d manager: Update LKM select file prompt, optimize “init_boot / vendor_boot” text (#211)
* Update Install.kt

* Update Install.kt

* Update strings.xml

* Update strings-rCN.xml

* Update strings-rTW.xml

* manger: Add a space to ensure pangu

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-06-24 15:50:48 +08:00
ShirkNeko
91ae4c9650 manager: Update LKM select file prompt, support “init_boot / vendor_boot” option 2025-06-24 15:03:14 +08:00
ShirkNeko
01f44dc1d9 ksud: Adding LKM patch support for vendor_boot images
- And improve the OTA update mechanism
- Updating the magiskboot library

Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
Co-authored-by: rifsxd <rifat.44.azad.rifs@gmail.com>
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-06-24 12:52:22 +08:00
Prslc
6e35b88041 Kernel: use main branch commit count for consistent versioning (#209) 2025-06-23 18:59:30 +08:00
Re*Index. (ot_inc)
c9c122d79b skip ci :Update & Fix Japanese (#208)
* Update README-ja.md

* Update README-ja.md

* Update README-ja.md

* Update strings.xml

* Update strings.xml

* Update strings.xml
2025-06-23 18:58:03 +08:00
ShirkNeko
4bec5ae7b1 ksud: Update version code calculations to adjust historical version offsets 2025-06-22 18:45:58 +08:00
ShirkNeko
f9b3478dbb Fix text parameter formatting in KstatConfigItemCard, remove redundant “parameter:” prefixes 2025-06-22 18:33:50 +08:00
ShirkNeko
561c82de0a manager: Refactoring the SuSFS configuration layout and simplifying functions 2025-06-22 18:31:11 +08:00
Amicia De Rune
e96ceb84c9 Update Indonesia Translate (#204)
* Update Indonesia Translate

* Update manager/app/src/main/res/values-in/strings.xml

<string name="show_kpm_info">Sembunyikan fungsi KPM</string>

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update manager/app/src/main/res/values-in/strings.xml

<string name="show_kpm_info_summary">Sembunyikan fungsi informasi KPM dan menu KPM di bilah navigasi</string>

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update manager/app/src/main/res/values-in/strings.xml

<string name="home_ContributionCard_kernelsu">Antusias Untuk SukiSU Ultra</string>

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update manager/app/src/main/res/values-in/strings.xml

<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra akan menjadi cabang KSU yang relatif independen di masa mendatang, tetapi kami tetap menghargai KernelSU dan MKSU resmi dan sebagainya atas kontribusi mereka!</string>

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update manager/app/src/main/res/values-in/strings.xml

<string name="engine_force_ksu">Penggunaan wajib KSU WebUI</string>

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update manager/app/src/main/res/values-in/strings.xml

<string name="language_changed">Bahasa dirubah, mulai ulang aplikasi untuk menerapkan</string>

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update manager/app/src/main/res/values-in/strings.xml

<string name="icon_switch_summary">Ubah ikon peluncur aplikasi ke ikon KernelSU</string>

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update manager/app/src/main/res/values-in/strings.xml

<string name="show_more_module_info_summary">Pajang info modul tambahan seperti URL pembaruan JSON</string>

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-06-21 23:40:11 +08:00
ShirkNeko
ddbbeafc64 manager: Added the SUS Mount Hide Control feature added in SuSFS version 1.5.8 2025-06-21 23:39:19 +08:00
ShirkNeko
285478a778 manager: Remove deprecated OverlayFS checks for automatic kernel stats support.
- Updating the LKM build

- New Crowdin updates
2025-06-21 18:34:37 +08:00
Rifat Azad
00ffa86705 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-21 17:09:16 +08:00
ShirkNeko
74ec20745c Uniformly use surfaceContainerHigh as the background color of the popup window 2025-06-21 16:34:38 +08:00
ShirkNeko
b7b995bf73 Updating the Crowdin Workflow Configuration 2025-06-21 15:37:33 +08:00
ShirkNeko
29b7f9e0ad New Crowdin updates (#200)
* New translations strings.xml (Japanese)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Chinese Traditional, Hong Kong)

* New translations strings.xml (Russian)
2025-06-21 14:51:13 +08:00
ShirkNeko
00a4c69227 Remove unused strings 2025-06-21 14:18:51 +08:00
愛莉希雅
9c204496c3 完善補充正體中文-香港 (#3) (#194) 2025-06-21 12:41:41 +08:00
ShirkNeko
519401cf39 Fixing SUS Path Execution Errors
- Simplify SuSFS configuration management
2025-06-21 00:21:14 +08:00
愛莉希雅
f69eb5c115 完善補充正體中文-香港#2 (#191) 2025-06-20 21:23:29 +08:00
NkBe
82e96f4394 manger: 完善補充正體中文 (#189)
* manger: Pangu Format

Pangu Format maintained for new text.

* manger: 完善正體中文
2025-06-20 19:11:30 +08:00
Prslc
8e3db00b9b README: Sync README_EN with README (#190) 2025-06-20 19:11:20 +08:00
ShirkNeko
adf299d9f3 manager: Update the feature definition
- remove the unused FEATURE_SUS_OVERLAYFS
- add FEATURE_SUSFS_HAS_MAGIC_MOUNT
2025-06-20 01:52:00 +08:00
rsuntk
483a39c7ac 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-19 18:28:21 +08:00
ShirkNeko
c83baad6d5 manager: Add SuSFS Kstat-related configuration 2025-06-19 11:26:15 +08:00
ShirkNeko
2ff3b5ee06 manager: Fix the character processing logic in the clear command of FlashScreen. 2025-06-18 15:52:48 +08:00
ShirkNeko
b537b51034 manager:Add SuSFS to obtain slot uname and build time information 2025-06-18 15:41:08 +08:00
ShirkNeko
bfb6ea3613 manager:Adjust the text display of setting items to allow multi-line text descriptions 2025-06-18 00:12:27 +08:00
ShirkNeko
edf7685e9a strings: Updates the string resources at the current execution location and modifies the associated text display 2025-06-17 23:58:42 +08:00
ShirkNeko
f65f62360a strings: Update path setting related strings and comments 2025-06-17 23:38:37 +08:00
ShirkNeko
af97488d58 manager: Add pseudo kernel and build time execution location settings 2025-06-17 23:30:29 +08:00
ShirkNeko
6b1f73aa3d manager: Small increase in app acquisition speed 2025-06-17 22:34:47 +08:00
Re*Index. (ot_inc)
4eeece9559 Fix Japanese (#186) 2025-06-17 10:52:16 +08:00
ShirkNeko
4d7d5547ac New Crowdin updates (#184)
* New translations strings.xml (Turkish)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Vietnamese)
2025-06-17 00:56:15 +08:00
NkBe
7b74e70f97 manger: 更新正體中文 (#183)
* manger: 更新正體中文

* 保证 pangu 格式
2025-06-17 00:25:12 +08:00
ShirkNeko
d92f8fc8fd New Crowdin updates (#181)
* New translations strings.xml (Romanian)

* New translations strings.xml (French)

* New translations strings.xml (Spanish)

* New translations strings.xml (Arabic)

* New translations strings.xml (Danish)

* New translations strings.xml (German)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Italian)

* New translations strings.xml (Japanese)

* New translations strings.xml (Korean)

* New translations strings.xml (Lithuanian)

* New translations strings.xml (Dutch)

* New translations strings.xml (Polish)

* New translations strings.xml (Russian)

* New translations strings.xml (Slovenian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Persian)

* New translations strings.xml (Marathi)

* New translations strings.xml (Thai)

* New translations strings.xml (Croatian)

* New translations strings.xml (Estonian)

* New translations strings.xml (Latvian)

* New translations strings.xml (Azerbaijani)

* New translations strings.xml (Hindi)

* New translations strings.xml (Malay)

* New translations strings.xml (Filipino)

* New translations strings.xml (Chinese Traditional, Hong Kong)

* New translations strings.xml (Bosnian)

* New translations strings.xml (Kannada)
2025-06-16 21:55:31 +08:00
ShirkNeko
55f9de2fa9 manager: split susfs module creation scripts
- Add a small number of scripts from the susfs4ksu module that lack a weak BL.
2025-06-16 21:50:51 +08:00
ShirkNeko
a12b14ef46 manager: Refactoring get the status of SUSFS functions
- More precise status cases
- Requires a recompile of your kernel to use it.
2025-06-16 20:16:25 +08:00
ShirkNeko
4ce6ff6286 manager: add ability to read and parse /proc/config.gz file, optimize function status checking 2025-06-15 22:48:56 +08:00
ShirkNeko
ce3566640c Add the ability to display more module information, support copying the update configuration address to the clipboard 2025-06-15 22:21:14 +08:00
ShirkNeko
a0a9fb01f4 manager: Add the function of hiding module label rows, optimize the module lagging problem 2025-06-15 21:50:09 +08:00
ShirkNeko
e1bd16d94f manager: Contrasting scroll to top and bottom functions 2025-06-15 20:05:40 +08:00
ShirkNeko
776ae8744c manager: add folder size labels for module items to optimize the display of module information 2025-06-15 19:27:26 +08:00
ShirkNeko
9285945e8b manager: Optimize the animation of floating action buttons, add zoom and transparency animation 2025-06-15 18:47:51 +08:00
ShirkNeko
75e56038ec manager: Add visibility state management for floating action buttons
- Get change button style from Apatch
2025-06-15 18:32:17 +08:00
ShirkNeko
730d58f18b dec++-ify jni part
- Refactoring to c

Co-authored-by: lamadaemon <i@lama.icu>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-06-15 17:17:19 +08:00
ShirkNeko
67a05e8813 strings: Modifying SuSFS Configuration to Optimize Boot Self-Start Description 2025-06-15 16:05:04 +08:00
ShirkNeko
e95a469bdb manager: Add a default tab item to the AppItem
- Maybe make the spacing consistent? I'm not sure.

Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-06-15 15:52:43 +08:00
HSSkyBoy
2ff122e235 manger: 更新正體中文 (#169)
* manger: 更新正體中文

翻譯已更新內容,優化原本翻譯

* Update strings.xml

* 保证 Pangu 格式

* 補全新內容
2025-06-15 15:08:51 +08:00
ShirkNeko
2319452306 manager: Refactor the bootstrap script to automatically create a KSU module to execute instead
- Add Shamiko's Hidden Weakness Bl Scripts

Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-06-15 14:41:14 +08:00
ShirkNeko
a0752d10c7 Merge branch 'main' of https://github.com/SukiSU-Ultra/SukiSU-Ultra 2025-06-15 03:39:13 +08:00
ShirkNeko
9110d89d61 manager: Add configuration for SuSFS logging feature, support enable/disable logging 2025-06-15 03:38:51 +08:00
米凛MiRin
39d6962320 modified: docs/README-en.md (#170)
modified:   docs/README.md
2025-06-15 01:35:25 +08:00
ShirkNeko
7b314116e9 manager: Refactored SuSFS pop-up window and changed to interface to optimize visual experience 2025-06-15 01:32:38 +08:00
ShirkNeko
ef4101cbf9 manager: Optimizing SuSFS Feature Status Display
- Use labels instead of Text

Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-06-14 22:35:36 +08:00
ShirkNeko
85f5459c1d manager: Add support for automatic selection of corresponding SuSFS version and build time artifacts 2025-06-14 22:04:40 +08:00
ShirkNeko
97e367aa92 manager: Update and add SuSFS related settings and functions. 2025-06-14 20:00:16 +08:00
ShirkNeko
7097986cf5 manager: Add loading animation and empty state component
- Improve user experience when app has no content

Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-06-14 15:39:06 +08:00
ShirkNeko
d6c8ef3737 manager: Add configure susfs uname value in more settings
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-06-14 01:10:40 +08:00
ShirkNeko
d7a5e80d34 manager: Modifying the getHookType function to return a string type
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
Co-authored-by: rifsxd <rifat.44.azad.rifs@gmail.com>
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-06-13 15:36:15 +08:00
ShirkNeko
2d9783e3d4 manager: Add the ability to get the hook type 2025-06-13 14:39:16 +08:00
backslashxx
9f407a94e3 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-13 02:38:02 +08:00
ShirkNeko
99726a2c4e [skip ci] docs: Updated README file to reflect instructions for the susfs-main branch
kernel: Added sukisu_set_manager_uid function to set the management UID
2025-06-13 02:36:50 +08:00
ShirkNeko
f3675e7f6e Revert "throne_tracker: avoid cross fs access 2025-06-11 18:55:25 +08:00
ShirkNeko
b84d528d99 [skip ci] manager: update values-tr/strings.xml (#161)
Co-authored-by: cvnertnc <148134890+cvnertnc@users.noreply.github.com>
2025-06-11 18:48:08 +08:00
ShirkNeko
0aab0c1d6b manager: Optimize the layout of PullToRefreshBox in SuperUserScreen to remove redundant padding 2025-06-11 00:47:03 +08:00
ShirkNeko
ab2367f7fa manager: Refactor AppItem layout and improve label display 2025-06-11 00:21:13 +08:00
Wang Han
1bac30930f Switch to prepare_creds/commit_creds
Update API as per kernel doc recommends, also fix setup_groups refcount
leak while at it.
2025-06-10 23:39:08 +08:00
ShirkNeko
6a9186300b [skip ci]New Crowdin updates (#156)
* New translations strings.xml (Romanian)

* New translations strings.xml (French)

* New translations strings.xml (Spanish)

* New translations strings.xml (Arabic)

* New translations strings.xml (Danish)

* New translations strings.xml (German)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Italian)

* New translations strings.xml (Japanese)

* New translations strings.xml (Korean)

* New translations strings.xml (Lithuanian)

* New translations strings.xml (Dutch)

* New translations strings.xml (Polish)

* New translations strings.xml (Russian)

* New translations strings.xml (Slovenian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Persian)

* New translations strings.xml (Marathi)

* New translations strings.xml (Thai)

* New translations strings.xml (Croatian)

* New translations strings.xml (Estonian)

* New translations strings.xml (Latvian)

* New translations strings.xml (Azerbaijani)

* New translations strings.xml (Hindi)

* New translations strings.xml (Malay)

* New translations strings.xml (Filipino)

* New translations strings.xml (Chinese Traditional, Hong Kong)

* New translations strings.xml (Bosnian)

* New translations strings.xml (Kannada)

* New translations strings.xml (Romanian)

* New translations strings.xml (French)

* New translations strings.xml (Spanish)

* New translations strings.xml (Arabic)

* New translations strings.xml (Danish)

* New translations strings.xml (German)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Italian)

* New translations strings.xml (Japanese)

* New translations strings.xml (Korean)

* New translations strings.xml (Lithuanian)

* New translations strings.xml (Dutch)

* New translations strings.xml (Polish)

* New translations strings.xml (Russian)

* New translations strings.xml (Slovenian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Persian)

* New translations strings.xml (Marathi)

* New translations strings.xml (Thai)

* New translations strings.xml (Croatian)

* New translations strings.xml (Estonian)

* New translations strings.xml (Latvian)

* New translations strings.xml (Azerbaijani)

* New translations strings.xml (Hindi)

* New translations strings.xml (Malay)

* New translations strings.xml (Filipino)

* New translations strings.xml (Chinese Traditional, Hong Kong)

* New translations strings.xml (Bosnian)

* New translations strings.xml (Kannada)

* New translations strings.xml (Japanese)

* New translations strings.xml (Russian)

* New translations strings.xml (Vietnamese)
2025-06-10 23:33:35 +08:00
WenHao2130
e6dea3c29e [skip ci]manager: Drop QQ group invitation link (#158)
Signed-off-by: WenHao2130 <wenhao2130@outlook.com>
2025-06-10 23:33:04 +08:00
ShirkNeko
c873ff74cb manager: Add status tracking to ensure that brush-write operations are performed correctly 2025-06-09 02:25:02 +08:00
ShirkNeko
7b6f451cfb manager: Optimize the function of app classification and sorting method 2025-06-09 01:27:33 +08:00
ShirkNeko
73dea0b8e7 Adjusting component spacing and interaction effects 2025-06-08 23:13:41 +08:00
米凛MiRin
f71d617cb3 manager: fix color (#154) 2025-06-08 22:07:29 +08:00
WenHao2130
f0d8e42026 manager: Fix get Google device model issues (#153)
- Inconsistent case of BRAND and MANUFACTURER information on Google devices results in unintended behavior (e.g. Google Google Pixel 9 XL)

Signed-off-by: WenHao2130 <wenhao2130@outlook.com>
2025-06-08 21:08:05 +08:00
ShirkNeko
5bbd95e821 manager: Updated superuser interface, added sidebar categories 2025-06-08 20:28:05 +08:00
WenHao2130
fa060dca58 manager: Refactoring the get device name logic (#152)
* manager: Import `getDeviceInfo()` from bmax/APatch

Co-authored-by: GarfieldHan <2652609017@qq.com>
Signed-off-by: WenHao2130 <wenhao2130@outlook.com>

* manager: Use `getDeviceInfo()` instead `Build.DEVICE`

Signed-off-by: WenHao2130 <wenhao2130@outlook.com>

---------

Signed-off-by: WenHao2130 <wenhao2130@outlook.com>
Co-authored-by: GarfieldHan <2652609017@qq.com>
2025-06-08 15:47:48 +08:00
ShirkNeko
9c7ba5b998 [skip ci]: docs: Updating the README file to add a description of support for non-GKI device builds
完整正體中文本地化

對缺失內容的完整翻譯,對現有內容參考 SukiSU-Ultra 簡體中文優化

New Crowdin updates (#140)

Co-authored-by: HSSkyBoy <HSSkyBoy@outlook.com>
Co-authored-by: cvnertnc <148134890+cvnertnc@users.noreply.github.com>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-06-07 22:23:49 +08:00
ShirkNeko
061136900a [skip ci]: New Crowdin updates (#138)
* New translations strings.xml (Romanian)

* New translations strings.xml (French)

* New translations strings.xml (Spanish)

* New translations strings.xml (Arabic)

* New translations strings.xml (Danish)

* New translations strings.xml (German)

* New translations strings.xml (Romanian)

* New translations strings.xml (French)

* New translations strings.xml (Spanish)

* New translations strings.xml (Arabic)

* New translations strings.xml (Danish)

* New translations strings.xml (German)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Italian)

* New translations strings.xml (Japanese)

* New translations strings.xml (Korean)

* New translations strings.xml (Lithuanian)

* New translations strings.xml (Dutch)

* New translations strings.xml (Polish)

* New translations strings.xml (Russian)

* New translations strings.xml (Slovenian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Persian)

* New translations strings.xml (Marathi)

* New translations strings.xml (Thai)

* New translations strings.xml (Croatian)

* New translations strings.xml (Estonian)

* New translations strings.xml (Latvian)

* New translations strings.xml (Azerbaijani)

* New translations strings.xml (Hindi)

* New translations strings.xml (Malay)

* New translations strings.xml (Filipino)

* New translations strings.xml (Chinese Traditional, Hong Kong)

* New translations strings.xml (Bosnian)

* New translations strings.xml (Kannada)
2025-06-03 17:16:15 +08:00
ShirkNeko
6375bf4b7c manager: Simplify state management of components for installation method selection
Remove unnecessary LKM upload logic
2025-06-03 16:57:41 +08:00
ShirkNeko
17288c086a manager: Simplify Home data initialization logic and remove unnecessary caching time 2025-06-03 16:29:41 +08:00
ShirkNeko
15747ceaa5 manager: Simplify KPM display judgment in Home messages 2025-06-03 15:48:21 +08:00
ShirkNeko
675bb20f52 manager: Modify the Show KPM function to hidden and update the related settings. 2025-06-03 15:26:03 +08:00
ShirkNeko
ec0b26a174 manager: Optimize slot selection dialog to remove unnecessary information 2025-06-03 15:15:48 +08:00
ShirkNeko
92f6f2f51e manager: Add card shadow effect control 2025-06-03 14:04:55 +08:00
5ec1cff
587e73b449 manager: persist show system app settings 2025-06-03 13:53:45 +08:00
ShirkNeko
07c9cce4b9 manager: Fixed flickering on activity refresh using a clever method.
- Add Activity lifecycle callback and method to refresh current Activity
2025-06-03 01:43:31 +08:00
ShirkNeko
1d34ea4995 Rename files and update package structure
Add tool classes related to displaying and refreshing data
2025-06-03 01:02:08 +08:00
5ec1cff
d58ec6952c throne_tracker: avoid cross fs access 2025-06-03 00:03:16 +08:00
ShirkNeko
50631aade6 Manager: Refactoring of hidden messages and display of KPM settings status management 2025-06-03 00:00:39 +08:00
ShirkNeko
6df8f6f5d4 refactor: simplify handling and add app restart utility 2025-06-02 22:47:30 +08:00
米凛MiRin
4aee26b48e manager: auto restart after Display KPM Function and Hide other info (#136) 2025-06-02 22:24:17 +08:00
ShirkNeko
3bbe415c7e Merge branch 'main' of https://github.com/SukiSU-Ultra/SukiSU-Ultra 2025-06-02 21:33:55 +08:00
ShirkNeko
892fa9040f docs: add troubleshooting section for KernelSU Manager uninstallation issues 2025-06-02 21:33:48 +08:00
ShirkNeko
cadc123eab [skip ci] New Crowdin updates (#135)
* New translations strings.xml (Romanian)

* New translations strings.xml (Romanian)

* New translations strings.xml (Russian)

* New translations strings.xml (Vietnamese)
2025-06-02 21:30:13 +08:00
ShirkNeko
3a27537648 [skip ci] strings: update the description of the hidden additional information 2025-06-02 21:06:08 +08:00
ShirkNeko
6fa1a5c8b8 Optimize the logic of badge display in the bottom navigation bar
Add support for settings to hide other information

README: add notice about stuck device solution (#134)

Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
Co-authored-by: =?UTF-8?q?=E7=B1=B3=E5=87=9BMiRin?= <148533509+MiRinChan@users.noreply.github.com>

Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-06-02 20:46:49 +08:00
ShirkNeko
b772c8ece1 manager: Refactoring data refresh management
New AppData object to optimize data fetching and state management.
2025-06-02 17:49:34 +08:00
ShirkNeko
c0e839dd8e manager: Implement module count refresh
- update count data periodically and optimize the bottom bar display
2025-06-02 17:24:34 +08:00
ShirkNeko
a6ed7befdc manager: Add count icon to bottom bar
- Remove count icon from Home
- Add put back button for more settings
2025-06-02 16:43:31 +08:00
米凛MiRin
c210b00d54 manager: accessibility optimization (#131)
manager: style optimization
2025-06-02 14:47:59 +08:00
ShirkNeko
13b5290598 [skip ci]New Crowdin updates (#133)
* New translations strings.xml (Romanian)

* New translations strings.xml (French)

* New translations strings.xml (Spanish)

* New translations strings.xml (Arabic)

* New translations strings.xml (Danish)

* New translations strings.xml (German)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Italian)

* New translations strings.xml (Japanese)

* New translations strings.xml (Korean)

* New translations strings.xml (Lithuanian)

* New translations strings.xml (Dutch)

* New translations strings.xml (Polish)

* New translations strings.xml (Russian)

* New translations strings.xml (Slovenian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Persian)

* New translations strings.xml (Marathi)

* New translations strings.xml (Thai)

* New translations strings.xml (Croatian)

* New translations strings.xml (Estonian)

* New translations strings.xml (Latvian)

* New translations strings.xml (Azerbaijani)

* New translations strings.xml (Hindi)

* New translations strings.xml (Malay)

* New translations strings.xml (Filipino)

* New translations strings.xml (Bosnian)

* New translations strings.xml (Kannada)

* New translations strings.xml (Japanese)

* New translations strings.xml (Chinese Simplified)
2025-06-02 14:34:41 +08:00
ShirkNeko
b99516da69 [skip ci]: New Crowdin updates (#130)
* Update source file strings.xml

* New translations strings.xml (Romanian)

* New translations strings.xml (Danish)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Italian)

* New translations strings.xml (Japanese)

* New translations strings.xml (Korean)

* New translations strings.xml (Lithuanian)

* New translations strings.xml (Dutch)

* New translations strings.xml (Polish)

* New translations strings.xml (Russian)

* New translations strings.xml (Slovenian)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Persian)

* New translations strings.xml (Marathi)

* New translations strings.xml (Thai)

* New translations strings.xml (Croatian)

* New translations strings.xml (Estonian)

* New translations strings.xml (Latvian)

* New translations strings.xml (Azerbaijani)

* New translations strings.xml (Hindi)

* New translations strings.xml (Malay)

* New translations strings.xml (Filipino)

* New translations strings.xml (Chinese Traditional, Hong Kong)

* New translations strings.xml (Bosnian)

* New translations strings.xml (Kannada)
2025-06-02 14:03:10 +08:00
lshwjgpt25
fe8b5f2135 [skip ci]: Align superuser app spacing with module spacing (#132) 2025-06-02 13:31:41 +08:00
ShirkNeko
04e1b9bf77 manager: Update back navigation logic in FlashScreen for module flashing 2025-06-02 04:10:41 +08:00
ShirkNeko
b8aaf918fe Merge branch 'main' of https://github.com/SukiSU-Ultra/SukiSU-Ultra 2025-06-02 02:11:40 +08:00
ShirkNeko
54925188e8 Optimize interface element spacing and styles 2025-06-02 02:09:46 +08:00
yycgit1
3443e48ef1 manager: Add alternate app icon toggle (#129)
Signed-off-by: WenHao2130 <wenhao2130@outlook.com>
Co-authored-by: MiRinChan <148533509+MiRinChan@users.noreply.github.com>
2025-06-01 22:43:08 +08:00
ShirkNeko
53b3e84890 Optimize button styles in SuperUser 2025-06-01 22:36:23 +08:00
ShirkNeko
a5b85bfdad manager: Update theme color display in MoreSettings screen and adjust title style 2025-06-01 21:56:56 +08:00
ShirkNeko
2817583e3c Optimize icon handling for settings cards
Allow icons to be optional and remove redundant group title displays
2025-06-01 21:24:21 +08:00
ShirkNeko
8a6116b4ec manager: Update surface colors to use cardAlpha for improved theme consistency 2025-06-01 20:58:28 +08:00
cvnertnc
6a4270787a [skip ci]Manager: update values-tr/strings.xml (#126) 2025-06-01 20:29:03 +08:00
ShirkNeko
5457a4772b manager: Refactor card elevation handling and improve theme support 2025-06-01 20:17:22 +08:00
ShirkNeko
ee4c3bb03b manager: Optimize color schemes for themes and module screens
- Remove unnecessary background color settings
2025-06-01 14:04:10 +08:00
ShirkNeko
dd1d17d2cf Optimize the display logic of reboot drop down menu items 2025-06-01 02:27:55 +08:00
WenHao2130
3c353e8f88 manager: Modify the display logic of safe_mode (#125)
Signed-off-by: WenHao2130 <wenhao2130@outlook.com>
2025-06-01 01:30:16 +08:00
ShirkNeko
d743073309 docs: Add instructions for manually integrating susfs 2025-06-01 00:20:38 +08:00
ShirkNeko
a636911612 [skip ci]: New Crowdin updates (#123)
* New translations strings.xml (Russian)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Chinese Traditional, Hong Kong)
2025-06-01 00:16:11 +08:00
ShirkNeko
7a62f91752 manager: Using SwitchItem instead of ListItem 2025-06-01 00:07:17 +08:00
米凛MiRin
b551a54c8f manager: convert bitmap image to vector by hand. document: add copyright infomation. (#121) 2025-05-31 23:30:37 +08:00
ShirkNeko
26d86aa2fe manager: Optimize Home data refresh logic 2025-05-31 23:29:34 +08:00
ShirkNeko
6ee9246650 Fixes the problem of not refreshing automatically 2025-05-31 20:59:47 +08:00
ShirkNeko
1cd96fbdbf Optimize data preloading 2025-05-31 20:40:55 +08:00
ShirkNeko
a030a026b1 Manager: optimizing Home's data caching logic 2025-05-31 20:26:23 +08:00
ShirkNeko
8bf9cd0bee manager: Add initialization to optimize loading of SuperUser and Home data 2025-05-31 19:17:43 +08:00
ShirkNeko
13b1aad4b8 manager: Optimizing Home Performance
- Reorganize Home structure using MVVM architecture pattern to separate UI and data logic
2025-05-31 17:39:24 +08:00
ShirkNeko
916d956ce2 [skip ci]: New Crowdin updates (#120)
* Update source file strings.xml

* New translations strings.xml (Chinese Traditional, Hong Kong)
2025-05-31 13:28:54 +08:00
ShirkNeko
87a7650d26 New Crowdin updates (#119)
* Update source file strings.xml

* New translations strings.xml (Romanian)

* New translations strings.xml (French)

* New translations strings.xml (Spanish)

* New translations strings.xml (Arabic)

* New translations strings.xml (Danish)

* New translations strings.xml (German)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Italian)

* New translations strings.xml (Japanese)

* New translations strings.xml (Korean)

* New translations strings.xml (Lithuanian)

* New translations strings.xml (Dutch)

* New translations strings.xml (Polish)

* New translations strings.xml (Russian)

* New translations strings.xml (Slovenian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Persian)

* New translations strings.xml (Marathi)

* New translations strings.xml (Thai)

* New translations strings.xml (Croatian)

* New translations strings.xml (Estonian)

* New translations strings.xml (Latvian)

* New translations strings.xml (Azerbaijani)

* New translations strings.xml (Hindi)

* New translations strings.xml (Malay)

* New translations strings.xml (Filipino)

* New translations strings.xml (Chinese Traditional, Hong Kong)

* New translations strings.xml (Bosnian)

* New translations strings.xml (Kannada)

* Update source file strings.xml
2025-05-31 13:19:14 +08:00
ShirkNeko
3484e187da manager: Refactoring the settings interface
- Merge Web Debugging and Web X Eruda switches
2025-05-31 12:49:58 +08:00
ShirkNeko
0835f330e2 manager: Modifying the WebUI Engine Global Options 2025-05-31 04:41:16 +08:00
ShirkNeko
8064472477 manager: better handle webui engine select
- Optimize the flashback problem caused by null pointer

Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
Co-authored-by: Der_Googler <54764558+DerGoogler@users.noreply.github.com>
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-05-31 03:03:22 +08:00
ShirkNeko
2281012e33 manager: Fallback allows developers to override user preferences for the selected WebUI engine
- Because the WebUI can cause some problems, the automatic fetching of the
2025-05-31 02:14:25 +08:00
ShirkNeko
83eaeab1ba New Crowdin updates (#115)
* New translations strings.xml (Romanian)

* New translations strings.xml (French)

* New translations strings.xml (Spanish)

* New translations strings.xml (Arabic)

* New translations strings.xml (Danish)

* New translations strings.xml (German)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Italian)

* New translations strings.xml (Japanese)

* New translations strings.xml (Korean)

* New translations strings.xml (Lithuanian)

* New translations strings.xml (Dutch)

* New translations strings.xml (Polish)

* New translations strings.xml (Russian)

* New translations strings.xml (Slovenian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Persian)

* New translations strings.xml (Marathi)

* New translations strings.xml (Thai)

* New translations strings.xml (Croatian)

* New translations strings.xml (Estonian)

* New translations strings.xml (Latvian)

* New translations strings.xml (Azerbaijani)

* New translations strings.xml (Hindi)

* New translations strings.xml (Malay)

* New translations strings.xml (Filipino)

* New translations strings.xml (Chinese Traditional, Hong Kong)

* New translations strings.xml (Bosnian)

* New translations strings.xml (Kannada)

* New translations strings.xml (Russian)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Chinese Traditional, Hong Kong)
2025-05-30 20:17:37 +08:00
ShirkNeko
6405764df3 Adjust settings and optimize theme styles 2025-05-30 20:00:33 +08:00
ShirkNeko
253276a27b Remove border styles from labels 2025-05-29 20:25:17 +08:00
ShirkNeko
855a71ac56 Adjust the Dark Mode Card Transparency setting to the default value of 1 2025-05-29 18:48:43 +08:00
ShirkNeko
96dc53977f manager: Refactoring kernel flash features and styles 2025-05-29 18:25:45 +08:00
ShirkNeko
31111e68eb [skip ci]: New translations strings.xml (Russian) (#113) 2025-05-29 15:21:14 +08:00
ShirkNeko
ac0de29872 Remove cards from Home 2025-05-29 15:00:05 +08:00
ShirkNeko
9e2b722491 manager: Adding Vacancies to WeiUI Configuration and Implementing Asynchronous Loading
- Upgrade agp version to 8.10.1
2025-05-29 14:44:24 +08:00
ShirkNeko
59627e6fe2 manager: update Crowdin workflow to include resource paths 2025-05-28 13:53:58 +08:00
ShirkNeko
cd0b5fb378 New Crowdin updates (#111)
* New translations strings.xml (Romanian)

* New translations strings.xml (French)

* New translations strings.xml (Spanish)

* New translations strings.xml (Arabic)

* New translations strings.xml (German)

* New translations strings.xml (Italian)

* New translations strings.xml (Japanese)

* New translations strings.xml (Russian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Persian)

* New translations strings.xml (Azerbaijani)

* New translations strings.xml (Hindi)

* New translations strings.xml (Chinese Traditional, Hong Kong)

* New translations strings.xml (Kannada)

* New translations strings.xml (Spanish)

* New translations strings.xml (Danish)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Korean)

* New translations strings.xml (Lithuanian)

* New translations strings.xml (Dutch)

* New translations strings.xml (Polish)

* New translations strings.xml (Slovenian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Marathi)

* New translations strings.xml (Thai)

* New translations strings.xml (Croatian)

* New translations strings.xml (Estonian)

* New translations strings.xml (Latvian)

* New translations strings.xml (Malay)

* New translations strings.xml (Filipino)

* New translations strings.xml (Bosnian)
2025-05-28 13:47:41 +08:00
ShirkNeko
48a3c64c7c New translations strings.xml (Vietnamese) (#109) 2025-05-28 12:22:58 +08:00
米凛MiRin
62da804518 manager: ksuEngine as default WebUI engine (#110) 2025-05-28 12:22:38 +08:00
ShirkNeko
439b99cc4a manager: refactor label item in superuser list
* manager: Improvements

* 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

Co-authored-by: Der_Googler <54764558+DerGoogler@users.noreply.github.com>
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-05-27 16:57:54 +08:00
ShirkNeko
64f0efc2c0 manager: use myUserId as fallback
Co-authored-by: Der_Googler <54764558+DerGoogler@users.noreply.github.com>
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-05-27 16:33:58 +08:00
ShirkNeko
f196bf5b76 manager: Updated Kpm and version info icons 2025-05-27 16:02:36 +08:00
ShirkNeko
790968be6a manager: Change icon 2025-05-27 15:47:24 +08:00
ShirkNeko
83f0f9537f New Crowdin updates (#107)
* New translations strings.xml (French)

* New translations strings.xml (Arabic)

* New translations strings.xml (German)

* New translations strings.xml (Russian)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Chinese Traditional, Hong Kong)

* New translations strings.xml (Thai)

* New translations strings.xml (Romanian)

* New translations strings.xml (Spanish)

* New translations strings.xml (Danish)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Italian)

* New translations strings.xml (Japanese)

* New translations strings.xml (Korean)

* New translations strings.xml (Lithuanian)

* New translations strings.xml (Dutch)

* New translations strings.xml (Polish)

* New translations strings.xml (Slovenian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Persian)

* New translations strings.xml (Marathi)

* New translations strings.xml (Croatian)

* New translations strings.xml (Estonian)

* New translations strings.xml (Latvian)

* New translations strings.xml (Azerbaijani)

* New translations strings.xml (Hindi)

* New translations strings.xml (Malay)

* New translations strings.xml (Filipino)

* New translations strings.xml (Bosnian)

* New translations strings.xml (Kannada)
2025-05-27 01:33:53 +08:00
ShirkNeko
68ebfec918 manager: Optimize the logic of displaying the Machine Architecture tab of the home status card
Fix the problem of displaying text in safe mode
2025-05-27 01:07:24 +08:00
ShirkNeko
8be4dea081 manager: Update interface card color to surfaceContainerLow to optimize visual effect. 2025-05-24 22:00:52 +08:00
Rifat Azad
cfdbba45c3 manager: make action execution screen have the same behavior as Magisk
based on pr https://github.com/tiann/KernelSU/pull/2321

* Magisk's behavior: Hide Bottom Navbar, Show close button if failed or success
and removed automatic exit when module execution success.
2025-05-24 17:03:20 +08:00
WenHao2130
d408c9f4bf manager: Modify Module page icon (#104)
Signed-off-by: WenHao2130 <wenhao2130@outlook.com>
2025-05-24 15:33:50 +08:00
ShirkNeko
8f4c58c4c3 [skip ci]: kernel: simplify KPM enabled check in ksu_handle_prctl 2025-05-24 15:25:54 +08:00
rsuntk
7e88e9648f kernel: guard nuke_ext4_sysfs
Rather than using depends on / select,
i just prefer this way, although, yes, it is
an ifdef hell.

Signed-off-by: rsuntk <rsuntk@yukiprjkt.my.id>
2025-05-24 15:05:44 +08:00
ShirkNeko
4516d136a4 Merge branch 'main' of https://github.com/SukiSU-Ultra/SukiSU-Ultra 2025-05-24 14:11:35 +08:00
ShirkNeko
1b85dfbed1 manager: Modify the text padding in the ElevatedCard
- Adding Formatting Characters

Signed-off-by: WenHao2130 <wenhao2130@outlook.com>
2025-05-24 14:11:14 +08:00
ShirkNeko
807ffb419a [skip ci] : Update source file strings.xml (#101) 2025-05-24 13:55:43 +08:00
ShirkNeko
e826f43aed Optimize KPM checking logic
- Simplify code and ensure KPM information is displayed under supported versions
2025-05-24 04:38:54 +08:00
ShirkNeko
d619f5fafc Refactoring KPM support to check KPM status using CMD_ENABLE_KPM 2025-05-24 03:28:28 +08:00
ShirkNeko
b3e2f9b7ff manager: Updated colors and styles
- Adapted from reference style

Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
Co-authored-by: Der_Googler <54764558+DerGoogler@users.noreply.github.com>
Co-authored-by: rifsxd <rifat.44.azad.rifs@gmail.com>
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-05-24 00:47:15 +08:00
ShirkNeko
99a39c6f52 New Crowdin updates (#100)
* Update source file strings.xml

* New translations strings.xml (Romanian)

* New translations strings.xml (French)

* New translations strings.xml (Spanish)

* New translations strings.xml (Arabic)

* New translations strings.xml (Danish)

* New translations strings.xml (German)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Italian)

* New translations strings.xml (Japanese)

* New translations strings.xml (Korean)

* New translations strings.xml (Lithuanian)

* New translations strings.xml (Dutch)

* New translations strings.xml (Polish)

* New translations strings.xml (Russian)

* New translations strings.xml (Slovenian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Persian)

* New translations strings.xml (Marathi)

* New translations strings.xml (Thai)

* New translations strings.xml (Croatian)

* New translations strings.xml (Estonian)

* New translations strings.xml (Latvian)

* New translations strings.xml (Azerbaijani)

* New translations strings.xml (Hindi)

* New translations strings.xml (Malay)

* New translations strings.xml (Filipino)

* New translations strings.xml (Chinese Traditional, Hong Kong)

* New translations strings.xml (Bosnian)

* New translations strings.xml (Kannada)

* Update source file strings.xml
2025-05-23 17:06:24 +08:00
ShirkNeko
22991e8740 Merge branch 'main' of https://github.com/SukiSU-Ultra/SukiSU-Ultra 2025-05-23 16:46:31 +08:00
ShirkNeko
7646ecb6f7 manager: Update theme color scheme, fix style
* Remove redundant strings
* Bump MMRL

Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
Co-authored-by: liaowenxuan <jby13147208050@163.com>
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-05-23 16:45:17 +08:00
ShirkNeko
204db674bb [skip ci]: New Crowdin updates (#99)
* New translations strings.xml (Spanish)

* New translations strings.xml (Portuguese, Brazilian)
2025-05-23 16:38:20 +08:00
ShirkNeko
99fe6623de manager: possible fix
- 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

Signed-off-by: Der_Googler <54764558+DerGoogler@users.noreply.github.com>
2025-05-23 16:31:13 +08:00
ShirkNeko
f1f78d2485 Add force refresh to get module list after installing a module 2025-05-22 18:12:13 +08:00
ShirkNeko
b2ae20b796 manager: Enhance and simplify module name capture
- Add the use of incoming module name to load the corresponding installation list when the file cannot be retrieved, using utf-8 encoding and formatting characters by default.
2025-05-20 22:23:45 +08:00
ShirkNeko
83bd4e9642 New translations strings.xml (French) (#95) 2025-05-20 19:34:08 +08:00
ShirkNeko
767349798a docs: Added a link to submit translations to the Crowdin project page in the documentation 2025-05-20 19:31:44 +08:00
Jiu
ae38f4709b [skip ci]: 删掉本地配置sdk (#94)
* feat: Update string resources for clarity and consistency; simplify build manager workflow

* 使用gki-kernel-local.yml

* build-lkm-local.yml

* 修改为谷歌源

* 修改为清华源

* 修改max-size为16G

* Updating Vietnamese strings

* kernel: kpm: add compatibility for kernel 4.14 and lower (#76)

`thread_pid` is not defined in kernel 4.14 and lower, leading to compilation issue.
To fix this, use `pids[PIDTYPE_PID].pid` for kernel versions 4.14 and lower.
Else use `thread_pid` for kernel versions 4.19 and higher.

Reference: 107717913b/tracee/tracee.bpf.c (L354)

* 1

* 1

* 1

---------

Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
Co-authored-by: KernelSUBot <bot@kernelsu.org>
Co-authored-by: sidex15 <24408329+sidex15@users.noreply.github.com>
Co-authored-by: build <123456@cnm.com>
2025-05-20 19:26:49 +08:00
473 changed files with 50541 additions and 33426 deletions

5
.github/FUNDING.yml vendored
View File

@@ -1,5 +1,4 @@
# These are supported funding model platforms
github: tiann github: tiann
patreon: weishu patreon: weishu
custom: https://vxposed.com/donate.html open_collective: sukisu-ultra

View File

@@ -1,5 +0,0 @@
blank_issues_enabled: false
contact_links:
- name: Feature Request
url: https://github.com/tiann/KernelSU/issues/1705
about: "We do not accept external Feature Requests, see this link for more details."

View File

@@ -0,0 +1,39 @@
name: Feature Request
description: "Suggest an idea for this project"
title: "[Feature]"
labels: "feature"
body:
- type: markdown
id: feature-info
attributes:
value: "## Feature Infomation"
- type: textarea
id: feature-main
validations:
required: true
attributes:
label: "Is your feature request related to a problem? Please describe."
description: "A clear and concise description of what the problem is."
placeholder: "I'm always frustrated when [...]"
- type: textarea
id: feature-solution
validations:
required: true
attributes:
label: "Describe the solution you'd like."
description: "A clear and concise description of what you want to happen."
- type: textarea
id: feature-describe
validations:
required: true
attributes:
label: "Describe alternatives you've considered."
description: "A clear and concise description of any alternative solutions or features you've considered."
- type: textarea
id: feature-extra
validations:
required: false
attributes:
label: "Additional context"
description: "Add any other context or screenshots about the feature request here."

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-22.04
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
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/.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
env:
PATCH_PATH: ${{ inputs.patch_path }}
IS_DEBUG_KERNEL: ${{ inputs.debug }}
run: |
cd $GITHUB_WORKSPACE/android-kernel
echo "[+] KernelSU setup"
GKI_ROOT=$(pwd)
echo "[+] GKI_ROOT: $GKI_ROOT"
echo "[+] Copy KernelSU driver to $GKI_ROOT/common/drivers"
ln -sf $GITHUB_WORKSPACE/KernelSU/kernel $GKI_ROOT/common/drivers/kernelsu
echo "[+] Add KernelSU 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 patches"
cd $GKI_ROOT/common/ && git apply $GITHUB_WORKSPACE/KernelSU/.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/kernel/Makefile
fi
repo status
echo "[+] KernelSU setup done."
cd $GITHUB_WORKSPACE/KernelSU
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 "KernelSUBot"
cd common/ && git add -A && git commit -a -m "Add KernelSU"
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 }}"

20
.github/workflows/build-gki-image.yml vendored Normal file
View File

@@ -0,0 +1,20 @@
name: Build Android GKI Image
on:
workflow_call:
jobs:
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
build-a16-kernel:
uses: ./.github/workflows/build-kernel-a16.yml
secrets: inherit

111
.github/workflows/build-kernel-a12.yml vendored Normal file
View File

@@ -0,0 +1,111 @@
name: Build Kernel - Android 12
on:
# push:
# branches: ["main", "ci", "checkci"]
# paths:
# - ".github/workflows/deps/gki/build-kernel-a12.yml"
# - ".github/workflows/deps/gki/gki-kernel.yml"
# - ".github/scripts/build_a12.sh"
# - "kernel/**"
workflow_call:
inputs:
debug:
description: 'Build debug kernel'
required: false
type: boolean
default: false
workflow_dispatch:
inputs:
debug:
description: 'Build debug kernel'
required: false
type: boolean
default: false
jobs:
build-kernel:
if: github.event_name != 'pull_request' && github.ref != 'refs/heads/checkci'
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
- sub_level: 233
os_patch_level: 2025-02
- sub_level: 236
os_patch_level: 2025-05
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"
debug: ${{ inputs.debug || false }}
upload-artifacts:
needs: build-kernel
runs-on: ubuntu-latest
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' || github.ref == 'refs/heads/ci' }}
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
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: 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
export VERSION=$(($(git rev-list --count HEAD) + 10200))
echo "VERSION: $VERSION"
cd -
bash $GITHUB_WORKSPACE/KernelSU/.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

146
.github/workflows/build-kernel-a13.yml vendored Normal file
View File

@@ -0,0 +1,146 @@
name: Build Kernel - Android 13
on:
# push:
# branches: ["main", "ci", "checkci"]
# paths:
# - ".github/workflows/deps/gki/build-kernel-a13.yml"
# - ".github/workflows/deps/gki/gki-kernel.yml"
# - ".github/scripts/build_a13.sh"
# - "kernel/**"
workflow_call:
inputs:
debug:
description: 'Build debug kernel'
required: false
type: boolean
default: false
workflow_dispatch:
inputs:
debug:
description: 'Build debug kernel'
required: false
type: boolean
default: false
jobs:
build-kernel:
if: github.event_name != 'pull_request' && github.ref != 'refs/heads/checkci'
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.10"
sub_level: 228
os_patch_level: 2025-01
- version: "5.10"
sub_level: 234
os_patch_level: 2025-03
- 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
- version: "5.15"
sub_level: 178
os_patch_level: 2024-11
- version: "5.15"
sub_level: 170
os_patch_level: 2025-01
- version: "5.15"
sub_level: 178
os_patch_level: 2025-03
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 }}
debug: ${{ inputs.debug || false }}
upload-artifacts:
needs: build-kernel
runs-on: ubuntu-latest
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' || github.ref == 'refs/heads/ci' }}
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
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: 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
export VERSION=$(($(git rev-list --count HEAD) + 10200))
echo "VERSION: $VERSION"
cd -
bash $GITHUB_WORKSPACE/KernelSU/.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

158
.github/workflows/build-kernel-a14.yml vendored Normal file
View File

@@ -0,0 +1,158 @@
name: Build Kernel - Android 14
on:
# push:
# branches: ["main", "ci", "checkci"]
# paths:
# - ".github/workflows/deps/gki/build-kernel-a14.yml"
# - ".github/workflows/deps/gki/gki-kernel.yml"
# - ".github/scripts/build_a13.sh"
# - "kernel/**"
workflow_call:
inputs:
debug:
description: 'Build debug kernel'
required: false
type: boolean
default: false
workflow_dispatch:
inputs:
debug:
description: 'Build debug kernel'
required: false
type: boolean
default: false
jobs:
build-kernel:
if: github.event_name != 'pull_request' && github.ref != 'refs/heads/checkci'
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: "5.15"
sub_level: 170
os_patch_level: 2025-01
- version: "5.15"
sub_level: 178
os_patch_level: 2025-03
- 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
- version: "6.1"
sub_level: 118
os_patch_level: 2025-01
- version: "6.1"
sub_level: 128
os_patch_level: 2025-03
- version: "6.1"
sub_level: 134
os_patch_level: 2025-05
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 }}
debug: ${{ inputs.debug || false }}
upload-artifacts:
needs: build-kernel
runs-on: ubuntu-latest
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' || github.ref == 'refs/heads/ci' }}
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
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: 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
export VERSION=$(($(git rev-list --count HEAD) + 10200))
echo "VERSION: $VERSION"
cd -
bash $GITHUB_WORKSPACE/KernelSU/.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

131
.github/workflows/build-kernel-a15.yml vendored Normal file
View File

@@ -0,0 +1,131 @@
name: Build Kernel - Android 15
on:
# push:
# branches: ["main", "ci", "checkci"]
# paths:
# - ".github/workflows/deps/gki/build-kernel-a15.yml"
# - ".github/workflows/deps/gki/gki-kernel.yml"
# - ".github/scripts/build_a13.sh"
# - "kernel/**"
workflow_call:
inputs:
debug:
description: 'Build debug kernel'
required: false
type: boolean
default: false
workflow_dispatch:
inputs:
debug:
description: 'Build debug kernel'
required: false
type: boolean
default: false
jobs:
build-kernel:
if: github.event_name != 'pull_request' && github.ref != 'refs/heads/checkci'
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
- version: "6.6"
sub_level: 58
os_patch_level: 2025-01
- version: "6.6"
sub_level: 66
os_patch_level: 2025-02
- version: "6.6"
sub_level: 77
os_patch_level: 2025-03
- version: "6.6"
sub_level: 82
os_patch_level: 2025-04
- version: "6.6"
sub_level: 87
os_patch_level: 2025-05
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 }}
debug: ${{ inputs.debug || false }}
upload-artifacts:
needs: build-kernel
runs-on: ubuntu-latest
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' || github.ref == 'refs/heads/ci' }}
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
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: 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
export VERSION=$(($(git rev-list --count HEAD) + 10200))
echo "VERSION: $VERSION"
cd -
bash $GITHUB_WORKSPACE/KernelSU/.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

104
.github/workflows/build-kernel-a16.yml vendored Normal file
View File

@@ -0,0 +1,104 @@
name: Build Kernel - Android 16
on:
# push:
# branches: ["main", "ci", "checkci"]
# paths:
# - ".github/workflows/deps/gki/build-kernel-a16.yml"
# - ".github/workflows/deps/gki/gki-kernel.yml"
# - ".github/scripts/build_a13.sh"
# - "kernel/**"
workflow_call:
inputs:
debug:
description: 'Build debug kernel'
required: false
type: boolean
default: false
workflow_dispatch:
inputs:
debug:
description: 'Build debug kernel'
required: false
type: boolean
default: false
jobs:
build-kernel:
if: github.event_name != 'pull_request' && github.ref != 'refs/heads/checkci'
strategy:
matrix:
include:
- version: "6.12"
sub_level: 38
os_patch_level: 2025-08
uses: ./.github/workflows/gki-kernel.yml
secrets: inherit
with:
version: android16-${{ matrix.version }}
version_name: android16-${{ matrix.version }}.${{ matrix.sub_level }}
tag: android16-${{ matrix.version }}-${{ matrix.os_patch_level }}
os_patch_level: ${{ matrix.os_patch_level }}
patch_path: ${{ matrix.version }}
debug: ${{ inputs.debug || false }}
upload-artifacts:
needs: build-kernel
runs-on: ubuntu-latest
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' || github.ref == 'refs/heads/ci' }}
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@v6
- uses: actions/checkout@v5
with:
path: KernelSU
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: 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
export VERSION=$(($(git rev-list --count HEAD) + 10200))
echo "VERSION: $VERSION"
cd -
bash $GITHUB_WORKSPACE/KernelSU/.github/scripts/build_a13.sh
- name: Display structure of boot files
run: ls -R
- name: Upload images artifact
uses: actions/upload-artifact@v5
with:
name: boot-images-android16
path: Image-android16*/*.img.gz

View File

@@ -1,74 +0,0 @@
name: Build LKM for KernelSU Local
on:
workflow_call:
inputs:
upload:
required: true
type: boolean
default: true
description: "Whether to upload to branch"
secrets:
# username:github_pat
TOKEN:
required: true
workflow_dispatch:
inputs:
upload:
required: true
type: boolean
default: true
description: "Whether to upload to branch"
jobs:
build-lkm:
strategy:
matrix:
include:
- version: "android12-5.10"
sub_level: 236
os_patch_level: 2025-05
- version: "android13-5.10"
sub_level: 234
os_patch_level: 2025-03
- version: "android13-5.15"
sub_level: 178
os_patch_level: 2025-03
- version: "android14-5.15"
sub_level: 178
os_patch_level: 2025-03
- version: "android14-6.1"
sub_level: 134
os_patch_level: 2025-05
- version: "android15-6.6"
sub_level: 87
os_patch_level: 2025-05
# uses: ./.github/workflows/gki-kernel-mock.yml when debugging
uses: ./.github/workflows/gki-kernel-local.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
push-to-branch:
needs: [build-lkm]
runs-on: self-hosted
if: ${{ inputs.upload }}
steps:
- name: Download all workflow run artifacts
uses: actions/download-artifact@v4
with:
path: bin/
merge-multiple: true
- name: Push to branch LKM
run: |
cd bin
git config --global init.defaultBranch lkm
git init
git remote add origin https://${{ secrets.TOKEN }}@github.com/${{ github.repository }}
git config --local user.name "github-actions[bot]"
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
find . -type f
git add .
git commit -m "Upload LKM from ${{ github.sha }}" -m "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
git push --force --set-upstream origin lkm

View File

@@ -1,74 +1,21 @@
name: Build LKM for KernelSU name: Build LKM for KernelSU
on: on:
workflow_call: workflow_call:
inputs:
upload:
required: true
type: boolean
default: true
description: "Whether to upload to branch"
secrets:
# username:github_pat
TOKEN:
required: true
workflow_dispatch: workflow_dispatch:
inputs:
upload:
required: true
type: boolean
default: true
description: "Whether to upload to branch"
jobs: jobs:
build-lkm: build-lkm:
strategy: strategy:
fail-fast: false
matrix: matrix:
include: kmi:
- version: "android12-5.10" - android12-5.10
sub_level: 236 - android13-5.10
os_patch_level: 2025-05 - android13-5.15
- version: "android13-5.10" - android14-5.15
sub_level: 234 - android14-6.1
os_patch_level: 2025-03 - android15-6.6
- version: "android13-5.15" - android16-6.12
sub_level: 178 uses: ./.github/workflows/ddk-lkm.yml
os_patch_level: 2025-03
- version: "android14-5.15"
sub_level: 178
os_patch_level: 2025-03
- version: "android14-6.1"
sub_level: 134
os_patch_level: 2025-05
- version: "android15-6.6"
sub_level: 87
os_patch_level: 2025-05
# uses: ./.github/workflows/gki-kernel-mock.yml when debugging
uses: ./.github/workflows/gki-kernel.yml
with: with:
version: ${{ matrix.version }} kmi: ${{ matrix.kmi }}
version_name: ${{ matrix.version }}.${{ matrix.sub_level }} ddk_release: '20251104'
tag: ${{ matrix.version }}-${{ matrix.os_patch_level }}
os_patch_level: ${{ matrix.os_patch_level }}
build_lkm: true
push-to-branch:
needs: [build-lkm]
runs-on: ubuntu-latest
if: ${{ inputs.upload }}
steps:
- name: Download all workflow run artifacts
uses: actions/download-artifact@v4
with:
path: bin/
merge-multiple: true
- name: Push to branch LKM
run: |
cd bin
git config --global init.defaultBranch lkm
git init
git remote add origin https://${{ secrets.TOKEN }}@github.com/${{ github.repository }}
git config --local user.name "github-actions[bot]"
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
find . -type f
git add .
git commit -m "Upload LKM from ${{ github.sha }}" -m "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
git push --force --set-upstream origin lkm

View File

@@ -1,261 +0,0 @@
name: Build Manager Manual
on:
workflow_dispatch:
inputs:
build_lkm:
required: true
type: choice
default: "auto"
options:
- "true"
- "false"
- "auto"
description: "Whether to build lkm"
upload_lkm:
required: true
type: boolean
default: true
description: "Whether to upload lkm"
jobs:
check-build-lkm:
runs-on: self-hosted
outputs:
build_lkm: ${{ steps.check-build.outputs.build_lkm }}
upload_lkm: ${{ steps.check-build.outputs.upload_lkm }}
steps:
- name: check build
id: check-build
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ] && [ "${{ inputs.build_lkm }}" != "auto" ]; then
kernel_changed="${{ inputs.build_lkm }}"
else
kernel_changed=true
mkdir tmp
cd tmp
git config --global init.defaultBranch bot
git config --global user.name 'Bot'
git config --global user.email 'bot@github.shirkneko.io'
git init .
git remote add origin https://github.com/${{ github.repository }}
CURRENT_COMMIT="${{ github.event.head_commit.id }}"
git fetch origin $CURRENT_COMMIT --depth=1
git fetch origin lkm --depth=1
LKM_COMMIT="$(git log --format=%B -n 1 origin/lkm | head -n 1)"
LKM_COMMIT="${LKM_COMMIT#Upload LKM from }"
LKM_COMMIT=$(echo "$LKM_COMMIT" | tr -d '[:space:]')
echo "LKM_COMMIT=$LKM_COMMIT"
git fetch origin "$LKM_COMMIT" --depth=1
git diff --quiet "$LKM_COMMIT" "$CURRENT_COMMIT" -- kernel :!kernel/setup.sh .github/workflows/build-lkm-local.yml .github/workflows/build-kernel-*.yml && kernel_changed=false
cd ..
rm -rf tmp
fi
if [ "${{ github.event_name }}" == "push" ] && [ "${{ github.ref }}" == 'refs/heads/main' ]; then
need_upload=true
elif [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
need_upload="${{ inputs.upload_lkm }}"
else
need_upload=false
fi
echo "kernel changed: $kernel_changed"
echo "need upload: $need_upload"
echo "build_lkm=$kernel_changed" >> "$GITHUB_OUTPUT"
echo "upload_lkm=$need_upload" >> "$GITHUB_OUTPUT"
build-lkm:
needs: check-build-lkm
uses: ./.github/workflows/build-lkm-local.yml
if: ${{ needs.check-build-lkm.outputs.build_lkm == 'true' }}
with:
upload: ${{ needs.check-build-lkm.outputs.upload_lkm == 'true' }}
secrets: inherit
build-susfs:
if: ${{ always() }}
needs: [ check-build-lkm, build-lkm ]
strategy:
matrix:
include:
- target: aarch64-linux-android
os: ubuntu-latest
uses: ./.github/workflows/susfs.yml
with:
target: ${{ matrix.target }}
os: ${{ matrix.os }}
build-kpmmgr:
if: ${{ always() }}
needs: [ check-build-lkm, build-lkm ]
strategy:
matrix:
include:
- target: aarch64-linux-android
os: ubuntu-latest
uses: ./.github/workflows/kpmmgr.yml
with:
target: ${{ matrix.target }}
os: ${{ matrix.os }}
build-ksud:
if: ${{ always() }}
needs: [ check-build-lkm, build-lkm ]
strategy:
matrix:
include:
- target: aarch64-linux-android
os: ubuntu-latest
- target: x86_64-linux-android
os: ubuntu-latest
- target: armv7-linux-androideabi
os: ubuntu-latest
uses: ./.github/workflows/ksud.yml
with:
target: ${{ matrix.target }}
os: ${{ matrix.os }}
pack_lkm: true
pull_lkm: ${{ needs.check-build-lkm.outputs.build_lkm != 'true' }}
build-manager:
if: ${{ always() }}
needs: build-ksud
runs-on: self-hosted
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
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref == 'refs/heads/susfs' || github.ref_type == 'tag' }}
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 susfs
uses: actions/download-artifact@v4
with:
name: susfs-aarch64-linux-android
path: .
- name: Download arm64 kpmmgr
uses: actions/download-artifact@v4
with:
name: kpmmgr-aarch64-linux-android
path: .
- name: Download arm64 ksud
uses: actions/download-artifact@v4
with:
name: ksud-aarch64-linux-android
path: .
- name: Download x86_64 ksud
uses: actions/download-artifact@v4
with:
name: ksud-x86_64-linux-android
path: .
- name: Download arm ksud
uses: actions/download-artifact@v4
with:
name: ksud-armv7-linux-androideabi
path: .
- name: Copy ksud to app jniLibs
run: |
mkdir -p app/src/main/jniLibs/arm64-v8a
mkdir -p app/src/main/jniLibs/x86_64
mkdir -p app/src/main/jniLibs/armeabi-v7a
cp -f ../aarch64-linux-android/release/zakozako ../manager/app/src/main/jniLibs/arm64-v8a/libzakozako.so
cp -f ../x86_64-linux-android/release/zakozako ../manager/app/src/main/jniLibs/x86_64/libzakozako.so
cp -f ../armv7-linux-androideabi/release/zakozako ../manager/app/src/main/jniLibs/armeabi-v7a/libzakozako.so
- name: Copy kpmmgr to app jniLibs
run: |
mkdir -p app/src/main/jniLibs/arm64-v8a
cp -f ../arm64-v8a/kpmmgr ../manager/app/src/main/jniLibs/arm64-v8a/libkpmmgr.so
- name: Copy susfs to app jniLibs
run: |
mkdir -p app/src/main/jniLibs/arm64-v8a
cp -f ../arm64-v8a/zakozakozako ../manager/app/src/main/jniLibs/arm64-v8a/libzakozakozako.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
./gradlew clean assembleRelease
- name: Upload build artifact
uses: actions/upload-artifact@v4
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' }}
with:
name: manager
path: manager/app/build/outputs/apk/release/*.apk
- name: Upload mappings
uses: actions/upload-artifact@v4
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' }}
with:
name: "mappings"
path: "manager/app/build/outputs/mapping/release/"
- name: Bot session cache
if: github.event_name != 'pull_request' && steps.need_upload.outputs.UPLOAD == 'true'
id: bot_session_cache
uses: actions/cache@v4
with:
path: scripts/ksubot.session
key: ${{ runner.os }}-bot-session
- name: Upload to telegram
if: github.event_name != 'pull_request' && steps.need_upload.outputs.UPLOAD == 'true'
env:
CHAT_ID: ${{ vars.CHAT_ID }}
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
MESSAGE_THREAD_ID: ${{ vars.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: Manager
run: |
if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then
export VERSION=$(git rev-list --count HEAD)
APK=$(find ./app/build/outputs/apk/release -name "*.apk")
python3 $GITHUB_WORKSPACE/scripts/ksubot.py $APK
fi

View File

@@ -2,116 +2,43 @@ name: Build Manager
on: on:
push: push:
branches: [ "main", "ci" ] branches: [ "main", "dev", "ci", "miuix" ]
paths: paths:
- '.github/workflows/build-manager.yml' - '.github/workflows/build-manager.yml'
- '.github/workflows/build-lkm.yml'
- 'manager/**' - 'manager/**'
- 'kernel/**' - 'kernel/**'
- 'userspace/ksud/**' - 'userspace/ksud/**'
- 'userspace/susfs/**' - 'userspace/user_scanner/**'
- 'userspace/kpmmgr/**'
pull_request: pull_request:
branches: [ "main" ] branches: [ "main", "dev", "miuix" ]
paths: paths:
- '.github/workflows/build-manager.yml'
- '.github/workflows/build-lkm.yml'
- 'manager/**' - 'manager/**'
- 'kernel/**'
- 'userspace/ksud/**'
- 'userspace/user_scanner/**'
workflow_call: workflow_call:
workflow_dispatch:
inputs:
build_lkm:
required: true
type: choice
default: "auto"
options:
- "true"
- "false"
- "auto"
description: "Whether to build lkm"
upload_lkm:
required: true
type: boolean
default: true
description: "Whether to upload lkm"
jobs:
check-build-lkm:
runs-on: ubuntu-latest
outputs:
build_lkm: ${{ steps.check-build.outputs.build_lkm }}
upload_lkm: ${{ steps.check-build.outputs.upload_lkm }}
steps:
- name: check build
id: check-build
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ] && [ "${{ inputs.build_lkm }}" != "auto" ]; then
kernel_changed="${{ inputs.build_lkm }}"
else
kernel_changed=true
mkdir tmp
cd tmp
git config --global init.defaultBranch bot
git config --global user.name 'Bot'
git config --global user.email 'bot@github.shirkneko.io'
git init .
git remote add origin https://github.com/${{ github.repository }}
CURRENT_COMMIT="${{ github.event.head_commit.id }}"
git fetch origin $CURRENT_COMMIT --depth=1
git fetch origin lkm --depth=1
LKM_COMMIT="$(git log --format=%B -n 1 origin/lkm | head -n 1)"
LKM_COMMIT="${LKM_COMMIT#Upload LKM from }"
LKM_COMMIT=$(echo "$LKM_COMMIT" | tr -d '[:space:]')
echo "LKM_COMMIT=$LKM_COMMIT"
git fetch origin "$LKM_COMMIT" --depth=1
git diff --quiet "$LKM_COMMIT" "$CURRENT_COMMIT" -- kernel :!kernel/setup.sh .github/workflows/build-lkm.yml .github/workflows/build-kernel-*.yml && kernel_changed=false
cd ..
rm -rf tmp
fi
if [ "${{ github.event_name }}" == "push" ] && [ "${{ github.ref }}" == 'refs/heads/main' ]; then
need_upload=true
elif [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
need_upload="${{ inputs.upload_lkm }}"
else
need_upload=false
fi
echo "kernel changed: $kernel_changed"
echo "need upload: $need_upload"
echo "build_lkm=$kernel_changed" >> "$GITHUB_OUTPUT"
echo "upload_lkm=$need_upload" >> "$GITHUB_OUTPUT"
jobs:
build-lkm: build-lkm:
needs: check-build-lkm
uses: ./.github/workflows/build-lkm.yml uses: ./.github/workflows/build-lkm.yml
if: ${{ needs.check-build-lkm.outputs.build_lkm == 'true' }}
with:
upload: ${{ needs.check-build-lkm.outputs.upload_lkm == 'true' }}
secrets: inherit secrets: inherit
build-susfs: build-user_scanner:
if: ${{ always() }} needs: build-lkm
needs: [ check-build-lkm, build-lkm ]
strategy: strategy:
matrix: matrix:
include: include:
- target: aarch64-linux-android - target: All-linux-android
os: ubuntu-latest os: ubuntu-latest
uses: ./.github/workflows/susfs.yml uses: ./.github/workflows/user_scanner.yml
with:
target: ${{ matrix.target }}
os: ${{ matrix.os }}
build-kpmmgr:
if: ${{ always() }}
needs: [ check-build-lkm, build-lkm ]
strategy:
matrix:
include:
- target: aarch64-linux-android
os: ubuntu-latest
uses: ./.github/workflows/kpmmgr.yml
with: with:
target: ${{ matrix.target }} target: ${{ matrix.target }}
os: ${{ matrix.os }} os: ${{ matrix.os }}
build-ksud: build-ksud:
if: ${{ always() }} needs: build-lkm
needs: [ check-build-lkm, build-lkm ]
strategy: strategy:
matrix: matrix:
include: include:
@@ -125,13 +52,13 @@ jobs:
with: with:
target: ${{ matrix.target }} target: ${{ matrix.target }}
os: ${{ matrix.os }} os: ${{ matrix.os }}
pack_lkm: true
pull_lkm: ${{ needs.check-build-lkm.outputs.build_lkm != 'true' }}
build-manager: build-manager:
if: ${{ always() }}
needs: build-ksud needs: build-ksud
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy:
matrix:
spoofed: ["true","false"]
defaults: defaults:
run: run:
working-directory: ./manager working-directory: ./manager
@@ -151,8 +78,34 @@ jobs:
echo "UPLOAD=false" >> $GITHUB_OUTPUT echo "UPLOAD=false" >> $GITHUB_OUTPUT
fi fi
- name: Determine manager variant for telegram bot
id: determine
run: |
if [ "${{ github.ref_name }}" == "miuix" ] && [ "${{ matrix.spoofed }}" == "true" ]; then
echo "SKIP=true" >> $GITHUB_OUTPUT
exit 0
fi
if [ "${{ github.ref_name }}" == "miuix" ]; then
echo "title=Manager" >> $GITHUB_OUTPUT
echo "topicid=${{ vars.MESSAGE_MIUIX_THREAD_ID }}" >> $GITHUB_OUTPUT
elif [ "${{ matrix.spoofed }}" == "true" ]; then
echo "title=Spoofed-Manager" >> $GITHUB_OUTPUT
# maybe need a new var
echo "topicid=${{ vars.MESSAGE_SPOOFED_THREAD_ID }}" >> $GITHUB_OUTPUT
else
echo "title=Manager" >> $GITHUB_OUTPUT
echo "topicid=${{ vars.MESSAGE_THREAD_ID }}" >> $GITHUB_OUTPUT
fi
- name: Run randomizer
if: ${{ matrix.spoofed == 'true' && steps.determine.outputs.SKIP != 'true' }}
run: |
chmod +x randomizer
./randomizer
- name: Write key - name: Write key
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref == 'refs/heads/susfs' || github.ref_type == 'tag' }} if: ${{ ( github.event_name != 'pull_request' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev' )) || github.ref_type == 'tag' }}
run: | run: |
if [ ! -z "${{ secrets.KEYSTORE }}" ]; then if [ ! -z "${{ secrets.KEYSTORE }}" ]; then
{ {
@@ -176,16 +129,10 @@ jobs:
- name: Setup Android SDK - name: Setup Android SDK
uses: android-actions/setup-android@v3 uses: android-actions/setup-android@v3
- name: Download arm64 susfs - name: Download all userscanner artifacts
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
name: susfs-aarch64-linux-android name: userscanner-all-linux-android
path: .
- name: Download arm64 kpmmgr
uses: actions/download-artifact@v4
with:
name: kpmmgr-aarch64-linux-android
path: . path: .
- name: Download arm64 ksud - name: Download arm64 ksud
@@ -211,62 +158,48 @@ jobs:
mkdir -p app/src/main/jniLibs/arm64-v8a mkdir -p app/src/main/jniLibs/arm64-v8a
mkdir -p app/src/main/jniLibs/x86_64 mkdir -p app/src/main/jniLibs/x86_64
mkdir -p app/src/main/jniLibs/armeabi-v7a mkdir -p app/src/main/jniLibs/armeabi-v7a
cp -f ../aarch64-linux-android/release/zakozako ../manager/app/src/main/jniLibs/arm64-v8a/libzakozako.so cp -f ../aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud.so
cp -f ../x86_64-linux-android/release/zakozako ../manager/app/src/main/jniLibs/x86_64/libzakozako.so cp -f ../x86_64-linux-android/release/ksud ../manager/app/src/main/jniLibs/x86_64/libksud.so
cp -f ../armv7-linux-androideabi/release/zakozako ../manager/app/src/main/jniLibs/armeabi-v7a/libzakozako.so cp -f ../armv7-linux-androideabi/release/ksud ../manager/app/src/main/jniLibs/armeabi-v7a/libksud.so
- name: Copy kpmmgr to app jniLibs - name: Copy user_scanner to app jniLibs
run: | run: |
mkdir -p app/src/main/jniLibs/arm64-v8a mkdir -p app/src/main/jniLibs/arm64-v8a
cp -f ../arm64-v8a/kpmmgr ../manager/app/src/main/jniLibs/arm64-v8a/libkpmmgr.so mkdir -p app/src/main/jniLibs/x86_64
mkdir -p app/src/main/jniLibs/armeabi-v7a
- name: Copy susfs to app jniLibs cp -f ../arm64-v8a/uid_scanner ../manager/app/src/main/jniLibs/arm64-v8a/libuid_scanner.so
run: | cp -f ../x86_64/uid_scanner ../manager/app/src/main/jniLibs/x86_64/libuid_scanner.so
mkdir -p app/src/main/jniLibs/arm64-v8a cp -f ../armeabi-v7a/uid_scanner ../manager/app/src/main/jniLibs/armeabi-v7a/libuid_scanner.so
cp -f ../arm64-v8a/zakozakozako ../manager/app/src/main/jniLibs/arm64-v8a/libzakozakozako.so
- name: Build with Gradle - name: Build with Gradle
run: | if: ${{ steps.determine.outputs.SKIP != 'true' }}
{ run: ./gradlew clean assembleRelease
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
./gradlew clean assembleRelease
- name: Upload build artifact - name: Upload build artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' }} if: ${{ ( github.event_name != 'pull_request' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev' )) || github.ref_type == 'tag' }}
with: with:
name: manager name: ${{ steps.determine.outputs.title }}
path: manager/app/build/outputs/apk/release/*.apk path: manager/app/build/outputs/apk/release/*.apk
- name: Upload mappings - name: Upload mappings
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' }} if: ${{ ( github.event_name != 'pull_request' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev' )) || github.ref_type == 'tag' }}
with: with:
name: "mappings" name: "${{ steps.determine.outputs.title }}-mappings"
path: "manager/app/build/outputs/mapping/release/" path: "manager/app/build/outputs/mapping/release/"
- name: Bot session cache
if: github.event_name != 'pull_request' && steps.need_upload.outputs.UPLOAD == 'true'
id: bot_session_cache
uses: actions/cache@v4
with:
path: scripts/ksubot.session
key: ${{ runner.os }}-bot-session
- name: Upload to telegram - name: Upload to telegram
if: github.event_name != 'pull_request' && steps.need_upload.outputs.UPLOAD == 'true' if: github.event_name != 'pull_request' && steps.need_upload.outputs.UPLOAD == 'true' && steps.determine.outputs.SKIP != 'true'
env: env:
CHAT_ID: ${{ vars.CHAT_ID }} CHAT_ID: ${{ vars.CHAT_ID }}
BOT_TOKEN: ${{ secrets.BOT_TOKEN }} BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
MESSAGE_THREAD_ID: ${{ vars.MESSAGE_THREAD_ID }} MESSAGE_THREAD_ID: ${{ steps.determine.outputs.topicid }}
COMMIT_MESSAGE: ${{ github.event.head_commit.message }} COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
COMMIT_URL: ${{ github.event.head_commit.url }} COMMIT_URL: ${{ github.event.head_commit.url }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
TITLE: Manager TITLE: ${{ steps.determine.outputs.title }}
BRANCH: ${{ github.ref_name }}
run: | run: |
if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then
export VERSION=$(git rev-list --count HEAD) export VERSION=$(git rev-list --count HEAD)

View File

@@ -34,4 +34,4 @@ jobs:
- name: Run clippy - name: Run clippy
run: | run: |
cross clippy --manifest-path userspace/ksud/Cargo.toml --target aarch64-linux-android --release 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 cross clippy --manifest-path userspace/ksud/Cargo.toml --target x86_64-linux-android --release

View File

@@ -3,34 +3,38 @@ name: Crowdin Action
on: on:
push: push:
branches: [ main ] branches: [ main ]
paths:
- 'manager/app/src/main/res/values/strings.xml'
- 'manager/app/src/main/res/values-*/strings.xml'
schedule:
- cron: '0 0 * * *'
workflow_dispatch:
jobs: jobs:
synchronize-with-crowdin: synchronize-with-crowdin:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: crowdin action - name: Crowdin Action
uses: crowdin/github-action@master uses: crowdin/github-action@v2
with: with:
upload_sources: true upload_sources: true
upload_translations: true upload_translations: true
download_translations: true auto_approve_imported: true
localization_branch_name: "Crowdin" download_translations: true
crowdin_branch_name: "main" skip_untranslated_files: false
create_pull_request: true skip_untranslated_strings: true
pull_request_title: 'New Crowdin Translations'
pull_request_body: 'New Crowdin translations by [Crowdin GH Action](https://github.com/crowdin/github-action)'
pull_request_base_branch_name: 'main'
skip_untranslated_files: true
env:
# A classic GitHub Personal Access Token with the 'repo' scope selected (the user should have write access to the repository).
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
# A numeric ID, found at https://crowdin.com/project/<projectName>/tools/api create_pull_request: true
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} localization_branch_name: "Crowdin"
pull_request_labels: 'enhancement, translation'
pull_request_title: 'opt: sync translation from Crowdin'
# Visit https://crowdin.com/settings#api-key to create this token config: 'crowdin.yml'
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} crowdin_branch_name: "main"
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_API_TOKEN: ${{ secrets.CROWDIN_API_TOKEN }}

53
.github/workflows/ddk-lkm.yml vendored Normal file
View File

@@ -0,0 +1,53 @@
name: Build KernelSU Kernel Module
on:
workflow_call:
inputs:
kmi:
description: 'KMI version'
required: true
type: string
ddk_release:
description: 'DDK release version'
required: false
default: '20251104'
type: string
jobs:
build-kernelsu-ko:
name: Build kernelsu.ko for ${{ inputs.kmi }}
runs-on: ubuntu-latest
container:
image: ghcr.io/ylarod/ddk:${{ inputs.kmi }}-${{ inputs.ddk_release }}
options: --privileged
steps:
- name: Checkout source code
uses: actions/checkout@v4
- name: Build kernelsu.ko
run: |
git config --global --add safe.directory /__w/SukiSU-Ultra/SukiSU-Ultra
cd kernel
echo "=== Building kernelsu.ko for KMI: ${{ inputs.kmi }} ==="
CONFIG_KSU=m CONFIG_KSU_MANUAL_SU=y make
echo "=== Build completed ==="
# Create output directory in GitHub workspace
mkdir -p /github/workspace/out
# Copy with KMI-specific naming
OUTPUT_NAME="${{ inputs.kmi }}_kernelsu.ko"
cp kernelsu.ko "/github/workspace/out/$OUTPUT_NAME"
echo "Copied to: /github/workspace/out/$OUTPUT_NAME"
ls -la "/github/workspace/out/$OUTPUT_NAME"
echo "Size: $(du -h "/github/workspace/out/$OUTPUT_NAME" | cut -f1)"
llvm-strip -d "/github/workspace/out/$OUTPUT_NAME"
echo "Size after stripping: $(du -h "/github/workspace/out/$OUTPUT_NAME" | cut -f1)"
- name: Upload kernelsu.ko artifact
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.kmi }}-lkm
path: /github/workspace/out/${{ inputs.kmi }}_kernelsu.ko

View File

@@ -64,4 +64,4 @@ jobs:
steps: steps:
- name: Deploy to GitHub Pages - name: Deploy to GitHub Pages
id: deployment id: deployment
uses: actions/deploy-pages@v4 uses: actions/deploy-pages@v4

View File

@@ -1,250 +0,0 @@
name: GKI Kernel Build Local
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: self-hosted
env:
CCACHE_COMPILERCHECK: "%compiler% -dumpmachine; %compiler% -dumpversion"
CCACHE_NOHASHDIR: "true"
CCACHE_HARDLINK: "true"
steps:
- uses: actions/checkout@v4
with:
path: KernelSU
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
export REPO_URL='https://mirrors.tuna.tsinghua.edu.cn/git/git-repo'
mkdir android-kernel && cd android-kernel
repo init --depth=1 --u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/kernel/manifest -b common-${{ inputs.tag }} --repo-rev=v2.35
REMOTE_BRANCH=$(git ls-remote https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/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
env:
PATCH_PATH: ${{ inputs.patch_path }}
IS_DEBUG_KERNEL: ${{ inputs.debug }}
run: |
cd $GITHUB_WORKSPACE/android-kernel
echo "[+] KernelSU setup"
GKI_ROOT=$(pwd)
echo "[+] GKI_ROOT: $GKI_ROOT"
echo "[+] Copy KernelSU driver to $GKI_ROOT/common/drivers"
ln -sf $GITHUB_WORKSPACE/KernelSU/kernel $GKI_ROOT/common/drivers/kernelsu
echo "[+] Add KernelSU 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/kernel/Makefile
fi
repo status
echo "[+] KernelSU 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
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 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: |
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: |
if [ -e common/BUILD.bazel ]; then
sed -i '/^[[:space:]]*"protected_exports_list"[[:space:]]*:[[:space:]]*"android\/abi_gki_protected_exports_aarch64",$/d' common/BUILD.bazel
fi
rm common/android/abi_gki_protected_exports_* || echo "No protected exports!"
git config --global user.email "bot@kernelsu.org"
git config --global user.name "KernelSUBot"
cd common/ && git add -A && git commit -a -m "Add KernelSU"
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,79 +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:
mock_build:
name: Mock build ${{ inputs.version_name }}
runs-on: ubuntu-latest
steps:
- name: Create mocking ko
run: |
echo "${{ inputs.version }}_kernelsu.ko" > ${{ inputs.version }}_kernelsu.ko
- name: Upload LKM
uses: actions/upload-artifact@v4
if: ${{ inputs.build_lkm == true }}
with:
name: ${{ inputs.version }}-lkm
path: ./*_kernelsu.ko

View File

@@ -77,10 +77,10 @@ jobs:
with: with:
root-reserve-mb: 8192 root-reserve-mb: 8192
temp-reserve-mb: 2048 temp-reserve-mb: 2048
remove-dotnet: 'true' remove-dotnet: "true"
remove-android: 'true' remove-android: "true"
remove-haskell: 'true' remove-haskell: "true"
remove-codeql: 'true' remove-codeql: "true"
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
@@ -103,7 +103,7 @@ jobs:
cd $GITHUB_WORKSPACE cd $GITHUB_WORKSPACE
sudo apt-get install repo -y sudo apt-get install repo -y
mkdir android-kernel && cd android-kernel mkdir android-kernel && cd android-kernel
repo init --depth=1 --u https://android.googlesource.com/kernel/manifest -b common-${{ inputs.tag }} --repo-rev=v2.35 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 }}) REMOTE_BRANCH=$(git ls-remote https://android.googlesource.com/kernel/common ${{ inputs.tag }})
DEFAULT_MANIFEST_PATH=.repo/manifests/default.xml DEFAULT_MANIFEST_PATH=.repo/manifests/default.xml
if grep -q deprecated <<< $REMOTE_BRANCH; then if grep -q deprecated <<< $REMOTE_BRANCH; then
@@ -195,12 +195,35 @@ jobs:
sed -i 's/needs unknown symbol/Dont abort when unknown symbol/g' build/kernel/*.sh || echo "No unknown symbol scripts found" sed -i 's/needs unknown symbol/Dont abort when unknown symbol/g' build/kernel/*.sh || echo "No unknown symbol scripts found"
fi fi
- name: Append ashmem exports if missing
if: startsWith(inputs.version, 'android16-6.12')
working-directory: android-kernel
run: |
FILE=common/drivers/staging/android/ashmem.c
if [[ -f "$FILE" ]] && ! grep -q 'is_ashmem_file' "$FILE"; then
cat >>"$FILE" <<'EOF'
bool is_ashmem_file(struct file *file) { return false; }
int ashmem_area_name(struct file *file, char *name) { return 0; }
long ashmem_area_size(struct file *file) { return 0; }
struct file *ashmem_area_vmfile(struct file *file) { return NULL; }
EXPORT_SYMBOL_GPL(is_ashmem_file);
EXPORT_SYMBOL_GPL(ashmem_area_name);
EXPORT_SYMBOL_GPL(ashmem_area_size);
EXPORT_SYMBOL_GPL(ashmem_area_vmfile);
EOF
fi
sed -i -E 's/\$\(CONFIG_ANDROID_BINDER_IPC_RUST\)/m/g' common/drivers/android/Makefile
- name: Make working directory clean to avoid dirty - name: Make working directory clean to avoid dirty
working-directory: android-kernel working-directory: android-kernel
run: | run: |
if [ -e common/BUILD.bazel ]; then # Fix bazel build error
sed -i '/^[[:space:]]*"protected_exports_list"[[:space:]]*:[[:space:]]*"android\/abi_gki_protected_exports_aarch64",$/d' common/BUILD.bazel if [ -f common/BUILD.bazel ]; then
[ -f android/abi_gki_protected_exports_aarch64 ] || sed -i '/^[[:space:]]*"protected_exports_list"[[:space:]]*:[[:space:]]*"android\/abi_gki_protected_exports_aarch64",$/d' common/BUILD.bazel
fi fi
rm common/android/abi_gki_protected_exports_* || echo "No protected exports!" rm common/android/abi_gki_protected_exports_* || echo "No protected exports!"
git config --global user.email "bot@kernelsu.org" git config --global user.email "bot@kernelsu.org"
git config --global user.name "KernelSUBot" git config --global user.name "KernelSUBot"
@@ -217,7 +240,11 @@ jobs:
if [ -e build/build.sh ]; then if [ -e build/build.sh ]; then
LTO=thin BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh CC="/usr/bin/ccache clang" LTO=thin BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh CC="/usr/bin/ccache clang"
else else
tools/bazel run --disk_cache=/home/runner/.cache/bazel --config=fast --config=stamp --lto=thin //common:kernel_aarch64_dist -- --dist_dir=dist if [ "${{ inputs.version }}" == "android16-6.12" ]; then
tools/bazel run --disk_cache=/home/runner/.cache/bazel --config=fast --config=stamp --lto=thin //common:kernel_aarch64_dist -- --destdir=dist
else
tools/bazel run --disk_cache=/home/runner/.cache/bazel --config=fast --config=stamp --lto=thin //common:kernel_aarch64_dist -- --dist_dir=dist
fi
fi fi
- name: Prepare artifacts - name: Prepare artifacts
@@ -228,7 +255,7 @@ jobs:
OUTDIR=android-kernel/dist OUTDIR=android-kernel/dist
fi fi
mkdir output mkdir output
if [ "${{ inputs.build_lkm}}" = "true" ]; then if [ "${{ inputs.build_lkm}}" = "true" ]; then
llvm-strip-15 -d $OUTDIR/kernelsu.ko llvm-strip-15 -d $OUTDIR/kernelsu.ko
mv $OUTDIR/kernelsu.ko ./output/${{ inputs.version }}_kernelsu.ko mv $OUTDIR/kernelsu.ko ./output/${{ inputs.version }}_kernelsu.ko
else else

View File

@@ -9,10 +9,6 @@ on:
required: false required: false
type: string type: string
default: ubuntu-latest default: ubuntu-latest
pull_lkm:
required: false
type: boolean
default: true
pack_lkm: pack_lkm:
required: false required: false
type: boolean type: boolean
@@ -21,6 +17,8 @@ on:
required: false required: false
type: boolean type: boolean
default: true default: true
env:
CARGO_TERM_COLOR: always
jobs: jobs:
build: build:
runs-on: ${{ inputs.os }} runs-on: ${{ inputs.os }}
@@ -29,36 +27,19 @@ jobs:
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Pull lkms from branch - name: Download artifacts
if: ${{ inputs.pack_lkm && inputs.pull_lkm }}
uses: actions/checkout@v4
with:
ref: lkm
path: lkm
- name: Download lkms from artifacts
if: ${{ inputs.pack_lkm && !inputs.pull_lkm }}
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
- name: Prepare LKM files - name: Prepare LKM fies
if: ${{ inputs.pack_lkm && inputs.pull_lkm }} if: ${{ inputs.pack_lkm }}
run: |
cp lkm/*_kernelsu.ko ./userspace/ksud/bin/aarch64/
- name: Prepare LKM files
if: ${{ inputs.pack_lkm && !inputs.pull_lkm }}
run: | run: |
cp android*-lkm/*_kernelsu.ko ./userspace/ksud/bin/aarch64/ cp android*-lkm/*_kernelsu.ko ./userspace/ksud/bin/aarch64/
- name: Setup rustup - name: Setup rustup
run: | run: |
rustup update stable rustup update stable
rustup target add x86_64-apple-darwin rustup target add x86_64-apple-darwin
rustup target add aarch64-apple-darwin rustup target add aarch64-apple-darwin
- uses: Swatinem/rust-cache@v2
with:
workspaces: userspace/ksud
cache-targets: false
- name: Install cross - name: Install cross
run: | run: |
@@ -71,4 +52,4 @@ jobs:
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: ksud-${{ inputs.target }} name: ksud-${{ inputs.target }}
path: userspace/ksud/target/**/release/zakozako* path: userspace/ksud/target/**/release/ksud*

View File

@@ -16,7 +16,7 @@ on:
jobs: jobs:
shellcheck: shellcheck:
runs-on: self-hosted runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4

View File

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

View File

@@ -1,11 +1,11 @@
name: Build kpmmgr name: Build user_scanner
on: on:
push: push:
branches: [ "mian" ] branches: [ "mian" ]
paths: paths:
- '.github/workflows/kpmmgr.yml' - '.github/workflows/user_scanner.yml'
- 'userspace/kpmmgr/**' - 'userspace/user_scanner/**'
workflow_dispatch: workflow_dispatch:
workflow_call: workflow_call:
inputs: inputs:
@@ -18,8 +18,8 @@ on:
default: self-hosted default: self-hosted
jobs: jobs:
build-susfs: build-user_scanner:
name: Build userspace kpmmgr name: Build userspace user_scanner
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@@ -28,13 +28,13 @@ jobs:
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Build kpmmgr - name: Build user_scanner
working-directory: ./userspace/kpmmgr working-directory: ./userspace/user_scanner
run: | run: |
$ANDROID_NDK_HOME/ndk-build $ANDROID_NDK_HOME/ndk-build
- name: Upload a Build Artifact - name: Upload a Build Artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: kpmmgr-aarch64-linux-android name: userscanner-all-linux-android
path: ./userspace/kpmmgr/libs path: ./userspace/user_scanner/libs

3
.gitignore vendored
View File

@@ -1,2 +1,3 @@
.idea .idea
.vscode CLAUDE.md
.DS_Store

View File

@@ -1,3 +1,6 @@
project_id_env: CROWDIN_PROJECT_ID
api_token_env: CROWDIN_API_TOKEN
preserve_hierarchy: 1
files: files:
- source: /manager/app/src/main/res/values/strings.xml - source: /manager/app/src/main/res/values/strings.xml
translation: /manager/app/src/main/res/values-%two_letters_code%/strings.xml translation: /manager/app/src/main/res/values-%two_letters_code%/strings.xml

View File

@@ -1,136 +0,0 @@
# SukiSU Ultra
**English** | [简体中文](README.md) | [日本語](README-ja.md) | [Türkçe](README-tr.md)
Android device root solution based on [KernelSU](https://github.com/tiann/KernelSU)
**Experimental! Use at your own risk!** This solution is based on [KernelSU](https://github.com/tiann/KernelSU) and is experimental!
> This is an unofficial fork. All rights are reserved to [@tiann](https://github.com/tiann)
>
> However, we will be a separately maintained branch of KSU in the future
## How to add
Using main branching (non-GKI device builds are not supported)
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s main
```
Using branches that support non-GKI devices
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s nongki
```
## How to use integrated susfs
1. Use the susfs-dev branch directly without any patching
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-dev
```
## KPM Support
- Based on KernelPatch, we have removed duplicates of KSU and kept only KPM support.
- We will introduce more APatch-compatible functions to ensure the integrity of KPM functionality.
We will introduce more APatch-compatible functions to ensure the completeness of KPM functionality.
KPM templates: https://github.com/udochina/KPM-Build-Anywhere
> [!Note]
> 1. `CONFIG_KPM=y` needs to be added.
> 2. Non-GKI devices need to add `CONFIG_KALLSYMS=y` and `CONFIG_KALLSYMS_ALL=y` as well.
> 3. Some kernel source code below `4.19` also needs to be backport from `4.19` to the header file `set_memory.h`.
## How to do a system update to retain ROOT
- After OTA, don't reboot first, go to the manager flashing/patching kernel interface, find `GKI/non_GKI install` and select the Anykernel3 kernel zip file that needs to be flashed, select the slot that is opposite to the current running slot of the system for flashing, and then reboot to retain the GKI mode update This method is not supported for all non-GKI devices, so please try it yourself. It is the safest way to use TWRP for non-GKI devices.
- Or use LKM mode to install to the unused slot (after OTA).
## Compatibility Status
- KernelSU (versions prior to v1.0.0) officially supports Android GKI 2.0 devices (kernel 5.10+)
- Older kernels (4.4+) are also compatible, but the kernel must be built manually
- KernelSU can support 3.x kernels (3.4-3.18) through additional reverse ports
- Currently supports `arm64-v8a`, `armeabi-v7a (bare)` and some `X86_64`
## More links
Projects compiled based on Sukisu and susfs
- [GKI](https://github.com/ShirkNeko/GKI_KernelSU_SUSFS)
- [OnePlus](https://github.com/ShirkNeko/Action_OnePlus_MKSU_SUSFS)
## Hook method
- This method references the hook method from (https://github.com/rsuntk/KernelSU)
1. **KPROBES hook:**
- Also used for Loadable Kernel Module (LKM)
- Default hook method on GKI kernels.
- Need `CONFIG_KPROBES=y`
2. **Manual hook:**
- Standard KernelSU hook: https://kernelsu.org/guide/how-to-integrate-for-non-gki.html#manually-modify-the-kernel-source
- backslashxx's syscall manual hook: https://github.com/backslashxx/KernelSU/issues/5
- Default hook method on Non-GKI kernels.
- Need `CONFIG_KSU_MANUAL_HOOK=y`
## Usage
### Universal GKI
Please **all** refer to https://kernelsu.org/zh_CN/guide/installation.html
> [!Note]
> 1. for devices with GKI 2.0 such as Xiaomi, Redmi, Samsung, etc. (excludes kernel-modified manufacturers such as Meizu, OnePlus, Zenith, and oppo)
> 2. Find the GKI build in [more links](#%E6%9B%B4%E5%A4%9A%E9%93%BE%E6%8E%A5). Find the device kernel version. Then download it and use TWRP or kernel flashing tool to flash the zip file with AnyKernel3 suffix.
> 3. The .zip archive without suffix is uncompressed, the gz suffix is the compression used by Tenguet models.
### OnePlus
1. Use the link mentioned in the 'More Links' section to create a customized build with your device information, and then flash the zip file with the AnyKernel3 suffix.
> [!Note]
> - You only need to fill in the first two parts of kernel versions, such as 5.10, 5.15, 6.1, or 6.6.
> - Please search for the processor codename by yourself, usually it is all English without numbers.
> - You can find the branch and configuration files from the OnePlus open-source kernel repository.
## Features
1. Kernel-based `su` and root access management.
2. Not based on [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS) module system, but based on [Magic Mount](https://github.com/5ec1cff/KernelSU) from 5ec1cff
3. [App Profile](https://kernelsu.org/guide/app-profile.html): Lock root privileges in a cage.
4. Bringing back non-GKI/GKI 1.0 support
5. More customization
6. Support for KPM kernel modules
## License
- The file in the “kernel” directory is under [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) license.
- All other parts except the “kernel” directory are under [GPL-3.0 or later](https://www.gnu.org/licenses/gpl-3.0.html) license.
## Sponsorship list
- [Ktouls](https://github.com/Ktouls) Thanks so much for bringing me support
- [zaoqi123](https://github.com/zaoqi123) It's not a bad idea to buy me a milk tea
- [wswzgdg](https://github.com/wswzgdg) Many thanks for supporting this project
- [yspbwx2010](https://github.com/yspbwx2010) Many thanks
- [DARKWWEE](https://github.com/DARKWWEE) Thanks for the 100 USDT Lao
If the above list does not have your name, I will update it as soon as possible, and thanks again for your support!
## Contributions
- [KernelSU](https://github.com/tiann/KernelSU): original project
- [MKSU](https://github.com/5ec1cff/KernelSU): Used project
- [RKSU](https://github.com/rsuntk/KernelsU): Reintroduced the support of non-GKI devices using the kernel of this project
- [susfs](https://gitlab.com/simonpunk/susfs4ksu)Used susfs file system
- [KernelSU](https://git.zx2c4.com/kernel-assisted-superuser/about/): KernelSU conceptualization
- [Magisk](https://github.com/topjohnwu/Magisk): Powerful root utility
- [genuine](https://github.com/brevent/genuine/): APK v2 Signature Verification
- [Diamorphine](https://github.com/m0nad/Diamorphine): Some rootkit utilities.
- [KernelPatch](https://github.com/bmax121/KernelPatch): KernelPatch is a key part of the APatch implementation of the kernel module

View File

@@ -1,136 +0,0 @@
# SukiSU Ultra
**日本語** | [简体中文](README.md) | [English](README-en.md) | [Türkçe](README-tr.md)
[KernelSU](https://github.com/tiann/KernelSU) をベースとした Android デバイスの root ソリューション
**試験中なビルドです!自己責任で使用してください!**<br>
このソリューションは [KernelSU](https://github.com/tiann/KernelSU) に基づいていますが、試験中なビルドです。
> これは非公式なフォークです。すべての権利は [@tiann](https://github.com/tiann) に帰属します。
>
> ただし、将来的には KSU とは別に管理されるブランチとなる予定です。
## 追加方法
メイン分岐の使用GKI デバイス以外のビルドはサポートされていません。)
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s main
```
GKI以外のデバイスをサポートするブランチを使用する
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s nongki
```
## 統合された susfs の使い方
1. パッチを当てずに susfs-dev ブランチを直接使用してください。
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-dev
```
## KPM に対応
- KernelPatch に基づいて重複した KSU の機能を削除、KPM の対応を維持させています。
- KPM 機能の整合性を確保するために、APatch の互換機能を更に向上させる予定です。
オープンソースアドレス: https://github.com/ShirkNeko/SukiSU_KernelPatch_patch
KPM テンプレートのアドレス: https://github.com/udochina/KPM-Build-Anywhere
> [!Note]
> 1. `CONFIG_KPM=y` が必要である。
> 2.非 GKI デバイスには `CONFIG_KALLSYMS=y` と `CONFIG_KALLSYMS_ALL=y` も必要です。
> 3.いくつかのカーネル `4.19` およびそれ以降のソースコードでは、 `4.19` からバックポートされた `set_memory.h` ヘッダーファイルも必要です。
## ROOT を保持するシステムアップデートの方法
- OTAの後、最初に再起動せず、マネージャのフラッシュ/パッチカーネルインターフェイスに移動し、`GKI/non_GKI 取り付け`を見つけ、フラッシュする必要があるAnykernel3カーネルzipファイルを選択し、フラッシュするためにシステムの現在の実行スロットと反対のスロットを選択し、GKIモードアップデートを保持するために再起動しますこの方法は、現時点ではすべてのnon_GKIデバイスでサポートされていませんので、各自でお試しください。 (この方法は、すべての非GKIデバイスでサポートされていませんので、ご自身でお試しください)。
- または、LKMモードを使用して未使用のスロットにインストールします(OTA後)。
## 互換性ステータス
- KernelSUv1.0.0より前のバージョンはAndroid GKI 2.0デバイスカーネル5.10以上)を公式にサポートしています。
- 古いカーネル4.4+)も互換性がありますが、カーネルは手動でビルドする必要があります。
- KernelSU は追加のリバースポートを通じて 3.x カーネル (3.4-3.18) をサポートしています。
- 現在は `arm64-v8a``armeabi-v7a (bare)`、いくつかの `X86_64` をサポートしています。
## その他のリンク
SukiSU と susfs をベースにコンパイルされたプロジェクトです。
- [GKI](https://github.com/ShirkNeko/GKI_KernelSU_SUSFS)
- [OnePlus](https://github.com/ShirkNeko/Action_OnePlus_MKSU_SUSFS)
## フックの方式
- この方式は (https://github.com/rsuntk/KernelSU) のフック方式を参照してください。
1. **KPROBES フック:**
- 読み込み可能なカーネルモジュールの場合 (LKM)
- GKI カーネルのデフォルトとなるフック方式
- `CONFIG_KPROBES=y` が必要です
2. **手動でフック:**
- 標準の KernelSU フック: https://kernelsu.org/guide/how-to-integrate-for-non-gki.html#manually-modify-the-kernel-source
- backslashxx syscall フック: https://github.com/backslashxx/KernelSU/issues/5
- 非 GKI カーネル用のデフォルトフッキングメソッド
- `CONFIG_KSU_MANUAL_HOOK=y` が必要です
## 使い方
### ユニバーサルGKI
https://kernelsu.org/zh_CN/guide/installation.html をご参照ください。
> [!Note]
> 1.Xiaomi、Redmi、Samsung などの GKI 2.0 を搭載したデバイス用 (Meizu、Yiga、Zenith、oppo などのマジックカーネルを搭載したメーカーは除く)。
> 2. [more links](#%E6%9B%B4%E5%A4%9A%E9%93%BE%E6%8E%A5) で GKI ビルドを検索します。 デバイスのカーネルバージョンを検索します。 次に、それをダウンロードし、TWRPまたはカーネルフラッシングツールを使用して、AnyKernel3の接尾辞が付いたzipファイルをフラッシュします。
> 接尾辞なしの.zipアーカイブは非圧縮で、接尾辞gzはTenguetモデルで使用されている圧縮方法です。
### OnePlus
1. `その他のリンク`の項目に記載されているリンクを開き、デバイス情報を使用してカスタマイズされたカーネルをビルドし、AnyKernel3 の接頭辞を持つ .zip ファイルをフラッシュします。
> [!Note]
> - 5.10、5.15、6.1、6.6 などのカーネルバージョンの最初の 2 文字のみを入力する必要があります。
> - SoC のコードネームは自分で検索してください。通常は、数字がなく英語表記のみです。
> - ブランチと構成ファイルは、OnePlus オープンソースカーネルリポジトリから見つけることができます。
## 機能
1. カーネルベースな `su` および root アクセスの管理。
2. [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS) モジュールシステムではなく、 5ec1cff 氏の [Magic Mount](https://github.com/5ec1cff/KernelSU) に基づいています。
3. [アプリプロファイル](https://kernelsu.org/guide/app-profile.html): root 権限をケージ内にロックします。
4. 非 GKI / GKI 1.0 の対応を復活
5. その他のカスタマイズ
6. KPM カーネルモジュールに対応
## ライセンス
- “kernel” ディレクトリ内のファイルは [GPL-2.0](https://www.gnu.org/licenses/old-licenses/gpl-2.0.ja.html) のみライセンス下にあります。
- “kernel” ディレクトリを除くその他すべての部分は [GPL-3.0 またはそれ以降](https://www.gnu.org/licenses/gpl-3.0.html) のライセンス下にあります。
## スポンサーシップの一覧
- [Ktouls](https://github.com/Ktouls) 応援をしてくれたことに感謝。
- [zaoqi123](https://github.com/zaoqi123) ミルクティーを買ってあげるのも良い考えですね。
- [wswzgdg](https://github.com/wswzgdg) このプロジェクトを支援していただき、ありがとうございます。
- [yspbwx2010](https://github.com/yspbwx2010) どうもありがとう。
- [DARKWWEE](https://github.com/DARKWWEE) ラオウ100USDTありがとう
上記の一覧にあなたの名前がない場合は、できるだけ早急に更新しますので再度ご支援をお願いします。
## 貢献者
- [KernelSU](https://github.com/tiann/KernelSU): オリジナルのプロジェクトです。
- [MKSU](https://github.com/5ec1cff/KernelSU): 使用しているプロジェクトです。
- [RKSU](https://github.com/rsuntk/KernelsU): このプロジェクトのカーネルを使用して非 GKI デバイスのサポートを追加しています。
- [susfs](https://gitlab.com/simonpunk/susfs4ksu):使用している susfs ファイルシステムです。
- [KernelSU](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 ユーティリティを使用しています。
- [KernelPatch](https://github.com/bmax121/KernelPatch): KernelPatch はカーネルモジュールの APatch 実装での重要な部分となります。

View File

@@ -1,142 +1,102 @@
# SukiSU Ultra # SukiSU Ultra
<img align='right' src='SukiSU-mini.svg' width='220px' alt="sukisu logo">
**简体中文** | [English](README-en.md) | [日本語](README-ja.md) | [Türkçe](README-tr.md)
基于 [KernelSU](https://github.com/tiann/KernelSU) 的安卓设备 root 解决方案 **English** | [简体中文](./zh/README.md) | [日本語](./ja/README.md) | [Türkçe](./tr/README.md)
**实验性! 使用风险自负!** A kernel-based root solution for Android devices, forked from [`tiann/KernelSU`](https://github.com/tiann/KernelSU), and added some interesting changes.
> 这是非官方分支,保留所有权利 [@tiann](https://github.com/tiann) [![Latest release](https://img.shields.io/github/v/release/SukiSU-Ultra/SukiSU-Ultra?label=Release&logo=github)](https://github.com/tiann/KernelSU/releases/latest)
[![Channel](https://img.shields.io/badge/Follow-Telegram-blue.svg?logo=telegram)](https://t.me/Sukiksu)
[![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/tiann/KernelSU?logo=gnu)](/LICENSE)
## Features
1. Kernel-based `su` and root access management
2. Module system based on [Magic Mount](https://github.com/5ec1cff/KernelSU)
> **Note:** SukiSU now delegates all module mounting to the installed *metamodule*; the core no longer handles mount operations.
3. [App Profile](https://kernelsu.org/guide/app-profile.html): Lock up the root power in a cage
4. Support non-GKI and GKI 1.0
5. KPM Support
6. Tweaks to the manager theme and the built-in susfs management tool.
## Compatibility Status
- KernelSU (before v1.0.0) officially supports Android GKI 2.0 devices (kernel 5.10+).
- Older kernels (4.4+) are also compatible, but the kernel will have to be built manually.
- With more backports, KernelSU can supports 3.x kernel (3.4-3.18).
- Currently, only `arm64-v8a`, `armeabi-v7a (bare)` and `X86_64`(some) are supported.
## Installation
See [`guide/installation.md`](guide/installation.md)
## Integration
See [`guide/how-to-integrate.md`](guide/how-to-integrate.md)
## Translation
If you need to submit a translation for the manager, please go to [Crowdin](https://crowdin.com/project/SukiSU-Ultra).
## KPM Support
- Based on KernelPatch, we removed features redundant with KSU and retained only KPM support.
- Work in Progress: Expanding APatch compatibility by integrating additional functions to ensure compatibility across different implementations.
**Open-source repository**: [https://github.com/ShirkNeko/SukiSU_KernelPatch_patch](https://github.com/ShirkNeko/SukiSU_KernelPatch_patch)
**KPM template**: [https://github.com/udochina/KPM-Build-Anywhere](https://github.com/udochina/KPM-Build-Anywhere)
> [!Note]
> >
> 但是,我们将会在未来成为一个单独维护的 KSU 分支 > 1. Requires `CONFIG_KPM=y`
> 2. Non-GKI devices requires `CONFIG_KALLSYMS=y` and `CONFIG_KALLSYMS_ALL=y`
> 3. For kernels below `4.19`, backporting from `set_memory.h` from `4.19` is required.
## 如何添加 ## Troubleshooting
在内核源码的根目录下执行以下命令: 1. Device stuck upon manager app uninstallation?
Uninstall _com.sony.playmemories.mobile_
使用 main 分支 (不支持非GKI设备构建) ## Sponsor
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s main
```
使用支持非 GKI 设备的分支 - [ShirkNeko](https://afdian.com/a/shirkneko) (maintainer of SukiSU)
``` - [weishu](https://github.com/sponsors/tiann) (author of KernelSU)
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s nongki
```
## 如何集成 susfs ## ShirkNeko's sponsorship list
1. 直接使用 susfs-stable 或者 susfs-dev 分支,不需要再集成 susfs - [Ktouls](https://github.com/Ktouls) Thanks so much for bringing me support.
- [zaoqi123](https://github.com/zaoqi123) Thanks for the milk tea.
- [wswzgdg](https://github.com/wswzgdg) Many thanks for supporting this project.
- [yspbwx2010](https://github.com/yspbwx2010) Many thanks.
- [DARKWWEE](https://github.com/DARKWWEE) 100 USDT
- [Saksham Singla](https://github.com/TypeFlu) Provide and maintain the website
- [OukaroMF](https://github.com/OukaroMF) Donation of website domain name
``` ## License
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-dev
```
## 钩子方法 - The file in the “kernel” directory is under [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) license.
- The images of the files `ic_launcher(?!.*alt.*).*` with anime character sticker are copyrighted by [怡子曰曰](https://space.bilibili.com/10545509), the Brand Intellectual Property in the images is owned by [明风 OuO](https://space.bilibili.com/274939213), and the vectorization is done by @MiRinChan. Before using these files, in addition to complying with [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt), you also need to comply with the authorization of the two authors to use these artistic contents.
- Except for the files or directories mentioned above, all other parts are under [GPL-3.0 or later](https://www.gnu.org/licenses/gpl-3.0.html) license.
- 此部分引用自 [rsuntk 的钩子方法](https://github.com/rsuntk/KernelSU) ## Credit
1. **KPROBES 钩子:** - [KernelSU](https://github.com/tiann/KernelSU): upstream
- 用于可加载内核模块 (LKM) - [MKSU](https://github.com/5ec1cff/KernelSU): Magic Mount
- GKI 2.0 内核的默认钩子方法 - [RKSU](https://github.com/rsuntk/KernelsU): support non-GKI
- 需要 `CONFIG_KPROBES=y` - [susfs](https://gitlab.com/simonpunk/susfs4ksu): An addon root hiding kernel patches and userspace module for KernelSU.
- [KernelPatch](https://github.com/bmax121/KernelPatch): KernelPatch is a key part of the APatch implementation of the kernel module
2. **手动钩子:** <details>
- 标准的 KernelSU 钩子https://kernelsu.org/guide/how-to-integrate-for-non-gki.html#manually-modify-the-kernel-source <summary>KernelSU's credit</summary>
- backslashxx 的 syscall 手动钩子https://github.com/backslashxx/KernelSU/issues/5
- 非 GKI 内核的默认挂钩方法
- 需要 `CONFIG_KSU_MANUAL_HOOK=y`
## KPM 支持 - [Kernel-Assisted Superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): The KernelSU idea.
- [Magisk](https://github.com/topjohnwu/Magisk): The powerful root tool.
- 我们基于 KernelPatch 去掉了和 KSU 重复的功能,仅保留了 KPM 支持 - [genuine](https://github.com/brevent/genuine/): APK v2 signature validation.
- 我们将会引入更多的兼容 APatch 的函数来确保 KPM 功能的完整性 - [Diamorphine](https://github.com/m0nad/Diamorphine): Some rootkit skills.
</details>
开源地址: https://github.com/ShirkNeko/SukiSU_KernelPatch_patch
KPM 模板地址: https://github.com/udochina/KPM-Build-Anywhere
> [!Note]
> 1. 需要 `CONFIG_KPM=y`
> 2. 非GKI设备还需要 `CONFIG_KALLSYMS=y` 和 `CONFIG_KALLSYMS_ALL=y`
> 3. 部分内核 `4.19` 以下源码还需要从 `4.19` 向后移植头文件 `set_memory.h`
## 如何进行系统更新保留ROOT
- OTA后先不要重启进入管理器刷写/修补内核界面,找到 `GKI/non_GKI安装` 选择需要刷写的Anykernel3内核压缩文件选择与现在系统运行槽位相反的槽位进行刷写并重启即可保留GKI模式更新暂不支持所有非GKI设备使用这种方法请自行尝试。非GKI设备使用TWRP刷写是最稳妥的
- 或者使用LKM模式的安装到未使用的槽位OTA后
## 兼容状态
- KernelSUv1.0.0 之前版本)正式支持 Android GKI 2.0 设备(内核 5.10+
- 旧内核4.4+)也兼容,但必须手动构建内核
- 通过更多的反向移植KernelSU 可以支持 3.x 内核3.4-3.18
- 目前支持 `arm64-v8a` `armeabi-v7a (bare)` 和部分 `X86_64`
## 更多链接
基于 SukiSU 和 susfs 编译的项目
- [GKI](https://github.com/ShirkNeko/GKI_KernelSU_SUSFS)
- [一加](https://github.com/ShirkNeko/Action_OnePlus_MKSU_SUSFS)
## 使用方法
### 普适的 GKI
请**全部**参考 https://kernelsu.org/zh_CN/guide/installation.html
> [!Note]
> 1. 适用于如小米、红米、三星等的 GKI 2.0 的设备 (不包含魔改内核的厂商如魅族、一加、真我和 oppo)
> 2. 找到[更多链接](#%E6%9B%B4%E5%A4%9A%E9%93%BE%E6%8E%A5)里的 GKI 构建的项目。找到设备内核版本。然后下载下来用TWRP或者内核刷写工具刷入带 AnyKernel3 后缀的压缩包即可
> 3. 一般不带后缀的 .zip 压缩包是未压缩的gz 后缀的为天玑机型所使用的压缩方式
### 一加
1.找到更多链接里的一加项目进行自行填写,然后云编译构建,最后刷入带 AnyKernel3 后缀的压缩包即可
> [!Note]
> - 内核版本只需要填写前两位即可,如 5.105.156.16.6
> - 处理器代号请自行搜索,一般为全英文不带数字的代号
> - 分支和配置文件请自行到一加内核开源地址进行填写
## 特点
1. 基于内核的 `su` 和 root 访问管理
2. 基于 5ec1cff 的 [Magic Mount](https://github.com/5ec1cff/KernelSU) 的模块系统
3. [App Profile](https://kernelsu.org/guide/app-profile.html):将 root 权限锁在笼子里
4. 恢复对非 GKI 2.0 内核的支持
5. 更多自定义功能
6. 对 KPM 内核模块的支持
## 许可证
- `kernel` 目录下的文件是 [GPL-2.0-only](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)。
## 爱发电链接
- https://afdian.com/a/shirkneko
## 赞助名单
- [Ktouls](https://github.com/Ktouls) 非常感谢你给我带来的支持
- [zaoqi123](https://github.com/zaoqi123) 请我喝奶茶也不错
- [wswzgdg](https://github.com/wswzgdg) 非常感谢对此项目的支持
- [yspbwx2010](https://github.com/yspbwx2010) 非常感谢
- [DARKWWEE](https://github.com/DARKWWEE) 感谢老哥的 100 USDT
如果以上名单没有你的名称,我会及时更新,再次感谢大家的支持
## 贡献
- [KernelSU](https://github.com/tiann/KernelSU):原始项目
- [MKSU](https://github.com/5ec1cff/KernelSU):使用的项目
- [RKSU](https://github.com/rsuntk/KernelsU):使用该项目的 kernel 对非GKI设备重新进行支持
- [susfs4ksu](https://gitlab.com/simonpunk/susfs4ksu):使用的 susfs 文件系统
- [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 技能
- [KernelPatch](https://github.com/bmax121/KernelPatch): KernelPatch 是 APatch 实现内核模块的关键部分

183
docs/SukiSU-mini.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 185 KiB

188
docs/SukiSU.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 200 KiB

View File

@@ -0,0 +1,97 @@
# Integrate
SukiSU can be integrated into both _GKI_ and _non-GKI_ kernels and has been backported to _4.14_.
<!-- It should be 3.4, but backslashxx's syscall manual hook cannot use in SukiSU-->
Some OEMs' customization could result in as much as 50% of kernel code being out-of-tree code and not from upstream Linux kernels or ACKs. Due to this, the custom nature of _non-GKI_ kernels resulted in significant kernel fragmentation, and we lacked a universal method for building them. Therefore, we cannot provide boot images of _non-GKI_ kernels.
Prerequisites: open source bootable kernel.
### Hook method
1. **KPROBES hook:**
- Default hook method on GKI kernels.
- Requires `# CONFIG_KSU_MANUAL_HOOK is not set` & `CONFIG_KPROBES=y`
- Used for Loadable Kernel Module (LKM).
2. **Manual hook:**
<!-- - backslashxx's syscall manual hook: https://github.com/backslashxx/KernelSU/issues/5 (v1.5 version is not available at the moment, if you want to use it, please use v1.4 version, or standard KernelSU hooks)-->
- Requires `CONFIG_KSU_MANUAL_HOOK=y`
- Requires [`guide/how-to-integrate.md`](guide/how-to-integrate.md)
- Requires [https://github.com/~](https://github.com/tiann/KernelSU/blob/main/website/docs/guide/how-to-integrate-for-non-gki.md#manually-modify-the-kernel-source)
3. **Tracepoint Hook:**
- Hook method introduced since SukiSU commit [49b01aad](https://github.com/SukiSU-Ultra/SukiSU-Ultra/commit/49b01aad74bcca6dba5a8a2e053bb54b648eb124)
- Requires `CONFIG_KSU_TRACEPOINT_HOOK=y`
- Requires [`guide/tracepoint-hook.md`](tracepoint-hook.md)
<!-- This part refer to [rsuntk/KernelSU](https://github.com/rsuntk/KernelSU). -->
If you're able to build a bootable kernel, there are two ways to integrate KernelSU into the kernel source code:
1. Automatically with `kprobe`
2. Manually
## Integrate with kprobe
Applicable:
- _GKI_ kernel
Not applicable:
- _non-GKI_ kernel
KernelSU uses kprobe to do kernel hooks. If kprobe runs well in your kernel, it's recommended to use it this way.
Please refer to this document [https://github.com/~](https://github.com/tiann/KernelSU/blob/main/website/docs/guide/how-to-integrate-for-non-gki.md#integrate-with-kprobe). Although it is titled “for _non-GKI_,” it only applies to _GKI_.
The execution command for the step that adds KernelSU to your kernel source tree is replaced with:
```sh
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s main
```
## Manually modify the kernel source
Applicable:
- GKI kernel
- non-GKI kernel
Please refer to this document [https://github.com/~ (Integrate for non-GKI)](https://github.com/tiann/KernelSU/blob/main/website/docs/guide/how-to-integrate-for-non-gki.md#manually-modify-the-kernel-source) and [https://github.com/~ (Build for GKI)](https://kernelsu.org/zh_CN/guide/how-to-build.html) to integrate manually, although first link is titled “for non-GKI,” it also applies to GKI. It can work on them both.
There is another way to integrate but still work in the process.
<!-- It is backslashxx's syscall manual hook, but it cannot be used now. -->
Run command for the step that adds KernelSU(SukiSU) to your kernel source tree is replaced with:
### GKI kernel
```sh
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s main
```
### non-GKI kernel
```sh
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s nongki
```
### GKI / non-GKI kernel with susfs (experiment)
```sh
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-{{branch}}
```
Branch:
- `main` (susfs-main)
- `test` (susfs-test)
- version (for example: susfs-1.5.7, you should check the [branches](https://github.com/SukiSU-Ultra/SukiSU-Ultra/branches))

View File

@@ -0,0 +1,34 @@
# Installation
You can go to [KernelSU Documentation - Installation](https://kernelsu.org/guide/installation.html) for a reference on how to install it, here are just additional instructions.
## Installation by loading the Loadable Kernel Module(LKM)
See [KernelSU Documentation - LKM Installation](https://kernelsu.org/guide/installation.html#lkm-installation)
Beginning with **Android™** (trademark meaning licensed Google Mobile Services) 12, devices shipping with kernel version 5.10 or higher must ship with the GKI kernel. You may be able to use LKM mode.
## Installation by installing the kernel
See [KernelSU Documentation - GKI mode Installation](https://kernelsu.org/guide/installation.html#gki-mode-installation)
We provide pre-built kernels for you to use:
- [ShirkNeko flavor kernel](https://github.com/ShirkNeko/GKI_KernelSU_SUSFS) (add ZRAM compression algorithm patch, susfs, KPM. Works on many devices.)
- [MiRinFork flavored kernel](https://github.com/MiRinFork/GKI_SukiSU_SUSFS) (adds susfs, KPM. Closest kernel to GKI, works on most devices.)
Although some devices can be installed using LKM mode, they cannot be installed on the device by using the GKI kernel; therefore, the kernel needs to be modified manually to compile it. For example:
- OPPO(OnePlus, REALME)
- Meizu
Also, we provide pre-built kernels for your OnePlus device to use:
- [ShirkNeko/Action_OnePlus_MKSU_SUSFS](https://github.com/ShirkNeko/Action_OnePlus_MKSU_SUSFS) (add ZRAM compression algorithm patch, susfs, KPM.)
Using the link above, Fork into GitHub Action, fill in the build parameters, compile, and finally flush in the zip with the AnyKernel3 suffix.
> [!Note]
>
> - You only need to fill in the first two parts of the version number, e.g. `5.10`, `6.1`...
> - Make sure you know the processor designation, kernel version, etc. before you use it.

View File

@@ -0,0 +1,239 @@
# Tracepoint Hook Integration
## Introduction
Since commit [49b01aad](https://github.com/SukiSU-Ultra/SukiSU-Ultra/commit/49b01aad74bcca6dba5a8a2e053bb54b648eb124), SukiSU has introduced Tracepoint Hook
This Hook theoretically has lower performance overhead compared to Kprobes Hook, but is inferior to Manual Hook / Syscall Hook
> [!NOTE]
> This tutorial references the syscall hook v1.4 version from [backslashxx/KernelSU#5](https://github.com/backslashxx/KernelSU/issues/5), as well as the original KernelSU's [Manual Hook](https://kernelsu.org/guide/how-to-integrate-for-non-gki.html#manually-modify-the-kernel-source)
## Guide
### execve Hook (`exec.c`)
Generally need to modify the `do_execve` and `compat_do_execve` methods in `fs/exec.c`
```patch
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -78,6 +78,10 @@
#include <trace/hooks/sched.h>
#endif
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+#include <../drivers/kernelsu/ksu_trace.h>
+#endif
+
EXPORT_TRACEPOINT_SYMBOL_GPL(task_rename);
static int bprm_creds_from_file(struct linux_binprm *bprm);
@@ -2037,6 +2041,9 @@ static int do_execve(struct filename *filename,
{
struct user_arg_ptr argv = { .ptr.native = __argv };
struct user_arg_ptr envp = { .ptr.native = __envp };
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+ trace_ksu_trace_execveat_hook((int *)AT_FDCWD, &filename, &argv, &envp, 0);
+#endif
return do_execveat_common(AT_FDCWD, filename, argv, envp, 0);
}
@@ -2064,6 +2071,9 @@ static int compat_do_execve(struct filename *filename,
.is_compat = true,
.ptr.compat = __envp,
};
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+ trace_ksu_trace_execveat_hook((int *)AT_FDCWD, &filename, &argv, &envp, 0); // 32-bit su and 32-on-64 support
+#endif
return do_execveat_common(AT_FDCWD, filename, argv, envp, 0);
}
```
### faccessat Hook (`open.c`)
Generally need to modify the `do_faccessat` method in `/fs/open.c`
```patch
--- a/fs/open.c
+++ b/fs/open.c
@@ -37,6 +37,10 @@
#include "internal.h"
#include <trace/hooks/syscall_check.h>
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+#include <../drivers/kernelsu/ksu_trace.h>
+#endif
+
int do_truncate(struct user_namespace *mnt_userns, struct dentry *dentry,
loff_t length, unsigned int time_attrs, struct file *filp)
{
@@ -468,6 +472,9 @@ static long do_faccessat(int dfd, const char __user *filename, int mode, int fla
SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
{
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+ trace_ksu_trace_faccessat_hook(&dfd, &filename, &mode, NULL);
+#endif
return do_faccessat(dfd, filename, mode, 0);
}
```
If there's no `do_faccessat` method, you can find the `faccessat` SYSCALL definition (for kernels earlier than 4.17)
```patch
--- a/fs/open.c
+++ b/fs/open.c
@@ -31,6 +31,9 @@
#include <linux/ima.h>
#include <linux/dnotify.h>
#include <linux/compat.h>
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+#include <../drivers/kernelsu/ksu_trace.h>
+#endif
#include "internal.h"
@@ -369,6 +372,9 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
int res;
unsigned int lookup_flags = LOOKUP_FOLLOW;
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+ trace_ksu_trace_faccessat_hook(&dfd, &filename, &mode, NULL);
+#endif
if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
return -EINVAL;
```
### sys_read Hook (`read_write.c`)
Need to modify the `sys_read` method in `fs/read_write.c` (4.19 and above)
```patch
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -25,6 +25,10 @@
#include <linux/uaccess.h>
#include <asm/unistd.h>
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+#include <../drivers/kernelsu/ksu_trace.h>
+#endif
+
const struct file_operations generic_ro_fops = {
.llseek = generic_file_llseek,
.read_iter = generic_file_read_iter,
@@ -630,6 +634,9 @@ ssize_t ksys_read(unsigned int fd, char __user *buf, size_t count)
SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
{
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+ trace_ksu_trace_sys_read_hook(fd, &buf, &count);
+#endif
return ksys_read(fd, buf, count);
}
```
Or the `read` SYSCALL definition (4.14 and below)
```patch
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -25,6 +25,11 @@
#include <linux/uaccess.h>
#include <asm/unistd.h>
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+#include <../drivers/kernelsu/ksu_trace.h>
+#endif
+
+
const struct file_operations generic_ro_fops = {
.llseek = generic_file_llseek,
.read_iter = generic_file_read_iter,
@@ -575,6 +580,9 @@ SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
if (f.file) {
loff_t pos = file_pos_read(f.file);
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+ trace_ksu_trace_sys_read_hook(fd, &buf, &count);
+#endif
ret = vfs_read(f.file, buf, count, &pos);
if (ret >= 0)
file_pos_write(f.file, pos);
```
### fstatat Hook (`stat.c`)
Need to modify the `newfstatat` SYSCALL definition in `stat.c`
If 32-bit support is needed, also need to modify the `statat64` SYSCALL definition
```patch
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -24,6 +24,10 @@
#include "internal.h"
#include "mount.h"
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+#include <../drivers/kernelsu/ksu_trace.h>
+#endif
+
/**
* generic_fillattr - Fill in the basic attributes from the inode struct
* @mnt_userns: user namespace of the mount the inode was found from
@@ -408,6 +412,10 @@ SYSCALL_DEFINE4(newfstatat, int, dfd, const char __user *, filename,
struct kstat stat;
int error;
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+ trace_ksu_trace_stat_hook(&dfd, &filename, &flag);
+#endif
+
error = vfs_fstatat(dfd, filename, &stat, flag);
if (error)
return error;
@@ -559,6 +567,10 @@ SYSCALL_DEFINE4(fstatat64, int, dfd, const char __user *, filename,
struct kstat stat;
int error;
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+ trace_ksu_trace_stat_hook(&dfd, &filename, &flag); /* 32-bit su support */
+#endif
+
error = vfs_fstatat(dfd, filename, &stat, flag);
if (error)
return error;
```
### input Hook (`input.c`, for entering KSU built-in security mode)
Need to modify the `input_event` method in `drivers/input/input.c`, not `input_handle_event`
```patch
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -26,6 +26,10 @@
#include "input-compat.h"
#include "input-poller.h"
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+#include <../../drivers/kernelsu/ksu_trace.h>
+#endif
+
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("Input core");
MODULE_LICENSE("GPL");
@@ -451,6 +455,10 @@ void input_event(struct input_dev *dev,
{
unsigned long flags;
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+ trace_ksu_trace_input_hook(&type, &code, &value);
+#endif
+
if (is_event_supported(type, dev->evbit, EV_MAX)) {
spin_lock_irqsave(&dev->event_lock, flags);
```

153
docs/ja/README.md Normal file
View File

@@ -0,0 +1,153 @@
# SukiSU Ultra
<img align='right' src='SukiSU-mini.svg' width='220px' alt="sukisu logo">
[English](../README.md) | [简体中文](../zh/README.md) | **日本語** | [Türkçe](../tr/README.md)
[KernelSU](https://github.com/tiann/KernelSU) をベースとした Android デバイスの root ソリューション
**試験中なビルドです!自己責任で使用してください!**<br>
このソリューションは [KernelSU](https://github.com/tiann/KernelSU) に基づいていますが、試験中なビルドです。
> これは非公式なフォークです。すべての権利は [@tiann](https://github.com/tiann) に帰属します。
>
> ただし、将来的には KSU とは別に管理されるブランチとなる予定です。
## 追加する方法
メインブランチを使用 (非 GKI のデバイスのビルドは非対応) (susfs を手動で統合が必要)
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s main
```
非 GKI のデバイスに対応するブランチを使用 (susfs を手動で統合が必要)
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s nongki
```
## 統合された susfs の使い方
1. susfs-main または他の susfs-\* ブランチを直接で使用、susfs の統合は不要 (非 GKI デバイスのビルドに対応)
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-main
```
## フックの方式
- この方式は (https://github.com/rsuntk/KernelSU) のフック方式を参照してください。
1. **KPROBES でフック:**
- 読み込み可能なカーネルモジュールの場合 (LKM)
- GKI カーネルのデフォルトとなるフック方式
- `CONFIG_KPROBES=y` が必要です
2. **手動でフック:**
- 標準の KernelSU フック: https://kernelsu.org/guide/how-to-integrate-for-non-gki.html#manually-modify-the-kernel-source
- backslashxx syscall フック: https://github.com/backslashxx/KernelSU/issues/5
- 非 GKI カーネル用のデフォルトフック方式
- `CONFIG_KSU_MANUAL_HOOK=y` が必要です
## KPM に対応
- KernelPatch に基づいて重複した KSU の機能を削除、KPM の対応を維持させています。
- KPM 機能の整合性を確保するために、APatch の互換機能を更に向上させる予定です。
オープンソースアドレス: https://github.com/ShirkNeko/SukiSU_KernelPatch_patch
KPM テンプレートのアドレス: https://github.com/udochina/KPM-Build-Anywhere
> [!Note]
>
> 1. `CONFIG_KPM=y` が必要です。
> 2. 非 GKI デバイスには `CONFIG_KALLSYMS=y` と `CONFIG_KALLSYMS_ALL=y` も必要です。
> 3. いくつかのカーネル `4.19` およびそれ以降のソースコードでは、 `4.19` からバックポートされた `set_memory.h` ヘッダーファイルも必要です。
## ROOT を保持した状態でのシステムアップデートの方法
- 始めに OTA 後すぐに再起動せずにマネージャーのカーネルのフラッシュ、パッチのインターフェースを開いて`GKI/非 GKI のインストール`を見つけます。フラッシュする AnyKernel3 の zip ファイルを選択し、フラッシュする実行中のスロットと逆のスロットを選択後に再起動をして GKI モードの更新が保持できます (この方法はすべての非 GKI のデバイスが対応している訳ではないので、自分でお試しください。これは非 GKI のデバイスで TWRP を使用する最も安全な方法です)。
- または LKM モードを使用して未使用のスロットにインストールします (OTA 後)。
## 互換性の状態
- KernelSU (v1.0.0 より前) は Android GKI 2.0 のデバイス (カーネル 5.10 以降) を公式に対応しています。
- 古いカーネル (4.4 以降) も互換性がありますが、カーネルを手動で再ビルドする必要があります。
- KernelSU は追加のリバースポートを通じて 3.x カーネル (3.4-3.18) で対応可能です。
- 現在 `arm64-v8a`, `armeabi-v7a (bare)` および一部の `X86_64` に対応しています。
## その他のリンク
**マネージャーの翻訳を行う場合** https://crowdin.com/project/SukiSU-Ultra
- [その他パッチ済み GKI](https://github.com/ShirkNeko/GKI_KernelSU_SUSFS) ZRAM パッチ、KPM、susfs が含まれています...
- [パッチの少ない GKI](https://github.com/MiRinFork/GKI_SukiSU_SUSFS/releases) susfs のみ
- [OnePlus](https://github.com/ShirkNeko/Action_OnePlus_MKSU_SUSFS)
## 使い方
### Universal GKI
**すべて**参照してください https://kernelsu.org/ja_JP/guide/installation.html
> [!Note]
>
> 1. Xiaomi、Redmi、Samsung などの GKI 2.0 を搭載したデバイス向け (Meizu、OnePlus、Zenith、Oppo などカーネルが変更されているメーカーを除く)
> 2. GKI のビルドは[その他のリンク](#その他のリンク)から入手できます。デバイスのカーネルバージョンを確認してください。ダウンロード後に TWRP またはカーネルフラッシュツールを使用して AnyKernel3 の接頭辞を持つ zip ファイルをフラッシュしてください。Pixel のユーザーは、パッチの少ない GKI を使用する必要があります。
> 3. 接頭辞のない .zip アーカイブは圧縮されていません。.gz の接頭辞は Tenguet モデルで使用される圧縮になります。
### OnePlus
1. `その他のリンク`の項目に記載されているリンクを開き、デバイス情報を使用してカスタマイズされたカーネルをビルドし、AnyKernel3 の接頭辞を持つ .zip ファイルをフラッシュします。
> [!Note]
>
> - 5.10、5.15、6.1、6.6 などのカーネルバージョンの最初の 2 文字のみを入力する必要があります。
> - SoC のコードネームは自分で検索してください。通常は、数字がなく英語表記のみです。
> - ブランチと構成ファイルは、OnePlus オープンソースカーネルリポジトリから見つけることができます。
## 機能
1. カーネルベースな `su` および root アクセスの管理。
2. [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS) モジュールシステムではなく、 5ec1cff 氏の [Magic Mount](https://github.com/5ec1cff/KernelSU) に基づいています。
3. [アプリプロファイル](https://kernelsu.org/guide/app-profile.html): root 権限をケージ内にロックします。
4. 非 GKI / GKI 1.0 の対応を復活
5. その他のカスタマイズ
6. KPM カーネルモジュールに対応
## トラブルシューティング
1. KernelSU Manager のアンインストールが停止してしまう → com.sony.playmemories.mobile のアプリをアンインストールしてください。
## ライセンス
- 「kernel」のディレクトリ内のファイルは [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) のライセンスに基づいています。
- アニメキャラクター画像とスタンプを含むこれらのファイルの `ic_launcher(?!.*alt.*).*` は[怡子曰曰](https://space.bilibili.com/10545509)によって著作権保護されており、画像の Brand Intellectual Property は[明风 OuO](https://space.bilibili.com/274939213)によって所有され、ベクター化は @MiRinChan によって行われています。 これらのファイルを使用する前に、[Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt)を遵守することに加えて、アートコンテンツを使用するために前の 2 人の作者から許可を得る必要があります。
- 上記のファイルまたはディレクトリを除き、その他のすべての部分は[GPL-3.0 以降](https://www.gnu.org/licenses/gpl-3.0.html)です。
## スポンサーシップの一覧
- [Ktouls](https://github.com/Ktouls) 応援してくれてありがとう
- [zaoqi123](https://github.com/zaoqi123) ミルクティーを買ってあげるのも良い考えですね
- [wswzgdg](https://github.com/wswzgdg) このプロジェクトにご支援いただき、ありがとうございます
- [yspbwx2010](https://github.com/yspbwx2010) ありがとうございます
- [DARKWWEE](https://github.com/DARKWWEE) ラオスから 100 USDT の支援に感謝します
- [Saksham Singla](https://github.com/TypeFlu) ウェブサイトの提供とメンテナンス
- [OukaroMF](https://github.com/OukaroMF) ウェブサイトのドメインと寄付
## 貢献者
- [KernelSU](https://github.com/tiann/KernelSU): オリジナルのプロジェクト
- [MKSU](https://github.com/5ec1cff/KernelSU): 使用しているプロジェクト
- [RKSU](https://github.com/rsuntk/KernelsU): このプロジェクトのカーネルを使用した非 GKI デバイスのサポートの再導入
- [susfs](https://gitlab.com/simonpunk/susfs4ksu): susfs ファイルシステムの使用
- [KernelSU](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): いくつかの root キットユーティリティ
- [KernelPatch](https://github.com/bmax121/KernelPatch): KernelPatch はカーネルモジュールの APatch 実装の重要な部分での活用

183
docs/ja/SukiSU-mini.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 185 KiB

View File

@@ -1,6 +1,8 @@
# SukiSU Ultra # SukiSU Ultra
<img align='right' src='SukiSU-mini.svg' width='250px' alt="sukisu logo">
**Türkçe** | [简体中文](README.md) | [English](README-en.md) | [日本語](README-ja.md)
[English](../README.md) | [简体中文](../zh/README.md) | [日本語](../ja/README.md) | **Türkçe**
[KernelSU](https://github.com/tiann/KernelSU) tabanlı Android cihaz root çözümü [KernelSU](https://github.com/tiann/KernelSU) tabanlı Android cihaz root çözümü
@@ -15,21 +17,23 @@
Çekirdek kaynak kodunun kök dizininde aşağıdaki komutları çalıştırın: Çekirdek kaynak kodunun kök dizininde aşağıdaki komutları çalıştırın:
Ana dalı kullanın (GKI olmayan cihazlar için desteklenmez) Ana dalı kullanın (GKI olmayan cihazlar için desteklenmez)
``` ```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s main curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s main
``` ```
GKI olmayan cihazları destekleyen dalı kullanın GKI olmayan cihazları destekleyen dalı kullanın
``` ```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s nongki curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s nongki
``` ```
## susfs Nasıl Entegre Edilir ## susfs Nasıl Entegre Edilir
1. Doğrudan susfs-stable veya susfs-dev dalını kullanın, susfs entegrasyonuna gerek yok 1. Doğrudan susfs-main veya susfs-\* dalını kullanın, susfs entegrasyonuna gerek yok
``` ```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-dev curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-main
``` ```
## Kanca Yöntemleri ## Kanca Yöntemleri
@@ -37,15 +41,16 @@ curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kern
- Bu bölüm [rsuntk\'nin kanca yöntemlerinden](https://github.com/rsuntk/KernelSU) alıntılanmıştır - Bu bölüm [rsuntk\'nin kanca yöntemlerinden](https://github.com/rsuntk/KernelSU) alıntılanmıştır
1. **KPROBES Kancası:** 1. **KPROBES Kancası:**
- Yüklenebilir çekirdek modülleri (LKM) için kullanılır
- GKI 2.0 çekirdeğinin varsayılan kanca yöntemi - Yüklenebilir çekirdek modülleri (LKM) için kullanılır
- `CONFIG_KPROBES=y` gerektirir - GKI 2.0 çekirdeğinin varsayılan kanca yöntemi
- `CONFIG_KPROBES=y` gerektirir
2. **Manuel Kanca:** 2. **Manuel Kanca:**
- Standart KernelSU kancası: https://kernelsu.org/guide/how-to-integrate-for-non-gki.html#manually-modify-the-kernel-source - Standart KernelSU kancası: https://kernelsu.org/guide/how-to-integrate-for-non-gki.html#manually-modify-the-kernel-source
- backslashxx\'nin syscall manuel kancası: https://github.com/backslashxx/KernelSU/issues/5 - backslashxx\'nin syscall manuel kancası: https://github.com/backslashxx/KernelSU/issues/5
- GKI olmayan çekirdeğin varsayılan kanca yöntemi - GKI olmayan çekirdeğin varsayılan kanca yöntemi
- `CONFIG_KSU_MANUAL_HOOK=y` gerektirir - `CONFIG_KSU_MANUAL_HOOK=y` gerektirir
## KPM Desteği ## KPM Desteği
@@ -57,6 +62,7 @@ Kaynak kodu: https://github.com/ShirkNeko/SukiSU_KernelPatch_patch
KPM şablonu: https://github.com/udochina/KPM-Build-Anywhere KPM şablonu: https://github.com/udochina/KPM-Build-Anywhere
> [!Note] > [!Note]
>
> 1. `CONFIG_KPM=y` gerektirir > 1. `CONFIG_KPM=y` gerektirir
> 2. GKI olmayan cihazlar ayrıca `CONFIG_KALLSYMS=y` ve `CONFIG_KALLSYMS_ALL=y` gerektirir > 2. GKI olmayan cihazlar ayrıca `CONFIG_KALLSYMS=y` ve `CONFIG_KALLSYMS_ALL=y` gerektirir
> 3. Bazı çekirdek `4.19` altı kaynak kodları, `4.19`dan geri taşınan başlık dosyası `set_memory.h` gerektirir > 3. Bazı çekirdek `4.19` altı kaynak kodları, `4.19`dan geri taşınan başlık dosyası `set_memory.h` gerektirir
@@ -79,6 +85,7 @@ KPM şablonu: https://github.com/udochina/KPM-Build-Anywhere
## Daha Fazla Bağlantı ## Daha Fazla Bağlantı
SukiSU ve susfs tabanlı derlenen projeler SukiSU ve susfs tabanlı derlenen projeler
- [GKI](https://github.com/ShirkNeko/GKI_KernelSU_SUSFS) - [GKI](https://github.com/ShirkNeko/GKI_KernelSU_SUSFS)
- [OnePlus](https://github.com/ShirkNeko/Action_OnePlus_MKSU_SUSFS) - [OnePlus](https://github.com/ShirkNeko/Action_OnePlus_MKSU_SUSFS)
@@ -89,6 +96,7 @@ SukiSU ve susfs tabanlı derlenen projeler
Lütfen **tümünü** https://kernelsu.org/zh_CN/guide/installation.html adresinden inceleyin Lütfen **tümünü** https://kernelsu.org/zh_CN/guide/installation.html adresinden inceleyin
> [!Note] > [!Note]
>
> 1. Xiaomi, Redmi, Samsung gibi GKI 2.0 cihazlar için uygundur (Meizu, OnePlus, Realme ve Oppo gibi değiştirilmiş çekirdekli üreticiler hariç) > 1. Xiaomi, Redmi, Samsung gibi GKI 2.0 cihazlar için uygundur (Meizu, OnePlus, Realme ve Oppo gibi değiştirilmiş çekirdekli üreticiler hariç)
> 2. [Daha fazla bağlantı](#daha-fazla-bağlantı) bölümündeki GKI tabanlı projeleri bulun. Cihaz çekirdek sürümünü bulun. Ardından indirin ve TWRP veya çekirdek yazma aracı kullanarak AnyKernel3 soneki olan sıkıştırılmış paketi yazın > 2. [Daha fazla bağlantı](#daha-fazla-bağlantı) bölümündeki GKI tabanlı projeleri bulun. Cihaz çekirdek sürümünü bulun. Ardından indirin ve TWRP veya çekirdek yazma aracı kullanarak AnyKernel3 soneki olan sıkıştırılmış paketi yazın
> 3. Genellikle sonek olmayan .zip sıkıştırılmış paketler sıkıştırılmamıştır, gz soneki olanlar ise Dimensity modelleri için kullanılan sıkıştırma yöntemidir > 3. Genellikle sonek olmayan .zip sıkıştırılmış paketler sıkıştırılmamıştır, gz soneki olanlar ise Dimensity modelleri için kullanılan sıkıştırma yöntemidir
@@ -98,6 +106,7 @@ Lütfen **tümünü** https://kernelsu.org/zh_CN/guide/installation.html adresin
1. Daha fazla bağlantı bölümündeki OnePlus projesini bulun ve kendiniz doldurun, ardından bulut derleme yapın ve AnyKernel3 soneki olan sıkıştırılmış paketi yazın 1. Daha fazla bağlantı bölümündeki OnePlus projesini bulun ve kendiniz doldurun, ardından bulut derleme yapın ve AnyKernel3 soneki olan sıkıştırılmış paketi yazın
> [!Note] > [!Note]
>
> - Çekirdek sürümü için yalnızca ilk iki haneyi doldurmanız yeterlidir, örneğin 5.10, 5.15, 6.1, 6.6 > - Çekirdek sürümü için yalnızca ilk iki haneyi doldurmanız yeterlidir, örneğin 5.10, 5.15, 6.1, 6.6
> - İşlemci kod adını kendiniz arayın, genellikle tamamen İngilizce ve sayı içermeden oluşur > - İşlemci kod adını kendiniz arayın, genellikle tamamen İngilizce ve sayı içermeden oluşur
> - Dal ve yapılandırma dosyasını kendiniz OnePlus çekirdek kaynak kodundan doldurun > - Dal ve yapılandırma dosyasını kendiniz OnePlus çekirdek kaynak kodundan doldurun
@@ -114,9 +123,11 @@ Lütfen **tümünü** https://kernelsu.org/zh_CN/guide/installation.html adresin
## Lisans ## Lisans
- `kernel` dizinindeki dosyalar [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) lisansı altındadır. - `kernel` dizinindeki dosyalar [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) lisansı altındadır.
- `kernel` dizini dışındaki tüm diğer bölümler [GPL-3.0 veya daha üstü](https://www.gnu.org/licenses/gpl-3.0.html) lisansı altındadır. - Anime karakter ifadeleri içeren `ic_launcher(?!.*alt.*).*` dosyalarının görüntüleri [怡子曰曰](https://space.bilibili.com/10545509) tarafından telif hakkıyla korunmaktadır, görüntülerdeki Marka Fikri Mülkiyeti [明风 OuO](https://space.bilibili.com/274939213)'ye aittir ve vektörleştirme @MiRinChan tarafından yapılmıştır. Bu dosyaları kullanmadan önce, [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt) ile uyumlu olmanın yanı sıra, bu sanatsal içerikleri kullanmak için iki yazarın yetkilendirmesine de uymanız gerekir.
- Yukarıda belirtilen dosyalar veya dizinler hariç, diğer tüm parçalar [GPL-3.0 veya üzeri](https://www.gnu.org/licenses/gpl-3.0.html)'dir.
## Afdian Bağlantısı ## Afdian Bağlantısı
- https://afdian.com/a/shirkneko - https://afdian.com/a/shirkneko
## Sponsor Listesi ## Sponsor Listesi
@@ -127,8 +138,6 @@ Lütfen **tümünü** https://kernelsu.org/zh_CN/guide/installation.html adresin
- [yspbwx2010](https://github.com/yspbwx2010) Çok teşekkür ederim - [yspbwx2010](https://github.com/yspbwx2010) Çok teşekkür ederim
- [DARKWWEE](https://github.com/DARKWWEE) 100 USDT için teşekkürler - [DARKWWEE](https://github.com/DARKWWEE) 100 USDT için teşekkürler
Eğer yukarıdaki listede adınız yoksa, zamanında güncelleyeceğim, herkese tekrar teşekkür ederim
## Katkıda Bulunanlar ## Katkıda Bulunanlar
- [KernelSU](https://github.com/tiann/KernelSU): Orijinal proje - [KernelSU](https://github.com/tiann/KernelSU): Orijinal proje
@@ -139,4 +148,4 @@ Eğer yukarıdaki listede adınız yoksa, zamanında güncelleyeceğim, herkese
- [Magisk](https://github.com/topjohnwu/Magisk): Güçlü root aracı - [Magisk](https://github.com/topjohnwu/Magisk): Güçlü root aracı
- [genuine](https://github.com/brevent/genuine/): APK v2 imza doğrulama - [genuine](https://github.com/brevent/genuine/): APK v2 imza doğrulama
- [Diamorphine](https://github.com/m0nad/Diamorphine): Bazı rootkit becerileri - [Diamorphine](https://github.com/m0nad/Diamorphine): Bazı rootkit becerileri
- [KernelPatch](https://github.com/bmax121/KernelPatch): KernelPatch, APatch\'in çekirdek modüllerini uygulamak için kritik bir parçadır - [KernelPatch](https://github.com/bmax121/KernelPatch): KernelPatch, APatch\'in çekirdek modüllerini uygulamak için kritik bir parçadır

183
docs/tr/SukiSU-mini.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 185 KiB

View File

@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="128"
height="128"
viewBox="0 0 128 128"
version="1.1"
id="svg1"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
sodipodi:docname="zakomonochrome-128.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#999999"
borderopacity="1"
inkscape:showpageshadow="2"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="px"
inkscape:zoom="2.6185048"
inkscape:cx="59.957881"
inkscape:cy="71.032903"
inkscape:window-width="1280"
inkscape:window-height="696"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1" />
<g
inkscape:label="图层 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:#ffffff;stroke:#000000;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.3;stroke-dasharray:none;paint-order:fill markers stroke;fill-opacity:1"
id="rect1"
width="128"
height="128"
x="0"
y="0"
rx="7.772471"
ry="7.772471" />
<path
id="path101"
style="fill:#ffffff;fill-opacity:0.734285;stroke:#000000;stroke-width:4.27504;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.3;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke"
d="m 42.510282,81.796052 c 0,0 -7.224141,-5.638356 -10.043315,-9.338525 M 14.847106,81.97224 25.41902,71.576535 m 0.17619,-6.695549 2.819179,19.910444 M 11.675534,73.338532 38.281518,71.047931 M 43.567475,62.7666 34.40515,62.942814 M 34.22896,62.590425 33.524162,48.494537 m -18.500855,1.58577 17.972249,-1.409582 m -11.8053,-5.462154 0.352397,18.853251"
inkscape:label="杂" />
<path
id="path111"
style="fill:#ffffff;fill-opacity:0.734285;stroke:#000000;stroke-width:3.94824;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.3;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke"
d="M 55.912937,82.876745 79.671596,81.412163 M 59.330273,75.391135 74.952411,74.089291 m -9.43837,-14.157553 1.139102,14.645756 m -8.299247,-7.160159 16.273048,-1.464569 m 0.650926,8.136525 0.325472,-14.808482 m -0.162747,0.162739 -17.900363,0.976379 m 0,-0.162738 1.952774,14.645756 m 12.042061,-21.154974 1.464576,-6.346492 m 0,-0.650928 -12.042063,0.650928 m -0.650918,6.509218 0.325459,-8.787441"
inkscape:label="鱼" />
<path
d="m 95.08569,51.121163 c -1.90515,0.116064 -3.64694,0.97349 -4.86738,2.391307 -1.34538,1.56738 -1.91476,3.733159 -1.59523,6.070852 0.40842,2.982962 2.1502,6.17135 5.13887,9.411078 0.63424,0.68546 1.08109,1.129773 1.98202,1.967071 1.58321,1.469144 3.01507,2.634638 4.9875,4.052454 0.70392,0.50905 2.09253,1.453525 2.61627,1.781734 l 0.15133,0.09594 0.22103,-0.140663 c 0.80481,-0.515755 2.23909,-1.504852 3.08956,-2.130057 3.21689,-2.364488 5.79232,-4.737902 7.70228,-7.100167 3.09676,-3.831409 4.4133,-7.562359 3.80549,-10.773058 -0.42043,-2.210414 -1.82588,-4.039057 -3.81992,-4.967887 -0.85767,-0.399664 -1.69132,-0.607312 -2.6355,-0.656431 -1.22285,-0.0647 -2.42648,0.178619 -3.57485,0.721182 -1.95561,0.922124 -3.58927,2.719503 -4.61752,5.081755 -0.072,0.165235 -0.1394,0.310355 -0.14895,0.319295 -0.0312,0.02902 -0.0648,-0.02679 -0.19458,-0.330457 -0.30752,-0.714476 -0.91055,-1.752718 -1.38382,-2.377871 -0.4853,-0.645282 -1.2661,-1.431214 -1.84749,-1.862143 -1.50155,-1.114153 -3.26013,-1.658924 -5.00914,-1.553996 z"
id="path1-4"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.00231605" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

101
docs/zh/README.md Normal file
View File

@@ -0,0 +1,101 @@
# SukiSU Ultra
<img align='right' src='SukiSU-mini.svg' width='220px' alt="sukisu logo">
[English](../README.md) | **简体中文** | [日本語](../ja/README.md) | [Türkçe](../tr/README.md)
一个 Android 上基于内核的 root 方案,由 [`tiann/KernelSU`](https://github.com/tiann/KernelSU) 分叉而来,添加了一些有趣的变更。
[![最新发行](https://img.shields.io/github/v/release/SukiSU-Ultra/SukiSU-Ultra?label=Release&logo=github)](https://github.com/tiann/KernelSU/releases/latest)
[![频道](https://img.shields.io/badge/Follow-Telegram-blue.svg?logo=telegram)](https://t.me/Sukiksu)
[![协议: 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/tiann/KernelSU?logo=gnu)](/LICENSE)
## 特性
1. 基于内核的 `su` 和权限管理。
2. 基于 [Magic Mount](https://github.com/5ec1cff/KernelSU) 的模块系统。
3. [App Profile](https://kernelsu.org/zh_CN/guide/app-profile.html): 把 Root 权限关进笼子里。
4. 支持 non-GKI 与 GKI 1.0。
5. KPM 支持
6. 可调整管理器外观,可自定义 susfs 配置。
## 兼容状态
- KernelSU 官方支持 GKI 2.0 的设备(内核版本 5.10 以上)。
- 旧内核也是兼容的(最低 4.14+),不过需要自己编译内核。
- 通过更多的反向移植KernelSU 可以支持 3.x 内核3.4-3.18)。
- 目前支持架构 : `arm64-v8a``armeabi-v7a (bare)``X86_64`
## 安装指导
查看 [`guide/installation.md`](guide/installation.md)
## 集成指导
查看 [`guide/how-to-integrate.md`](guide/how-to-integrate.md)
## 参与翻译
要将 SukiSU 翻译成您的语言,或完善现有的翻译,请使用 [Crowdin](https://crowdin.com/project/SukiSU-Ultra).
## KPM 支持
- 基于 KernelPatch 开发,移除了与 KernelSU 重复的功能。
- 正在进行WIP通过集成附加功能来扩展 APatch 兼容性,以确保跨不同实现的兼容性。
**开源仓库**: [https://github.com/ShirkNeko/SukiSU_KernelPatch_patch](https://github.com/ShirkNeko/SukiSU_KernelPatch_patch)
**KPM 模板**: [https://github.com/udochina/KPM-Build-Anywhere](https://github.com/udochina/KPM-Build-Anywhere)
> [!Note]
>
> 1. 需要 `CONFIG_KPM=y`
> 2. Non-GKI 设备需要 `CONFIG_KALLSYMS=y` and `CONFIG_KALLSYMS_ALL=y`
> 3. 对于低于 `4.19` 的内核,需要从 `4.19` 的 `set_memory.h` 进行反向移植。
## 故障排除
1. 卸载管理器后系统卡住?
卸载 _com.sony.playmemories.mobile_
## 许可证
- 目录 `kernel` 下所有文件为 [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)。
- 有动漫人物图片表情包的这些文件 `ic_launcher(?!.*alt.*).*` 的图像版权为[怡子曰曰](https://space.bilibili.com/10545509)所有,图像中的知识产权由[明风 OuO](https://space.bilibili.com/274939213)所有,矢量化由 @MiRinChan 完成,在使用这些文件之前,除了必须遵守 [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt) 以外,还需要遵守向前两者索要使用这些艺术内容的授权。
- 除上述文件及目录的其他部分均为 [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html)。
## 赞助
- [ShirkNeko](https://afdian.com/a/shirkneko) (SukiSU 主要维护者)
- [weishu](https://github.com/sponsors/tiann) (KernelSU 作者)
## ShirkNeko 的赞助列表
- [Ktouls](https://github.com/Ktouls) 非常感谢你给我带来的支持
- [zaoqi123](https://github.com/zaoqi123) 请我喝奶茶也不错
- [wswzgdg](https://github.com/wswzgdg) 非常感谢对此项目的支持
- [yspbwx2010](https://github.com/yspbwx2010) 非常感谢
- [DARKWWEE](https://github.com/DARKWWEE) 感谢老哥的 100 USDT
- [Saksham Singla](https://github.com/TypeFlu) 网站的提供以及维护
- [OukaroMF](https://github.com/OukaroMF) 网站域名捐赠
## 鸣谢
- [KernelSU](https://github.com/tiann/KernelSU): 上游
- [MKSU](https://github.com/5ec1cff/KernelSU): 魔法坐骑支持
- [RKSU](https://github.com/rsuntk/KernelsU): non-GKI 支持
- [susfs](https://gitlab.com/simonpunk/susfs4ksu): 隐藏内核补丁以及用户空间模组的 KernelSU 附件
- [KernelPatch](https://github.com/bmax121/KernelPatch): KernelPatch 是内核模块 APatch 实现的关键部分
<details>
<summary>KernelSU 的鸣谢</summary>
- [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 技巧。
</details>

183
docs/zh/SukiSU-mini.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 185 KiB

188
docs/zh/SukiSU.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 200 KiB

View File

@@ -0,0 +1,97 @@
# 集成指导
SukiSU 可以集成到 GKI 和 non-GKI 内核中,并且已反向移植到 4.14 版本。
<!-- 应该是 3.4 版本,但 backslashxx 的 syscall manual hook 无法在 SukiSU 中使用-->
有些 OEM 定制可能导致多达 50% 的内核代码超出内核树代码,而非来自上游 Linux 内核或 ACK。因此non-GKI 内核的定制特性导致了严重的内核碎片化,而且我们缺乏构建它们的通用方法。因此,我们无法提供 non-GKI 内核的启动映像。
前提条件:开源的、可启动的内核。
## Hook 方法
1. **KPROBES hook:**
- GKI kernels 的默认 hook 方法。
- 需要 `# CONFIG_KSU_MANUAL_HOOK is not set`(未设定) & `CONFIG_KPROBES=y`
- 用作可加载的内核模块 (LKM).
2. **Manual hook:**
<!-- - backslashxx's syscall manual hook: https://github.com/backslashxx/KernelSU/issues/5 (v1.5 version is not available at the moment, if you want to use it, please use v1.4 version, or standard KernelSU hooks)-->
- 需要 `CONFIG_KSU_MANUAL_HOOK=y`
- 需要 [`guide/how-to-integrate.md`](how-to-integrate.md)
- 需要 [https://github.com/~](https://github.com/tiann/KernelSU/blob/main/website/docs/guide/how-to-integrate-for-non-gki.md#manually-modify-the-kernel-source)
3. **Tracepoint Hook:**
- 自 SukiSU commit [49b01aad](https://github.com/SukiSU-Ultra/SukiSU-Ultra/commit/49b01aad74bcca6dba5a8a2e053bb54b648eb124) 引入的 hook 方法
- 需要 `CONFIG_KSU_TRACEPOINT_HOOK=y`
- 需要 [`guide/tracepoint-hook.md`](tracepoint-hook.md)
<!-- This part refer to [rsuntk/KernelSU](https://github.com/rsuntk/KernelSU). -->
如果您能够构建可启动内核,有两种方法可以将 KernelSU 集成到内核源代码中:
1. 使用 `kprobe` 自动集成
2. 手动集成
## 与 kprobe 集成
适用:
- GKI 内核
不适用:
- non-GKI 内核
KernelSU 使用 kprobe 机制来做内核的相关 hook如果 _kprobe_ 可以在你编译的内核中正常运行,那么推荐用这个方法来集成。
请参阅此文档 [https://github.com/~](https://github.com/tiann/KernelSU/blob/main/website/docs/guide/how-to-integrate-for-non-gki.md#integrate-with-kprobe)。虽然标题为“适用于 non-GKI”但仅适用于 GKI。
替换 KernelSU 添加到内核源代码树的步骤的执行命令为:
```sh
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s main
```
## 手动修改内核源代码
适用:
- GKI 内核
- non-GKI 内核
请参考此文档 [https://github.com/~ (non-GKI 内核集成)](https://github.com/tiann/KernelSU/blob/main/website/docs/guide/how-to-integrate-for-non-gki.md#manually-modify-the-kernel-source) 和 [https://github.com/~ (GKI 内核构建)](https://kernelsu.org/zh_CN/guide/how-to-build.html) 进行手动集成。虽然第一个链接的标题是“适用于 non-GKI”但它也适用于 GKI。两者都可以正常工作。
还有另一种集成方法,但是仍在开发中。
<!-- 这是 backslashxx 的syscall manual hook但目前无法使用。 -->
将 KernelSUSukiSU添加到内核源代码树的步骤的运行命令将被替换为
### GKI 内核
```sh
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s main
```
### non-GKI 内核
```sh
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s nongki
```
### 带有 susfs 的 GKI / non-GKI 内核(实验)
```sh
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-{{branch}}
```
分支:
- `main` (susfs-main)
- `test` (susfs-test)
- 版本号 (例如: susfs-1.5.7, 你需要在 [分支](https://github.com/SukiSU-Ultra/SukiSU-Ultra/branches) 里找到它)

View File

@@ -0,0 +1,34 @@
# 安装指导
您可以前往 [KernelSU 文档 - 安装](https://kernelsu.org/guide/installation.html) 获取有关如何安装的参考,这里只是额外的说明。
## 通过加载可加载内核模块 (LKM) 进行安装
请参阅 [KernelSU 文档 - LKM 安装](https://kernelsu.org/guide/installation.html#lkm-installation)
**Android™**(商标,意为获得 Google 移动服务的许可12 开始,搭载内核版本 5.10 或更高版本的设备必须搭载 GKI 内核。因此你或许可以使用 LKM 模式。
## 通过安装内核进行安装
请参阅 [KernelSU 文档 - GKI 模式安装](https://kernelsu.org/guide/installation.html#gki-mode-installation)
我们提供预编译的内核供您使用:
- [ShirkNeko 内核](https://github.com/ShirkNeko/GKI_KernelSU_SUSFS)(添加了 ZRAM 压缩算法补丁、susfs 文件和 KPM 文件。适用于很多设备。)
- [MiRinFork 内核](https://github.com/MiRinFork/GKI_SukiSU_SUSFS)(添加了 susfs 文件和 KPM 文件。最接近 GKI 的内核,适用于大多数设备。)
虽然某些设备可以使用 LKM 模式安装,但无法使用 GKI 内核将其安装到设备上;因此,需要手动修改内核进行编译。例如:
- 欧珀(一加、真我)
- 魅族
此外,我们还为您的 OnePlus 设备提供预编译的内核:
- [ShirkNeko/Action_OnePlus_MKSU_SUSFS](https://github.com/ShirkNeko/Action_OnePlus_MKSU_SUSFS)(添加 ZRAM 压缩算法补丁、susfs 和 KPM。
使用上面的链接Fork 到 GitHub Action填写构建参数进行编译最后将 zip 文件以 AnyKernel3 后缀上传到 GitHub Action。
> [!Note]
>
> - 使用时,您只需填写版本号的前两部分,例如 `5.10`、`6.1`...
> - 使用前请确保您了解处理器名称、内核版本等信息。

View File

@@ -0,0 +1,239 @@
# Tracepoint Hook 集成
## 介绍
自 commit [49b01aad](https://github.com/SukiSU-Ultra/SukiSU-Ultra/commit/49b01aad74bcca6dba5a8a2e053bb54b648eb124) 起SukiSU 引入了 Tracepoint Hook
该 Hook 理论上相比于 Kprobes Hook性能开销更小但次于 Manual Hook / Syscall Hook
> [!NOTE]
> 本教程参考了 [backslashxx/KernelSU#5](https://github.com/backslashxx/KernelSU/issues/5) 的 syscall hook v1.4 版本钩子,以及原版 KernelSU 的 [Manual Hook](https://kernelsu.org/guide/how-to-integrate-for-non-gki.html#manually-modify-the-kernel-source)
## Guide
### execve 钩子(`exec.c`
一般需要修改 `fs/exec.c``do_execve``compat_do_execve` 方法
```patch
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -78,6 +78,10 @@
#include <trace/hooks/sched.h>
#endif
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+#include <../drivers/kernelsu/ksu_trace.h>
+#endif
+
EXPORT_TRACEPOINT_SYMBOL_GPL(task_rename);
static int bprm_creds_from_file(struct linux_binprm *bprm);
@@ -2037,6 +2041,9 @@ static int do_execve(struct filename *filename,
{
struct user_arg_ptr argv = { .ptr.native = __argv };
struct user_arg_ptr envp = { .ptr.native = __envp };
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+ trace_ksu_trace_execveat_hook((int *)AT_FDCWD, &filename, &argv, &envp, 0);
+#endif
return do_execveat_common(AT_FDCWD, filename, argv, envp, 0);
}
@@ -2064,6 +2071,9 @@ static int compat_do_execve(struct filename *filename,
.is_compat = true,
.ptr.compat = __envp,
};
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+ trace_ksu_trace_execveat_hook((int *)AT_FDCWD, &filename, &argv, &envp, 0)); // 32-bit su and 32-on-64 support
+#endif
return do_execveat_common(AT_FDCWD, filename, argv, envp, 0);
}
```
### faccessat 钩子 (`open.c`)
一般需要修改 `/fs/open.c``do_faccessat` 方法
```patch
--- a/fs/open.c
+++ b/fs/open.c
@@ -37,6 +37,10 @@
#include "internal.h"
#include <trace/hooks/syscall_check.h>
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+#include <../drivers/kernelsu/ksu_trace.h>
+#endif
+
int do_truncate(struct user_namespace *mnt_userns, struct dentry *dentry,
loff_t length, unsigned int time_attrs, struct file *filp)
{
@@ -468,6 +472,9 @@ static long do_faccessat(int dfd, const char __user *filename, int mode, int fla
SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
{
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+ trace_ksu_trace_faccessat_hook(&dfd, &filename, &mode, NULL);
+#endif
return do_faccessat(dfd, filename, mode, 0);
}
```
如果没有 `do_faccessat` 方法,可以找 `faccessat` 的 SYSCALL 定义(对于早于 4.17 的内核)
```patch
--- a/fs/open.c
+++ b/fs/open.c
@@ -31,6 +31,9 @@
#include <linux/ima.h>
#include <linux/dnotify.h>
#include <linux/compat.h>
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+#include <../drivers/kernelsu/ksu_trace.h>
+#endif
#include "internal.h"
@@ -369,6 +372,9 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
int res;
unsigned int lookup_flags = LOOKUP_FOLLOW;
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+ trace_ksu_trace_faccessat_hook(&dfd, &filename, &mode, NULL);
+#endif
if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
return -EINVAL;
```
### sys_read 钩子 ( `read_write.c` )
需要修改 `fs/read_write.c``sys_read` 方法4.19 及以上)
```patch
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -25,6 +25,10 @@
#include <linux/uaccess.h>
#include <asm/unistd.h>
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+#include <../drivers/kernelsu/ksu_trace.h>
+#endif
+
const struct file_operations generic_ro_fops = {
.llseek = generic_file_llseek,
.read_iter = generic_file_read_iter,
@@ -630,6 +634,9 @@ ssize_t ksys_read(unsigned int fd, char __user *buf, size_t count)
SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
{
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+ trace_ksu_trace_sys_read_hook(fd, &buf, &count);
+#endif
return ksys_read(fd, buf, count);
}
```
或者是 `read` 的 SYSCALL 定义4.14 及以下)
```patch
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -25,6 +25,11 @@
#include <linux/uaccess.h>
#include <asm/unistd.h>
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+#include <../drivers/kernelsu/ksu_trace.h>
+#endif
+
+
const struct file_operations generic_ro_fops = {
.llseek = generic_file_llseek,
.read_iter = generic_file_read_iter,
@@ -575,6 +580,9 @@ SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
if (f.file) {
loff_t pos = file_pos_read(f.file);
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+ trace_ksu_trace_sys_read_hook(fd, &buf, &count);
+#endif
ret = vfs_read(f.file, buf, count, &pos);
if (ret >= 0)
file_pos_write(f.file, pos);
```
### fstatat 钩子 ( `stat.c` )
需要修改 `stat.c``newfstatat` SYSCALL 定义
如果需要 32 位支持,还需要修改 `statat64` SYSCALL 定义
```patch
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -24,6 +24,10 @@
#include "internal.h"
#include "mount.h"
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+#include <../drivers/kernelsu/ksu_trace.h>
+#endif
+
/**
* generic_fillattr - Fill in the basic attributes from the inode struct
* @mnt_userns: user namespace of the mount the inode was found from
@@ -408,6 +412,10 @@ SYSCALL_DEFINE4(newfstatat, int, dfd, const char __user *, filename,
struct kstat stat;
int error;
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+ trace_ksu_trace_stat_hook(&dfd, &filename, &flag);
+#endif
+
error = vfs_fstatat(dfd, filename, &stat, flag);
if (error)
return error;
@@ -559,6 +567,10 @@ SYSCALL_DEFINE4(fstatat64, int, dfd, const char __user *, filename,
struct kstat stat;
int error;
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+ trace_ksu_trace_stat_hook(&dfd, &filename, &flag); /* 32-bit su support */
+#endif
+
error = vfs_fstatat(dfd, filename, &stat, flag);
if (error)
return error;
```
### input 钩子 (`input.c` ,用于进入KSU系的内置安全模式)
需要修改 `drivers/input/input.c``input_event` 方法,而不是 `input_handle_event`
```patch
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -26,6 +26,10 @@
#include "input-compat.h"
#include "input-poller.h"
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+#include <../../drivers/kernelsu/ksu_trace.h>
+#endif
+
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("Input core");
MODULE_LICENSE("GPL");
@@ -451,6 +455,10 @@ void input_event(struct input_dev *dev,
{
unsigned long flags;
+#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK)
+ trace_ksu_trace_input_hook(&type, &code, &value);
+#endif
+
if (is_event_supported(type, dev->evbit, EV_MAX)) {
spin_lock_irqsave(&dev->event_lock, flags);
```

View File

@@ -56,8 +56,8 @@ ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:' CommentPragmas: '^ IWYU pragma:'
#CompactNamespaces: false # Unknown to clang-format-4.0 #CompactNamespaces: false # Unknown to clang-format-4.0
ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 8 ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 8 ContinuationIndentWidth: 4
Cpp11BracedListStyle: false Cpp11BracedListStyle: false
DerivePointerAlignment: false DerivePointerAlignment: false
DisableFormat: false DisableFormat: false
@@ -501,7 +501,7 @@ IncludeCategories:
IncludeIsMainRegex: '(Test)?$' IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false IndentCaseLabels: false
#IndentPPDirectives: None # Unknown to clang-format-5.0 #IndentPPDirectives: None # Unknown to clang-format-5.0
IndentWidth: 8 IndentWidth: 4
IndentWrappedFunctionNames: false IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave JavaScriptQuotes: Leave
JavaScriptWrapImports: true JavaScriptWrapImports: true
@@ -511,7 +511,7 @@ MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1 MaxEmptyLinesToKeep: 1
NamespaceIndentation: None NamespaceIndentation: None
#ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0 #ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0
ObjCBlockIndentWidth: 8 ObjCBlockIndentWidth: 4
ObjCSpaceAfterProperty: true ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true ObjCSpaceBeforeProtocolList: true
@@ -543,6 +543,6 @@ SpacesInCStyleCastParentheses: false
SpacesInParentheses: false SpacesInParentheses: false
SpacesInSquareBrackets: false SpacesInSquareBrackets: false
Standard: Cpp03 Standard: Cpp03
TabWidth: 8 TabWidth: 4
UseTab: Always UseTab: Never
... ...

22
kernel/.gitignore vendored Normal file
View File

@@ -0,0 +1,22 @@
.cache/
.thinlto-cache/
compile_commands.json
*.ko
*.o
*.mod
*.lds
*.mod.o
.*.o*
.*.mod*
*.ko*
*.mod.c
*.symvers*
*.order
.*.ko.cmd
.tmp_versions/
libs/
obj/
CLAUDE.md
.ddk-version
.vscode/settings.json

11
kernel/.vscode/c_cpp_properties.json vendored Normal file
View File

@@ -0,0 +1,11 @@
{
"configurations": [
{
"name": "Linux",
"cStandard": "c11",
"intelliSenseMode": "gcc-arm64",
"compileCommands": "${workspaceFolder}/compile_commands.json"
}
],
"version": 4
}

92
kernel/.vscode/generate_compdb.py vendored Normal file
View File

@@ -0,0 +1,92 @@
#!/usr/bin/env python3
from __future__ import print_function, division
import argparse
import fnmatch
import functools
import json
import math
import multiprocessing
import os
import re
import sys
CMD_VAR_RE = re.compile(r'^\s*(?:saved)?cmd_(\S+)\s*:=\s*(.+)\s*$', re.MULTILINE)
SOURCE_VAR_RE = re.compile(r'^\s*source_(\S+)\s*:=\s*(.+)\s*$', re.MULTILINE)
def print_progress_bar(progress):
progress_bar = '[' + '|' * int(50 * progress) + '-' * int(50 * (1.0 - progress)) + ']'
print('\r', progress_bar, "{0:.1%}".format(progress), end='\r', file=sys.stderr)
def parse_cmd_file(out_dir, cmdfile_path):
with open(cmdfile_path, 'r') as cmdfile:
cmdfile_content = cmdfile.read()
commands = { match.group(1): match.group(2) for match in CMD_VAR_RE.finditer(cmdfile_content) }
sources = { match.group(1): match.group(2) for match in SOURCE_VAR_RE.finditer(cmdfile_content) }
return [{
'directory': out_dir,
'command': commands[o_file_name],
'file': source,
'output': o_file_name
} for o_file_name, source in sources.items()]
def gen_compile_commands(cmd_file_search_path, out_dir):
print("Building *.o.cmd file list...", file=sys.stderr)
out_dir = os.path.abspath(out_dir)
if not cmd_file_search_path:
cmd_file_search_path = [out_dir]
cmd_files = []
for search_path in cmd_file_search_path:
if (os.path.isdir(search_path)):
for cur_dir, subdir, files in os.walk(search_path):
cmd_files.extend(os.path.join(cur_dir, cmdfile_name) for cmdfile_name in fnmatch.filter(files, '*.o.cmd'))
else:
cmd_files.extend(search_path)
if not cmd_files:
print("No *.o.cmd files found in", ", ".join(cmd_file_search_path), file=sys.stderr)
return
print("Parsing *.o.cmd files...", file=sys.stderr)
n_processed = 0
print_progress_bar(0)
compdb = []
pool = multiprocessing.Pool()
try:
for compdb_chunk in pool.imap_unordered(functools.partial(parse_cmd_file, out_dir), cmd_files, chunksize=int(math.sqrt(len(cmd_files)))):
compdb.extend(compdb_chunk)
n_processed += 1
print_progress_bar(n_processed / len(cmd_files))
finally:
pool.terminate()
pool.join()
print(file=sys.stderr)
print("Writing compile_commands.json...", file=sys.stderr)
with open('compile_commands.json', 'w') as compdb_file:
json.dump(compdb, compdb_file, indent=1)
def main():
cmd_parser = argparse.ArgumentParser()
cmd_parser.add_argument('-O', '--out-dir', type=str, default=os.getcwd(), help="Build output directory")
cmd_parser.add_argument('cmd_file_search_path', nargs='*', help="*.cmd file search path")
gen_compile_commands(**vars(cmd_parser.parse_args()))
if __name__ == '__main__':
main()

16
kernel/.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,16 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Generate compile_commands.json",
"type": "process",
"command": "python",
"args": [
"${workspaceRoot}/.vscode/generate_compdb.py"
],
"problemMatcher": []
}
]
}

View File

@@ -1,28 +1,42 @@
menu "KernelSU" menu "KernelSU"
config KSU config KSU
tristate "KernelSU function support" tristate "KernelSU function support"
depends on OVERLAY_FS default y
default y help
help Enable kernel-level root privileges on Android System.
Enable kernel-level root privileges on Android System. To compile as a module, choose M here: the
To compile as a module, choose M here: the module will be called kernelsu.
module will be called kernelsu.
config KSU_DEBUG config KSU_DEBUG
bool "KernelSU debug mode" bool "KernelSU debug mode"
depends on KSU depends on KSU
default n default n
help help
Enable KernelSU debug mode. Enable KernelSU debug mode.
config KSU_MANUAL_SU
bool "Use manual su"
depends on KSU
default y
help
Use manual su and authorize the corresponding command line and application via prctl
config KPM config KPM
bool "Enable SukiSU KPM" bool "Enable SukiSU KPM"
depends on KSU && 64BIT depends on KSU && 64BIT
default n default n
help help
Enabling this option will activate the KPM feature of SukiSU. Enabling this option will activate the KPM feature of SukiSU.
This option is suitable for scenarios where you need to force KPM to be enabled. This option is suitable for scenarios where you need to force KPM to be enabled.
but it may affect system stability. but it may affect system stability.
select KALLSYMS
select KALLSYMS_ALL
config KSU_MANUAL_HOOK
bool "Hook KernelSU manually"
depends on KSU != m
help
If enabled, Hook required KernelSU syscalls with manually-patched function.
endmenu endmenu

View File

@@ -1,12 +1,29 @@
kernelsu-objs := ksu.o kernelsu-objs := ksu.o
kernelsu-objs += allowlist.o kernelsu-objs += allowlist.o
kernelsu-objs += app_profile.o
kernelsu-objs += dynamic_manager.o
kernelsu-objs += apk_sign.o kernelsu-objs += apk_sign.o
kernelsu-objs += sucompat.o kernelsu-objs += sucompat.o
kernelsu-objs += syscall_hook_manager.o
kernelsu-objs += throne_tracker.o kernelsu-objs += throne_tracker.o
kernelsu-objs += core_hook.o kernelsu-objs += pkg_observer.o
kernelsu-objs += throne_tracker.o
kernelsu-objs += umount_manager.o
kernelsu-objs += setuid_hook.o
kernelsu-objs += kernel_umount.o
kernelsu-objs += supercalls.o
kernelsu-objs += feature.o
kernelsu-objs += ksud.o kernelsu-objs += ksud.o
kernelsu-objs += embed_ksud.o kernelsu-objs += embed_ksud.o
kernelsu-objs += kernel_compat.o kernelsu-objs += seccomp_cache.o
kernelsu-objs += file_wrapper.o
kernelsu-objs += throne_comm.o
kernelsu-objs += sulog.o
ifeq ($(CONFIG_KSU_MANUAL_SU), y)
ccflags-y += -DCONFIG_KSU_MANUAL_SU
kernelsu-objs += manual_su.o
endif
kernelsu-objs += selinux/selinux.o kernelsu-objs += selinux/selinux.o
kernelsu-objs += selinux/sepolicy.o kernelsu-objs += selinux/sepolicy.o
@@ -18,26 +35,84 @@ obj-$(CONFIG_KSU) += kernelsu.o
obj-$(CONFIG_KPM) += kpm/ obj-$(CONFIG_KPM) += kpm/
REPO_OWNER := SukiSU-Ultra
REPO_NAME := SukiSU-Ultra
REPO_BRANCH := main
KSU_VERSION_API := 4.0.0
GIT_BIN := /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin git
CURL_BIN := /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin curl
KDIR := $(KDIR)
MDIR := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
ifneq ($(KDIR),)
$(info -- KDIR: $(KDIR))
$(info -- MDIR: $(MDIR))
endif
KSU_GITHUB_VERSION := $(shell $(CURL_BIN) -s "https://api.github.com/repos/$(REPO_OWNER)/$(REPO_NAME)/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
KSU_GITHUB_VERSION_COMMIT := $(shell $(CURL_BIN) -sI "https://api.github.com/repos/$(REPO_OWNER)/$(REPO_NAME)/commits?sha=$(REPO_BRANCH)&per_page=1" | grep -i "link:" | sed -n 's/.*page=\([0-9]*\)>; rel="last".*/\1/p')
ifeq ($(findstring $(srctree),$(src)),$(srctree))
KSU_SRC := $(src)
else
KSU_SRC := $(srctree)/$(src)
endif
ifneq ($(shell test -e $(KSU_SRC)/../.git && echo "in-tree"),in-tree)
KSU_SRC := $(MDIR)
endif
LOCAL_GIT_EXISTS := $(shell test -e $(KSU_SRC)/../.git && echo 1 || echo 0)
define get_ksu_version_full
v$1-$(shell cd $(KSU_SRC); $(GIT_BIN) rev-parse --short=8 HEAD)@$(shell cd $(KSU_SRC); $(GIT_BIN) rev-parse --abbrev-ref HEAD)
endef
ifeq ($(KSU_GITHUB_VERSION_COMMIT),)
ifeq ($(LOCAL_GIT_EXISTS),1)
$(shell cd $(KSU_SRC); [ -f ../.git/shallow ] && $(GIT_BIN) fetch --unshallow)
KSU_LOCAL_VERSION := $(shell cd $(KSU_SRC); $(GIT_BIN) rev-list --count $(REPO_BRANCH))
KSU_VERSION := $(shell expr 40000 + $(KSU_LOCAL_VERSION) - 2815)
$(info -- $(REPO_NAME) version (local .git): $(KSU_VERSION))
else
KSU_VERSION := 13000
$(warning -- Could not fetch version online or via local .git! Using fallback version: $(KSU_VERSION))
endif
else
KSU_VERSION := $(shell expr 40000 + $(KSU_GITHUB_VERSION_COMMIT) - 2815)
$(info -- $(REPO_NAME) version (GitHub): $(KSU_VERSION))
endif
ifeq ($(KSU_GITHUB_VERSION),)
ifeq ($(LOCAL_GIT_EXISTS),1)
$(shell cd $(KSU_SRC); [ -f ../.git/shallow ] && $(GIT_BIN) fetch --unshallow)
KSU_VERSION_FULL := $(call get_ksu_version_full,$(KSU_VERSION_API))
$(info -- $(REPO_NAME) version (local .git): $(KSU_VERSION_FULL))
$(info -- $(REPO_NAME) Formatted version (local .git): $(KSU_VERSION))
else
KSU_VERSION_FULL := v$(KSU_VERSION_API)-$(REPO_NAME)-unknown@unknown
$(warning -- $(REPO_NAME) version: $(KSU_VERSION_FULL))
endif
else
$(shell cd $(KSU_SRC); [ -f ../.git/shallow ] && $(GIT_BIN) fetch --unshallow)
KSU_VERSION_FULL := $(call get_ksu_version_full,$(KSU_GITHUB_VERSION))
$(info -- $(REPO_NAME) version (Github): $(KSU_VERSION_FULL))
endif
# .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 main)
# ksu_version: major * 10000 + git version + 606 for historical reasons
$(eval KSU_VERSION=$(shell expr 10000 + $(KSU_GIT_VERSION) + 606))
$(info -- KernelSU version: $(KSU_VERSION))
ccflags-y += -DKSU_VERSION=$(KSU_VERSION) ccflags-y += -DKSU_VERSION=$(KSU_VERSION)
else # If there is no .git file, the default version will be passed. ccflags-y += -DKSU_VERSION_FULL=\"$(KSU_VERSION_FULL)\"
$(warning "KSU_GIT_VERSION not defined! It is better to make KernelSU a git submodule!")
ccflags-y += -DKSU_VERSION=16 # Custom Signs
ifdef KSU_EXPECTED_SIZE
ccflags-y += -DEXPECTED_SIZE=$(KSU_EXPECTED_SIZE)
$(info -- Custom KernelSU Manager signature size: $(KSU_EXPECTED_SIZE))
endif endif
ifndef KSU_EXPECTED_SIZE ifdef KSU_EXPECTED_HASH
KSU_EXPECTED_SIZE := 0x35c ccflags-y += -DEXPECTED_HASH=\"$(KSU_EXPECTED_HASH)\"
endif $(info -- Custom KernelSU Manager signature hash: $(KSU_EXPECTED_HASH))
ifndef KSU_EXPECTED_HASH
KSU_EXPECTED_HASH := 947ae944f3de4ed4c21a7e4f7953ecf351bfa2b36239da37a34111ad29993eef
endif endif
ifdef KSU_MANAGER_PACKAGE ifdef KSU_MANAGER_PACKAGE
@@ -45,9 +120,15 @@ ccflags-y += -DKSU_MANAGER_PACKAGE=\"$(KSU_MANAGER_PACKAGE)\"
$(info -- SukiSU Manager package name: $(KSU_MANAGER_PACKAGE)) $(info -- SukiSU Manager package name: $(KSU_MANAGER_PACKAGE))
endif endif
$(info -- SukiSU Manager signature size: $(KSU_EXPECTED_SIZE)) ifeq ($(CONFIG_KSU_MANUAL_HOOK), y)
$(info -- SukiSU Manager signature hash: $(KSU_EXPECTED_HASH)) ccflags-y += -DKSU_MANUAL_HOOK
$(info -- Supported Unofficial Manager: 5ec1cff (GKI) ShirkNeko udochina (GKI and KPM)) $(info -- SukiSU: KSU_MANUAL_HOOK Temporarily discontinued)
else
ccflags-y += -DKSU_KPROBES_HOOK
ccflags-y += -DKSU_TP_HOOK
$(info -- SukiSU: KSU_TRACEPOINT_HOOK)
endif
KERNEL_VERSION := $(VERSION).$(PATCHLEVEL) KERNEL_VERSION := $(VERSION).$(PATCHLEVEL)
KERNEL_TYPE := Non-GKI KERNEL_TYPE := Non-GKI
# Check for GKI 2.0 (5.10+ or 6.x+) # Check for GKI 2.0 (5.10+ or 6.x+)
@@ -62,18 +143,30 @@ endif
$(info -- KERNEL_VERSION: $(KERNEL_VERSION)) $(info -- KERNEL_VERSION: $(KERNEL_VERSION))
$(info -- KERNEL_TYPE: $(KERNEL_TYPE)) $(info -- KERNEL_TYPE: $(KERNEL_TYPE))
$(info -- KERNEL_VERSION: $(KERNEL_VERSION)) ifeq ($(CONFIG_KPM), y)
ifeq ($(CONFIG_KPM),y)
$(info -- KPM is enabled) $(info -- KPM is enabled)
else else
$(info -- KPM is disabled) $(info -- KPM is disabled)
endif endif
# Check new vfs_getattr()
ifeq ($(shell grep -A1 "^int vfs_getattr" $(srctree)/fs/stat.c | grep -q "query_flags" ; echo $$?),0)
ccflags-y += -DKSU_HAS_NEW_VFS_GETATTR
endif
ccflags-y += -DEXPECTED_SIZE=$(KSU_EXPECTED_SIZE) # Function proc_ops check
ccflags-y += -DEXPECTED_HASH=\"$(KSU_EXPECTED_HASH)\" ifeq ($(shell grep -q "struct proc_ops " $(srctree)/include/linux/proc_fs.h; echo $$?),0)
ccflags-y += -DKSU_COMPAT_HAS_PROC_OPS
endif
ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat ccflags-y += -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat -Wno-missing-prototypes
ccflags-y += -Wno-declaration-after-statement -Wno-unused-function ccflags-y += -Wno-declaration-after-statement -Wno-unused-function -Wno-unused-variable
all:
make -C $(KDIR) M=$(MDIR) modules
compdb:
python3 $(MDIR)/.vscode/generate_compdb.py -O $(KDIR) $(MDIR)
clean:
make -C $(KDIR) M=$(MDIR) clean
# Keep a new line here!! Because someone may append config # Keep a new line here!! Because someone may append config

View File

@@ -1,3 +1,5 @@
#include <linux/mutex.h>
#include <linux/task_work.h>
#include <linux/capability.h> #include <linux/capability.h>
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/fs.h> #include <linux/fs.h>
@@ -8,14 +10,16 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/version.h> #include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
#include <linux/compiler_types.h> #include <linux/compiler_types.h>
#endif
#include "ksu.h"
#include "klog.h" // IWYU pragma: keep #include "klog.h" // IWYU pragma: keep
#include "ksud.h"
#include "selinux/selinux.h" #include "selinux/selinux.h"
#include "kernel_compat.h"
#include "allowlist.h" #include "allowlist.h"
#include "manager.h" #include "manager.h"
#include "syscall_hook_manager.h"
#define FILE_MAGIC 0x7f4b5355 // ' KSU', u32 #define FILE_MAGIC 0x7f4b5355 // ' KSU', u32
#define FILE_FORMAT_VERSION 3 // u32 #define FILE_FORMAT_VERSION 3 // u32
@@ -29,58 +33,61 @@ static DEFINE_MUTEX(allowlist_mutex);
static struct root_profile default_root_profile; static struct root_profile default_root_profile;
static struct non_root_profile default_non_root_profile; static struct non_root_profile default_non_root_profile;
static int allow_list_arr[PAGE_SIZE / sizeof(int)] __read_mostly __aligned(PAGE_SIZE); void persistent_allow_list(void);
static int allow_list_arr[PAGE_SIZE / sizeof(int)] __read_mostly
__aligned(PAGE_SIZE);
static int allow_list_pointer __read_mostly = 0; static int allow_list_pointer __read_mostly = 0;
static void remove_uid_from_arr(uid_t uid) static void remove_uid_from_arr(uid_t uid)
{ {
int *temp_arr; int *temp_arr;
int i, j; int i, j;
if (allow_list_pointer == 0) if (allow_list_pointer == 0)
return; return;
temp_arr = kmalloc(sizeof(allow_list_arr), GFP_KERNEL); temp_arr = kzalloc(sizeof(allow_list_arr), GFP_KERNEL);
if (temp_arr == NULL) { if (temp_arr == NULL) {
pr_err("%s: unable to allocate memory\n", __func__); pr_err("%s: unable to allocate memory\n", __func__);
return; return;
} }
for (i = j = 0; i < allow_list_pointer; i++) { for (i = j = 0; i < allow_list_pointer; i++) {
if (allow_list_arr[i] == uid) if (allow_list_arr[i] == uid)
continue; continue;
temp_arr[j++] = allow_list_arr[i]; temp_arr[j++] = allow_list_arr[i];
} }
allow_list_pointer = j; allow_list_pointer = j;
for (; j < ARRAY_SIZE(allow_list_arr); j++) for (; j < ARRAY_SIZE(allow_list_arr); j++)
temp_arr[j] = -1; temp_arr[j] = -1;
memcpy(&allow_list_arr, temp_arr, PAGE_SIZE); memcpy(&allow_list_arr, temp_arr, PAGE_SIZE);
kfree(temp_arr); kfree(temp_arr);
} }
static void init_default_profiles() static void init_default_profiles(void)
{ {
kernel_cap_t full_cap = CAP_FULL_SET; kernel_cap_t full_cap = CAP_FULL_SET;
default_root_profile.uid = 0; default_root_profile.uid = 0;
default_root_profile.gid = 0; default_root_profile.gid = 0;
default_root_profile.groups_count = 1; default_root_profile.groups_count = 1;
default_root_profile.groups[0] = 0; default_root_profile.groups[0] = 0;
memcpy(&default_root_profile.capabilities.effective, &full_cap, memcpy(&default_root_profile.capabilities.effective, &full_cap,
sizeof(default_root_profile.capabilities.effective)); sizeof(default_root_profile.capabilities.effective));
default_root_profile.namespaces = 0; default_root_profile.namespaces = 0;
strcpy(default_root_profile.selinux_domain, KSU_DEFAULT_SELINUX_DOMAIN); strcpy(default_root_profile.selinux_domain, KSU_DEFAULT_SELINUX_DOMAIN);
// This means that we will umount modules by default! // This means that we will umount modules by default!
default_non_root_profile.umount_modules = true; default_non_root_profile.umount_modules = true;
} }
struct perm_data { struct perm_data {
struct list_head list; struct list_head list;
struct app_profile profile; struct app_profile profile;
}; };
static struct list_head allow_list; static struct list_head allow_list;
@@ -90,437 +97,535 @@ static uint8_t allow_list_bitmap[PAGE_SIZE] __read_mostly __aligned(PAGE_SIZE);
#define KERNEL_SU_ALLOWLIST "/data/adb/ksu/.allowlist" #define KERNEL_SU_ALLOWLIST "/data/adb/ksu/.allowlist"
static struct work_struct ksu_save_work;
static struct work_struct ksu_load_work;
bool persistent_allow_list(void);
void ksu_show_allow_list(void) void ksu_show_allow_list(void)
{ {
struct perm_data *p = NULL; struct perm_data *p = NULL;
struct list_head *pos = NULL; struct list_head *pos = NULL;
pr_info("ksu_show_allow_list\n"); pr_info("ksu_show_allow_list\n");
list_for_each (pos, &allow_list) { list_for_each (pos, &allow_list) {
p = list_entry(pos, struct perm_data, list); p = list_entry(pos, struct perm_data, list);
pr_info("uid :%d, allow: %d\n", p->profile.current_uid, pr_info("uid :%d, allow: %d\n", p->profile.current_uid,
p->profile.allow_su); p->profile.allow_su);
} }
} }
#ifdef CONFIG_KSU_DEBUG #ifdef CONFIG_KSU_DEBUG
static void ksu_grant_root_to_shell() static void ksu_grant_root_to_shell(void)
{ {
struct app_profile profile = { struct app_profile profile = {
.version = KSU_APP_PROFILE_VER, .version = KSU_APP_PROFILE_VER,
.allow_su = true, .allow_su = true,
.current_uid = 2000, .current_uid = 2000,
}; };
strcpy(profile.key, "com.android.shell"); strcpy(profile.key, "com.android.shell");
strcpy(profile.rp_config.profile.selinux_domain, KSU_DEFAULT_SELINUX_DOMAIN); strcpy(profile.rp_config.profile.selinux_domain,
ksu_set_app_profile(&profile, false); KSU_DEFAULT_SELINUX_DOMAIN);
ksu_set_app_profile(&profile, false);
} }
#endif #endif
bool ksu_get_app_profile(struct app_profile *profile) bool ksu_get_app_profile(struct app_profile *profile)
{ {
struct perm_data *p = NULL; struct perm_data *p = NULL;
struct list_head *pos = NULL; struct list_head *pos = NULL;
bool found = false; bool found = false;
list_for_each (pos, &allow_list) { list_for_each (pos, &allow_list) {
p = list_entry(pos, struct perm_data, list); p = list_entry(pos, struct perm_data, list);
bool uid_match = profile->current_uid == p->profile.current_uid; bool uid_match = profile->current_uid == p->profile.current_uid;
if (uid_match) { if (uid_match) {
// found it, override it with ours // found it, override it with ours
memcpy(profile, &p->profile, sizeof(*profile)); memcpy(profile, &p->profile, sizeof(*profile));
found = true; found = true;
goto exit; goto exit;
} }
} }
exit: exit:
return found; return found;
} }
static inline bool forbid_system_uid(uid_t uid) { static inline bool forbid_system_uid(uid_t uid)
#define SHELL_UID 2000 {
#define SYSTEM_UID 1000 #define SHELL_UID 2000
return uid < SHELL_UID && uid != SYSTEM_UID; #define SYSTEM_UID 1000
return uid < SHELL_UID && uid != SYSTEM_UID;
} }
static bool profile_valid(struct app_profile *profile) static bool profile_valid(struct app_profile *profile)
{ {
if (!profile) { if (!profile) {
return false; return false;
} }
if (profile->version < KSU_APP_PROFILE_VER) { if (profile->version < KSU_APP_PROFILE_VER) {
pr_info("Unsupported profile version: %d\n", profile->version); pr_info("Unsupported profile version: %d\n", profile->version);
return false; return false;
} }
if (profile->allow_su) { if (profile->allow_su) {
if (profile->rp_config.profile.groups_count > KSU_MAX_GROUPS) { if (profile->rp_config.profile.groups_count > KSU_MAX_GROUPS) {
return false; return false;
} }
if (strlen(profile->rp_config.profile.selinux_domain) == 0) { if (strlen(profile->rp_config.profile.selinux_domain) == 0) {
return false; return false;
} }
} }
return true; return true;
} }
bool ksu_set_app_profile(struct app_profile *profile, bool persist) bool ksu_set_app_profile(struct app_profile *profile, bool persist)
{ {
struct perm_data *p = NULL; struct perm_data *p = NULL;
struct list_head *pos = NULL; struct list_head *pos = NULL;
bool result = false; bool result = false;
if (!profile_valid(profile)) { if (!profile_valid(profile)) {
pr_err("Failed to set app profile: invalid profile!\n"); pr_err("Failed to set app profile: invalid profile!\n");
return false; return false;
} }
list_for_each (pos, &allow_list) { list_for_each (pos, &allow_list) {
p = list_entry(pos, struct perm_data, list); p = list_entry(pos, struct perm_data, list);
// both uid and package must match, otherwise it will break multiple package with different user id // both uid and package must match, otherwise it will break multiple package with different user id
if (profile->current_uid == p->profile.current_uid && if (profile->current_uid == p->profile.current_uid &&
!strcmp(profile->key, p->profile.key)) { !strcmp(profile->key, p->profile.key)) {
// found it, just override it all! // found it, just override it all!
memcpy(&p->profile, profile, sizeof(*profile)); memcpy(&p->profile, profile, sizeof(*profile));
result = true; result = true;
goto out; goto out;
} }
} }
// not found, alloc a new node! // not found, alloc a new node!
p = (struct perm_data *)kmalloc(sizeof(struct perm_data), GFP_KERNEL); p = (struct perm_data *)kzalloc(sizeof(struct perm_data), GFP_KERNEL);
if (!p) { if (!p) {
pr_err("ksu_set_app_profile alloc failed\n"); pr_err("ksu_set_app_profile alloc failed\n");
return false; return false;
} }
memcpy(&p->profile, profile, sizeof(*profile)); memcpy(&p->profile, profile, sizeof(*profile));
if (profile->allow_su) { if (profile->allow_su) {
pr_info("set root profile, key: %s, uid: %d, gid: %d, context: %s\n", pr_info("set root profile, key: %s, uid: %d, gid: %d, context: %s\n",
profile->key, profile->current_uid, profile->key, profile->current_uid,
profile->rp_config.profile.gid, profile->rp_config.profile.gid,
profile->rp_config.profile.selinux_domain); profile->rp_config.profile.selinux_domain);
} else { } else {
pr_info("set app profile, key: %s, uid: %d, umount modules: %d\n", pr_info("set app profile, key: %s, uid: %d, umount modules: %d\n",
profile->key, profile->current_uid, profile->key, profile->current_uid,
profile->nrp_config.profile.umount_modules); profile->nrp_config.profile.umount_modules);
} }
list_add_tail(&p->list, &allow_list); list_add_tail(&p->list, &allow_list);
out: out:
if (profile->current_uid <= BITMAP_UID_MAX) { if (profile->current_uid <= BITMAP_UID_MAX) {
if (profile->allow_su) if (profile->allow_su)
allow_list_bitmap[profile->current_uid / BITS_PER_BYTE] |= 1 << (profile->current_uid % BITS_PER_BYTE); allow_list_bitmap[profile->current_uid / BITS_PER_BYTE] |=
else 1 << (profile->current_uid % BITS_PER_BYTE);
allow_list_bitmap[profile->current_uid / BITS_PER_BYTE] &= ~(1 << (profile->current_uid % BITS_PER_BYTE)); else
} else { allow_list_bitmap[profile->current_uid / BITS_PER_BYTE] &=
if (profile->allow_su) { ~(1 << (profile->current_uid % BITS_PER_BYTE));
/* } else {
* 1024 apps with uid higher than BITMAP_UID_MAX if (profile->allow_su) {
* registered to request superuser? /*
*/ * 1024 apps with uid higher than BITMAP_UID_MAX
if (allow_list_pointer >= ARRAY_SIZE(allow_list_arr)) { * registered to request superuser?
pr_err("too many apps registered\n"); */
WARN_ON(1); if (allow_list_pointer >= ARRAY_SIZE(allow_list_arr)) {
return false; pr_err("too many apps registered\n");
} WARN_ON(1);
allow_list_arr[allow_list_pointer++] = profile->current_uid; return false;
} else { }
remove_uid_from_arr(profile->current_uid); allow_list_arr[allow_list_pointer++] = profile->current_uid;
} } else {
} remove_uid_from_arr(profile->current_uid);
result = true; }
}
result = true;
// check if the default profiles is changed, cache it to a single struct to accelerate access. // check if the default profiles is changed, cache it to a single struct to accelerate access.
if (unlikely(!strcmp(profile->key, "$"))) { if (unlikely(!strcmp(profile->key, "$"))) {
// set default non root profile // set default non root profile
memcpy(&default_non_root_profile, &profile->nrp_config.profile, memcpy(&default_non_root_profile, &profile->nrp_config.profile,
sizeof(default_non_root_profile)); sizeof(default_non_root_profile));
} }
if (unlikely(!strcmp(profile->key, "#"))) { if (unlikely(!strcmp(profile->key, "#"))) {
// set default root profile // set default root profile
memcpy(&default_root_profile, &profile->rp_config.profile, memcpy(&default_root_profile, &profile->rp_config.profile,
sizeof(default_root_profile)); sizeof(default_root_profile));
} }
if (persist) if (persist) {
persistent_allow_list(); persistent_allow_list();
// FIXME: use a new flag
ksu_mark_running_process();
}
return result; return result;
} }
bool __ksu_is_allow_uid(uid_t uid) bool __ksu_is_allow_uid(uid_t uid)
{ {
int i; int i;
if (unlikely(uid == 0)) { if (forbid_system_uid(uid)) {
// already root, but only allow our domain. // do not bother going through the list if it's system
return is_ksu_domain(); return false;
} }
if (forbid_system_uid(uid)) { if (likely(ksu_is_manager_uid_valid()) &&
// do not bother going through the list if it's system unlikely(ksu_get_manager_uid() == uid)) {
return false; // manager is always allowed!
} return true;
}
if (likely(ksu_is_manager_uid_valid()) && unlikely(ksu_get_manager_uid() == uid)) { if (likely(uid <= BITMAP_UID_MAX)) {
// manager is always allowed! return !!(allow_list_bitmap[uid / BITS_PER_BYTE] &
return true; (1 << (uid % BITS_PER_BYTE)));
} } else {
for (i = 0; i < allow_list_pointer; i++) {
if (allow_list_arr[i] == uid)
return true;
}
}
if (likely(uid <= BITMAP_UID_MAX)) { return false;
return !!(allow_list_bitmap[uid / BITS_PER_BYTE] & (1 << (uid % BITS_PER_BYTE))); }
} else {
for (i = 0; i < allow_list_pointer; i++) {
if (allow_list_arr[i] == uid)
return true;
}
}
return false; bool __ksu_is_allow_uid_for_current(uid_t uid)
{
if (unlikely(uid == 0)) {
// already root, but only allow our domain.
return is_ksu_domain();
}
return __ksu_is_allow_uid(uid);
} }
bool ksu_uid_should_umount(uid_t uid) bool ksu_uid_should_umount(uid_t uid)
{ {
struct app_profile profile = { .current_uid = uid }; struct app_profile profile = { .current_uid = uid };
if (likely(ksu_is_manager_uid_valid()) && unlikely(ksu_get_manager_uid() == uid)) { if (likely(ksu_is_manager_uid_valid()) &&
// we should not umount on manager! unlikely(ksu_get_manager_uid() == uid)) {
return false; // we should not umount on manager!
} return false;
bool found = ksu_get_app_profile(&profile); }
if (!found) { bool found = ksu_get_app_profile(&profile);
// no app profile found, it must be non root app if (!found) {
return default_non_root_profile.umount_modules; // no app profile found, it must be non root app
} return default_non_root_profile.umount_modules;
if (profile.allow_su) { }
// if found and it is granted to su, we shouldn't umount for it if (profile.allow_su) {
return false; // if found and it is granted to su, we shouldn't umount for it
} else { return false;
// found an app profile } else {
if (profile.nrp_config.use_default) { // found an app profile
return default_non_root_profile.umount_modules; if (profile.nrp_config.use_default) {
} else { return default_non_root_profile.umount_modules;
return profile.nrp_config.profile.umount_modules; } else {
} return profile.nrp_config.profile.umount_modules;
} }
}
} }
struct root_profile *ksu_get_root_profile(uid_t uid) struct root_profile *ksu_get_root_profile(uid_t uid)
{ {
struct perm_data *p = NULL; struct perm_data *p = NULL;
struct list_head *pos = NULL; struct list_head *pos = NULL;
list_for_each (pos, &allow_list) { list_for_each (pos, &allow_list) {
p = list_entry(pos, struct perm_data, list); p = list_entry(pos, struct perm_data, list);
if (uid == p->profile.current_uid && p->profile.allow_su) { if (uid == p->profile.current_uid && p->profile.allow_su) {
if (!p->profile.rp_config.use_default) { if (!p->profile.rp_config.use_default) {
return &p->profile.rp_config.profile; return &p->profile.rp_config.profile;
} }
} }
} }
// use default profile // use default profile
return &default_root_profile; return &default_root_profile;
} }
bool ksu_get_allow_list(int *array, int *length, bool allow) bool ksu_get_allow_list(int *array, int *length, bool allow)
{ {
struct perm_data *p = NULL; struct perm_data *p = NULL;
struct list_head *pos = NULL; struct list_head *pos = NULL;
int i = 0; int i = 0;
list_for_each (pos, &allow_list) { list_for_each (pos, &allow_list) {
p = list_entry(pos, struct perm_data, list); p = list_entry(pos, struct perm_data, list);
// pr_info("get_allow_list uid: %d allow: %d\n", p->uid, p->allow); // pr_info("get_allow_list uid: %d allow: %d\n", p->uid, p->allow);
if (p->profile.allow_su == allow) { if (p->profile.allow_su == allow) {
array[i++] = p->profile.current_uid; array[i++] = p->profile.current_uid;
} }
} }
*length = i; *length = i;
return true; return true;
} }
void do_save_allow_list(struct work_struct *work) static void do_persistent_allow_list(struct callback_head *_cb)
{ {
u32 magic = FILE_MAGIC; u32 magic = FILE_MAGIC;
u32 version = FILE_FORMAT_VERSION; u32 version = FILE_FORMAT_VERSION;
struct perm_data *p = NULL; struct perm_data *p = NULL;
struct list_head *pos = NULL; struct list_head *pos = NULL;
loff_t off = 0; loff_t off = 0;
struct file *fp = mutex_lock(&allowlist_mutex);
ksu_filp_open_compat(KERNEL_SU_ALLOWLIST, O_WRONLY | O_CREAT | O_TRUNC, 0644); struct file *fp =
if (IS_ERR(fp)) { filp_open(KERNEL_SU_ALLOWLIST, O_WRONLY | O_CREAT | O_TRUNC, 0644);
pr_err("save_allow_list create file failed: %ld\n", PTR_ERR(fp)); if (IS_ERR(fp)) {
return; pr_err("save_allow_list create file failed: %ld\n", PTR_ERR(fp));
} goto unlock;
}
// store magic and version // store magic and version
if (ksu_kernel_write_compat(fp, &magic, sizeof(magic), &off) != if (kernel_write(fp, &magic, sizeof(magic), &off) != sizeof(magic)) {
sizeof(magic)) { pr_err("save_allow_list write magic failed.\n");
pr_err("save_allow_list write magic failed.\n"); goto close_file;
goto exit; }
}
if (ksu_kernel_write_compat(fp, &version, sizeof(version), &off) != if (kernel_write(fp, &version, sizeof(version), &off) != sizeof(version)) {
sizeof(version)) { pr_err("save_allow_list write version failed.\n");
pr_err("save_allow_list write version failed.\n"); goto close_file;
goto exit; }
}
list_for_each (pos, &allow_list) { list_for_each (pos, &allow_list) {
p = list_entry(pos, struct perm_data, list); p = list_entry(pos, struct perm_data, list);
pr_info("save allow list, name: %s uid :%d, allow: %d\n", pr_info("save allow list, name: %s uid :%d, allow: %d\n",
p->profile.key, p->profile.current_uid, p->profile.key, p->profile.current_uid, p->profile.allow_su);
p->profile.allow_su);
ksu_kernel_write_compat(fp, &p->profile, sizeof(p->profile), kernel_write(fp, &p->profile, sizeof(p->profile), &off);
&off); }
}
exit: close_file:
filp_close(fp, 0); filp_close(fp, 0);
unlock:
mutex_unlock(&allowlist_mutex);
kfree(_cb);
} }
void do_load_allow_list(struct work_struct *work) void persistent_allow_list()
{ {
loff_t off = 0; struct task_struct *tsk;
ssize_t ret = 0;
struct file *fp = NULL; tsk = get_pid_task(find_vpid(1), PIDTYPE_PID);
u32 magic; if (!tsk) {
u32 version; pr_err("save_allow_list find init task err\n");
return;
}
struct callback_head *cb =
kzalloc(sizeof(struct callback_head), GFP_KERNEL);
if (!cb) {
pr_err("save_allow_list alloc cb err\b");
goto put_task;
}
cb->func = do_persistent_allow_list;
task_work_add(tsk, cb, TWA_RESUME);
put_task:
put_task_struct(tsk);
}
void ksu_load_allow_list()
{
loff_t off = 0;
ssize_t ret = 0;
struct file *fp = NULL;
u32 magic;
u32 version;
#ifdef CONFIG_KSU_DEBUG #ifdef CONFIG_KSU_DEBUG
// always allow adb shell by default // always allow adb shell by default
ksu_grant_root_to_shell(); ksu_grant_root_to_shell();
#endif #endif
// load allowlist now! // load allowlist now!
fp = ksu_filp_open_compat(KERNEL_SU_ALLOWLIST, O_RDONLY, 0); fp = filp_open(KERNEL_SU_ALLOWLIST, O_RDONLY, 0);
if (IS_ERR(fp)) { if (IS_ERR(fp)) {
pr_err("load_allow_list open file failed: %ld\n", PTR_ERR(fp)); pr_err("load_allow_list open file failed: %ld\n", PTR_ERR(fp));
return; return;
} }
// verify magic // verify magic
if (ksu_kernel_read_compat(fp, &magic, sizeof(magic), &off) != if (kernel_read(fp, &magic, sizeof(magic), &off) != sizeof(magic) ||
sizeof(magic) || magic != FILE_MAGIC) {
magic != FILE_MAGIC) { pr_err("allowlist file invalid: %d!\n", magic);
pr_err("allowlist file invalid: %d!\n", magic); goto exit;
goto exit; }
}
if (ksu_kernel_read_compat(fp, &version, sizeof(version), &off) != if (kernel_read(fp, &version, sizeof(version), &off) != sizeof(version)) {
sizeof(version)) { pr_err("allowlist read version: %d failed\n", version);
pr_err("allowlist read version: %d failed\n", version); goto exit;
goto exit; }
}
pr_info("allowlist version: %d\n", version); pr_info("allowlist version: %d\n", version);
while (true) { while (true) {
struct app_profile profile; struct app_profile profile;
ret = ksu_kernel_read_compat(fp, &profile, sizeof(profile), ret = kernel_read(fp, &profile, sizeof(profile), &off);
&off);
if (ret <= 0) { if (ret <= 0) {
pr_info("load_allow_list read err: %zd\n", ret); pr_info("load_allow_list read err: %zd\n", ret);
break; break;
} }
pr_info("load_allow_uid, name: %s, uid: %d, allow: %d\n", pr_info("load_allow_uid, name: %s, uid: %d, allow: %d\n", profile.key,
profile.key, profile.current_uid, profile.allow_su); profile.current_uid, profile.allow_su);
ksu_set_app_profile(&profile, false); ksu_set_app_profile(&profile, false);
} }
exit: exit:
ksu_show_allow_list(); ksu_show_allow_list();
filp_close(fp, 0); filp_close(fp, 0);
} }
void ksu_prune_allowlist(bool (*is_uid_valid)(uid_t, char *, void *), void *data) void ksu_prune_allowlist(bool (*is_uid_valid)(uid_t, char *, void *),
void *data)
{ {
struct perm_data *np = NULL; struct perm_data *np = NULL;
struct perm_data *n = NULL; struct perm_data *n = NULL;
bool modified = false; if (!ksu_boot_completed) {
// TODO: use RCU! pr_info("boot not completed, skip prune\n");
mutex_lock(&allowlist_mutex); return;
list_for_each_entry_safe (np, n, &allow_list, list) { }
uid_t uid = np->profile.current_uid;
char *package = np->profile.key;
// we use this uid for special cases, don't prune it!
bool is_preserved_uid = uid == KSU_APP_PROFILE_PRESERVE_UID;
if (!is_preserved_uid && !is_uid_valid(uid, package, data)) {
modified = true;
pr_info("prune uid: %d, package: %s\n", uid, package);
list_del(&np->list);
if (likely(uid <= BITMAP_UID_MAX)) {
allow_list_bitmap[uid / BITS_PER_BYTE] &= ~(1 << (uid % BITS_PER_BYTE));
}
remove_uid_from_arr(uid);
smp_mb();
kfree(np);
}
}
mutex_unlock(&allowlist_mutex);
if (modified) { bool modified = false;
persistent_allow_list(); // TODO: use RCU!
} mutex_lock(&allowlist_mutex);
} list_for_each_entry_safe (np, n, &allow_list, list) {
uid_t uid = np->profile.current_uid;
char *package = np->profile.key;
// we use this uid for special cases, don't prune it!
bool is_preserved_uid = uid == KSU_APP_PROFILE_PRESERVE_UID;
if (!is_preserved_uid && !is_uid_valid(uid, package, data)) {
modified = true;
pr_info("prune uid: %d, package: %s\n", uid, package);
list_del(&np->list);
if (likely(uid <= BITMAP_UID_MAX)) {
allow_list_bitmap[uid / BITS_PER_BYTE] &=
~(1 << (uid % BITS_PER_BYTE));
}
remove_uid_from_arr(uid);
smp_mb();
kfree(np);
}
}
mutex_unlock(&allowlist_mutex);
// make sure allow list works cross boot if (modified) {
bool persistent_allow_list(void) persistent_allow_list();
{ }
return ksu_queue_work(&ksu_save_work);
}
bool ksu_load_allow_list(void)
{
return ksu_queue_work(&ksu_load_work);
} }
void ksu_allowlist_init(void) void ksu_allowlist_init(void)
{ {
int i; int i;
BUILD_BUG_ON(sizeof(allow_list_bitmap) != PAGE_SIZE); BUILD_BUG_ON(sizeof(allow_list_bitmap) != PAGE_SIZE);
BUILD_BUG_ON(sizeof(allow_list_arr) != PAGE_SIZE); BUILD_BUG_ON(sizeof(allow_list_arr) != PAGE_SIZE);
for (i = 0; i < ARRAY_SIZE(allow_list_arr); i++) for (i = 0; i < ARRAY_SIZE(allow_list_arr); i++)
allow_list_arr[i] = -1; allow_list_arr[i] = -1;
INIT_LIST_HEAD(&allow_list); INIT_LIST_HEAD(&allow_list);
INIT_WORK(&ksu_save_work, do_save_allow_list); init_default_profiles();
INIT_WORK(&ksu_load_work, do_load_allow_list);
init_default_profiles();
} }
void ksu_allowlist_exit(void) void ksu_allowlist_exit(void)
{ {
struct perm_data *np = NULL; struct perm_data *np = NULL;
struct perm_data *n = NULL; struct perm_data *n = NULL;
do_save_allow_list(NULL); // free allowlist
mutex_lock(&allowlist_mutex);
// free allowlist list_for_each_entry_safe (np, n, &allow_list, list) {
mutex_lock(&allowlist_mutex); list_del(&np->list);
list_for_each_entry_safe (np, n, &allow_list, list) { kfree(np);
list_del(&np->list); }
kfree(np); mutex_unlock(&allowlist_mutex);
}
mutex_unlock(&allowlist_mutex);
} }
#ifdef CONFIG_KSU_MANUAL_SU
bool ksu_temp_grant_root_once(uid_t uid)
{
struct app_profile profile = {
.version = KSU_APP_PROFILE_VER,
.allow_su = true,
.current_uid = uid,
};
const char *default_key = "com.temp.once";
struct perm_data *p = NULL;
struct list_head *pos = NULL;
bool found = false;
list_for_each (pos, &allow_list) {
p = list_entry(pos, struct perm_data, list);
if (p->profile.current_uid == uid) {
strcpy(profile.key, p->profile.key);
found = true;
break;
}
}
if (!found) {
strcpy(profile.key, default_key);
}
profile.rp_config.profile.uid = default_root_profile.uid;
profile.rp_config.profile.gid = default_root_profile.gid;
profile.rp_config.profile.groups_count = default_root_profile.groups_count;
memcpy(profile.rp_config.profile.groups, default_root_profile.groups, sizeof(default_root_profile.groups));
memcpy(&profile.rp_config.profile.capabilities, &default_root_profile.capabilities, sizeof(default_root_profile.capabilities));
profile.rp_config.profile.namespaces = default_root_profile.namespaces;
strcpy(profile.rp_config.profile.selinux_domain, default_root_profile.selinux_domain);
bool ok = ksu_set_app_profile(&profile, false);
if (ok)
pr_info("pending_root: UID=%d granted and persisted\n", uid);
return ok;
}
void ksu_temp_revoke_root_once(uid_t uid)
{
struct app_profile profile = {
.version = KSU_APP_PROFILE_VER,
.allow_su = false,
.current_uid = uid,
};
const char *default_key = "com.temp.once";
struct perm_data *p = NULL;
struct list_head *pos = NULL;
bool found = false;
list_for_each (pos, &allow_list) {
p = list_entry(pos, struct perm_data, list);
if (p->profile.current_uid == uid) {
strcpy(profile.key, p->profile.key);
found = true;
break;
}
}
if (!found) {
strcpy(profile.key, default_key);
}
profile.nrp_config.profile.umount_modules = default_non_root_profile.umount_modules;
strcpy(profile.rp_config.profile.selinux_domain, KSU_DEFAULT_SELINUX_DOMAIN);
ksu_set_app_profile(&profile, false);
persistent_allow_list();
pr_info("pending_root: UID=%d removed and persist updated\n", uid);
}
#endif

View File

@@ -2,19 +2,31 @@
#define __KSU_H_ALLOWLIST #define __KSU_H_ALLOWLIST
#include <linux/types.h> #include <linux/types.h>
#include "ksu.h" #include <linux/uidgid.h>
#include "app_profile.h"
#define PER_USER_RANGE 100000
#define FIRST_APPLICATION_UID 10000
#define LAST_APPLICATION_UID 19999
#define FIRST_ISOLATED_UID 99000
#define LAST_ISOLATED_UID 99999
void ksu_allowlist_init(void); void ksu_allowlist_init(void);
void ksu_allowlist_exit(void); void ksu_allowlist_exit(void);
bool ksu_load_allow_list(void); void ksu_load_allow_list(void);
void ksu_show_allow_list(void); void ksu_show_allow_list(void);
// Check if the uid is in allow list
bool __ksu_is_allow_uid(uid_t uid); bool __ksu_is_allow_uid(uid_t uid);
#define ksu_is_allow_uid(uid) unlikely(__ksu_is_allow_uid(uid)) #define ksu_is_allow_uid(uid) unlikely(__ksu_is_allow_uid(uid))
// Check if the uid is in allow list, or current is ksu domain root
bool __ksu_is_allow_uid_for_current(uid_t uid);
#define ksu_is_allow_uid_for_current(uid) unlikely(__ksu_is_allow_uid_for_current(uid))
bool ksu_get_allow_list(int *array, int *length, bool allow); bool ksu_get_allow_list(int *array, int *length, bool allow);
void ksu_prune_allowlist(bool (*is_uid_exist)(uid_t, char *, void *), void *data); void ksu_prune_allowlist(bool (*is_uid_exist)(uid_t, char *, void *), void *data);
@@ -24,4 +36,22 @@ bool ksu_set_app_profile(struct app_profile *, bool persist);
bool ksu_uid_should_umount(uid_t uid); bool ksu_uid_should_umount(uid_t uid);
struct root_profile *ksu_get_root_profile(uid_t uid); struct root_profile *ksu_get_root_profile(uid_t uid);
static inline bool is_appuid(uid_t uid)
{
uid_t appid = uid % PER_USER_RANGE;
return appid >= FIRST_APPLICATION_UID && appid <= LAST_APPLICATION_UID;
}
static inline bool is_isolated_process(uid_t uid)
{
uid_t appid = uid % PER_USER_RANGE;
return appid >= FIRST_ISOLATED_UID && appid <= LAST_ISOLATED_UID;
}
#ifdef CONFIG_KSU_MANUAL_SU
bool ksu_temp_grant_root_once(uid_t uid);
void ksu_temp_revoke_root_once(uid_t uid);
#endif
#endif #endif

View File

@@ -15,279 +15,375 @@
#endif #endif
#include "apk_sign.h" #include "apk_sign.h"
#include "dynamic_manager.h"
#include "klog.h" // IWYU pragma: keep #include "klog.h" // IWYU pragma: keep
#include "kernel_compat.h" #include "manager_sign.h"
struct sdesc { struct sdesc {
struct shash_desc shash; struct shash_desc shash;
char ctx[]; char ctx[];
};
static apk_sign_key_t apk_sign_keys[] = {
{EXPECTED_SIZE_SHIRKNEKO, EXPECTED_HASH_SHIRKNEKO}, // ShirkNeko/SukiSU
#ifdef EXPECTED_SIZE
{EXPECTED_SIZE, EXPECTED_HASH}, // Custom
#endif
}; };
static struct sdesc *init_sdesc(struct crypto_shash *alg) static struct sdesc *init_sdesc(struct crypto_shash *alg)
{ {
struct sdesc *sdesc; struct sdesc *sdesc;
int size; int size;
size = sizeof(struct shash_desc) + crypto_shash_descsize(alg); size = sizeof(struct shash_desc) + crypto_shash_descsize(alg);
sdesc = kmalloc(size, GFP_KERNEL); sdesc = kzalloc(size, GFP_KERNEL);
if (!sdesc) if (!sdesc)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
sdesc->shash.tfm = alg; sdesc->shash.tfm = alg;
return sdesc; return sdesc;
} }
static int calc_hash(struct crypto_shash *alg, const unsigned char *data, static int calc_hash(struct crypto_shash *alg, const unsigned char *data,
unsigned int datalen, unsigned char *digest) unsigned int datalen, unsigned char *digest)
{ {
struct sdesc *sdesc; struct sdesc *sdesc;
int ret; int ret;
sdesc = init_sdesc(alg); sdesc = init_sdesc(alg);
if (IS_ERR(sdesc)) { if (IS_ERR(sdesc)) {
pr_info("can't alloc sdesc\n"); pr_info("can't alloc sdesc\n");
return PTR_ERR(sdesc); return PTR_ERR(sdesc);
} }
ret = crypto_shash_digest(&sdesc->shash, data, datalen, digest); ret = crypto_shash_digest(&sdesc->shash, data, datalen, digest);
kfree(sdesc); kfree(sdesc);
return ret; return ret;
} }
static int ksu_sha256(const unsigned char *data, unsigned int datalen, static int ksu_sha256(const unsigned char *data, unsigned int datalen,
unsigned char *digest) unsigned char *digest)
{ {
struct crypto_shash *alg; struct crypto_shash *alg;
char *hash_alg_name = "sha256"; char *hash_alg_name = "sha256";
int ret; int ret;
alg = crypto_alloc_shash(hash_alg_name, 0, 0); alg = crypto_alloc_shash(hash_alg_name, 0, 0);
if (IS_ERR(alg)) { if (IS_ERR(alg)) {
pr_info("can't alloc alg %s\n", hash_alg_name); pr_info("can't alloc alg %s\n", hash_alg_name);
return PTR_ERR(alg); return PTR_ERR(alg);
} }
ret = calc_hash(alg, data, datalen, digest); ret = calc_hash(alg, data, datalen, digest);
crypto_free_shash(alg); crypto_free_shash(alg);
return ret; return ret;
} }
static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset,
unsigned expected_size, const char *expected_sha256) static struct dynamic_sign_key dynamic_sign = DYNAMIC_SIGN_DEFAULT_CONFIG;
static bool check_dynamic_sign(struct file *fp, u32 size4, loff_t *pos, int *matched_index)
{ {
ksu_kernel_read_compat(fp, size4, 0x4, pos); // signer-sequence length struct dynamic_sign_key current_dynamic_key = dynamic_sign;
ksu_kernel_read_compat(fp, size4, 0x4, pos); // signer length
ksu_kernel_read_compat(fp, size4, 0x4, pos); // signed data length if (ksu_get_dynamic_manager_config(&current_dynamic_key.size, &current_dynamic_key.hash)) {
pr_debug("Using dynamic manager config: size=0x%x, hash=%.16s...\n",
*offset += 0x4 * 3; current_dynamic_key.size, current_dynamic_key.hash);
}
ksu_kernel_read_compat(fp, size4, 0x4, pos); // digests-sequence length
if (size4 != current_dynamic_key.size) {
*pos += *size4; return false;
*offset += 0x4 + *size4; }
ksu_kernel_read_compat(fp, size4, 0x4, pos); // certificates length
ksu_kernel_read_compat(fp, size4, 0x4, pos); // certificate length
*offset += 0x4 * 2;
if (*size4 == expected_size) {
*offset += *size4;
#define CERT_MAX_LENGTH 1024 #define CERT_MAX_LENGTH 1024
char cert[CERT_MAX_LENGTH]; char cert[CERT_MAX_LENGTH];
if (*size4 > CERT_MAX_LENGTH) { if (size4 > CERT_MAX_LENGTH) {
pr_info("cert length overlimit\n"); pr_info("cert length overlimit\n");
return false; return false;
} }
ksu_kernel_read_compat(fp, cert, *size4, pos);
unsigned char digest[SHA256_DIGEST_SIZE]; kernel_read(fp, cert, size4, pos);
if (IS_ERR(ksu_sha256(cert, *size4, digest))) {
pr_info("sha256 error\n"); unsigned char digest[SHA256_DIGEST_SIZE];
return false; if (ksu_sha256(cert, size4, digest) < 0) {
} pr_info("sha256 error\n");
return false;
}
char hash_str[SHA256_DIGEST_SIZE * 2 + 1]; char hash_str[SHA256_DIGEST_SIZE * 2 + 1];
hash_str[SHA256_DIGEST_SIZE * 2] = '\0'; hash_str[SHA256_DIGEST_SIZE * 2] = '\0';
bin2hex(hash_str, digest, SHA256_DIGEST_SIZE);
pr_info("sha256: %s, expected: %s, index: dynamic\n", hash_str, current_dynamic_key.hash);
if (strcmp(current_dynamic_key.hash, hash_str) == 0) {
if (matched_index) {
*matched_index = DYNAMIC_SIGN_INDEX;
}
return true;
}
return false;
}
bin2hex(hash_str, digest, SHA256_DIGEST_SIZE); static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset, int *matched_index)
pr_info("sha256: %s, expected: %s\n", hash_str, {
expected_sha256); int i;
if (strcmp(expected_sha256, hash_str) == 0) { apk_sign_key_t sign_key;
return true; bool signature_valid = false;
}
} kernel_read(fp, size4, 0x4, pos); // signer-sequence length
return false; kernel_read(fp, size4, 0x4, pos); // signer length
kernel_read(fp, size4, 0x4, pos); // signed data length
*offset += 0x4 * 3;
kernel_read(fp, size4, 0x4, pos); // digests-sequence length
*pos += *size4;
*offset += 0x4 + *size4;
kernel_read(fp, size4, 0x4, pos); // certificates length
kernel_read(fp, size4, 0x4, pos); // certificate length
*offset += 0x4 * 2;
if (ksu_is_dynamic_manager_enabled()) {
loff_t temp_pos = *pos;
if (check_dynamic_sign(fp, *size4, &temp_pos, matched_index)) {
*pos = temp_pos;
*offset += *size4;
return true;
}
}
for (i = 0; i < ARRAY_SIZE(apk_sign_keys); i++) {
sign_key = apk_sign_keys[i];
if (*size4 != sign_key.size)
continue;
*offset += *size4;
#define CERT_MAX_LENGTH 1024
char cert[CERT_MAX_LENGTH];
if (*size4 > CERT_MAX_LENGTH) {
pr_info("cert length overlimit\n");
return false;
}
kernel_read(fp, cert, *size4, pos);
unsigned char digest[SHA256_DIGEST_SIZE];
if (ksu_sha256(cert, *size4, digest) < 0 ) {
pr_info("sha256 error\n");
return false;
}
char hash_str[SHA256_DIGEST_SIZE * 2 + 1];
hash_str[SHA256_DIGEST_SIZE * 2] = '\0';
bin2hex(hash_str, digest, SHA256_DIGEST_SIZE);
pr_info("sha256: %s, expected: %s, index: %d\n", hash_str, sign_key.sha256, i);
if (strcmp(sign_key.sha256, hash_str) == 0) {
signature_valid = true;
if (matched_index) {
*matched_index = i;
}
break;
}
}
return signature_valid;
} }
struct zip_entry_header { struct zip_entry_header {
uint32_t signature; uint32_t signature;
uint16_t version; uint16_t version;
uint16_t flags; uint16_t flags;
uint16_t compression; uint16_t compression;
uint16_t mod_time; uint16_t mod_time;
uint16_t mod_date; uint16_t mod_date;
uint32_t crc32; uint32_t crc32;
uint32_t compressed_size; uint32_t compressed_size;
uint32_t uncompressed_size; uint32_t uncompressed_size;
uint16_t file_name_length; uint16_t file_name_length;
uint16_t extra_field_length; uint16_t extra_field_length;
} __attribute__((packed)); } __attribute__((packed));
// This is a necessary but not sufficient condition, but it is enough for us // This is a necessary but not sufficient condition, but it is enough for us
static bool has_v1_signature_file(struct file *fp) static bool has_v1_signature_file(struct file *fp)
{ {
struct zip_entry_header header; struct zip_entry_header header;
const char MANIFEST[] = "META-INF/MANIFEST.MF"; const char MANIFEST[] = "META-INF/MANIFEST.MF";
loff_t pos = 0; loff_t pos = 0;
while (ksu_kernel_read_compat(fp, &header, while (kernel_read(fp, &header,
sizeof(struct zip_entry_header), &pos) == sizeof(struct zip_entry_header), &pos) ==
sizeof(struct zip_entry_header)) { sizeof(struct zip_entry_header)) {
if (header.signature != 0x04034b50) { if (header.signature != 0x04034b50) {
// ZIP magic: 'PK' // ZIP magic: 'PK'
return false; return false;
} }
// Read the entry file name // Read the entry file name
if (header.file_name_length == sizeof(MANIFEST) - 1) { if (header.file_name_length == sizeof(MANIFEST) - 1) {
char fileName[sizeof(MANIFEST)]; char fileName[sizeof(MANIFEST)];
ksu_kernel_read_compat(fp, fileName, kernel_read(fp, fileName,
header.file_name_length, &pos); header.file_name_length, &pos);
fileName[header.file_name_length] = '\0'; fileName[header.file_name_length] = '\0';
// Check if the entry matches META-INF/MANIFEST.MF // Check if the entry matches META-INF/MANIFEST.MF
if (strncmp(MANIFEST, fileName, sizeof(MANIFEST) - 1) == if (strncmp(MANIFEST, fileName, sizeof(MANIFEST) - 1) ==
0) { 0) {
return true; return true;
} }
} else { } else {
// Skip the entry file name // Skip the entry file name
pos += header.file_name_length; pos += header.file_name_length;
} }
// Skip to the next entry // Skip to the next entry
pos += header.extra_field_length + header.compressed_size; pos += header.extra_field_length + header.compressed_size;
} }
return false; return false;
} }
static __always_inline bool check_v2_signature(char *path, static __always_inline bool check_v2_signature(char *path, bool check_multi_manager, int *signature_index)
unsigned expected_size,
const char *expected_sha256)
{ {
unsigned char buffer[0x11] = { 0 }; unsigned char buffer[0x11] = { 0 };
u32 size4; u32 size4;
u64 size8, size_of_block; u64 size8, size_of_block;
loff_t pos; loff_t pos;
bool v2_signing_valid = false; bool v2_signing_valid = false;
int v2_signing_blocks = 0; int v2_signing_blocks = 0;
bool v3_signing_exist = false; bool v3_signing_exist = false;
bool v3_1_signing_exist = false; bool v3_1_signing_exist = false;
int matched_index = -1;
int i;
struct file *fp = filp_open(path, O_RDONLY, 0);
if (IS_ERR(fp)) {
pr_err("open %s error.\n", path);
return false;
}
int i; // If you want to check for multi-manager APK signing, but dynamic managering is not enabled, skip
struct file *fp = ksu_filp_open_compat(path, O_RDONLY, 0); if (check_multi_manager && !ksu_is_dynamic_manager_enabled()) {
if (IS_ERR(fp)) { filp_close(fp, 0);
pr_err("open %s error.\n", path); return 0;
return false; }
}
// disable inotify for this file // disable inotify for this file
fp->f_mode |= FMODE_NONOTIFY; fp->f_mode |= FMODE_NONOTIFY;
// https://en.wikipedia.org/wiki/Zip_(file_format)#End_of_central_directory_record_(EOCD) // https://en.wikipedia.org/wiki/Zip_(file_format)#End_of_central_directory_record_(EOCD)
for (i = 0;; ++i) { for (i = 0;; ++i) {
unsigned short n; unsigned short n;
pos = generic_file_llseek(fp, -i - 2, SEEK_END); pos = generic_file_llseek(fp, -i - 2, SEEK_END);
ksu_kernel_read_compat(fp, &n, 2, &pos); kernel_read(fp, &n, 2, &pos);
if (n == i) { if (n == i) {
pos -= 22; pos -= 22;
ksu_kernel_read_compat(fp, &size4, 4, &pos); kernel_read(fp, &size4, 4, &pos);
if ((size4 ^ 0xcafebabeu) == 0xccfbf1eeu) { if ((size4 ^ 0xcafebabeu) == 0xccfbf1eeu) {
break; break;
} }
} }
if (i == 0xffff) { if (i == 0xffff) {
pr_info("error: cannot find eocd\n"); pr_info("error: cannot find eocd\n");
goto clean; goto clean;
} }
} }
pos += 12; pos += 12;
// offset // offset
ksu_kernel_read_compat(fp, &size4, 0x4, &pos); kernel_read(fp, &size4, 0x4, &pos);
pos = size4 - 0x18; pos = size4 - 0x18;
ksu_kernel_read_compat(fp, &size8, 0x8, &pos); kernel_read(fp, &size8, 0x8, &pos);
ksu_kernel_read_compat(fp, buffer, 0x10, &pos); kernel_read(fp, buffer, 0x10, &pos);
if (strcmp((char *)buffer, "APK Sig Block 42")) { if (strcmp((char *)buffer, "APK Sig Block 42")) {
goto clean; goto clean;
} }
pos = size4 - (size8 + 0x8); pos = size4 - (size8 + 0x8);
ksu_kernel_read_compat(fp, &size_of_block, 0x8, &pos); kernel_read(fp, &size_of_block, 0x8, &pos);
if (size_of_block != size8) { if (size_of_block != size8) {
goto clean; goto clean;
} }
int loop_count = 0; int loop_count = 0;
while (loop_count++ < 10) { while (loop_count++ < 10) {
uint32_t id; uint32_t id;
uint32_t offset; uint32_t offset;
ksu_kernel_read_compat(fp, &size8, 0x8, kernel_read(fp, &size8, 0x8,
&pos); // sequence length &pos); // sequence length
if (size8 == size_of_block) { if (size8 == size_of_block) {
break; break;
} }
ksu_kernel_read_compat(fp, &id, 0x4, &pos); // id kernel_read(fp, &id, 0x4, &pos); // id
offset = 4; offset = 4;
if (id == 0x7109871au) { if (id == 0x7109871au) {
v2_signing_blocks++; v2_signing_blocks++;
v2_signing_valid = bool result = check_block(fp, &size4, &pos, &offset, &matched_index);
check_block(fp, &size4, &pos, &offset, if (result) {
expected_size, expected_sha256); v2_signing_valid = true;
} else if (id == 0xf05368c0u) { }
// http://aospxref.com/android-14.0.0_r2/xref/frameworks/base/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java#73 } else if (id == 0xf05368c0u) {
v3_signing_exist = true; // http://aospxref.com/android-14.0.0_r2/xref/frameworks/base/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java#73
} else if (id == 0x1b93ad61u) { v3_signing_exist = true;
// http://aospxref.com/android-14.0.0_r2/xref/frameworks/base/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java#74 } else if (id == 0x1b93ad61u) {
v3_1_signing_exist = true; // http://aospxref.com/android-14.0.0_r2/xref/frameworks/base/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java#74
} else { v3_1_signing_exist = true;
} else {
#ifdef CONFIG_KSU_DEBUG #ifdef CONFIG_KSU_DEBUG
pr_info("Unknown id: 0x%08x\n", id); pr_info("Unknown id: 0x%08x\n", id);
#endif #endif
} }
pos += (size8 - offset); pos += (size8 - offset);
} }
if (v2_signing_blocks != 1) { if (v2_signing_blocks != 1) {
#ifdef CONFIG_KSU_DEBUG #ifdef CONFIG_KSU_DEBUG
pr_err("Unexpected v2 signature count: %d\n", pr_err("Unexpected v2 signature count: %d\n",
v2_signing_blocks); v2_signing_blocks);
#endif #endif
v2_signing_valid = false; v2_signing_valid = false;
} }
if (v2_signing_valid) { if (v2_signing_valid) {
int has_v1_signing = has_v1_signature_file(fp); int has_v1_signing = has_v1_signature_file(fp);
if (has_v1_signing) { if (has_v1_signing) {
pr_err("Unexpected v1 signature scheme found!\n"); pr_err("Unexpected v1 signature scheme found!\n");
filp_close(fp, 0); filp_close(fp, 0);
return false; return false;
} }
} }
clean: clean:
filp_close(fp, 0); filp_close(fp, 0);
if (v3_signing_exist || v3_1_signing_exist) { if (v3_signing_exist || v3_1_signing_exist) {
#ifdef CONFIG_KSU_DEBUG #ifdef CONFIG_KSU_DEBUG
pr_err("Unexpected v3 signature scheme found!\n"); pr_err("Unexpected v3 signature scheme found!\n");
#endif #endif
return false; return false;
} }
return v2_signing_valid; if (v2_signing_valid) {
if (signature_index) {
*signature_index = matched_index;
}
if (check_multi_manager) {
// 0: ShirkNeko/SukiSU, DYNAMIC_SIGN_INDEX : Dynamic Sign
if (matched_index == 0 || matched_index == DYNAMIC_SIGN_INDEX) {
pr_info("Multi-manager APK detected (dynamic_manager enabled): signature_index=%d\n", matched_index);
return true;
}
return false;
} else {
// Common manager check: any valid signature will do
return true;
}
}
return false;
} }
#ifdef CONFIG_KSU_DEBUG #ifdef CONFIG_KSU_DEBUG
@@ -298,23 +394,28 @@ int ksu_debug_manager_uid = -1;
static int set_expected_size(const char *val, const struct kernel_param *kp) static int set_expected_size(const char *val, const struct kernel_param *kp)
{ {
int rv = param_set_uint(val, kp); int rv = param_set_uint(val, kp);
ksu_set_manager_uid(ksu_debug_manager_uid); ksu_set_manager_uid(ksu_debug_manager_uid);
pr_info("ksu_manager_uid set to %d\n", ksu_debug_manager_uid); pr_info("ksu_manager_uid set to %d\n", ksu_debug_manager_uid);
return rv; return rv;
} }
static struct kernel_param_ops expected_size_ops = { static struct kernel_param_ops expected_size_ops = {
.set = set_expected_size, .set = set_expected_size,
.get = param_get_uint, .get = param_get_uint,
}; };
module_param_cb(ksu_debug_manager_uid, &expected_size_ops, module_param_cb(ksu_debug_manager_uid, &expected_size_ops,
&ksu_debug_manager_uid, S_IRUSR | S_IWUSR); &ksu_debug_manager_uid, S_IRUSR | S_IWUSR);
#endif #endif
bool is_manager_apk(char *path) bool is_manager_apk(char *path)
{ {
return check_v2_signature(path, EXPECTED_SIZE, EXPECTED_HASH); return check_v2_signature(path, false, NULL);
}
bool is_dynamic_manager_apk(char *path, int *signature_index)
{
return check_v2_signature(path, true, signature_index);
} }

View File

@@ -2,7 +2,10 @@
#define __KSU_H_APK_V2_SIGN #define __KSU_H_APK_V2_SIGN
#include <linux/types.h> #include <linux/types.h>
#include "ksu.h"
bool is_manager_apk(char *path); bool is_manager_apk(char *path);
bool is_dynamic_manager_apk(char *path, int *signature_index);
#endif #endif

303
kernel/app_profile.c Normal file
View File

@@ -0,0 +1,303 @@
#include <linux/capability.h>
#include <linux/cred.h>
#include <linux/sched.h>
#include <linux/sched/signal.h>
#include <linux/seccomp.h>
#include <linux/thread_info.h>
#include <linux/uidgid.h>
#include <linux/version.h>
#include "objsec.h"
#include "allowlist.h"
#include "app_profile.h"
#include "klog.h" // IWYU pragma: keep
#include "selinux/selinux.h"
#include "syscall_hook_manager.h"
#include "sucompat.h"
#include "sulog.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION (6, 7, 0)
static struct group_info root_groups = { .usage = REFCOUNT_INIT(2), };
#else
static struct group_info root_groups = { .usage = ATOMIC_INIT(2) };
#endif
static void setup_groups(struct root_profile *profile, struct cred *cred)
{
if (profile->groups_count > KSU_MAX_GROUPS) {
pr_warn("Failed to setgroups, too large group: %d!\n",
profile->uid);
return;
}
if (profile->groups_count == 1 && profile->groups[0] == 0) {
// setgroup to root and return early.
if (cred->group_info)
put_group_info(cred->group_info);
cred->group_info = get_group_info(&root_groups);
return;
}
u32 ngroups = profile->groups_count;
struct group_info *group_info = groups_alloc(ngroups);
if (!group_info) {
pr_warn("Failed to setgroups, ENOMEM for: %d\n", profile->uid);
return;
}
int i;
for (i = 0; i < ngroups; i++) {
gid_t gid = profile->groups[i];
kgid_t kgid = make_kgid(current_user_ns(), gid);
if (!gid_valid(kgid)) {
pr_warn("Failed to setgroups, invalid gid: %d\n", gid);
put_group_info(group_info);
return;
}
group_info->gid[i] = kgid;
}
groups_sort(group_info);
set_groups(cred, group_info);
put_group_info(group_info);
}
void disable_seccomp(void)
{
assert_spin_locked(&current->sighand->siglock);
// disable seccomp
#if defined(CONFIG_GENERIC_ENTRY) && \
LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
clear_syscall_work(SECCOMP);
#else
clear_thread_flag(TIF_SECCOMP);
#endif
#ifdef CONFIG_SECCOMP
current->seccomp.mode = 0;
current->seccomp.filter = NULL;
atomic_set(&current->seccomp.filter_count, 0);
#else
#endif
}
void escape_with_root_profile(void)
{
struct cred *cred;
struct task_struct *p = current;
struct task_struct *t;
cred = prepare_creds();
if (!cred) {
pr_warn("prepare_creds failed!\n");
return;
}
if (cred->euid.val == 0) {
pr_warn("Already root, don't escape!\n");
#if __SULOG_GATE
ksu_sulog_report_su_grant(current_euid().val, NULL, "escape_to_root_failed");
#endif
abort_creds(cred);
return;
}
struct root_profile *profile = ksu_get_root_profile(cred->uid.val);
cred->uid.val = profile->uid;
cred->suid.val = profile->uid;
cred->euid.val = profile->uid;
cred->fsuid.val = profile->uid;
cred->gid.val = profile->gid;
cred->fsgid.val = profile->gid;
cred->sgid.val = profile->gid;
cred->egid.val = profile->gid;
cred->securebits = 0;
BUILD_BUG_ON(sizeof(profile->capabilities.effective) !=
sizeof(kernel_cap_t));
// setup capabilities
// we need CAP_DAC_READ_SEARCH becuase `/data/adb/ksud` is not accessible for non root process
// we add it here but don't add it to cap_inhertiable, it would be dropped automaticly after exec!
u64 cap_for_ksud =
profile->capabilities.effective | CAP_DAC_READ_SEARCH;
memcpy(&cred->cap_effective, &cap_for_ksud,
sizeof(cred->cap_effective));
memcpy(&cred->cap_permitted, &profile->capabilities.effective,
sizeof(cred->cap_permitted));
memcpy(&cred->cap_bset, &profile->capabilities.effective,
sizeof(cred->cap_bset));
setup_groups(profile, cred);
commit_creds(cred);
// Refer to kernel/seccomp.c: seccomp_set_mode_strict
// When disabling Seccomp, ensure that current->sighand->siglock is held during the operation.
spin_lock_irq(&current->sighand->siglock);
disable_seccomp();
spin_unlock_irq(&current->sighand->siglock);
setup_selinux(profile->selinux_domain);
#if __SULOG_GATE
ksu_sulog_report_su_grant(current_euid().val, NULL, "escape_to_root");
#endif
for_each_thread (p, t) {
ksu_set_task_tracepoint_flag(t);
}
}
#ifdef CONFIG_KSU_MANUAL_SU
#include "ksud.h"
#ifndef DEVPTS_SUPER_MAGIC
#define DEVPTS_SUPER_MAGIC 0x1cd1
#endif
static int __manual_su_handle_devpts(struct inode *inode)
{
if (!current->mm) {
return 0;
}
uid_t uid = current_uid().val;
if (uid % 100000 < 10000) {
// not untrusted_app, ignore it
return 0;
}
if (likely(!ksu_is_allow_uid_for_current(uid)))
return 0;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) || defined(KSU_OPTIONAL_SELINUX_INODE)
struct inode_security_struct *sec = selinux_inode(inode);
#else
struct inode_security_struct *sec =
(struct inode_security_struct *)inode->i_security;
#endif
if (ksu_file_sid && sec)
sec->sid = ksu_file_sid;
return 0;
}
static void disable_seccomp_for_task(struct task_struct *tsk)
{
assert_spin_locked(&tsk->sighand->siglock);
#ifdef CONFIG_SECCOMP
if (tsk->seccomp.mode == SECCOMP_MODE_DISABLED && !tsk->seccomp.filter)
return;
#endif
clear_tsk_thread_flag(tsk, TIF_SECCOMP);
#ifdef CONFIG_SECCOMP
tsk->seccomp.mode = SECCOMP_MODE_DISABLED;
if (tsk->seccomp.filter) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
seccomp_filter_release(tsk);
#else
put_seccomp_filter(tsk);
tsk->seccomp.filter = NULL;
#endif
}
#endif
}
void escape_to_root_for_cmd_su(uid_t target_uid, pid_t target_pid)
{
struct cred *newcreds;
struct task_struct *target_task;
unsigned long flags;
struct task_struct *p = current;
struct task_struct *t;
pr_info("cmd_su: escape_to_root_for_cmd_su called for UID: %d, PID: %d\n", target_uid, target_pid);
// Find target task by PID
rcu_read_lock();
target_task = pid_task(find_vpid(target_pid), PIDTYPE_PID);
if (!target_task) {
rcu_read_unlock();
pr_err("cmd_su: target task not found for PID: %d\n", target_pid);
#if __SULOG_GATE
ksu_sulog_report_su_grant(target_uid, "cmd_su", "target_not_found");
#endif
return;
}
get_task_struct(target_task);
rcu_read_unlock();
if (task_uid(target_task).val == 0) {
pr_warn("cmd_su: target task is already root, PID: %d\n", target_pid);
put_task_struct(target_task);
return;
}
newcreds = prepare_kernel_cred(target_task);
if (newcreds == NULL) {
pr_err("cmd_su: failed to allocate new cred for PID: %d\n", target_pid);
#if __SULOG_GATE
ksu_sulog_report_su_grant(target_uid, "cmd_su", "cred_alloc_failed");
#endif
put_task_struct(target_task);
return;
}
struct root_profile *profile = ksu_get_root_profile(target_uid);
newcreds->uid.val = profile->uid;
newcreds->suid.val = profile->uid;
newcreds->euid.val = profile->uid;
newcreds->fsuid.val = profile->uid;
newcreds->gid.val = profile->gid;
newcreds->fsgid.val = profile->gid;
newcreds->sgid.val = profile->gid;
newcreds->egid.val = profile->gid;
newcreds->securebits = 0;
u64 cap_for_cmd_su = profile->capabilities.effective | CAP_DAC_READ_SEARCH | CAP_SETUID | CAP_SETGID;
memcpy(&newcreds->cap_effective, &cap_for_cmd_su, sizeof(newcreds->cap_effective));
memcpy(&newcreds->cap_permitted, &profile->capabilities.effective, sizeof(newcreds->cap_permitted));
memcpy(&newcreds->cap_bset, &profile->capabilities.effective, sizeof(newcreds->cap_bset));
setup_groups(profile, newcreds);
task_lock(target_task);
const struct cred *old_creds = get_task_cred(target_task);
rcu_assign_pointer(target_task->real_cred, newcreds);
rcu_assign_pointer(target_task->cred, get_cred(newcreds));
task_unlock(target_task);
if (target_task->sighand) {
spin_lock_irqsave(&target_task->sighand->siglock, flags);
disable_seccomp_for_task(target_task);
spin_unlock_irqrestore(&target_task->sighand->siglock, flags);
}
setup_selinux(profile->selinux_domain);
put_cred(old_creds);
wake_up_process(target_task);
if (target_task->signal->tty) {
struct inode *inode = target_task->signal->tty->driver_data;
if (inode && inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC) {
__manual_su_handle_devpts(inode);
}
}
put_task_struct(target_task);
#if __SULOG_GATE
ksu_sulog_report_su_grant(target_uid, "cmd_su", "manual_escalation");
#endif
for_each_thread (p, t) {
ksu_set_task_tracepoint_flag(t);
}
pr_info("cmd_su: privilege escalation completed for UID: %d, PID: %d\n", target_uid, target_pid);
}
#endif

70
kernel/app_profile.h Normal file
View File

@@ -0,0 +1,70 @@
#ifndef __KSU_H_APP_PROFILE
#define __KSU_H_APP_PROFILE
#include <linux/types.h>
// Forward declarations
struct cred;
#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
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 {
u64 effective;
u64 permitted;
u64 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.
u32 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;
};
};
// Escalate current process to root with the appropriate profile
void escape_with_root_profile(void);
void escape_to_root_for_cmd_su(uid_t target_uid, pid_t target_pid);
void disable_seccomp(void);
#endif

View File

@@ -18,10 +18,8 @@
#define __PT_SP_REG sp #define __PT_SP_REG sp
#define __PT_IP_REG pc #define __PT_IP_REG pc
#define PRCTL_SYMBOL "__arm64_sys_prctl" #define REBOOT_SYMBOL "__arm64_sys_reboot"
#define SYS_READ_SYMBOL "__arm64_sys_read" #define SYS_READ_SYMBOL "__arm64_sys_read"
#define SYS_NEWFSTATAT_SYMBOL "__arm64_sys_newfstatat"
#define SYS_FACCESSAT_SYMBOL "__arm64_sys_faccessat"
#define SYS_EXECVE_SYMBOL "__arm64_sys_execve" #define SYS_EXECVE_SYMBOL "__arm64_sys_execve"
#elif defined(__x86_64__) #elif defined(__x86_64__)
@@ -39,10 +37,8 @@
#define __PT_RC_REG ax #define __PT_RC_REG ax
#define __PT_SP_REG sp #define __PT_SP_REG sp
#define __PT_IP_REG ip #define __PT_IP_REG ip
#define PRCTL_SYMBOL "__x64_sys_prctl" #define REBOOT_SYMBOL "__x64_sys_reboot"
#define SYS_READ_SYMBOL "__x64_sys_read" #define SYS_READ_SYMBOL "__x64_sys_read"
#define SYS_NEWFSTATAT_SYMBOL "__x64_sys_newfstatat"
#define SYS_FACCESSAT_SYMBOL "__x64_sys_faccessat"
#define SYS_EXECVE_SYMBOL "__x64_sys_execve" #define SYS_EXECVE_SYMBOL "__x64_sys_execve"
#else #else

View File

@@ -1,907 +0,0 @@
#include <linux/capability.h>
#include <linux/cred.h>
#include <linux/dcache.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/init_task.h>
#include <linux/kallsyms.h>
#include <linux/kernel.h>
#include <linux/kprobes.h>
#include <linux/lsm_hooks.h>
#include <linux/mm.h>
#include <linux/nsproxy.h>
#include <linux/path.h>
#include <linux/printk.h>
#include <linux/sched.h>
#include <linux/security.h>
#include <linux/stddef.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <linux/uidgid.h>
#include <linux/version.h>
#include <linux/mount.h>
#include <linux/fs.h>
#include <linux/namei.h>
#ifdef MODULE
#include <linux/list.h>
#include <linux/irqflags.h>
#include <linux/mm_types.h>
#include <linux/rcupdate.h>
#include <linux/vmalloc.h>
#endif
#include "allowlist.h"
#include "arch.h"
#include "core_hook.h"
#include "klog.h" // IWYU pragma: keep
#include "ksu.h"
#include "ksud.h"
#include "manager.h"
#include "selinux/selinux.h"
#include "throne_tracker.h"
#include "throne_tracker.h"
#include "kernel_compat.h"
#include "kpm/kpm.h"
static bool ksu_module_mounted = false;
extern int handle_sepolicy(unsigned long arg3, void __user *arg4);
static bool ksu_su_compat_enabled = true;
extern void ksu_sucompat_init();
extern void ksu_sucompat_exit();
static inline bool is_allow_su()
{
if (is_manager()) {
// we are manager, allow!
return true;
}
return ksu_is_allow_uid(current_uid().val);
}
static inline bool is_unsupported_uid(uid_t uid)
{
#define LAST_APPLICATION_UID 19999
uid_t appid = uid % 100000;
return appid > LAST_APPLICATION_UID;
}
static struct group_info root_groups = { .usage = ATOMIC_INIT(2) };
static void setup_groups(struct root_profile *profile, struct cred *cred)
{
if (profile->groups_count > KSU_MAX_GROUPS) {
pr_warn("Failed to setgroups, too large group: %d!\n",
profile->uid);
return;
}
if (profile->groups_count == 1 && profile->groups[0] == 0) {
// setgroup to root and return early.
if (cred->group_info)
put_group_info(cred->group_info);
cred->group_info = get_group_info(&root_groups);
return;
}
u32 ngroups = profile->groups_count;
struct group_info *group_info = groups_alloc(ngroups);
if (!group_info) {
pr_warn("Failed to setgroups, ENOMEM for: %d\n", profile->uid);
return;
}
int i;
for (i = 0; i < ngroups; i++) {
gid_t gid = profile->groups[i];
kgid_t kgid = make_kgid(current_user_ns(), gid);
if (!gid_valid(kgid)) {
pr_warn("Failed to setgroups, invalid gid: %d\n", gid);
put_group_info(group_info);
return;
}
group_info->gid[i] = kgid;
}
groups_sort(group_info);
set_groups(cred, group_info);
}
static void disable_seccomp()
{
assert_spin_locked(&current->sighand->siglock);
// disable seccomp
#if defined(CONFIG_GENERIC_ENTRY) && \
LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
current_thread_info()->syscall_work &= ~SYSCALL_WORK_SECCOMP;
#else
current_thread_info()->flags &= ~(TIF_SECCOMP | _TIF_SECCOMP);
#endif
#ifdef CONFIG_SECCOMP
current->seccomp.mode = 0;
current->seccomp.filter = NULL;
#else
#endif
}
void escape_to_root(void)
{
struct cred *cred;
rcu_read_lock();
do {
cred = (struct cred *)__task_cred((current));
BUG_ON(!cred);
} while (!get_cred_rcu(cred));
if (cred->euid.val == 0) {
pr_warn("Already root, don't escape!\n");
rcu_read_unlock();
return;
}
struct root_profile *profile = ksu_get_root_profile(cred->uid.val);
cred->uid.val = profile->uid;
cred->suid.val = profile->uid;
cred->euid.val = profile->uid;
cred->fsuid.val = profile->uid;
cred->gid.val = profile->gid;
cred->fsgid.val = profile->gid;
cred->sgid.val = profile->gid;
cred->egid.val = profile->gid;
cred->securebits = 0;
BUILD_BUG_ON(sizeof(profile->capabilities.effective) !=
sizeof(kernel_cap_t));
// setup capabilities
// we need CAP_DAC_READ_SEARCH becuase `/data/adb/ksud` is not accessible for non root process
// we add it here but don't add it to cap_inhertiable, it would be dropped automaticly after exec!
u64 cap_for_ksud =
profile->capabilities.effective | CAP_DAC_READ_SEARCH;
memcpy(&cred->cap_effective, &cap_for_ksud,
sizeof(cred->cap_effective));
memcpy(&cred->cap_permitted, &profile->capabilities.effective,
sizeof(cred->cap_permitted));
memcpy(&cred->cap_bset, &profile->capabilities.effective,
sizeof(cred->cap_bset));
setup_groups(profile, cred);
rcu_read_unlock();
// Refer to kernel/seccomp.c: seccomp_set_mode_strict
// When disabling Seccomp, ensure that current->sighand->siglock is held during the operation.
spin_lock_irq(&current->sighand->siglock);
disable_seccomp();
spin_unlock_irq(&current->sighand->siglock);
setup_selinux(profile->selinux_domain);
}
int ksu_handle_rename(struct dentry *old_dentry, struct dentry *new_dentry)
{
if (!current->mm) {
// skip kernel threads
return 0;
}
if (current_uid().val != 1000) {
// skip non system uid
return 0;
}
if (!old_dentry || !new_dentry) {
return 0;
}
// /data/system/packages.list.tmp -> /data/system/packages.list
if (strcmp(new_dentry->d_iname, "packages.list")) {
return 0;
}
char path[128];
char *buf = dentry_path_raw(new_dentry, path, sizeof(path));
if (IS_ERR(buf)) {
pr_err("dentry_path_raw failed.\n");
return 0;
}
if (!strstr(buf, "/system/packages.list")) {
return 0;
}
pr_info("renameat: %s -> %s, new path: %s\n", old_dentry->d_iname,
new_dentry->d_iname, buf);
track_throne();
return 0;
}
static void nuke_ext4_sysfs() {
struct path path;
int err = kern_path("/data/adb/modules", 0, &path);
if (err) {
pr_err("nuke path err: %d\n", err);
return;
}
struct super_block* sb = path.dentry->d_inode->i_sb;
const char* name = sb->s_type->name;
if (strcmp(name, "ext4") != 0) {
pr_info("nuke but module aren't mounted\n");
return;
}
ext4_unregister_sysfs(sb);
}
int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5)
{
// if success, we modify the arg5 as result!
u32 *result = (u32 *)arg5;
u32 reply_ok = KERNEL_SU_OPTION;
if (KERNEL_SU_OPTION != option) {
return 0;
}
// TODO: find it in throne tracker!
uid_t current_uid_val = current_uid().val;
uid_t manager_uid = ksu_get_manager_uid();
if (current_uid_val != manager_uid &&
current_uid_val % 100000 == manager_uid) {
ksu_set_manager_uid(current_uid_val);
}
bool from_root = 0 == current_uid().val;
bool from_manager = is_manager();
if (!from_root && !from_manager) {
// only root or manager can access this interface
return 0;
}
#ifdef CONFIG_KSU_DEBUG
pr_info("option: 0x%x, cmd: %ld\n", option, arg2);
#endif
if (arg2 == CMD_BECOME_MANAGER) {
if (from_manager) {
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
pr_err("become_manager: prctl reply error\n");
}
return 0;
}
return 0;
}
if (arg2 == CMD_GRANT_ROOT) {
if (is_allow_su()) {
pr_info("allow root for: %d\n", current_uid().val);
escape_to_root();
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
pr_err("grant_root: prctl reply error\n");
}
}
return 0;
}
// Both root manager and root processes should be allowed to get version
if (arg2 == CMD_GET_VERSION) {
u32 version = KERNEL_SU_VERSION;
if (copy_to_user(arg3, &version, sizeof(version))) {
pr_err("prctl reply error, cmd: %lu\n", arg2);
}
u32 version_flags = 0;
#ifdef MODULE
version_flags |= 0x1;
#endif
if (arg4 &&
copy_to_user(arg4, &version_flags, sizeof(version_flags))) {
pr_err("prctl reply error, cmd: %lu\n", arg2);
}
return 0;
}
if (arg2 == CMD_REPORT_EVENT) {
if (!from_root) {
return 0;
}
switch (arg3) {
case EVENT_POST_FS_DATA: {
static bool post_fs_data_lock = false;
if (!post_fs_data_lock) {
post_fs_data_lock = true;
pr_info("post-fs-data triggered\n");
on_post_fs_data();
}
break;
}
case EVENT_BOOT_COMPLETED: {
static bool boot_complete_lock = false;
if (!boot_complete_lock) {
boot_complete_lock = true;
pr_info("boot_complete triggered\n");
}
break;
}
case EVENT_MODULE_MOUNTED: {
ksu_module_mounted = true;
pr_info("module mounted!\n");
nuke_ext4_sysfs();
break;
}
default:
break;
}
return 0;
}
if (arg2 == CMD_SET_SEPOLICY) {
if (!from_root) {
return 0;
}
if (!handle_sepolicy(arg3, arg4)) {
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
pr_err("sepolicy: prctl reply error\n");
}
}
return 0;
}
if (arg2 == CMD_CHECK_SAFEMODE) {
if (ksu_is_safe_mode()) {
pr_warn("safemode enabled!\n");
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
pr_err("safemode: prctl reply error\n");
}
}
return 0;
}
if (arg2 == CMD_GET_ALLOW_LIST || arg2 == CMD_GET_DENY_LIST) {
u32 array[128];
u32 array_length;
bool success = ksu_get_allow_list(array, &array_length,
arg2 == CMD_GET_ALLOW_LIST);
if (success) {
if (!copy_to_user(arg4, &array_length,
sizeof(array_length)) &&
!copy_to_user(arg3, array,
sizeof(u32) * array_length)) {
if (copy_to_user(result, &reply_ok,
sizeof(reply_ok))) {
pr_err("prctl reply error, cmd: %lu\n",
arg2);
}
} else {
pr_err("prctl copy allowlist error\n");
}
}
return 0;
}
if (arg2 == CMD_UID_GRANTED_ROOT || arg2 == CMD_UID_SHOULD_UMOUNT) {
uid_t target_uid = (uid_t)arg3;
bool allow = false;
if (arg2 == CMD_UID_GRANTED_ROOT) {
allow = ksu_is_allow_uid(target_uid);
} else if (arg2 == CMD_UID_SHOULD_UMOUNT) {
allow = ksu_uid_should_umount(target_uid);
} else {
pr_err("unknown cmd: %lu\n", arg2);
}
if (!copy_to_user(arg4, &allow, sizeof(allow))) {
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
pr_err("prctl reply error, cmd: %lu\n", arg2);
}
} else {
pr_err("prctl copy err, cmd: %lu\n", arg2);
}
return 0;
}
#ifdef CONFIG_KPM
// ADD: 添加KPM模块控制
if(sukisu_is_kpm_control_code(arg2)) {
int res;
pr_info("KPM: calling before arg2=%d\n", (int) arg2);
res = sukisu_handle_kpm(arg2, arg3, arg4, arg5);
return 0;
}
#endif
// all other cmds are for 'root manager'
if (!from_manager) {
return 0;
}
// we are already manager
if (arg2 == CMD_GET_APP_PROFILE) {
struct app_profile profile;
if (copy_from_user(&profile, arg3, sizeof(profile))) {
pr_err("copy profile failed\n");
return 0;
}
bool success = ksu_get_app_profile(&profile);
if (success) {
if (copy_to_user(arg3, &profile, sizeof(profile))) {
pr_err("copy profile failed\n");
return 0;
}
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
pr_err("prctl reply error, cmd: %lu\n", arg2);
}
}
return 0;
}
if (arg2 == CMD_SET_APP_PROFILE) {
struct app_profile profile;
if (copy_from_user(&profile, arg3, sizeof(profile))) {
pr_err("copy profile failed\n");
return 0;
}
// todo: validate the params
if (ksu_set_app_profile(&profile, true)) {
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
pr_err("prctl reply error, cmd: %lu\n", arg2);
}
}
return 0;
}
if (arg2 == CMD_IS_SU_ENABLED) {
if (copy_to_user(arg3, &ksu_su_compat_enabled,
sizeof(ksu_su_compat_enabled))) {
pr_err("copy su compat failed\n");
return 0;
}
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
pr_err("prctl reply error, cmd: %lu\n", arg2);
}
return 0;
}
if (arg2 == CMD_ENABLE_SU) {
bool enabled = (arg3 != 0);
if (enabled == ksu_su_compat_enabled) {
pr_info("cmd enable su but no need to change.\n");
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {// return the reply_ok directly
pr_err("prctl reply error, cmd: %lu\n", arg2);
}
return 0;
}
if (enabled) {
ksu_sucompat_init();
} else {
ksu_sucompat_exit();
}
ksu_su_compat_enabled = enabled;
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
pr_err("prctl reply error, cmd: %lu\n", arg2);
}
return 0;
}
return 0;
}
static bool is_appuid(kuid_t uid)
{
#define PER_USER_RANGE 100000
#define FIRST_APPLICATION_UID 10000
#define LAST_APPLICATION_UID 19999
uid_t appid = uid.val % PER_USER_RANGE;
return appid >= FIRST_APPLICATION_UID && appid <= LAST_APPLICATION_UID;
}
static bool should_umount(struct path *path)
{
if (!path) {
return false;
}
if (current->nsproxy->mnt_ns == init_nsproxy.mnt_ns) {
pr_info("ignore global mnt namespace process: %d\n",
current_uid().val);
return false;
}
if (path->mnt && path->mnt->mnt_sb && path->mnt->mnt_sb->s_type) {
const char *fstype = path->mnt->mnt_sb->s_type->name;
return strcmp(fstype, "overlay") == 0;
}
return false;
}
static void ksu_umount_mnt(struct path *path, int flags)
{
int err = path_umount(path, flags);
if (err) {
pr_info("umount %s failed: %d\n", path->dentry->d_iname, err);
}
}
static void try_umount(const char *mnt, bool check_mnt, int flags)
{
struct path path;
int err = kern_path(mnt, 0, &path);
if (err) {
return;
}
if (path.dentry != path.mnt->mnt_root) {
// it is not root mountpoint, maybe umounted by others already.
return;
}
// we are only interest in some specific mounts
if (check_mnt && !should_umount(&path)) {
return;
}
ksu_umount_mnt(&path, flags);
}
int ksu_handle_setuid(struct cred *new, const struct cred *old)
{
// this hook is used for umounting overlayfs for some uid, if there isn't any module mounted, just ignore it!
if (!ksu_module_mounted) {
return 0;
}
if (!new || !old) {
return 0;
}
kuid_t new_uid = new->uid;
kuid_t old_uid = old->uid;
if (0 != old_uid.val) {
// old process is not root, ignore it.
return 0;
}
if (!is_appuid(new_uid) || is_unsupported_uid(new_uid.val)) {
// pr_info("handle setuid ignore non application or isolated uid: %d\n", new_uid.val);
return 0;
}
if (ksu_is_allow_uid(new_uid.val)) {
// pr_info("handle setuid ignore allowed application: %d\n", new_uid.val);
return 0;
}
if (!ksu_uid_should_umount(new_uid.val)) {
return 0;
} else {
#ifdef CONFIG_KSU_DEBUG
pr_info("uid: %d should not umount!\n", current_uid().val);
#endif
}
// check old process's selinux context, if it is not zygote, ignore it!
// because some su apps may setuid to untrusted_app but they are in global mount namespace
// when we umount for such process, that is a disaster!
bool is_zygote_child = is_zygote(old->security);
if (!is_zygote_child) {
pr_info("handle umount ignore non zygote child: %d\n",
current->pid);
return 0;
}
#ifdef CONFIG_KSU_DEBUG
// umount the target mnt
pr_info("handle umount for uid: %d, pid: %d\n", new_uid.val,
current->pid);
#endif
// fixme: use `collect_mounts` and `iterate_mount` to iterate all mountpoint and
// filter the mountpoint whose target is `/data/adb`
try_umount("/system", true, 0);
try_umount("/vendor", true, 0);
try_umount("/product", true, 0);
try_umount("/system_ext", true, 0);
try_umount("/data/adb/modules", false, MNT_DETACH);
// try umount ksu temp path
try_umount("/debug_ramdisk", false, MNT_DETACH);
return 0;
}
// Init functons
static int handler_pre(struct kprobe *p, struct pt_regs *regs)
{
struct pt_regs *real_regs = PT_REAL_REGS(regs);
int option = (int)PT_REGS_PARM1(real_regs);
unsigned long arg2 = (unsigned long)PT_REGS_PARM2(real_regs);
unsigned long arg3 = (unsigned long)PT_REGS_PARM3(real_regs);
// PRCTL_SYMBOL is the arch-specificed one, which receive raw pt_regs from syscall
unsigned long arg4 = (unsigned long)PT_REGS_SYSCALL_PARM4(real_regs);
unsigned long arg5 = (unsigned long)PT_REGS_PARM5(real_regs);
return ksu_handle_prctl(option, arg2, arg3, arg4, arg5);
}
static struct kprobe prctl_kp = {
.symbol_name = PRCTL_SYMBOL,
.pre_handler = handler_pre,
};
static int renameat_handler_pre(struct kprobe *p, struct pt_regs *regs)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)
// https://elixir.bootlin.com/linux/v5.12-rc1/source/include/linux/fs.h
struct renamedata *rd = PT_REGS_PARM1(regs);
struct dentry *old_entry = rd->old_dentry;
struct dentry *new_entry = rd->new_dentry;
#else
struct dentry *old_entry = (struct dentry *)PT_REGS_PARM2(regs);
struct dentry *new_entry = (struct dentry *)PT_REGS_CCALL_PARM4(regs);
#endif
return ksu_handle_rename(old_entry, new_entry);
}
static struct kprobe renameat_kp = {
.symbol_name = "vfs_rename",
.pre_handler = renameat_handler_pre,
};
__maybe_unused int ksu_kprobe_init(void)
{
int rc = 0;
rc = register_kprobe(&prctl_kp);
if (rc) {
pr_info("prctl kprobe failed: %d.\n", rc);
return rc;
}
rc = register_kprobe(&renameat_kp);
pr_info("renameat kp: %d\n", rc);
return rc;
}
__maybe_unused int ksu_kprobe_exit(void)
{
unregister_kprobe(&prctl_kp);
unregister_kprobe(&renameat_kp);
return 0;
}
static int ksu_task_prctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5)
{
ksu_handle_prctl(option, arg2, arg3, arg4, arg5);
return -ENOSYS;
}
static int ksu_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
struct inode *new_inode, struct dentry *new_dentry)
{
return ksu_handle_rename(old_dentry, new_dentry);
}
static int ksu_task_fix_setuid(struct cred *new, const struct cred *old,
int flags)
{
return ksu_handle_setuid(new, old);
}
#ifndef MODULE
static struct security_hook_list ksu_hooks[] = {
LSM_HOOK_INIT(task_prctl, ksu_task_prctl),
LSM_HOOK_INIT(inode_rename, ksu_inode_rename),
LSM_HOOK_INIT(task_fix_setuid, ksu_task_fix_setuid),
};
void __init ksu_lsm_hook_init(void)
{
security_add_hooks(ksu_hooks, ARRAY_SIZE(ksu_hooks), "ksu");
}
#else
static int override_security_head(void *head, const void *new_head, size_t len)
{
unsigned long base = (unsigned long)head & PAGE_MASK;
unsigned long offset = offset_in_page(head);
// this is impossible for our case because the page alignment
// but be careful for other cases!
BUG_ON(offset + len > PAGE_SIZE);
struct page *page = phys_to_page(__pa(base));
if (!page) {
return -EFAULT;
}
void *addr = vmap(&page, 1, VM_MAP, PAGE_KERNEL);
if (!addr) {
return -ENOMEM;
}
local_irq_disable();
memcpy(addr + offset, new_head, len);
local_irq_enable();
vunmap(addr);
return 0;
}
static void free_security_hook_list(struct hlist_head *head)
{
struct hlist_node *temp;
struct security_hook_list *entry;
if (!head)
return;
hlist_for_each_entry_safe (entry, temp, head, list) {
hlist_del(&entry->list);
kfree(entry);
}
kfree(head);
}
struct hlist_head *copy_security_hlist(struct hlist_head *orig)
{
struct hlist_head *new_head = kmalloc(sizeof(*new_head), GFP_KERNEL);
if (!new_head)
return NULL;
INIT_HLIST_HEAD(new_head);
struct security_hook_list *entry;
struct security_hook_list *new_entry;
hlist_for_each_entry (entry, orig, list) {
new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL);
if (!new_entry) {
free_security_hook_list(new_head);
return NULL;
}
*new_entry = *entry;
hlist_add_tail_rcu(&new_entry->list, new_head);
}
return new_head;
}
#define LSM_SEARCH_MAX 180 // This should be enough to iterate
static void *find_head_addr(void *security_ptr, int *index)
{
if (!security_ptr) {
return NULL;
}
struct hlist_head *head_start =
(struct hlist_head *)&security_hook_heads;
for (int i = 0; i < LSM_SEARCH_MAX; i++) {
struct hlist_head *head = head_start + i;
struct security_hook_list *pos;
hlist_for_each_entry (pos, head, list) {
if (pos->hook.capget == security_ptr) {
if (index) {
*index = i;
}
return head;
}
}
}
return NULL;
}
#define GET_SYMBOL_ADDR(sym) \
({ \
void *addr = kallsyms_lookup_name(#sym ".cfi_jt"); \
if (!addr) { \
addr = kallsyms_lookup_name(#sym); \
} \
addr; \
})
#define KSU_LSM_HOOK_HACK_INIT(head_ptr, name, func) \
do { \
static struct security_hook_list hook = { \
.hook = { .name = func } \
}; \
hook.head = head_ptr; \
hook.lsm = "ksu"; \
struct hlist_head *new_head = copy_security_hlist(hook.head); \
if (!new_head) { \
pr_err("Failed to copy security list: %s\n", #name); \
break; \
} \
hlist_add_tail_rcu(&hook.list, new_head); \
if (override_security_head(hook.head, new_head, \
sizeof(*new_head))) { \
free_security_hook_list(new_head); \
pr_err("Failed to hack lsm for: %s\n", #name); \
} \
} while (0)
void __init ksu_lsm_hook_init(void)
{
void *cap_prctl = GET_SYMBOL_ADDR(cap_task_prctl);
void *prctl_head = find_head_addr(cap_prctl, NULL);
if (prctl_head) {
if (prctl_head != &security_hook_heads.task_prctl) {
pr_warn("prctl's address has shifted!\n");
}
KSU_LSM_HOOK_HACK_INIT(prctl_head, task_prctl, ksu_task_prctl);
} else {
pr_warn("Failed to find task_prctl!\n");
}
int inode_killpriv_index = -1;
void *cap_killpriv = GET_SYMBOL_ADDR(cap_inode_killpriv);
find_head_addr(cap_killpriv, &inode_killpriv_index);
if (inode_killpriv_index < 0) {
pr_warn("Failed to find inode_rename, use kprobe instead!\n");
register_kprobe(&renameat_kp);
} else {
int inode_rename_index = inode_killpriv_index +
&security_hook_heads.inode_rename -
&security_hook_heads.inode_killpriv;
struct hlist_head *head_start =
(struct hlist_head *)&security_hook_heads;
void *inode_rename_head = head_start + inode_rename_index;
if (inode_rename_head != &security_hook_heads.inode_rename) {
pr_warn("inode_rename's address has shifted!\n");
}
KSU_LSM_HOOK_HACK_INIT(inode_rename_head, inode_rename,
ksu_inode_rename);
}
void *cap_setuid = GET_SYMBOL_ADDR(cap_task_fix_setuid);
void *setuid_head = find_head_addr(cap_setuid, NULL);
if (setuid_head) {
if (setuid_head != &security_hook_heads.task_fix_setuid) {
pr_warn("setuid's address has shifted!\n");
}
KSU_LSM_HOOK_HACK_INIT(setuid_head, task_fix_setuid,
ksu_task_fix_setuid);
} else {
pr_warn("Failed to find task_fix_setuid!\n");
}
smp_mb();
}
#endif
void __init ksu_core_init(void)
{
ksu_lsm_hook_init();
}
void ksu_core_exit(void)
{
#ifdef CONFIG_KPROBE
pr_info("ksu_core_kprobe_exit\n");
// we dont use this now
// ksu_kprobe_exit();
#endif
}

View File

@@ -1,9 +0,0 @@
#ifndef __KSU_H_KSU_CORE
#define __KSU_H_KSU_CORE
#include <linux/init.h>
void __init ksu_core_init(void);
void ksu_core_exit(void);
#endif

504
kernel/dynamic_manager.c Normal file
View File

@@ -0,0 +1,504 @@
#include <linux/err.h>
#include <linux/fs.h>
#include <linux/gfp.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/version.h>
#include <linux/workqueue.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>
#else
#include <crypto/sha.h>
#endif
#include "dynamic_manager.h"
#include "klog.h" // IWYU pragma: keep
#include "manager.h"
#define MAX_MANAGERS 2
// Dynamic sign configuration
static struct dynamic_manager_config dynamic_manager = {
.size = 0x300,
.hash = "0000000000000000000000000000000000000000000000000000000000000000",
.is_set = 0
};
// Multi-manager state
static struct manager_info active_managers[MAX_MANAGERS];
static DEFINE_SPINLOCK(managers_lock);
static DEFINE_SPINLOCK(dynamic_manager_lock);
// Work queues for persistent storage
static struct work_struct save_dynamic_manager_work;
static struct work_struct load_dynamic_manager_work;
static struct work_struct clear_dynamic_manager_work;
bool ksu_is_dynamic_manager_enabled(void)
{
unsigned long flags;
bool enabled;
spin_lock_irqsave(&dynamic_manager_lock, flags);
enabled = dynamic_manager.is_set;
spin_unlock_irqrestore(&dynamic_manager_lock, flags);
return enabled;
}
void ksu_add_manager(uid_t uid, int signature_index)
{
unsigned long flags;
int i;
if (!ksu_is_dynamic_manager_enabled()) {
pr_info("Dynamic sign not enabled, skipping multi-manager add\n");
return;
}
spin_lock_irqsave(&managers_lock, flags);
// Check if manager already exists and update
for (i = 0; i < MAX_MANAGERS; i++) {
if (active_managers[i].is_active && active_managers[i].uid == uid) {
active_managers[i].signature_index = signature_index;
spin_unlock_irqrestore(&managers_lock, flags);
pr_info("Updated manager uid=%d, signature_index=%d\n", uid, signature_index);
return;
}
}
// Find free slot for new manager
for (i = 0; i < MAX_MANAGERS; i++) {
if (!active_managers[i].is_active) {
active_managers[i].uid = uid;
active_managers[i].signature_index = signature_index;
active_managers[i].is_active = true;
spin_unlock_irqrestore(&managers_lock, flags);
pr_info("Added manager uid=%d, signature_index=%d\n", uid, signature_index);
return;
}
}
spin_unlock_irqrestore(&managers_lock, flags);
pr_warn("Failed to add manager, no free slots\n");
}
void ksu_remove_manager(uid_t uid)
{
unsigned long flags;
int i;
if (!ksu_is_dynamic_manager_enabled()) {
return;
}
spin_lock_irqsave(&managers_lock, flags);
for (i = 0; i < MAX_MANAGERS; i++) {
if (active_managers[i].is_active && active_managers[i].uid == uid) {
active_managers[i].is_active = false;
pr_info("Removed manager uid=%d\n", uid);
break;
}
}
spin_unlock_irqrestore(&managers_lock, flags);
}
bool ksu_is_any_manager(uid_t uid)
{
unsigned long flags;
bool is_manager = false;
int i;
if (!ksu_is_dynamic_manager_enabled()) {
return false;
}
spin_lock_irqsave(&managers_lock, flags);
for (i = 0; i < MAX_MANAGERS; i++) {
if (active_managers[i].is_active && active_managers[i].uid == uid) {
is_manager = true;
break;
}
}
spin_unlock_irqrestore(&managers_lock, flags);
return is_manager;
}
int ksu_get_manager_signature_index(uid_t uid)
{
unsigned long flags;
int signature_index = -1;
int i;
// Check traditional manager first
if (ksu_manager_uid != KSU_INVALID_UID && uid == ksu_manager_uid) {
return DYNAMIC_SIGN_INDEX;
}
if (!ksu_is_dynamic_manager_enabled()) {
return -1;
}
spin_lock_irqsave(&managers_lock, flags);
for (i = 0; i < MAX_MANAGERS; i++) {
if (active_managers[i].is_active && active_managers[i].uid == uid) {
signature_index = active_managers[i].signature_index;
break;
}
}
spin_unlock_irqrestore(&managers_lock, flags);
return signature_index;
}
static void clear_dynamic_manager(void)
{
unsigned long flags;
int i;
spin_lock_irqsave(&managers_lock, flags);
for (i = 0; i < MAX_MANAGERS; i++) {
if (active_managers[i].is_active) {
pr_info("Clearing dynamic manager uid=%d (signature_index=%d) for rescan\n",
active_managers[i].uid, active_managers[i].signature_index);
active_managers[i].is_active = false;
}
}
spin_unlock_irqrestore(&managers_lock, flags);
}
int ksu_get_active_managers(struct manager_list_info *info)
{
unsigned long flags;
int i, count = 0;
if (!info) {
return -EINVAL;
}
// Add traditional manager first
if (ksu_manager_uid != KSU_INVALID_UID && count < 2) {
info->managers[count].uid = ksu_manager_uid;
info->managers[count].signature_index = 0;
count++;
}
// Add dynamic managers
if (ksu_is_dynamic_manager_enabled()) {
spin_lock_irqsave(&managers_lock, flags);
for (i = 0; i < MAX_MANAGERS && count < 2; i++) {
if (active_managers[i].is_active) {
info->managers[count].uid = active_managers[i].uid;
info->managers[count].signature_index = active_managers[i].signature_index;
count++;
}
}
spin_unlock_irqrestore(&managers_lock, flags);
}
info->count = count;
return 0;
}
static void do_save_dynamic_manager(struct work_struct *work)
{
u32 magic = DYNAMIC_MANAGER_FILE_MAGIC;
u32 version = DYNAMIC_MANAGER_FILE_VERSION;
struct dynamic_manager_config config_to_save;
loff_t off = 0;
unsigned long flags;
struct file *fp;
spin_lock_irqsave(&dynamic_manager_lock, flags);
config_to_save = dynamic_manager;
spin_unlock_irqrestore(&dynamic_manager_lock, flags);
if (!config_to_save.is_set) {
pr_info("Dynamic sign config not set, skipping save\n");
return;
}
fp = filp_open(KERNEL_SU_DYNAMIC_MANAGER, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (IS_ERR(fp)) {
pr_err("save_dynamic_manager create file failed: %ld\n", PTR_ERR(fp));
return;
}
if (kernel_write(fp, &magic, sizeof(magic), &off) != sizeof(magic)) {
pr_err("save_dynamic_manager write magic failed.\n");
goto exit;
}
if (kernel_write(fp, &version, sizeof(version), &off) != sizeof(version)) {
pr_err("save_dynamic_manager write version failed.\n");
goto exit;
}
if (kernel_write(fp, &config_to_save, sizeof(config_to_save), &off) != sizeof(config_to_save)) {
pr_err("save_dynamic_manager write config failed.\n");
goto exit;
}
pr_info("Dynamic sign config saved successfully\n");
exit:
filp_close(fp, 0);
}
static void do_load_dynamic_manager(struct work_struct *work)
{
loff_t off = 0;
ssize_t ret = 0;
struct file *fp = NULL;
u32 magic;
u32 version;
struct dynamic_manager_config loaded_config;
unsigned long flags;
int i;
fp = filp_open(KERNEL_SU_DYNAMIC_MANAGER, O_RDONLY, 0);
if (IS_ERR(fp)) {
if (PTR_ERR(fp) == -ENOENT) {
pr_info("No saved dynamic manager config found\n");
} else {
pr_err("load_dynamic_manager open file failed: %ld\n", PTR_ERR(fp));
}
return;
}
if (kernel_read(fp, &magic, sizeof(magic), &off) != sizeof(magic) ||
magic != DYNAMIC_MANAGER_FILE_MAGIC) {
pr_err("dynamic manager file invalid magic: %x!\n", magic);
goto exit;
}
if (kernel_read(fp, &version, sizeof(version), &off) != sizeof(version)) {
pr_err("dynamic manager read version failed\n");
goto exit;
}
pr_info("dynamic manager file version: %d\n", version);
ret = kernel_read(fp, &loaded_config, sizeof(loaded_config), &off);
if (ret <= 0) {
pr_info("load_dynamic_manager read err: %zd\n", ret);
goto exit;
}
if (ret != sizeof(loaded_config)) {
pr_err("load_dynamic_manager read incomplete config: %zd/%zu\n", ret, sizeof(loaded_config));
goto exit;
}
if (loaded_config.size < 0x100 || loaded_config.size > 0x1000) {
pr_err("Invalid saved config size: 0x%x\n", loaded_config.size);
goto exit;
}
if (strlen(loaded_config.hash) != 64) {
pr_err("Invalid saved config hash length: %zu\n", strlen(loaded_config.hash));
goto exit;
}
// Validate hash format
for (i = 0; i < 64; i++) {
char c = loaded_config.hash[i];
if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'))) {
pr_err("Invalid saved config hash character at position %d: %c\n", i, c);
goto exit;
}
}
spin_lock_irqsave(&dynamic_manager_lock, flags);
dynamic_manager = loaded_config;
spin_unlock_irqrestore(&dynamic_manager_lock, flags);
pr_info("Dynamic sign config loaded: size=0x%x, hash=%.16s...\n",
loaded_config.size, loaded_config.hash);
exit:
filp_close(fp, 0);
}
static bool persistent_dynamic_manager(void)
{
return ksu_queue_work(&save_dynamic_manager_work);
}
static void do_clear_dynamic_manager(struct work_struct *work)
{
loff_t off = 0;
struct file *fp;
char zero_buffer[512];
memset(zero_buffer, 0, sizeof(zero_buffer));
fp = filp_open(KERNEL_SU_DYNAMIC_MANAGER, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (IS_ERR(fp)) {
pr_err("clear_dynamic_manager create file failed: %ld\n", PTR_ERR(fp));
return;
}
// Write null bytes to overwrite the file content
if (kernel_write(fp, zero_buffer, sizeof(zero_buffer), &off) != sizeof(zero_buffer)) {
pr_err("clear_dynamic_manager write null bytes failed.\n");
} else {
pr_info("Dynamic sign config file cleared successfully\n");
}
filp_close(fp, 0);
}
static bool clear_dynamic_manager_file(void)
{
return ksu_queue_work(&clear_dynamic_manager_work);
}
int ksu_handle_dynamic_manager(struct dynamic_manager_user_config *config)
{
unsigned long flags;
int ret = 0;
int i;
if (!config) {
return -EINVAL;
}
switch (config->operation) {
case DYNAMIC_MANAGER_OP_SET:
if (config->size < 0x100 || config->size > 0x1000) {
pr_err("invalid size: 0x%x\n", config->size);
return -EINVAL;
}
if (strlen(config->hash) != 64) {
pr_err("invalid hash length: %zu\n", strlen(config->hash));
return -EINVAL;
}
// Validate hash format
for (i = 0; i < 64; i++) {
char c = config->hash[i];
if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'))) {
pr_err("invalid hash character at position %d: %c\n", i, c);
return -EINVAL;
}
}
spin_lock_irqsave(&dynamic_manager_lock, flags);
dynamic_manager.size = config->size;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
strscpy(dynamic_manager.hash, config->hash, sizeof(dynamic_manager.hash));
#else
strlcpy(dynamic_manager.hash, config->hash, sizeof(dynamic_manager.hash));
#endif
dynamic_manager.is_set = 1;
spin_unlock_irqrestore(&dynamic_manager_lock, flags);
persistent_dynamic_manager();
pr_info("dynamic manager updated: size=0x%x, hash=%.16s... (multi-manager enabled)\n",
config->size, config->hash);
break;
case DYNAMIC_MANAGER_OP_GET:
spin_lock_irqsave(&dynamic_manager_lock, flags);
if (dynamic_manager.is_set) {
config->size = dynamic_manager.size;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
strscpy(config->hash, dynamic_manager.hash, sizeof(config->hash));
#else
strlcpy(config->hash, dynamic_manager.hash, sizeof(config->hash));
#endif
ret = 0;
} else {
ret = -ENODATA;
}
spin_unlock_irqrestore(&dynamic_manager_lock, flags);
break;
case DYNAMIC_MANAGER_OP_CLEAR:
spin_lock_irqsave(&dynamic_manager_lock, flags);
dynamic_manager.size = 0x300;
strcpy(dynamic_manager.hash, "0000000000000000000000000000000000000000000000000000000000000000");
dynamic_manager.is_set = 0;
spin_unlock_irqrestore(&dynamic_manager_lock, flags);
// Clear only dynamic managers, preserve default manager
clear_dynamic_manager();
// Clear file using the same method as save
clear_dynamic_manager_file();
pr_info("Dynamic sign config cleared (multi-manager disabled)\n");
break;
default:
pr_err("Invalid dynamic manager operation: %d\n", config->operation);
return -EINVAL;
}
return ret;
}
bool ksu_load_dynamic_manager(void)
{
return ksu_queue_work(&load_dynamic_manager_work);
}
void ksu_dynamic_manager_init(void)
{
int i;
INIT_WORK(&save_dynamic_manager_work, do_save_dynamic_manager);
INIT_WORK(&load_dynamic_manager_work, do_load_dynamic_manager);
INIT_WORK(&clear_dynamic_manager_work, do_clear_dynamic_manager);
// Initialize manager slots
for (i = 0; i < MAX_MANAGERS; i++) {
active_managers[i].is_active = false;
}
ksu_load_dynamic_manager();
pr_info("Dynamic sign initialized with conditional multi-manager support\n");
}
void ksu_dynamic_manager_exit(void)
{
clear_dynamic_manager();
// Save current config before exit
do_save_dynamic_manager(NULL);
pr_info("Dynamic sign exited with persistent storage\n");
}
// Get dynamic manager configuration for signature verification
bool ksu_get_dynamic_manager_config(unsigned int *size, const char **hash)
{
unsigned long flags;
bool valid = false;
spin_lock_irqsave(&dynamic_manager_lock, flags);
if (dynamic_manager.is_set) {
if (size) *size = dynamic_manager.size;
if (hash) *hash = dynamic_manager.hash;
valid = true;
}
spin_unlock_irqrestore(&dynamic_manager_lock, flags);
return valid;
}

51
kernel/dynamic_manager.h Normal file
View File

@@ -0,0 +1,51 @@
#ifndef __KSU_H_DYNAMIC_MANAGER
#define __KSU_H_DYNAMIC_MANAGER
#include <linux/types.h>
#include "ksu.h"
#define DYNAMIC_MANAGER_FILE_MAGIC 0x7f445347 // 'DSG', u32
#define DYNAMIC_MANAGER_FILE_VERSION 1 // u32
#define KERNEL_SU_DYNAMIC_MANAGER "/data/adb/ksu/.dynamic_manager"
#define DYNAMIC_SIGN_INDEX 100
struct dynamic_sign_key {
unsigned int size;
const char *hash;
};
#define DYNAMIC_SIGN_DEFAULT_CONFIG { \
.size = 0x300, \
.hash = "0000000000000000000000000000000000000000000000000000000000000000" \
}
struct dynamic_manager_config {
unsigned int size;
char hash[65];
int is_set;
};
struct manager_info {
uid_t uid;
int signature_index;
bool is_active;
};
// Dynamic sign operations
void ksu_dynamic_manager_init(void);
void ksu_dynamic_manager_exit(void);
int ksu_handle_dynamic_manager(struct dynamic_manager_user_config *config);
bool ksu_load_dynamic_manager(void);
bool ksu_is_dynamic_manager_enabled(void);
// Multi-manager operations
void ksu_add_manager(uid_t uid, int signature_index);
void ksu_remove_manager(uid_t uid);
bool ksu_is_any_manager(uid_t uid);
int ksu_get_manager_signature_index(uid_t uid);
int ksu_get_active_managers(struct manager_list_info *info);
// Configuration access for signature verification
bool ksu_get_dynamic_manager_config(unsigned int *size, const char **hash);
#endif

173
kernel/feature.c Normal file
View File

@@ -0,0 +1,173 @@
#include "feature.h"
#include "klog.h" // IWYU pragma: keep
#include <linux/mutex.h>
static const struct ksu_feature_handler *feature_handlers[KSU_FEATURE_MAX];
static DEFINE_MUTEX(feature_mutex);
int ksu_register_feature_handler(const struct ksu_feature_handler *handler)
{
if (!handler) {
pr_err("feature: register handler is NULL\n");
return -EINVAL;
}
if (handler->feature_id >= KSU_FEATURE_MAX) {
pr_err("feature: invalid feature_id %u\n", handler->feature_id);
return -EINVAL;
}
if (!handler->get_handler && !handler->set_handler) {
pr_err("feature: no handler provided for feature %u\n", handler->feature_id);
return -EINVAL;
}
mutex_lock(&feature_mutex);
if (feature_handlers[handler->feature_id]) {
pr_warn("feature: handler for %u already registered, overwriting\n",
handler->feature_id);
}
feature_handlers[handler->feature_id] = handler;
pr_info("feature: registered handler for %s (id=%u)\n",
handler->name ? handler->name : "unknown", handler->feature_id);
mutex_unlock(&feature_mutex);
return 0;
}
int ksu_unregister_feature_handler(u32 feature_id)
{
int ret = 0;
if (feature_id >= KSU_FEATURE_MAX) {
pr_err("feature: invalid feature_id %u\n", feature_id);
return -EINVAL;
}
mutex_lock(&feature_mutex);
if (!feature_handlers[feature_id]) {
pr_warn("feature: no handler registered for %u\n", feature_id);
ret = -ENOENT;
goto out;
}
feature_handlers[feature_id] = NULL;
pr_info("feature: unregistered handler for id=%u\n", feature_id);
out:
mutex_unlock(&feature_mutex);
return ret;
}
int ksu_get_feature(u32 feature_id, u64 *value, bool *supported)
{
int ret = 0;
const struct ksu_feature_handler *handler;
if (feature_id >= KSU_FEATURE_MAX) {
pr_err("feature: invalid feature_id %u\n", feature_id);
return -EINVAL;
}
if (!value || !supported) {
pr_err("feature: invalid parameters\n");
return -EINVAL;
}
mutex_lock(&feature_mutex);
handler = feature_handlers[feature_id];
if (!handler) {
*supported = false;
*value = 0;
pr_debug("feature: feature %u not supported\n", feature_id);
goto out;
}
*supported = true;
if (!handler->get_handler) {
pr_warn("feature: no get_handler for feature %u\n", feature_id);
ret = -EOPNOTSUPP;
goto out;
}
ret = handler->get_handler(value);
if (ret) {
pr_err("feature: get_handler for %u failed: %d\n", feature_id, ret);
}
out:
mutex_unlock(&feature_mutex);
return ret;
}
int ksu_set_feature(u32 feature_id, u64 value)
{
int ret = 0;
const struct ksu_feature_handler *handler;
if (feature_id >= KSU_FEATURE_MAX) {
pr_err("feature: invalid feature_id %u\n", feature_id);
return -EINVAL;
}
mutex_lock(&feature_mutex);
handler = feature_handlers[feature_id];
if (!handler) {
pr_err("feature: feature %u not registered\n", feature_id);
ret = -EOPNOTSUPP;
goto out;
}
if (!handler->set_handler) {
pr_warn("feature: no set_handler for feature %u\n", feature_id);
ret = -EOPNOTSUPP;
goto out;
}
ret = handler->set_handler(value);
if (ret) {
pr_err("feature: set_handler for %u failed: %d\n", feature_id, ret);
}
out:
mutex_unlock(&feature_mutex);
return ret;
}
void ksu_feature_init(void)
{
int i;
for (i = 0; i < KSU_FEATURE_MAX; i++) {
feature_handlers[i] = NULL;
}
pr_info("feature: feature management initialized\n");
}
void ksu_feature_exit(void)
{
int i;
mutex_lock(&feature_mutex);
for (i = 0; i < KSU_FEATURE_MAX; i++) {
feature_handlers[i] = NULL;
}
mutex_unlock(&feature_mutex);
pr_info("feature: feature management cleaned up\n");
}

37
kernel/feature.h Normal file
View File

@@ -0,0 +1,37 @@
#ifndef __KSU_H_FEATURE
#define __KSU_H_FEATURE
#include <linux/types.h>
enum ksu_feature_id {
KSU_FEATURE_SU_COMPAT = 0,
KSU_FEATURE_KERNEL_UMOUNT = 1,
KSU_FEATURE_ENHANCED_SECURITY = 2,
KSU_FEATURE_SULOG = 3,
KSU_FEATURE_MAX
};
typedef int (*ksu_feature_get_t)(u64 *value);
typedef int (*ksu_feature_set_t)(u64 value);
struct ksu_feature_handler {
u32 feature_id;
const char *name;
ksu_feature_get_t get_handler;
ksu_feature_set_t set_handler;
};
int ksu_register_feature_handler(const struct ksu_feature_handler *handler);
int ksu_unregister_feature_handler(u32 feature_id);
int ksu_get_feature(u32 feature_id, u64 *value, bool *supported);
int ksu_set_feature(u32 feature_id, u64 value);
void ksu_feature_init(void);
void ksu_feature_exit(void);
#endif // __KSU_H_FEATURE

341
kernel/file_wrapper.c Normal file
View File

@@ -0,0 +1,341 @@
#include <linux/export.h>
#include <linux/anon_inodes.h>
#include <linux/capability.h>
#include <linux/cred.h>
#include <linux/err.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/version.h>
#include "klog.h" // IWYU pragma: keep
#include "selinux/selinux.h"
#include "file_wrapper.h"
static loff_t ksu_wrapper_llseek(struct file *fp, loff_t off, int flags) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
return orig->f_op->llseek(data->orig, off, flags);
}
static ssize_t ksu_wrapper_read(struct file *fp, char __user *ptr, size_t sz, loff_t *off) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
return orig->f_op->read(orig, ptr, sz, off);
}
static ssize_t ksu_wrapper_write(struct file *fp, const char __user *ptr, size_t sz, loff_t *off) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
return orig->f_op->write(orig, ptr, sz, off);
}
static ssize_t ksu_wrapper_read_iter(struct kiocb *iocb, struct iov_iter *iovi) {
struct ksu_file_wrapper* data = iocb->ki_filp->private_data;
struct file* orig = data->orig;
iocb->ki_filp = orig;
return orig->f_op->read_iter(iocb, iovi);
}
static ssize_t ksu_wrapper_write_iter(struct kiocb *iocb, struct iov_iter *iovi) {
struct ksu_file_wrapper* data = iocb->ki_filp->private_data;
struct file* orig = data->orig;
iocb->ki_filp = orig;
return orig->f_op->write_iter(iocb, iovi);
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
static int ksu_wrapper_iopoll(struct kiocb *kiocb, struct io_comp_batch* icb, unsigned int v) {
struct ksu_file_wrapper* data = kiocb->ki_filp->private_data;
struct file* orig = data->orig;
kiocb->ki_filp = orig;
return orig->f_op->iopoll(kiocb, icb, v);
}
#else
static int ksu_wrapper_iopoll(struct kiocb *kiocb, bool spin) {
struct ksu_file_wrapper* data = kiocb->ki_filp->private_data;
struct file* orig = data->orig;
kiocb->ki_filp = orig;
return orig->f_op->iopoll(kiocb, spin);
}
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
static int ksu_wrapper_iterate (struct file *fp, struct dir_context *dc) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
return orig->f_op->iterate(orig, dc);
}
#endif
static int ksu_wrapper_iterate_shared(struct file *fp, struct dir_context *dc) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
return orig->f_op->iterate_shared(orig, dc);
}
static __poll_t ksu_wrapper_poll(struct file *fp, struct poll_table_struct *pts) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
return orig->f_op->poll(orig, pts);
}
static long ksu_wrapper_unlocked_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
return orig->f_op->unlocked_ioctl(orig, cmd, arg);
}
static long ksu_wrapper_compat_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
return orig->f_op->compat_ioctl(orig, cmd, arg);
}
static int ksu_wrapper_mmap(struct file *fp, struct vm_area_struct * vma) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
return orig->f_op->mmap(orig, vma);
}
// static unsigned long mmap_supported_flags {}
static int ksu_wrapper_open(struct inode *ino, struct file *fp) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
struct inode *orig_ino = file_inode(orig);
return orig->f_op->open(orig_ino, orig);
}
static int ksu_wrapper_flush(struct file *fp, fl_owner_t id) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
return orig->f_op->flush(orig, id);
}
static int ksu_wrapper_fsync(struct file *fp, loff_t off1, loff_t off2, int datasync) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
return orig->f_op->fsync(orig, off1, off2, datasync);
}
static int ksu_wrapper_fasync(int arg, struct file *fp, int arg2) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
return orig->f_op->fasync(arg, orig, arg2);
}
static int ksu_wrapper_lock(struct file *fp, int arg1, struct file_lock *fl) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
return orig->f_op->lock(orig, arg1, fl);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
static ssize_t ksu_wrapper_sendpage(struct file *fp, struct page *pg, int arg1, size_t sz, loff_t *off, int arg2) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
if (orig->f_op->sendpage) {
return orig->f_op->sendpage(orig, pg, arg1, sz, off, arg2);
}
return -EINVAL;
}
#endif
static unsigned long ksu_wrapper_get_unmapped_area(struct file *fp, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
if (orig->f_op->get_unmapped_area) {
return orig->f_op->get_unmapped_area(orig, arg1, arg2, arg3, arg4);
}
return -EINVAL;
}
// static int ksu_wrapper_check_flags(int arg) {}
static int ksu_wrapper_flock(struct file *fp, int arg1, struct file_lock *fl) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
if (orig->f_op->flock) {
return orig->f_op->flock(orig, arg1, fl);
}
return -EINVAL;
}
static ssize_t ksu_wrapper_splice_write(struct pipe_inode_info * pii, struct file *fp, loff_t *off, size_t sz, unsigned int arg1) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
if (orig->f_op->splice_write) {
return orig->f_op->splice_write(pii, orig, off, sz, arg1);
}
return -EINVAL;
}
static ssize_t ksu_wrapper_splice_read(struct file *fp, loff_t *off, struct pipe_inode_info *pii, size_t sz, unsigned int arg1) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
if (orig->f_op->splice_read) {
return orig->f_op->splice_read(orig, off, pii, sz, arg1);
}
return -EINVAL;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
void ksu_wrapper_splice_eof(struct file *fp) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
if (orig->f_op->splice_eof) {
return orig->f_op->splice_eof(orig);
}
}
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
static int ksu_wrapper_setlease(struct file *fp, int arg1, struct file_lease **fl, void **p) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
if (orig->f_op->setlease) {
return orig->f_op->setlease(orig, arg1, fl, p);
}
return -EINVAL;
}
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
static int ksu_wrapper_setlease(struct file *fp, int arg1, struct file_lock **fl, void **p) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
if (orig->f_op->setlease) {
return orig->f_op->setlease(orig, arg1, fl, p);
}
return -EINVAL;
}
#else
static int ksu_wrapper_setlease(struct file *fp, long arg1, struct file_lock **fl, void **p) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
if (orig->f_op->setlease) {
return orig->f_op->setlease(orig, arg1, fl, p);
}
return -EINVAL;
}
#endif
static long ksu_wrapper_fallocate(struct file *fp, int mode, loff_t offset, loff_t len) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
if (orig->f_op->fallocate) {
return orig->f_op->fallocate(orig, mode, offset, len);
}
return -EINVAL;
}
static void ksu_wrapper_show_fdinfo(struct seq_file *m, struct file *f) {
struct ksu_file_wrapper* data = f->private_data;
struct file* orig = data->orig;
if (orig->f_op->show_fdinfo) {
orig->f_op->show_fdinfo(m, orig);
}
}
static ssize_t ksu_wrapper_copy_file_range(struct file *f1, loff_t off1, struct file *f2,
loff_t off2, size_t sz, unsigned int flags) {
// TODO: determine which file to use
struct ksu_file_wrapper* data = f1->private_data;
struct file* orig = data->orig;
if (orig->f_op->copy_file_range) {
return orig->f_op->copy_file_range(orig, off1, f2, off2, sz, flags);
}
return -EINVAL;
}
static loff_t ksu_wrapper_remap_file_range(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out,
loff_t len, unsigned int remap_flags) {
// TODO: determine which file to use
struct ksu_file_wrapper* data = file_in->private_data;
struct file* orig = data->orig;
if (orig->f_op->remap_file_range) {
return orig->f_op->remap_file_range(orig, pos_in, file_out, pos_out, len, remap_flags);
}
return -EINVAL;
}
static int ksu_wrapper_fadvise(struct file *fp, loff_t off1, loff_t off2, int flags) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
if (orig->f_op->fadvise) {
return orig->f_op->fadvise(orig, off1, off2, flags);
}
return -EINVAL;
}
static int ksu_wrapper_release(struct inode *inode, struct file *filp) {
ksu_delete_file_wrapper(filp->private_data);
return 0;
}
struct ksu_file_wrapper* ksu_create_file_wrapper(struct file* fp) {
struct ksu_file_wrapper* p = kcalloc(sizeof(struct ksu_file_wrapper), 1, GFP_KERNEL);
if (!p) {
return NULL;
}
get_file(fp);
p->orig = fp;
p->ops.owner = THIS_MODULE;
p->ops.llseek = fp->f_op->llseek ? ksu_wrapper_llseek : NULL;
p->ops.read = fp->f_op->read ? ksu_wrapper_read : NULL;
p->ops.write = fp->f_op->write ? ksu_wrapper_write : NULL;
p->ops.read_iter = fp->f_op->read_iter ? ksu_wrapper_read_iter : NULL;
p->ops.write_iter = fp->f_op->write_iter ? ksu_wrapper_write_iter : NULL;
p->ops.iopoll = fp->f_op->iopoll ? ksu_wrapper_iopoll : NULL;
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
p->ops.iterate = fp->f_op->iterate ? ksu_wrapper_iterate : NULL;
#endif
p->ops.iterate_shared = fp->f_op->iterate_shared ? ksu_wrapper_iterate_shared : NULL;
p->ops.poll = fp->f_op->poll ? ksu_wrapper_poll : NULL;
p->ops.unlocked_ioctl = fp->f_op->unlocked_ioctl ? ksu_wrapper_unlocked_ioctl : NULL;
p->ops.compat_ioctl = fp->f_op->compat_ioctl ? ksu_wrapper_compat_ioctl : NULL;
p->ops.mmap = fp->f_op->mmap ? ksu_wrapper_mmap : NULL;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
p->ops.fop_flags = fp->f_op->fop_flags;
#else
p->ops.mmap_supported_flags = fp->f_op->mmap_supported_flags;
#endif
p->ops.open = fp->f_op->open ? ksu_wrapper_open : NULL;
p->ops.flush = fp->f_op->flush ? ksu_wrapper_flush : NULL;
p->ops.release = ksu_wrapper_release;
p->ops.fsync = fp->f_op->fsync ? ksu_wrapper_fsync : NULL;
p->ops.fasync = fp->f_op->fasync ? ksu_wrapper_fasync : NULL;
p->ops.lock = fp->f_op->lock ? ksu_wrapper_lock : NULL;
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
p->ops.sendpage = fp->f_op->sendpage ? ksu_wrapper_sendpage : NULL;
#endif
p->ops.get_unmapped_area = fp->f_op->get_unmapped_area ? ksu_wrapper_get_unmapped_area : NULL;
p->ops.check_flags = fp->f_op->check_flags;
p->ops.flock = fp->f_op->flock ? ksu_wrapper_flock : NULL;
p->ops.splice_write = fp->f_op->splice_write ? ksu_wrapper_splice_write : NULL;
p->ops.splice_read = fp->f_op->splice_read ? ksu_wrapper_splice_read : NULL;
p->ops.setlease = fp->f_op->setlease ? ksu_wrapper_setlease : NULL;
p->ops.fallocate = fp->f_op->fallocate ? ksu_wrapper_fallocate : NULL;
p->ops.show_fdinfo = fp->f_op->show_fdinfo ? ksu_wrapper_show_fdinfo : NULL;
p->ops.copy_file_range = fp->f_op->copy_file_range ? ksu_wrapper_copy_file_range : NULL;
p->ops.remap_file_range = fp->f_op->remap_file_range ? ksu_wrapper_remap_file_range : NULL;
p->ops.fadvise = fp->f_op->fadvise ? ksu_wrapper_fadvise : NULL;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
p->ops.splice_eof = fp->f_op->splice_eof ? ksu_wrapper_splice_eof : NULL;
#endif
return p;
}
void ksu_delete_file_wrapper(struct ksu_file_wrapper* data) {
fput((struct file*) data->orig);
kfree(data);
}

14
kernel/file_wrapper.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef KSU_FILE_WRAPPER_H
#define KSU_FILE_WRAPPER_H
#include <linux/file.h>
#include <linux/fs.h>
struct ksu_file_wrapper {
struct file* orig;
struct file_operations ops;
};
struct ksu_file_wrapper* ksu_create_file_wrapper(struct file* fp);
void ksu_delete_file_wrapper(struct ksu_file_wrapper* data);
#endif // KSU_FILE_WRAPPER_H

View File

@@ -1,28 +0,0 @@
#ifndef __KSU_H_KSHOOK
#define __KSU_H_KSHOOK
#include <linux/fs.h>
#include <linux/types.h>
// For sucompat
int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
int *flags);
int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags);
// For ksud
int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
size_t *count_ptr, loff_t **pos);
// For ksud and sucompat
int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv,
void *envp, int *flags);
// For volume button
int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code,
int *value);
#endif

View File

@@ -1,88 +0,0 @@
#include <linux/version.h>
#include <linux/fs.h>
#include <linux/nsproxy.h>
#include <linux/sched/task.h>
#include <linux/uaccess.h>
#include "klog.h" // IWYU pragma: keep
#include "kernel_compat.h"
extern struct task_struct init_task;
// mnt_ns context switch for environment that android_init->nsproxy->mnt_ns != init_task.nsproxy->mnt_ns, such as WSA
struct ksu_ns_fs_saved {
struct nsproxy *ns;
struct fs_struct *fs;
};
static void ksu_save_ns_fs(struct ksu_ns_fs_saved *ns_fs_saved)
{
ns_fs_saved->ns = current->nsproxy;
ns_fs_saved->fs = current->fs;
}
static void ksu_load_ns_fs(struct ksu_ns_fs_saved *ns_fs_saved)
{
current->nsproxy = ns_fs_saved->ns;
current->fs = ns_fs_saved->fs;
}
static bool android_context_saved_checked = false;
static bool android_context_saved_enabled = false;
static struct ksu_ns_fs_saved android_context_saved;
void ksu_android_ns_fs_check()
{
if (android_context_saved_checked)
return;
android_context_saved_checked = true;
task_lock(current);
if (current->nsproxy && current->fs &&
current->nsproxy->mnt_ns != init_task.nsproxy->mnt_ns) {
android_context_saved_enabled = true;
pr_info("android context saved enabled due to init mnt_ns(%p) != android mnt_ns(%p)\n",
current->nsproxy->mnt_ns, init_task.nsproxy->mnt_ns);
ksu_save_ns_fs(&android_context_saved);
} else {
pr_info("android context saved disabled\n");
}
task_unlock(current);
}
struct file *ksu_filp_open_compat(const char *filename, int flags, umode_t mode)
{
// switch mnt_ns even if current is not wq_worker, to ensure what we open is the correct file in android mnt_ns, rather than user created mnt_ns
struct ksu_ns_fs_saved saved;
if (android_context_saved_enabled) {
pr_info("start switch current nsproxy and fs to android context\n");
task_lock(current);
ksu_save_ns_fs(&saved);
ksu_load_ns_fs(&android_context_saved);
task_unlock(current);
}
struct file *fp = filp_open(filename, flags, mode);
if (android_context_saved_enabled) {
task_lock(current);
ksu_load_ns_fs(&saved);
task_unlock(current);
pr_info("switch current nsproxy and fs back to saved successfully\n");
}
return fp;
}
ssize_t ksu_kernel_read_compat(struct file *p, void *buf, size_t count,
loff_t *pos)
{
return kernel_read(p, buf, count, pos);
}
ssize_t ksu_kernel_write_compat(struct file *p, const void *buf, size_t count,
loff_t *pos)
{
return kernel_write(p, buf, count, pos);
}
long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
long count)
{
return strncpy_from_user_nofault(dst, unsafe_addr, count);
}

View File

@@ -3,33 +3,22 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/version.h> #include <linux/version.h>
#include "ss/policydb.h"
#include "linux/key.h"
/* /*
* Adapt to Huawei HISI kernel without affecting other kernels , * ksu_copy_from_user_retry
* Huawei Hisi Kernel EBITMAP Enable or Disable Flag , * try nofault copy first, if it fails, try with plain
* From ss/ebitmap.h * paramters are the same as copy_from_user
* 0 = success
*/ */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) && \ static long ksu_copy_from_user_retry(void *to,
(LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) || \ const void __user *from, unsigned long count)
(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) && \ {
(LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) long ret = copy_from_user_nofault(to, from, count);
#ifdef HISI_SELINUX_EBITMAP_RO if (likely(!ret))
#define CONFIG_IS_HW_HISI return ret;
#endif
#endif
extern long ksu_strncpy_from_user_nofault(char *dst, // we faulted! fallback to slow path
const void __user *unsafe_addr, return copy_from_user(to, from, count);
long count); }
extern void ksu_android_ns_fs_check();
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,
loff_t *pos);
extern ssize_t ksu_kernel_write_compat(struct file *p, const void *buf,
size_t count, loff_t *pos);
#endif #endif

181
kernel/kernel_umount.c Normal file
View File

@@ -0,0 +1,181 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/task_work.h>
#include <linux/cred.h>
#include <linux/fs.h>
#include <linux/mount.h>
#include <linux/namei.h>
#include <linux/nsproxy.h>
#include <linux/path.h>
#include <linux/printk.h>
#include <linux/types.h>
#include "kernel_umount.h"
#include "klog.h" // IWYU pragma: keep
#include "allowlist.h"
#include "selinux/selinux.h"
#include "feature.h"
#include "ksud.h"
#include "umount_manager.h"
#include "sulog.h"
static bool ksu_kernel_umount_enabled = true;
static int kernel_umount_feature_get(u64 *value)
{
*value = ksu_kernel_umount_enabled ? 1 : 0;
return 0;
}
static int kernel_umount_feature_set(u64 value)
{
bool enable = value != 0;
ksu_kernel_umount_enabled = enable;
pr_info("kernel_umount: set to %d\n", enable);
return 0;
}
static const struct ksu_feature_handler kernel_umount_handler = {
.feature_id = KSU_FEATURE_KERNEL_UMOUNT,
.name = "kernel_umount",
.get_handler = kernel_umount_feature_get,
.set_handler = kernel_umount_feature_set,
};
extern int path_umount(struct path *path, int flags);
static void ksu_umount_mnt(struct path *path, int flags)
{
int err = path_umount(path, flags);
if (err) {
pr_info("umount %s failed: %d\n", path->dentry->d_iname, err);
}
}
void try_umount(const char *mnt, int flags)
{
struct path path;
int err = kern_path(mnt, 0, &path);
if (err) {
return;
}
if (path.dentry != path.mnt->mnt_root) {
// it is not root mountpoint, maybe umounted by others already.
path_put(&path);
return;
}
ksu_umount_mnt(&path, flags);
}
struct umount_tw {
struct callback_head cb;
const struct cred *old_cred;
};
static void umount_tw_func(struct callback_head *cb)
{
struct umount_tw *tw = container_of(cb, struct umount_tw, cb);
const struct cred *saved = NULL;
if (tw->old_cred) {
saved = override_creds(tw->old_cred);
}
struct mount_entry *entry;
down_read(&mount_list_lock);
list_for_each_entry(entry, &mount_list, list) {
pr_info("%s: unmounting: %s flags 0x%x\n", __func__, entry->umountable, entry->flags);
try_umount(entry->umountable, entry->flags);
}
up_read(&mount_list_lock);
ksu_umount_manager_execute_all(tw->old_cred);
if (saved)
revert_creds(saved);
if (tw->old_cred)
put_cred(tw->old_cred);
kfree(tw);
}
int ksu_handle_umount(uid_t old_uid, uid_t new_uid)
{
struct umount_tw *tw;
// if there isn't any module mounted, just ignore it!
if (!ksu_module_mounted) {
return 0;
}
if (!ksu_kernel_umount_enabled) {
return 0;
}
// There are 5 scenarios:
// 1. Normal app: zygote -> appuid
// 2. Isolated process forked from zygote: zygote -> isolated_process
// 3. App zygote forked from zygote: zygote -> appuid
// 4. Isolated process froked from app zygote: appuid -> isolated_process (already handled by 3)
// 5. Isolated process froked from webview zygote (no need to handle, app cannot run custom code)
if (!is_appuid(new_uid) && !is_isolated_process(new_uid)) {
return 0;
}
if (!ksu_uid_should_umount(new_uid) && !is_isolated_process(new_uid)) {
return 0;
}
// check old process's selinux context, if it is not zygote, ignore it!
// because some su apps may setuid to untrusted_app but they are in global mount namespace
// when we umount for such process, that is a disaster!
// also handle case 4 and 5
bool is_zygote_child = is_zygote(get_current_cred());
if (!is_zygote_child) {
pr_info("handle umount ignore non zygote child: %d\n", current->pid);
return 0;
}
#if __SULOG_GATE
ksu_sulog_report_syscall(new_uid, NULL, "setuid", NULL);
#endif
// umount the target mnt
pr_info("handle umount for uid: %d, pid: %d\n", new_uid, current->pid);
tw = kzalloc(sizeof(*tw), GFP_ATOMIC);
if (!tw)
return 0;
tw->old_cred = get_current_cred();
tw->cb.func = umount_tw_func;
int err = task_work_add(current, &tw->cb, TWA_RESUME);
if (err) {
if (tw->old_cred) {
put_cred(tw->old_cred);
}
kfree(tw);
pr_warn("unmount add task_work failed\n");
}
return 0;
}
void ksu_kernel_umount_init(void)
{
int rc = 0;
rc = ksu_umount_manager_init();
if (rc) {
pr_err("Failed to initialize umount manager: %d\n", rc);
}
if (ksu_register_feature_handler(&kernel_umount_handler)) {
pr_err("Failed to register kernel_umount feature handler\n");
}
}
void ksu_kernel_umount_exit(void)
{
ksu_unregister_feature_handler(KSU_FEATURE_KERNEL_UMOUNT);
}

25
kernel/kernel_umount.h Normal file
View File

@@ -0,0 +1,25 @@
#ifndef __KSU_H_KERNEL_UMOUNT
#define __KSU_H_KERNEL_UMOUNT
#include <linux/types.h>
#include <linux/list.h>
#include <linux/rwsem.h>
void ksu_kernel_umount_init(void);
void ksu_kernel_umount_exit(void);
void try_umount(const char *mnt, int flags);
// Handler function to be called from setresuid hook
int ksu_handle_umount(uid_t old_uid, uid_t new_uid);
// for the umount list
struct mount_entry {
char *umountable;
unsigned int flags;
struct list_head list;
};
extern struct list_head mount_list;
extern struct rw_semaphore mount_list_lock;
#endif

View File

@@ -3,4 +3,4 @@ obj-y += compact.o
obj-y += super_access.o obj-y += super_access.o
ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat
ccflags-y += -Wno-declaration-after-statement -Wno-unused-function ccflags-y += -Wno-declaration-after-statement -Wno-unused-function

View File

@@ -13,7 +13,7 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <asm/elf.h> /* 包含 ARM64 重定位类型定义 */ #include <asm/elf.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/string.h> #include <linux/string.h>
@@ -29,74 +29,72 @@
#include "../allowlist.h" #include "../allowlist.h"
#include "../manager.h" #include "../manager.h"
unsigned long sukisu_compact_find_symbol(const char* name); static int sukisu_is_su_allow_uid(uid_t uid)
{
// ====================================================================== return ksu_is_allow_uid_for_current(uid) ? 1 : 0;
// 兼容函数 for KPM
static
int sukisu_is_su_allow_uid(uid_t uid) {
return ksu_is_allow_uid(uid) ? 1 : 0;
} }
static static int sukisu_get_ap_mod_exclude(uid_t uid)
int sukisu_get_ap_mod_exclude(uid_t uid) { {
// Not supported return 0; /* Not supported */
return 0;
} }
static static int sukisu_is_uid_should_umount(uid_t uid)
int sukisu_is_uid_should_umount(uid_t uid) { {
return ksu_uid_should_umount(uid) ? 1 : 0; return ksu_uid_should_umount(uid) ? 1 : 0;
} }
static static int sukisu_is_current_uid_manager(void)
int sukisu_is_current_uid_manager() { {
return is_manager(); return is_manager();
} }
static static uid_t sukisu_get_manager_uid(void)
uid_t sukisu_get_manager_uid() { {
return ksu_manager_uid; return ksu_manager_uid;
} }
// ====================================================================== static void sukisu_set_manager_uid(uid_t uid, int force)
{
if (force || ksu_manager_uid == -1)
ksu_manager_uid = uid;
}
struct CompactAddressSymbol { struct CompactAddressSymbol {
const char* symbol_name; const char *symbol_name;
void* addr; void *addr;
}; };
static struct CompactAddressSymbol address_symbol [] = { unsigned long sukisu_compact_find_symbol(const char *name);
static struct CompactAddressSymbol address_symbol[] = {
{ "kallsyms_lookup_name", &kallsyms_lookup_name }, { "kallsyms_lookup_name", &kallsyms_lookup_name },
{ "compact_find_symbol", &sukisu_compact_find_symbol }, { "compact_find_symbol", &sukisu_compact_find_symbol },
{ "is_run_in_sukisu_ultra", (void*)1 }, { "is_run_in_sukisu_ultra", (void *)1 },
{ "is_su_allow_uid", &sukisu_is_su_allow_uid }, { "is_su_allow_uid", &sukisu_is_su_allow_uid },
{ "get_ap_mod_exclude", &sukisu_get_ap_mod_exclude }, { "get_ap_mod_exclude", &sukisu_get_ap_mod_exclude },
{ "is_uid_should_umount", &sukisu_is_uid_should_umount }, { "is_uid_should_umount", &sukisu_is_uid_should_umount },
{ "is_current_uid_manager", &sukisu_is_current_uid_manager }, { "is_current_uid_manager", &sukisu_is_current_uid_manager },
{ "get_manager_uid", &sukisu_get_manager_uid } { "get_manager_uid", &sukisu_get_manager_uid },
{ "sukisu_set_manager_uid", &sukisu_set_manager_uid }
}; };
unsigned long sukisu_compact_find_symbol(const char* name) { unsigned long sukisu_compact_find_symbol(const char* name)
{
int i; int i;
unsigned long addr; unsigned long addr;
// 先自己在地址表部分查出来 for (i = 0; i < (sizeof(address_symbol) / sizeof(struct CompactAddressSymbol)); i++) {
for(i = 0; i < (sizeof(address_symbol) / sizeof(struct CompactAddressSymbol)); i++) { struct CompactAddressSymbol *symbol = &address_symbol[i];
struct CompactAddressSymbol* symbol = &address_symbol[i];
if(strcmp(name, symbol->symbol_name) == 0) { if (strcmp(name, symbol->symbol_name) == 0)
return (unsigned long) symbol->addr; return (unsigned long)symbol->addr;
}
} }
// 通过内核来查
addr = kallsyms_lookup_name(name); addr = kallsyms_lookup_name(name);
if(addr) { if (addr)
return addr; return addr;
}
return 0; return 0;
} }
EXPORT_SYMBOL(sukisu_compact_find_symbol); EXPORT_SYMBOL(sukisu_compact_find_symbol);

View File

@@ -1,6 +1,6 @@
#ifndef ___SUKISU_KPM_COMPACT_H #ifndef __SUKISU_KPM_COMPACT_H
#define ___SUKISU_KPM_COMPACT_H #define __SUKISU_KPM_COMPACT_H
unsigned long sukisu_compact_find_symbol(const char* name); extern unsigned long sukisu_compact_find_symbol(const char *name);
#endif #endif

View File

@@ -8,13 +8,11 @@
* 集成了 ELF 解析、内存布局、符号处理、重定位(支持 ARM64 重定位类型) * 集成了 ELF 解析、内存布局、符号处理、重定位(支持 ARM64 重定位类型)
* 并参照KernelPatch的标准KPM格式实现加载和控制 * 并参照KernelPatch的标准KPM格式实现加载和控制
*/ */
#include <linux/export.h>
#include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/kernfs.h> #include <linux/kernfs.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/slab.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/elf.h> #include <linux/elf.h>
@@ -23,27 +21,26 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <asm/elf.h> /* 包含 ARM64 重定位类型定义 */ #include <asm/elf.h>
#include <linux/vmalloc.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/string.h> #include <linux/string.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/vmalloc.h>
#include <linux/set_memory.h> #include <linux/set_memory.h>
#include <linux/version.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <asm/insn.h> #include <asm/insn.h>
#include <linux/kprobes.h> #include <linux/kprobes.h>
#include <linux/stacktrace.h> #include <linux/stacktrace.h>
#include <linux/kallsyms.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) && defined(CONFIG_MODULES) #if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) && defined(CONFIG_MODULES)
#include <linux/moduleloader.h> // 需要启用 CONFIG_MODULES #include <linux/moduleloader.h>
#endif #endif
#include "kpm.h" #include "kpm.h"
#include "compact.h" #include "compact.h"
#define KPM_NAME_LEN 32
#define KPM_ARGS_LEN 1024
#ifndef NO_OPTIMIZE #ifndef NO_OPTIMIZE
#if defined(__GNUC__) && !defined(__clang__) #if defined(__GNUC__) && !defined(__clang__)
#define NO_OPTIMIZE __attribute__((optimize("O0"))) #define NO_OPTIMIZE __attribute__((optimize("O0")))
@@ -54,131 +51,232 @@
#endif #endif
#endif #endif
// ============================================================================================ noinline NO_OPTIMIZE void sukisu_kpm_load_module_path(const char *path,
const char *args, void *ptr, int *result)
{
pr_info("kpm: Stub function called (sukisu_kpm_load_module_path). "
"path=%s args=%s ptr=%p\n", path, args, ptr);
noinline __asm__ volatile("nop");
NO_OPTIMIZE
void sukisu_kpm_load_module_path(const char* path, const char* args, void* ptr, void __user* result) {
// This is a KPM module stub.
int res = -1;
printk("KPM: Stub function called (sukisu_kpm_load_module_path). path=%s args=%s ptr=%p\n", path, args, ptr);
__asm__ volatile("nop"); // 精确控制循环不被优化
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user faild.");
} }
noinline
NO_OPTIMIZE
void sukisu_kpm_unload_module(const char* name, void* ptr, void __user* result) {
// This is a KPM module stub.
int res = -1;
printk("KPM: Stub function called (sukisu_kpm_unload_module). name=%s ptr=%p\n", name, ptr);
__asm__ volatile("nop"); // 精确控制循环不被优化
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user faild.");
}
noinline
NO_OPTIMIZE
void sukisu_kpm_num(void __user* result) {
// This is a KPM module stub.
int res = 0;
printk("KPM: Stub function called (sukisu_kpm_num).\n");
__asm__ volatile("nop"); // 精确控制循环不被优化
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user faild.");
}
noinline
NO_OPTIMIZE
void sukisu_kpm_info(const char* name, void __user* out, void __user* result) {
// This is a KPM module stub.
int res = -1;
printk("KPM: Stub function called (sukisu_kpm_info). name=%s buffer=%p\n", name, out);
__asm__ volatile("nop"); // 精确控制循环不被优化
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user faild.");
}
noinline
NO_OPTIMIZE
void sukisu_kpm_list(void __user* out, unsigned int bufferSize, void __user* result) {
// This is a KPM module stub.
int res = -1;
printk("KPM: Stub function called (sukisu_kpm_list). buffer=%p size=%d\n", out, bufferSize);
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user faild.");
}
noinline
NO_OPTIMIZE
void sukisu_kpm_control(void __user* name, void __user* args, void __user* result) {
// This is a KPM module stub.
int res = -1;
printk("KPM: Stub function called (sukisu_kpm_control). name=%p args=%p\n", name, args);
__asm__ volatile("nop"); // 精确控制循环不被优化
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user faild.");
}
noinline
NO_OPTIMIZE
void sukisu_kpm_version(void __user* out, unsigned int bufferSize, void __user* result) {
int res = -1;
printk("KPM: Stub function called (sukisu_kpm_version). buffer=%p size=%d\n", out, bufferSize);
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user faild.");
}
EXPORT_SYMBOL(sukisu_kpm_load_module_path); EXPORT_SYMBOL(sukisu_kpm_load_module_path);
noinline NO_OPTIMIZE void sukisu_kpm_unload_module(const char *name,
void *ptr, int *result)
{
pr_info("kpm: Stub function called (sukisu_kpm_unload_module). "
"name=%s ptr=%p\n", name, ptr);
__asm__ volatile("nop");
}
EXPORT_SYMBOL(sukisu_kpm_unload_module); EXPORT_SYMBOL(sukisu_kpm_unload_module);
noinline NO_OPTIMIZE void sukisu_kpm_num(int *result)
{
pr_info("kpm: Stub function called (sukisu_kpm_num).\n");
__asm__ volatile("nop");
}
EXPORT_SYMBOL(sukisu_kpm_num); EXPORT_SYMBOL(sukisu_kpm_num);
noinline NO_OPTIMIZE void sukisu_kpm_info(const char *name, char *buf, int bufferSize,
int *size)
{
pr_info("kpm: Stub function called (sukisu_kpm_info). "
"name=%s buffer=%p\n", name, buf);
__asm__ volatile("nop");
}
EXPORT_SYMBOL(sukisu_kpm_info); EXPORT_SYMBOL(sukisu_kpm_info);
noinline NO_OPTIMIZE void sukisu_kpm_list(void *out, int bufferSize,
int *result)
{
pr_info("kpm: Stub function called (sukisu_kpm_list). "
"buffer=%p size=%d\n", out, bufferSize);
}
EXPORT_SYMBOL(sukisu_kpm_list); EXPORT_SYMBOL(sukisu_kpm_list);
EXPORT_SYMBOL(sukisu_kpm_version);
noinline NO_OPTIMIZE void sukisu_kpm_control(const char *name, const char *args, long arg_len,
int *result)
{
pr_info("kpm: Stub function called (sukisu_kpm_control). "
"name=%p args=%p arg_len=%ld\n", name, args, arg_len);
__asm__ volatile("nop");
}
EXPORT_SYMBOL(sukisu_kpm_control); EXPORT_SYMBOL(sukisu_kpm_control);
noinline noinline NO_OPTIMIZE void sukisu_kpm_version(char *buf, int bufferSize)
int sukisu_handle_kpm(unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5)
{ {
if(arg2 == SUKISU_KPM_LOAD) { pr_info("kpm: Stub function called (sukisu_kpm_version). "
char kernel_load_path[256] = { 0 }; "buffer=%p\n", buf);
char kernel_args_buffer[256] = { 0 }; }
EXPORT_SYMBOL(sukisu_kpm_version);
if(arg3 == 0) { noinline int sukisu_handle_kpm(unsigned long control_code, unsigned long arg1, unsigned long arg2,
return -1; unsigned long result_code)
{
int res = -1;
if (control_code == SUKISU_KPM_LOAD) {
char kernel_load_path[256];
char kernel_args_buffer[256];
if (arg1 == 0) {
res = -EINVAL;
goto exit;
}
if (!access_ok(arg1, 255)) {
goto invalid_arg;
} }
strncpy_from_user((char*)&kernel_load_path, (const char __user *)arg3, 255); strncpy_from_user((char *)&kernel_load_path, (const char *)arg1, 255);
if(arg4 != 0) {
strncpy_from_user((char*)&kernel_args_buffer, (const char __user *)arg4, 255); if (arg2 != 0) {
} if (!access_ok(arg2, 255)) {
sukisu_kpm_load_module_path((const char*)&kernel_load_path, (const char*) &kernel_args_buffer, NULL, (void __user*) arg5); goto invalid_arg;
} else if(arg2 == SUKISU_KPM_UNLOAD) { }
char kernel_name_buffer[256] = { 0 };
if(arg3 == 0) { strncpy_from_user((char *)&kernel_args_buffer, (const char *)arg2, 255);
return -1; }
sukisu_kpm_load_module_path((const char *)&kernel_load_path,
(const char *)&kernel_args_buffer, NULL, &res);
} else if (control_code == SUKISU_KPM_UNLOAD) {
char kernel_name_buffer[256];
if (arg1 == 0) {
res = -EINVAL;
goto exit;
}
if (!access_ok(arg1, sizeof(kernel_name_buffer))) {
goto invalid_arg;
} }
strncpy_from_user((char*)&kernel_name_buffer, (const char __user *)arg3, 255); strncpy_from_user((char *)&kernel_name_buffer, (const char *)arg1, sizeof(kernel_name_buffer));
sukisu_kpm_unload_module((const char*) &kernel_name_buffer, NULL, (void __user*) arg5);
} else if(arg2 == SUKISU_KPM_NUM) { sukisu_kpm_unload_module((const char *)&kernel_name_buffer, NULL, &res);
sukisu_kpm_num((void __user*) arg5); } else if (control_code == SUKISU_KPM_NUM) {
} else if(arg2 == SUKISU_KPM_INFO) { sukisu_kpm_num(&res);
char kernel_name_buffer[256] = { 0 }; } else if (control_code == SUKISU_KPM_INFO) {
char kernel_name_buffer[256];
char buf[256];
int size;
if(arg3 == 0 || arg4 == 0) { if (arg1 == 0 || arg2 == 0) {
return -1; res = -EINVAL;
goto exit;
}
if (!access_ok(arg1, sizeof(kernel_name_buffer))) {
goto invalid_arg;
} }
strncpy_from_user((char*)&kernel_name_buffer, (const char __user *)arg3, 255); strncpy_from_user((char *)&kernel_name_buffer, (const char __user *)arg1, sizeof(kernel_name_buffer));
sukisu_kpm_info((const char*) &kernel_name_buffer, (char __user*) arg4, (void __user*) arg5);
} else if(arg2 == SUKISU_KPM_LIST) { sukisu_kpm_info((const char *)&kernel_name_buffer, (char *)&buf, sizeof(buf), &size);
sukisu_kpm_list((char __user*) arg3, (unsigned int) arg4, (void __user*) arg5);
} else if(arg2 == SUKISU_KPM_VERSION) { if (!access_ok(arg2, size)) {
sukisu_kpm_version((char __user*) arg3, (unsigned int) arg4, (void __user*) arg5); goto invalid_arg;
} else if(arg2 == SUKISU_KPM_CONTROL) { }
sukisu_kpm_control((char __user*) arg3, (char __user*) arg4, (void __user*) arg5);
res = copy_to_user(arg2, &buf, size);
} else if (control_code == SUKISU_KPM_LIST) {
char buf[1024];
int len = (int) arg2;
if (len <= 0) {
res = -EINVAL;
goto exit;
}
if (!access_ok(arg2, len)) {
goto invalid_arg;
}
sukisu_kpm_list((char *)&buf, sizeof(buf), &res);
if (res > len) {
res = -ENOBUFS;
goto exit;
}
if (copy_to_user(arg1, &buf, len) != 0)
pr_info("kpm: Copy to user failed.");
} else if (control_code == SUKISU_KPM_CONTROL) {
char kpm_name[KPM_NAME_LEN] = { 0 };
char kpm_args[KPM_ARGS_LEN] = { 0 };
if (!access_ok(arg1, sizeof(kpm_name))) {
goto invalid_arg;
}
if (!access_ok(arg2, sizeof(kpm_args))) {
goto invalid_arg;
}
long name_len = strncpy_from_user((char *)&kpm_name, (const char __user *)arg1, sizeof(kpm_name));
if (name_len <= 0) {
res = -EINVAL;
goto exit;
}
long arg_len = strncpy_from_user((char *)&kpm_args, (const char __user *)arg2, sizeof(kpm_args));
sukisu_kpm_control((const char *)&kpm_name, (const char *)&kpm_args, arg_len, &res);
} else if (control_code == SUKISU_KPM_VERSION) {
char buffer[256] = {0};
sukisu_kpm_version((char*) &buffer, sizeof(buffer));
unsigned int outlen = (unsigned int) arg2;
int len = strlen(buffer);
if (len >= outlen) len = outlen - 1;
res = copy_to_user(arg1, &buffer, len + 1);
} }
exit:
if (copy_to_user(result_code, &res, sizeof(res)) != 0)
pr_info("kpm: Copy to user failed.");
return 0; return 0;
invalid_arg:
pr_err("kpm: invalid pointer detected! arg1: %px arg2: %px\n", (void *)arg1, (void *)arg2);
res = -EFAULT;
goto exit;
}
EXPORT_SYMBOL(sukisu_handle_kpm);
int sukisu_is_kpm_control_code(unsigned long control_code) {
return (control_code >= CMD_KPM_CONTROL &&
control_code <= CMD_KPM_CONTROL_MAX) ? 1 : 0;
} }
int sukisu_is_kpm_control_code(unsigned long arg2) { int do_kpm(void __user *arg)
return (arg2 >= CMD_KPM_CONTROL && arg2 <= CMD_KPM_CONTROL_MAX) ? 1 : 0; {
struct ksu_kpm_cmd cmd;
if (copy_from_user(&cmd, arg, sizeof(cmd))) {
pr_err("kpm: copy_from_user failed\n");
return -EFAULT;
}
if (!access_ok(cmd.control_code, sizeof(int))) {
pr_err("kpm: invalid control_code pointer %px\n", (void *)cmd.control_code);
return -EFAULT;
}
if (!access_ok(cmd.result_code, sizeof(int))) {
pr_err("kpm: invalid result_code pointer %px\n", (void *)cmd.result_code);
return -EFAULT;
}
return sukisu_handle_kpm(cmd.control_code, cmd.arg1, cmd.arg2, cmd.result_code);
} }
EXPORT_SYMBOL(sukisu_handle_kpm);

View File

@@ -1,44 +1,70 @@
#ifndef ___SUKISU_KPM_H #ifndef __SUKISU_KPM_H
#define ___SUKISU_KPM_H #define __SUKISU_KPM_H
int sukisu_handle_kpm(unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5); #include <linux/types.h>
int sukisu_is_kpm_control_code(unsigned long arg2); #include <linux/ioctl.h>
// KPM控制代码 struct ksu_kpm_cmd {
#define CMD_KPM_CONTROL 28 __aligned_u64 __user control_code;
#define CMD_KPM_CONTROL_MAX 35 __aligned_u64 __user arg1;
__aligned_u64 __user arg2;
__aligned_u64 __user result_code;
};
// 控制代码 int sukisu_handle_kpm(unsigned long control_code, unsigned long arg3, unsigned long arg4, unsigned long result_code);
int sukisu_is_kpm_control_code(unsigned long control_code);
int do_kpm(void __user *arg);
// prctl(xxx, 28, "PATH", "ARGS") #define KSU_IOCTL_KPM _IOC(_IOC_READ|_IOC_WRITE, 'K', 200, 0)
// success return 0, error return -N
#define SUKISU_KPM_LOAD 28
// prctl(xxx, 29, "NAME") /* KPM Control Code */
// success return 0, error return -N #define CMD_KPM_CONTROL 1
#define SUKISU_KPM_UNLOAD 29 #define CMD_KPM_CONTROL_MAX 10
// num = prctl(xxx, 30) /* Control Code */
// error return -N /*
// success return +num or 0 * prctl(xxx, 1, "PATH", "ARGS")
#define SUKISU_KPM_NUM 30 * success return 0, error return -N
*/
#define SUKISU_KPM_LOAD 1
// prctl(xxx, 31, Buffer, BufferSize) /*
// success return +out, error return -N * prctl(xxx, 2, "NAME")
#define SUKISU_KPM_LIST 31 * success return 0, error return -N
*/
#define SUKISU_KPM_UNLOAD 2
// prctl(xxx, 32, "NAME", Buffer[256]) /*
// success return +out, error return -N * num = prctl(xxx, 3)
#define SUKISU_KPM_INFO 32 * error return -N
* success return +num or 0
*/
#define SUKISU_KPM_NUM 3
// prctl(xxx, 33, "NAME", "ARGS") /*
// success return KPM's result value * prctl(xxx, 4, Buffer, BufferSize)
// error return -N * success return +out, error return -N
#define SUKISU_KPM_CONTROL 33 */
#define SUKISU_KPM_LIST 4
// prctl(xxx, 34, buffer, bufferSize) /*
// success return KPM's result value * prctl(xxx, 5, "NAME", Buffer[256])
// error return -N * success return +out, error return -N
#define SUKISU_KPM_VERSION 34 */
#define SUKISU_KPM_INFO 5
#endif /*
* prctl(xxx, 6, "NAME", "ARGS")
* success return KPM's result value
* error return -N
*/
#define SUKISU_KPM_CONTROL 6
/*
* prctl(xxx, 7, buffer, bufferSize)
* success return KPM's result value
* error return -N
*/
#define SUKISU_KPM_VERSION 7
#endif

View File

@@ -13,7 +13,7 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <asm/elf.h> /* 包含 ARM64 重定位类型定义 */ #include <asm/elf.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/string.h> #include <linux/string.h>
@@ -24,34 +24,37 @@
#include <linux/version.h> #include <linux/version.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "kpm.h"
#include "compact.h"
#include <linux/types.h> #include <linux/types.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/mount.h>
#include <linux/kprobes.h>
#include <linux/mm_types.h>
#include <linux/netlink.h>
#include <linux/sched.h>
#include <../fs/mount.h>
#include "kpm.h"
#include "compact.h"
// 结构体成员元数据
struct DynamicStructMember { struct DynamicStructMember {
const char* name; const char *name;
size_t size; size_t size;
size_t offset; size_t offset;
}; };
// 结构体元数据(包含总大小)
struct DynamicStructInfo { struct DynamicStructInfo {
const char* name; const char *name;
size_t count; size_t count;
size_t total_size; size_t total_size;
struct DynamicStructMember* members; struct DynamicStructMember *members;
}; };
// 定义结构体元数据的宏(直接使用 struct 名称)
#define DYNAMIC_STRUCT_BEGIN(struct_name) \ #define DYNAMIC_STRUCT_BEGIN(struct_name) \
static struct DynamicStructMember struct_name##_members[] = { static struct DynamicStructMember struct_name##_members[] = {
#define DEFINE_MEMBER(struct_name, member) \ #define DEFINE_MEMBER(struct_name, member) \
{ \ { \
.name = #member, \ .name = #member, \
.size = sizeof(((struct struct_name*)0)->member), \ .size = sizeof(((struct struct_name *)0)->member), \
.offset = offsetof(struct struct_name, member) \ .offset = offsetof(struct struct_name, member) \
}, },
@@ -64,17 +67,6 @@ struct DynamicStructInfo {
.members = struct_name##_members \ .members = struct_name##_members \
}; };
// ==================================================================================
#include <linux/version.h>
#define KERNEL_VERSION_6_1 KERNEL_VERSION(6, 1, 0)
#define KERNEL_VERSION_5_15 KERNEL_VERSION(5, 15, 0)
#include <../fs/mount.h>
#include <linux/mount.h>
// 定义元数据
DYNAMIC_STRUCT_BEGIN(mount) DYNAMIC_STRUCT_BEGIN(mount)
DEFINE_MEMBER(mount, mnt_parent) DEFINE_MEMBER(mount, mnt_parent)
DEFINE_MEMBER(mount, mnt) DEFINE_MEMBER(mount, mnt)
@@ -96,13 +88,11 @@ DYNAMIC_STRUCT_BEGIN(mnt_namespace)
DEFINE_MEMBER(mnt_namespace, root) DEFINE_MEMBER(mnt_namespace, root)
DEFINE_MEMBER(mnt_namespace, seq) DEFINE_MEMBER(mnt_namespace, seq)
DEFINE_MEMBER(mnt_namespace, mounts) DEFINE_MEMBER(mnt_namespace, mounts)
#if LINUX_VERSION_CODE < KERNEL_VERSION_5_15 #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)
DEFINE_MEMBER(mnt_namespace, count) DEFINE_MEMBER(mnt_namespace, count)
#endif #endif
DYNAMIC_STRUCT_END(mnt_namespace) DYNAMIC_STRUCT_END(mnt_namespace)
#include <linux/kprobes.h>
#ifdef CONFIG_KPROBES #ifdef CONFIG_KPROBES
DYNAMIC_STRUCT_BEGIN(kprobe) DYNAMIC_STRUCT_BEGIN(kprobe)
DEFINE_MEMBER(kprobe, addr) DEFINE_MEMBER(kprobe, addr)
@@ -110,16 +100,13 @@ DYNAMIC_STRUCT_BEGIN(kprobe)
DEFINE_MEMBER(kprobe, offset) DEFINE_MEMBER(kprobe, offset)
DEFINE_MEMBER(kprobe, pre_handler) DEFINE_MEMBER(kprobe, pre_handler)
DEFINE_MEMBER(kprobe, post_handler) DEFINE_MEMBER(kprobe, post_handler)
#if LINUX_VERSION_CODE < KERNEL_VERSION_5_15 #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)
DEFINE_MEMBER(kprobe, fault_handler) DEFINE_MEMBER(kprobe, fault_handler)
#endif #endif
DEFINE_MEMBER(kprobe, flags) DEFINE_MEMBER(kprobe, flags)
DYNAMIC_STRUCT_END(kprobe) DYNAMIC_STRUCT_END(kprobe)
#endif #endif
#include <linux/mm.h>
#include <linux/mm_types.h>
DYNAMIC_STRUCT_BEGIN(vm_area_struct) DYNAMIC_STRUCT_BEGIN(vm_area_struct)
DEFINE_MEMBER(vm_area_struct,vm_start) DEFINE_MEMBER(vm_area_struct,vm_start)
DEFINE_MEMBER(vm_area_struct,vm_end) DEFINE_MEMBER(vm_area_struct,vm_end)
@@ -128,9 +115,9 @@ DYNAMIC_STRUCT_BEGIN(vm_area_struct)
DEFINE_MEMBER(vm_area_struct,vm_pgoff) DEFINE_MEMBER(vm_area_struct,vm_pgoff)
DEFINE_MEMBER(vm_area_struct,vm_file) DEFINE_MEMBER(vm_area_struct,vm_file)
DEFINE_MEMBER(vm_area_struct,vm_private_data) DEFINE_MEMBER(vm_area_struct,vm_private_data)
#ifdef CONFIG_ANON_VMA_NAME #ifdef CONFIG_ANON_VMA_NAME
DEFINE_MEMBER(vm_area_struct, anon_name) DEFINE_MEMBER(vm_area_struct, anon_name)
#endif #endif
DEFINE_MEMBER(vm_area_struct, vm_ops) DEFINE_MEMBER(vm_area_struct, vm_ops)
DYNAMIC_STRUCT_END(vm_area_struct) DYNAMIC_STRUCT_END(vm_area_struct)
@@ -141,8 +128,6 @@ DYNAMIC_STRUCT_BEGIN(vm_operations_struct)
DEFINE_MEMBER(vm_operations_struct, access) DEFINE_MEMBER(vm_operations_struct, access)
DYNAMIC_STRUCT_END(vm_operations_struct) DYNAMIC_STRUCT_END(vm_operations_struct)
#include <linux/netlink.h>
DYNAMIC_STRUCT_BEGIN(netlink_kernel_cfg) DYNAMIC_STRUCT_BEGIN(netlink_kernel_cfg)
DEFINE_MEMBER(netlink_kernel_cfg, groups) DEFINE_MEMBER(netlink_kernel_cfg, groups)
DEFINE_MEMBER(netlink_kernel_cfg, flags) DEFINE_MEMBER(netlink_kernel_cfg, flags)
@@ -150,13 +135,11 @@ DYNAMIC_STRUCT_BEGIN(netlink_kernel_cfg)
DEFINE_MEMBER(netlink_kernel_cfg, cb_mutex) DEFINE_MEMBER(netlink_kernel_cfg, cb_mutex)
DEFINE_MEMBER(netlink_kernel_cfg, bind) DEFINE_MEMBER(netlink_kernel_cfg, bind)
DEFINE_MEMBER(netlink_kernel_cfg, unbind) DEFINE_MEMBER(netlink_kernel_cfg, unbind)
#if LINUX_VERSION_CODE < KERNEL_VERSION_6_1 #if LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)
DEFINE_MEMBER(netlink_kernel_cfg, compare) DEFINE_MEMBER(netlink_kernel_cfg, compare)
#endif #endif
DYNAMIC_STRUCT_END(netlink_kernel_cfg) DYNAMIC_STRUCT_END(netlink_kernel_cfg)
#include <linux/sched.h>
DYNAMIC_STRUCT_BEGIN(task_struct) DYNAMIC_STRUCT_BEGIN(task_struct)
DEFINE_MEMBER(task_struct, pid) DEFINE_MEMBER(task_struct, pid)
DEFINE_MEMBER(task_struct, tgid) DEFINE_MEMBER(task_struct, tgid)
@@ -186,104 +169,110 @@ DYNAMIC_STRUCT_BEGIN(task_struct)
DEFINE_MEMBER(task_struct, thread) DEFINE_MEMBER(task_struct, thread)
DYNAMIC_STRUCT_END(task_struct) DYNAMIC_STRUCT_END(task_struct)
// =====================================================================================================================
#define STRUCT_INFO(name) &(name##_info) #define STRUCT_INFO(name) &(name##_info)
static static struct DynamicStructInfo *dynamic_struct_infos[] = {
struct DynamicStructInfo* dynamic_struct_infos[] = {
STRUCT_INFO(mount), STRUCT_INFO(mount),
STRUCT_INFO(vfsmount), STRUCT_INFO(vfsmount),
STRUCT_INFO(mnt_namespace), STRUCT_INFO(mnt_namespace),
#ifdef CONFIG_KPROBES #ifdef CONFIG_KPROBES
STRUCT_INFO(kprobe), STRUCT_INFO(kprobe),
#endif #endif
STRUCT_INFO(vm_area_struct), STRUCT_INFO(vm_area_struct),
STRUCT_INFO(vm_operations_struct), STRUCT_INFO(vm_operations_struct),
STRUCT_INFO(netlink_kernel_cfg), STRUCT_INFO(netlink_kernel_cfg),
STRUCT_INFO(task_struct) STRUCT_INFO(task_struct)
}; };
// return 0 if successful /*
// return -1 if struct not defined * return 0 if successful
int sukisu_super_find_struct( * return -1 if struct not defined
const char* struct_name, */
size_t* out_size, int sukisu_super_find_struct(const char *struct_name, size_t *out_size, int *out_members)
int* out_members {
) { for (size_t i = 0; i < (sizeof(dynamic_struct_infos) / sizeof(dynamic_struct_infos[0])); i++) {
for(size_t i = 0; i < (sizeof(dynamic_struct_infos) / sizeof(dynamic_struct_infos[0])); i++) { struct DynamicStructInfo *info = dynamic_struct_infos[i];
struct DynamicStructInfo* info = dynamic_struct_infos[i];
if(strcmp(struct_name, info->name) == 0) { if (strcmp(struct_name, info->name) == 0) {
if(out_size) if (out_size)
*out_size = info->total_size; *out_size = info->total_size;
if(out_members)
if (out_members)
*out_members = info->count; *out_members = info->count;
return 0; return 0;
} }
} }
return -1; return -1;
} }
EXPORT_SYMBOL(sukisu_super_find_struct); EXPORT_SYMBOL(sukisu_super_find_struct);
// Dynamic access struct /*
// return 0 if successful * Dynamic access struct
// return -1 if struct not defined * return 0 if successful
// return -2 if member not defined * return -1 if struct not defined
int sukisu_super_access ( * return -2 if member not defined
const char* struct_name, */
const char* member_name, int sukisu_super_access(const char *struct_name, const char *member_name, size_t *out_offset,
size_t* out_offset, size_t *out_size)
size_t* out_size {
) { for (size_t i = 0; i < (sizeof(dynamic_struct_infos) / sizeof(dynamic_struct_infos[0])); i++) {
for(size_t i = 0; i < (sizeof(dynamic_struct_infos) / sizeof(dynamic_struct_infos[0])); i++) { struct DynamicStructInfo *info = dynamic_struct_infos[i];
struct DynamicStructInfo* info = dynamic_struct_infos[i];
if(strcmp(struct_name, info->name) == 0) { if (strcmp(struct_name, info->name) == 0) {
for (size_t i1 = 0; i1 < info->count; i1++) { for (size_t i1 = 0; i1 < info->count; i1++) {
if (strcmp(info->members[i1].name, member_name) == 0) { if (strcmp(info->members[i1].name, member_name) == 0) {
if(out_offset) if (out_offset)
*out_offset = info->members[i].offset; *out_offset = info->members[i].offset;
if(out_size)
if (out_size)
*out_size = info->members[i].size; *out_size = info->members[i].size;
return 0; return 0;
} }
} }
return -2; return -2;
} }
} }
return -1; return -1;
} }
EXPORT_SYMBOL(sukisu_super_access); EXPORT_SYMBOL(sukisu_super_access);
// 动态 container_of 宏
#define DYNAMIC_CONTAINER_OF(offset, member_ptr) ({ \ #define DYNAMIC_CONTAINER_OF(offset, member_ptr) ({ \
(offset != (size_t)-1) ? (void*)((char*)(member_ptr) - offset) : NULL; \ (offset != (size_t)-1) ? (void*)((char*)(member_ptr) - offset) : NULL; \
}) })
// Dynamic container_of /*
// return 0 if success * Dynamic container_of
// return -1 if current struct not defined * return 0 if success
// return -2 if target member not defined * return -1 if current struct not defined
int sukisu_super_container_of( * return -2 if target member not defined
const char* struct_name, */
const char* member_name, int sukisu_super_container_of(const char *struct_name, const char *member_name, void *ptr,
void* ptr, void **out_ptr)
void** out_ptr {
) { if (ptr == NULL)
if(ptr == NULL) {
return -3; return -3;
}
for(size_t i = 0; i < (sizeof(dynamic_struct_infos) / sizeof(dynamic_struct_infos[0])); i++) { for (size_t i = 0; i < (sizeof(dynamic_struct_infos) / sizeof(dynamic_struct_infos[0])); i++) {
struct DynamicStructInfo* info = dynamic_struct_infos[i]; struct DynamicStructInfo *info = dynamic_struct_infos[i];
if(strcmp(struct_name, info->name) == 0) {
if (strcmp(struct_name, info->name) == 0) {
for (size_t i1 = 0; i1 < info->count; i1++) { for (size_t i1 = 0; i1 < info->count; i1++) {
if (strcmp(info->members[i1].name, member_name) == 0) { if (strcmp(info->members[i1].name, member_name) == 0) {
*out_ptr = (void*) DYNAMIC_CONTAINER_OF(info->members[i1].offset, ptr); *out_ptr = (void *)DYNAMIC_CONTAINER_OF(info->members[i1].offset, ptr);
return 0; return 0;
} }
} }
return -2; return -2;
} }
} }
return -1; return -1;
} }
EXPORT_SYMBOL(sukisu_super_container_of); EXPORT_SYMBOL(sukisu_super_container_of);

View File

@@ -6,34 +6,10 @@
#include "kpm.h" #include "kpm.h"
#include "compact.h" #include "compact.h"
// return 0 if successful extern int sukisu_super_find_struct(const char *struct_name, size_t *out_size, int *out_members);
// return -1 if struct not defined extern int sukisu_super_access(const char *struct_name, const char *member_name, size_t *out_offset,
int sukisu_super_find_struct( size_t *out_size);
const char* struct_name, extern int sukisu_super_container_of(const char *struct_name, const char *member_name, void *ptr,
size_t* out_size, void **out_ptr);
int* out_members
);
// Dynamic access struct
// return 0 if successful
// return -1 if struct not defined
// return -2 if member not defined
int sukisu_super_access (
const char* struct_name,
const char* member_name,
size_t* out_offset,
size_t* out_size
);
// Dynamic container_of
// return 0 if success
// return -1 if current struct not defined
// return -2 if target member not defined
int sukisu_super_container_of(
const char* struct_name,
const char* member_name,
void* ptr,
void** out_ptr
);
#endif #endif

View File

@@ -3,88 +3,103 @@
#include <linux/kobject.h> #include <linux/kobject.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/version.h>
#include "allowlist.h" #include "allowlist.h"
#include "arch.h" #include "feature.h"
#include "core_hook.h"
#include "klog.h" // IWYU pragma: keep #include "klog.h" // IWYU pragma: keep
#include "ksu.h"
#include "throne_tracker.h" #include "throne_tracker.h"
#include "syscall_hook_manager.h"
#include "ksud.h"
#include "supercalls.h"
#include "sulog.h"
#include "throne_comm.h"
#include "dynamic_manager.h"
static struct workqueue_struct *ksu_workqueue; static struct workqueue_struct *ksu_workqueue;
bool ksu_queue_work(struct work_struct *work) bool ksu_queue_work(struct work_struct *work)
{ {
return queue_work(ksu_workqueue, work); return queue_work(ksu_workqueue, work);
} }
extern int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr, void sukisu_custom_config_init(void)
void *argv, void *envp, int *flags);
extern int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
void *argv, void *envp, int *flags);
int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv,
void *envp, int *flags)
{ {
ksu_handle_execveat_ksud(fd, filename_ptr, argv, envp, flags);
return ksu_handle_execveat_sucompat(fd, filename_ptr, argv, envp,
flags);
} }
extern void ksu_sucompat_init(); void sukisu_custom_config_exit(void)
extern void ksu_sucompat_exit(); {
extern void ksu_ksud_init(); ksu_uid_exit();
extern void ksu_ksud_exit(); ksu_throne_comm_exit();
ksu_dynamic_manager_exit();
#if __SULOG_GATE
ksu_sulog_exit();
#endif
}
int __init kernelsu_init(void) int __init kernelsu_init(void)
{ {
#ifdef CONFIG_KSU_DEBUG #ifdef CONFIG_KSU_DEBUG
pr_alert("*************************************************************"); pr_alert("*************************************************************");
pr_alert("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **"); pr_alert("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **");
pr_alert("** **"); pr_alert("** **");
pr_alert("** You are running KernelSU in DEBUG mode **"); pr_alert("** You are running KernelSU in DEBUG mode **");
pr_alert("** **"); pr_alert("** **");
pr_alert("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **"); pr_alert("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **");
pr_alert("*************************************************************"); pr_alert("*************************************************************");
#endif #endif
ksu_core_init(); ksu_feature_init();
ksu_workqueue = alloc_ordered_workqueue("kernelsu_work_queue", 0); ksu_supercalls_init();
ksu_allowlist_init(); sukisu_custom_config_init();
ksu_throne_tracker_init(); ksu_syscall_hook_manager_init();
#ifdef CONFIG_KPROBES
ksu_sucompat_init(); ksu_workqueue = alloc_ordered_workqueue("kernelsu_work_queue", 0);
ksu_ksud_init();
ksu_allowlist_init();
ksu_throne_tracker_init();
#ifdef KSU_KPROBES_HOOK
ksu_ksud_init();
#else #else
pr_alert("KPROBES is disabled, KernelSU may not work, please check https://kernelsu.org/guide/how-to-integrate-for-non-gki.html"); pr_alert("KPROBES is disabled, KernelSU may not work, please check https://kernelsu.org/guide/how-to-integrate-for-non-gki.html");
#endif #endif
#ifdef MODULE #ifdef MODULE
#ifndef CONFIG_KSU_DEBUG #ifndef CONFIG_KSU_DEBUG
kobject_del(&THIS_MODULE->mkobj.kobj); kobject_del(&THIS_MODULE->mkobj.kobj);
#endif #endif
#endif #endif
return 0; return 0;
} }
extern void ksu_observer_exit(void);
void kernelsu_exit(void) void kernelsu_exit(void)
{ {
ksu_allowlist_exit(); ksu_allowlist_exit();
ksu_throne_tracker_exit(); ksu_observer_exit();
destroy_workqueue(ksu_workqueue); ksu_throne_tracker_exit();
#ifdef CONFIG_KPROBES destroy_workqueue(ksu_workqueue);
ksu_ksud_exit();
ksu_sucompat_exit(); #ifdef KSU_KPROBES_HOOK
ksu_ksud_exit();
#endif #endif
ksu_core_exit(); ksu_syscall_hook_manager_exit();
sukisu_custom_config_exit();
ksu_supercalls_exit();
ksu_feature_exit();
} }
module_init(kernelsu_init); module_init(kernelsu_init);
@@ -93,4 +108,9 @@ module_exit(kernelsu_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("weishu"); MODULE_AUTHOR("weishu");
MODULE_DESCRIPTION("Android KernelSU"); MODULE_DESCRIPTION("Android KernelSU");
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0)
MODULE_IMPORT_NS("VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver");
#else
MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver);
#endif

View File

@@ -7,95 +7,56 @@
#define KERNEL_SU_VERSION KSU_VERSION #define KERNEL_SU_VERSION KSU_VERSION
#define KERNEL_SU_OPTION 0xDEADBEEF #define KERNEL_SU_OPTION 0xDEADBEEF
#define CMD_GRANT_ROOT 0 extern bool ksu_uid_scanner_enabled;
#define CMD_BECOME_MANAGER 1
#define CMD_GET_VERSION 2
#define CMD_ALLOW_SU 3
#define CMD_DENY_SU 4
#define CMD_GET_ALLOW_LIST 5
#define CMD_GET_DENY_LIST 6
#define CMD_REPORT_EVENT 7
#define CMD_SET_SEPOLICY 8
#define CMD_CHECK_SAFEMODE 9
#define CMD_GET_APP_PROFILE 10
#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 EVENT_POST_FS_DATA 1 #define EVENT_POST_FS_DATA 1
#define EVENT_BOOT_COMPLETED 2 #define EVENT_BOOT_COMPLETED 2
#define EVENT_MODULE_MOUNTED 3 #define EVENT_MODULE_MOUNTED 3
#define KSU_APP_PROFILE_VER 2 // SukiSU Ultra kernel su version full strings
#define KSU_MAX_PACKAGE_NAME 256 #ifndef KSU_VERSION_FULL
// NGROUPS_MAX for Linux is 65535 generally, but we only supports 32 groups. #define KSU_VERSION_FULL "v3.x-00000000@unknown"
#define KSU_MAX_GROUPS 32 #endif
#define KSU_SELINUX_DOMAIN 64 #define KSU_FULL_VERSION_STRING 255
struct root_profile { #define DYNAMIC_MANAGER_OP_SET 0
int32_t uid; #define DYNAMIC_MANAGER_OP_GET 1
int32_t gid; #define DYNAMIC_MANAGER_OP_CLEAR 2
int32_t groups_count; #define UID_SCANNER_OP_GET_STATUS 0
int32_t groups[KSU_MAX_GROUPS]; #define UID_SCANNER_OP_TOGGLE 1
#define UID_SCANNER_OP_CLEAR_ENV 2
// kernel_cap_t is u32[2] for capabilities v3 struct dynamic_manager_user_config {
struct { unsigned int operation;
u64 effective; unsigned int size;
u64 permitted; char hash[65];
u64 inheritable;
} capabilities;
char selinux_domain[KSU_SELINUX_DOMAIN];
int32_t namespaces;
}; };
struct non_root_profile { struct manager_list_info {
bool umount_modules; int count;
}; struct {
uid_t uid;
struct app_profile { int signature_index;
// It may be utilized for backward compatibility, although we have never explicitly made any promises regarding this. } managers[2];
u32 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 ksu_queue_work(struct work_struct *work); bool ksu_queue_work(struct work_struct *work);
#if 0
static inline int startswith(char *s, char *prefix) static inline int startswith(char *s, char *prefix)
{ {
return strncmp(s, prefix, strlen(prefix)); return strncmp(s, prefix, strlen(prefix));
} }
static inline int endswith(const char *s, const char *t) static inline int endswith(const char *s, const char *t)
{ {
size_t slen = strlen(s); size_t slen = strlen(s);
size_t tlen = strlen(t); size_t tlen = strlen(t);
if (tlen > slen) if (tlen > slen)
return 1; return 1;
return strcmp(s + slen - tlen, t); return strcmp(s + slen - tlen, t);
} }
#endif
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@@ -3,9 +3,19 @@
#define KSUD_PATH "/data/adb/ksud" #define KSUD_PATH "/data/adb/ksud"
void ksu_ksud_init();
void ksu_ksud_exit();
void on_post_fs_data(void); void on_post_fs_data(void);
void on_module_mounted(void);
void on_boot_completed(void);
bool ksu_is_safe_mode(void); bool ksu_is_safe_mode(void);
extern u32 ksu_devpts_sid; int nuke_ext4_sysfs(const char* mnt);
extern u32 ksu_file_sid;
extern bool ksu_module_mounted;
extern bool ksu_boot_completed;
#endif #endif

View File

@@ -8,29 +8,36 @@
extern uid_t ksu_manager_uid; // DO NOT DIRECT USE extern uid_t ksu_manager_uid; // DO NOT DIRECT USE
static inline bool ksu_is_manager_uid_valid() extern bool ksu_is_any_manager(uid_t uid);
extern void ksu_add_manager(uid_t uid, int signature_index);
extern void ksu_remove_manager(uid_t uid);
extern int ksu_get_manager_signature_index(uid_t uid);
static inline bool ksu_is_manager_uid_valid(void)
{ {
return ksu_manager_uid != KSU_INVALID_UID; return ksu_manager_uid != KSU_INVALID_UID;
} }
static inline bool is_manager() static inline bool is_manager(void)
{ {
return unlikely(ksu_manager_uid == current_uid().val); return unlikely(ksu_is_any_manager(current_uid().val) ||
(ksu_manager_uid != KSU_INVALID_UID && ksu_manager_uid == current_uid().val));
} }
static inline uid_t ksu_get_manager_uid() static inline uid_t ksu_get_manager_uid(void)
{ {
return ksu_manager_uid; return ksu_manager_uid;
} }
static inline void ksu_set_manager_uid(uid_t uid) static inline void ksu_set_manager_uid(uid_t uid)
{ {
ksu_manager_uid = uid; ksu_manager_uid = uid;
} }
static inline void ksu_invalidate_manager_uid() static inline void ksu_invalidate_manager_uid(void)
{ {
ksu_manager_uid = KSU_INVALID_UID; ksu_manager_uid = KSU_INVALID_UID;
} }
int ksu_observer_init(void);
#endif #endif

17
kernel/manager_sign.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef MANAGER_SIGN_H
#define MANAGER_SIGN_H
// ShirkNeko/SukiSU
#define EXPECTED_SIZE_SHIRKNEKO 0x35c
#define EXPECTED_HASH_SHIRKNEKO "947ae944f3de4ed4c21a7e4f7953ecf351bfa2b36239da37a34111ad29993eef"
// Dynamic Sign
#define EXPECTED_SIZE_OTHER 0x300
#define EXPECTED_HASH_OTHER "0000000000000000000000000000000000000000000000000000000000000000"
typedef struct {
unsigned size;
const char *sha256;
} apk_sign_key_t;
#endif /* MANAGER_SIGN_H */

357
kernel/manual_su.c Normal file
View File

@@ -0,0 +1,357 @@
#include <linux/string.h>
#include <linux/uaccess.h>
#include <linux/printk.h>
#include <linux/cred.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/file.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/binfmts.h>
#include "manual_su.h"
#include "ksu.h"
#include "allowlist.h"
#include "manager.h"
#include "app_profile.h"
static bool current_verified = false;
static void ksu_cleanup_expired_tokens(void);
static bool is_current_verified(void);
static void add_pending_root(uid_t uid);
static struct pending_uid pending_uids[MAX_PENDING] = {0};
static int pending_cnt = 0;
static struct ksu_token_entry auth_tokens[MAX_TOKENS] = {0};
static int token_count = 0;
static DEFINE_SPINLOCK(token_lock);
static char* get_token_from_envp(void)
{
struct mm_struct *mm;
char *envp_start, *envp_end;
char *env_ptr, *token = NULL;
unsigned long env_len;
char *env_copy = NULL;
if (!current->mm)
return NULL;
mm = current->mm;
down_read(&mm->mmap_lock);
envp_start = (char *)mm->env_start;
envp_end = (char *)mm->env_end;
env_len = envp_end - envp_start;
if (env_len <= 0 || env_len > PAGE_SIZE * 32) {
up_read(&mm->mmap_lock);
return NULL;
}
env_copy = kzalloc(env_len + 1, GFP_KERNEL);
if (!env_copy) {
up_read(&mm->mmap_lock);
return NULL;
}
if (copy_from_user(env_copy, envp_start, env_len)) {
kfree(env_copy);
up_read(&mm->mmap_lock);
return NULL;
}
up_read(&mm->mmap_lock);
env_copy[env_len] = '\0';
env_ptr = env_copy;
while (env_ptr < env_copy + env_len) {
if (strncmp(env_ptr, KSU_TOKEN_ENV_NAME "=", strlen(KSU_TOKEN_ENV_NAME) + 1) == 0) {
char *token_start = env_ptr + strlen(KSU_TOKEN_ENV_NAME) + 1;
char *token_end = strchr(token_start, '\0');
if (token_end && (token_end - token_start) == KSU_TOKEN_LENGTH) {
token = kzalloc(KSU_TOKEN_LENGTH + 1, GFP_KERNEL);
if (token) {
memcpy(token, token_start, KSU_TOKEN_LENGTH);
token[KSU_TOKEN_LENGTH] = '\0';
pr_info("manual_su: found auth token in environment\n");
}
}
break;
}
env_ptr += strlen(env_ptr) + 1;
}
kfree(env_copy);
return token;
}
static char* ksu_generate_auth_token(void)
{
static char token_buffer[KSU_TOKEN_LENGTH + 1];
unsigned long flags;
int i;
ksu_cleanup_expired_tokens();
spin_lock_irqsave(&token_lock, flags);
if (token_count >= MAX_TOKENS) {
for (i = 0; i < MAX_TOKENS - 1; i++) {
auth_tokens[i] = auth_tokens[i + 1];
}
token_count = MAX_TOKENS - 1;
}
for (i = 0; i < KSU_TOKEN_LENGTH; i++) {
u8 rand_byte;
get_random_bytes(&rand_byte, 1);
int char_type = rand_byte % 3;
if (char_type == 0) {
token_buffer[i] = 'A' + (rand_byte % 26);
} else if (char_type == 1) {
token_buffer[i] = 'a' + (rand_byte % 26);
} else {
token_buffer[i] = '0' + (rand_byte % 10);
}
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
strscpy(auth_tokens[token_count].token, token_buffer, KSU_TOKEN_LENGTH + 1);
#else
strlcpy(auth_tokens[token_count].token, token_buffer, KSU_TOKEN_LENGTH + 1);
#endif
auth_tokens[token_count].expire_time = jiffies + KSU_TOKEN_EXPIRE_TIME * HZ;
auth_tokens[token_count].used = false;
token_count++;
spin_unlock_irqrestore(&token_lock, flags);
pr_info("manual_su: generated new auth token (expires in %d seconds)\n", KSU_TOKEN_EXPIRE_TIME);
return token_buffer;
}
static bool ksu_verify_auth_token(const char *token)
{
unsigned long flags;
bool valid = false;
int i;
if (!token || strlen(token) != KSU_TOKEN_LENGTH) {
return false;
}
spin_lock_irqsave(&token_lock, flags);
for (i = 0; i < token_count; i++) {
if (!auth_tokens[i].used &&
time_before(jiffies, auth_tokens[i].expire_time) &&
strcmp(auth_tokens[i].token, token) == 0) {
auth_tokens[i].used = true;
valid = true;
pr_info("manual_su: auth token verified successfully\n");
break;
}
}
spin_unlock_irqrestore(&token_lock, flags);
if (!valid) {
pr_warn("manual_su: invalid or expired auth token\n");
}
return valid;
}
static void ksu_cleanup_expired_tokens(void)
{
unsigned long flags;
int i, j;
spin_lock_irqsave(&token_lock, flags);
for (i = 0; i < token_count; ) {
if (time_after(jiffies, auth_tokens[i].expire_time) || auth_tokens[i].used) {
for (j = i; j < token_count - 1; j++) {
auth_tokens[j] = auth_tokens[j + 1];
}
token_count--;
pr_debug("manual_su: cleaned up expired/used token\n");
} else {
i++;
}
}
spin_unlock_irqrestore(&token_lock, flags);
}
static int handle_token_generation(struct manual_su_request *request)
{
if (current_uid().val > 2000) {
pr_warn("manual_su: token generation denied for app UID %d\n", current_uid().val);
return -EPERM;
}
char *new_token = ksu_generate_auth_token();
if (!new_token) {
pr_err("manual_su: failed to generate token\n");
return -ENOMEM;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
strscpy(request->token_buffer, new_token, KSU_TOKEN_LENGTH + 1);
#else
strlcpy(request->token_buffer, new_token, KSU_TOKEN_LENGTH + 1);
#endif
pr_info("manual_su: auth token generated successfully\n");
return 0;
}
static int handle_escalation_request(struct manual_su_request *request)
{
uid_t target_uid = request->target_uid;
pid_t target_pid = request->target_pid;
struct task_struct *tsk;
rcu_read_lock();
tsk = pid_task(find_vpid(target_pid), PIDTYPE_PID);
if (!tsk || ksu_task_is_dead(tsk)) {
rcu_read_unlock();
pr_err("cmd_su: PID %d is invalid or dead\n", target_pid);
return -ESRCH;
}
rcu_read_unlock();
if (current_uid().val == 0 || is_manager() || ksu_is_allow_uid_for_current(current_uid().val))
goto allowed;
char *env_token = get_token_from_envp();
if (!env_token) {
pr_warn("manual_su: no auth token found in environment\n");
return -EACCES;
}
bool token_valid = ksu_verify_auth_token(env_token);
kfree(env_token);
if (!token_valid) {
pr_warn("manual_su: token verification failed\n");
return -EACCES;
}
allowed:
current_verified = true;
escape_to_root_for_cmd_su(target_uid, target_pid);
return 0;
}
static int handle_add_pending_request(struct manual_su_request *request)
{
uid_t target_uid = request->target_uid;
if (!is_current_verified()) {
pr_warn("manual_su: add_pending denied, not verified\n");
return -EPERM;
}
add_pending_root(target_uid);
current_verified = false;
pr_info("manual_su: pending root added for UID %d\n", target_uid);
return 0;
}
int ksu_handle_manual_su_request(int option, struct manual_su_request *request)
{
if (!request) {
pr_err("manual_su: invalid request pointer\n");
return -EINVAL;
}
switch (option) {
case MANUAL_SU_OP_GENERATE_TOKEN:
pr_info("manual_su: handling token generation request\n");
return handle_token_generation(request);
case MANUAL_SU_OP_ESCALATE:
pr_info("manual_su: handling escalation request for UID %d, PID %d\n",
request->target_uid, request->target_pid);
return handle_escalation_request(request);
case MANUAL_SU_OP_ADD_PENDING:
pr_info("manual_su: handling add pending request for UID %d\n", request->target_uid);
return handle_add_pending_request(request);
default:
pr_err("manual_su: unknown option %d\n", option);
return -EINVAL;
}
}
static bool is_current_verified(void)
{
return current_verified;
}
bool is_pending_root(uid_t uid)
{
for (int i = 0; i < pending_cnt; i++) {
if (pending_uids[i].uid == uid) {
pending_uids[i].use_count++;
pending_uids[i].remove_calls++;
return true;
}
}
return false;
}
void remove_pending_root(uid_t uid)
{
for (int i = 0; i < pending_cnt; i++) {
if (pending_uids[i].uid == uid) {
pending_uids[i].remove_calls++;
if (pending_uids[i].remove_calls >= REMOVE_DELAY_CALLS) {
pending_uids[i] = pending_uids[--pending_cnt];
pr_info("pending_root: removed UID %d after %d calls\n", uid, REMOVE_DELAY_CALLS);
ksu_temp_revoke_root_once(uid);
} else {
pr_info("pending_root: UID %d remove_call=%d (<%d)\n",
uid, pending_uids[i].remove_calls, REMOVE_DELAY_CALLS);
}
return;
}
}
}
static void add_pending_root(uid_t uid)
{
if (pending_cnt >= MAX_PENDING) {
pr_warn("pending_root: cache full\n");
return;
}
for (int i = 0; i < pending_cnt; i++) {
if (pending_uids[i].uid == uid) {
pending_uids[i].use_count = 0;
pending_uids[i].remove_calls = 0;
return;
}
}
pending_uids[pending_cnt++] = (struct pending_uid){uid, 0};
ksu_temp_grant_root_once(uid);
pr_info("pending_root: cached UID %d\n", uid);
}
void ksu_try_escalate_for_uid(uid_t uid)
{
if (!is_pending_root(uid))
return;
pr_info("pending_root: UID=%d temporarily allowed\n", uid);
remove_pending_root(uid);
}

49
kernel/manual_su.h Normal file
View File

@@ -0,0 +1,49 @@
#ifndef __KSU_MANUAL_SU_H
#define __KSU_MANUAL_SU_H
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 7, 0)
#define mmap_lock mmap_sem
#endif
#define ksu_task_is_dead(t) ((t)->exit_state != 0)
#define MAX_PENDING 16
#define REMOVE_DELAY_CALLS 150
#define MAX_TOKENS 10
#define KSU_SU_VERIFIED_BIT (1UL << 0)
#define KSU_TOKEN_LENGTH 32
#define KSU_TOKEN_ENV_NAME "KSU_AUTH_TOKEN"
#define KSU_TOKEN_EXPIRE_TIME 150
#define MANUAL_SU_OP_GENERATE_TOKEN 0
#define MANUAL_SU_OP_ESCALATE 1
#define MANUAL_SU_OP_ADD_PENDING 2
struct pending_uid {
uid_t uid;
int use_count;
int remove_calls;
};
struct manual_su_request {
uid_t target_uid;
pid_t target_pid;
char token_buffer[KSU_TOKEN_LENGTH + 1];
};
struct ksu_token_entry {
char token[KSU_TOKEN_LENGTH + 1];
unsigned long expire_time;
bool used;
};
int ksu_handle_manual_su_request(int option, struct manual_su_request *request);
bool is_pending_root(uid_t uid);
void remove_pending_root(uid_t uid);
void ksu_try_escalate_for_uid(uid_t uid);
#endif

133
kernel/pkg_observer.c Normal file
View File

@@ -0,0 +1,133 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/namei.h>
#include <linux/fsnotify_backend.h>
#include <linux/slab.h>
#include <linux/rculist.h>
#include <linux/version.h>
#include "klog.h" // IWYU pragma: keep
#include "ksu.h"
#include "throne_tracker.h"
#include "throne_comm.h"
#define MASK_SYSTEM (FS_CREATE | FS_MOVE | FS_EVENT_ON_CHILD)
struct watch_dir {
const char *path;
u32 mask;
struct path kpath;
struct inode *inode;
struct fsnotify_mark *mark;
};
static struct fsnotify_group *g;
static int ksu_handle_inode_event(struct fsnotify_mark *mark, u32 mask,
struct inode *inode, struct inode *dir,
const struct qstr *file_name, u32 cookie)
{
if (!file_name)
return 0;
if (mask & FS_ISDIR)
return 0;
if (file_name->len == 13 &&
!memcmp(file_name->name, "packages.list", 13)) {
pr_info("packages.list detected: %d\n", mask);
if (ksu_uid_scanner_enabled) {
ksu_request_userspace_scan();
}
track_throne(false);
}
return 0;
}
static const struct fsnotify_ops ksu_ops = {
.handle_inode_event = ksu_handle_inode_event,
};
static int add_mark_on_inode(struct inode *inode, u32 mask,
struct fsnotify_mark **out)
{
struct fsnotify_mark *m;
m = kzalloc(sizeof(*m), GFP_KERNEL);
if (!m)
return -ENOMEM;
fsnotify_init_mark(m, g);
m->mask = mask;
if (fsnotify_add_inode_mark(m, inode, 0)) {
fsnotify_put_mark(m);
return -EINVAL;
}
*out = m;
return 0;
}
static int watch_one_dir(struct watch_dir *wd)
{
int ret = kern_path(wd->path, LOOKUP_FOLLOW, &wd->kpath);
if (ret) {
pr_info("path not ready: %s (%d)\n", wd->path, ret);
return ret;
}
wd->inode = d_inode(wd->kpath.dentry);
ihold(wd->inode);
ret = add_mark_on_inode(wd->inode, wd->mask, &wd->mark);
if (ret) {
pr_err("Add mark failed for %s (%d)\n", wd->path, ret);
path_put(&wd->kpath);
iput(wd->inode);
wd->inode = NULL;
return ret;
}
pr_info("watching %s\n", wd->path);
return 0;
}
static void unwatch_one_dir(struct watch_dir *wd)
{
if (wd->mark) {
fsnotify_destroy_mark(wd->mark, g);
fsnotify_put_mark(wd->mark);
wd->mark = NULL;
}
if (wd->inode) {
iput(wd->inode);
wd->inode = NULL;
}
if (wd->kpath.dentry) {
path_put(&wd->kpath);
memset(&wd->kpath, 0, sizeof(wd->kpath));
}
}
static struct watch_dir g_watch = { .path = "/data/system",
.mask = MASK_SYSTEM };
int ksu_observer_init(void)
{
int ret = 0;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)
g = fsnotify_alloc_group(&ksu_ops, 0);
#else
g = fsnotify_alloc_group(&ksu_ops);
#endif
if (IS_ERR(g))
return PTR_ERR(g);
ret = watch_one_dir(&g_watch);
pr_info("observer init done\n");
return 0;
}
void ksu_observer_exit(void)
{
unwatch_one_dir(&g_watch);
fsnotify_put_group(g);
pr_info("observer exit done\n");
}

69
kernel/seccomp_cache.c Normal file
View File

@@ -0,0 +1,69 @@
#include <linux/version.h>
#include <linux/fs.h>
#include <linux/nsproxy.h>
#include <linux/sched/task.h>
#include <linux/uaccess.h>
#include <linux/filter.h>
#include <linux/seccomp.h>
#include "klog.h" // IWYU pragma: keep
#include "seccomp_cache.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 2) // Android backport this feature in 5.10.2
struct action_cache {
DECLARE_BITMAP(allow_native, SECCOMP_ARCH_NATIVE_NR);
#ifdef SECCOMP_ARCH_COMPAT
DECLARE_BITMAP(allow_compat, SECCOMP_ARCH_COMPAT_NR);
#endif
};
struct seccomp_filter {
refcount_t refs;
refcount_t users;
bool log;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
bool wait_killable_recv;
#endif
struct action_cache cache;
struct seccomp_filter *prev;
struct bpf_prog *prog;
struct notification *notif;
struct mutex notify_lock;
wait_queue_head_t wqh;
};
void ksu_seccomp_clear_cache(struct seccomp_filter *filter, int nr)
{
if (!filter) {
return;
}
if (nr >= 0 && nr < SECCOMP_ARCH_NATIVE_NR) {
clear_bit(nr, filter->cache.allow_native);
}
#ifdef SECCOMP_ARCH_COMPAT
if (nr >= 0 && nr < SECCOMP_ARCH_COMPAT_NR) {
clear_bit(nr, filter->cache.allow_compat);
}
#endif
}
void ksu_seccomp_allow_cache(struct seccomp_filter *filter, int nr)
{
if (!filter) {
return;
}
if (nr >= 0 && nr < SECCOMP_ARCH_NATIVE_NR) {
set_bit(nr, filter->cache.allow_native);
}
#ifdef SECCOMP_ARCH_COMPAT
if (nr >= 0 && nr < SECCOMP_ARCH_COMPAT_NR) {
set_bit(nr, filter->cache.allow_compat);
}
#endif
}
#endif

12
kernel/seccomp_cache.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef __KSU_H_SECCOMP_CACHE
#define __KSU_H_SECCOMP_CACHE
#include <linux/fs.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 2) // Android backport this feature in 5.10.2
extern void ksu_seccomp_clear_cache(struct seccomp_filter *filter, int nr);
extern void ksu_seccomp_allow_cache(struct seccomp_filter *filter, int nr);
#endif
#endif

View File

@@ -2,15 +2,7 @@ obj-y += selinux.o
obj-y += sepolicy.o obj-y += sepolicy.o
obj-y += rules.o obj-y += rules.o
ifeq ($(shell grep -q " current_sid(void)" $(srctree)/security/selinux/include/objsec.h; echo $$?),0) ccflags-y += -Wno-strict-prototypes -Wno-int-conversion
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 += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion
ccflags-y += -Wno-declaration-after-statement -Wno-unused-function ccflags-y += -Wno-declaration-after-statement -Wno-unused-function
ccflags-y += -I$(srctree)/security/selinux -I$(srctree)/security/selinux/include ccflags-y += -I$(srctree)/security/selinux -I$(srctree)/security/selinux/include
ccflags-y += -I$(objtree)/security/selinux -include $(srctree)/include/uapi/asm-generic/errno.h ccflags-y += -I$(objtree)/security/selinux -include $(srctree)/include/uapi/asm-generic/errno.h

View File

@@ -6,7 +6,7 @@
#include "selinux.h" #include "selinux.h"
#include "sepolicy.h" #include "sepolicy.h"
#include "ss/services.h" #include "ss/services.h"
#include "linux/lsm_audit.h" #include "linux/lsm_audit.h" // IWYU pragma: keep
#include "xfrm.h" #include "xfrm.h"
#define SELINUX_POLICY_INSTEAD_SELINUX_SS #define SELINUX_POLICY_INSTEAD_SELINUX_SS
@@ -18,111 +18,119 @@
static struct policydb *get_policydb(void) static struct policydb *get_policydb(void)
{ {
struct policydb *db; struct policydb *db;
struct selinux_policy *policy = rcu_dereference(selinux_state.policy); struct selinux_policy *policy = selinux_state.policy;
db = &policy->policydb; db = &policy->policydb;
return db; return db;
} }
static DEFINE_MUTEX(ksu_rules);
void apply_kernelsu_rules() void apply_kernelsu_rules()
{ {
if (!getenforce()) { struct policydb *db;
pr_info("SELinux permissive or disabled, apply rules!\n");
}
rcu_read_lock(); if (!getenforce()) {
struct policydb *db = get_policydb(); pr_info("SELinux permissive or disabled, apply rules!\n");
}
ksu_permissive(db, KERNEL_SU_DOMAIN); mutex_lock(&ksu_rules);
ksu_typeattribute(db, KERNEL_SU_DOMAIN, "mlstrustedsubject");
ksu_typeattribute(db, KERNEL_SU_DOMAIN, "netdomain");
ksu_typeattribute(db, KERNEL_SU_DOMAIN, "bluetoothdomain");
// Create unconstrained file type db = get_policydb();
ksu_type(db, KERNEL_SU_FILE, "file_type");
ksu_typeattribute(db, KERNEL_SU_FILE, "mlstrustedobject");
ksu_allow(db, ALL, KERNEL_SU_FILE, ALL, ALL);
// allow all! ksu_permissive(db, KERNEL_SU_DOMAIN);
ksu_allow(db, KERNEL_SU_DOMAIN, ALL, ALL, ALL); ksu_typeattribute(db, KERNEL_SU_DOMAIN, "mlstrustedsubject");
ksu_typeattribute(db, KERNEL_SU_DOMAIN, "netdomain");
ksu_typeattribute(db, KERNEL_SU_DOMAIN, "bluetoothdomain");
// allow us do any ioctl // Create unconstrained file type
if (db->policyvers >= POLICYDB_VERSION_XPERMS_IOCTL) { ksu_type(db, KERNEL_SU_FILE, "file_type");
ksu_allowxperm(db, KERNEL_SU_DOMAIN, ALL, "blk_file", ALL); ksu_typeattribute(db, KERNEL_SU_FILE, "mlstrustedobject");
ksu_allowxperm(db, KERNEL_SU_DOMAIN, ALL, "fifo_file", ALL); ksu_allow(db, ALL, KERNEL_SU_FILE, ALL, ALL);
ksu_allowxperm(db, KERNEL_SU_DOMAIN, ALL, "chr_file", ALL);
ksu_allowxperm(db, KERNEL_SU_DOMAIN, ALL, "file", ALL);
}
// we need to save allowlist in /data/adb/ksu // allow all!
ksu_allow(db, "kernel", "adb_data_file", "dir", ALL); ksu_allow(db, KERNEL_SU_DOMAIN, ALL, ALL, ALL);
ksu_allow(db, "kernel", "adb_data_file", "file", ALL);
// we need to search /data/app
ksu_allow(db, "kernel", "apk_data_file", "file", "open");
ksu_allow(db, "kernel", "apk_data_file", "dir", "open");
ksu_allow(db, "kernel", "apk_data_file", "dir", "read");
ksu_allow(db, "kernel", "apk_data_file", "dir", "search");
// we may need to do mount on shell
ksu_allow(db, "kernel", "shell_data_file", "file", ALL);
// we need to read /data/system/packages.list
ksu_allow(db, "kernel", "kernel", "capability", "dac_override");
// Android 10+:
// http://aospxref.com/android-12.0.0_r3/xref/system/sepolicy/private/file_contexts#512
ksu_allow(db, "kernel", "packages_list_file", "file", ALL);
// Kernel 4.4
ksu_allow(db, "kernel", "packages_list_file", "dir", ALL);
// Android 9-:
// http://aospxref.com/android-9.0.0_r61/xref/system/sepolicy/private/file_contexts#360
ksu_allow(db, "kernel", "system_data_file", "file", ALL);
ksu_allow(db, "kernel", "system_data_file", "dir", ALL);
// our ksud triggered by init
ksu_allow(db, "init", "adb_data_file", "file", ALL);
ksu_allow(db, "init", "adb_data_file", "dir", ALL); // #1289
ksu_allow(db, "init", KERNEL_SU_DOMAIN, ALL, ALL);
// we need to umount modules in zygote
ksu_allow(db, "zygote", "adb_data_file", "dir", "search");
// copied from Magisk rules // allow us do any ioctl
// suRights if (db->policyvers >= POLICYDB_VERSION_XPERMS_IOCTL) {
ksu_allow(db, "servicemanager", KERNEL_SU_DOMAIN, "dir", "search"); ksu_allowxperm(db, KERNEL_SU_DOMAIN, ALL, "blk_file", ALL);
ksu_allow(db, "servicemanager", KERNEL_SU_DOMAIN, "dir", "read"); ksu_allowxperm(db, KERNEL_SU_DOMAIN, ALL, "fifo_file", ALL);
ksu_allow(db, "servicemanager", KERNEL_SU_DOMAIN, "file", "open"); ksu_allowxperm(db, KERNEL_SU_DOMAIN, ALL, "chr_file", ALL);
ksu_allow(db, "servicemanager", KERNEL_SU_DOMAIN, "file", "read"); ksu_allowxperm(db, KERNEL_SU_DOMAIN, ALL, "file", ALL);
ksu_allow(db, "servicemanager", KERNEL_SU_DOMAIN, "process", "getattr"); }
ksu_allow(db, ALL, KERNEL_SU_DOMAIN, "process", "sigchld");
// allowLog // we need to save allowlist in /data/adb/ksu
ksu_allow(db, "logd", KERNEL_SU_DOMAIN, "dir", "search"); ksu_allow(db, "kernel", "adb_data_file", "dir", ALL);
ksu_allow(db, "logd", KERNEL_SU_DOMAIN, "file", "read"); ksu_allow(db, "kernel", "adb_data_file", "file", ALL);
ksu_allow(db, "logd", KERNEL_SU_DOMAIN, "file", "open"); // we need to search /data/app
ksu_allow(db, "logd", KERNEL_SU_DOMAIN, "file", "getattr"); ksu_allow(db, "kernel", "apk_data_file", "file", "open");
ksu_allow(db, "kernel", "apk_data_file", "dir", "open");
ksu_allow(db, "kernel", "apk_data_file", "dir", "read");
ksu_allow(db, "kernel", "apk_data_file", "dir", "search");
// we may need to do mount on shell
ksu_allow(db, "kernel", "shell_data_file", "file", ALL);
// we need to read /data/system/packages.list
ksu_allow(db, "kernel", "kernel", "capability", "dac_override");
// Android 10+:
// http://aospxref.com/android-12.0.0_r3/xref/system/sepolicy/private/file_contexts#512
ksu_allow(db, "kernel", "packages_list_file", "file", ALL);
// Kernel 4.4
ksu_allow(db, "kernel", "packages_list_file", "dir", ALL);
// Android 9-:
// http://aospxref.com/android-9.0.0_r61/xref/system/sepolicy/private/file_contexts#360
ksu_allow(db, "kernel", "system_data_file", "file", ALL);
ksu_allow(db, "kernel", "system_data_file", "dir", ALL);
// our ksud triggered by init
ksu_allow(db, "init", "adb_data_file", "file", ALL);
ksu_allow(db, "init", "adb_data_file", "dir", ALL); // #1289
ksu_allow(db, "init", KERNEL_SU_DOMAIN, ALL, ALL);
// we need to umount modules in zygote
ksu_allow(db, "zygote", "adb_data_file", "dir", "search");
// dumpsys // copied from Magisk rules
ksu_allow(db, ALL, KERNEL_SU_DOMAIN, "fd", "use"); // suRights
ksu_allow(db, ALL, KERNEL_SU_DOMAIN, "fifo_file", "write"); ksu_allow(db, "servicemanager", KERNEL_SU_DOMAIN, "dir", "search");
ksu_allow(db, ALL, KERNEL_SU_DOMAIN, "fifo_file", "read"); ksu_allow(db, "servicemanager", KERNEL_SU_DOMAIN, "dir", "read");
ksu_allow(db, ALL, KERNEL_SU_DOMAIN, "fifo_file", "open"); ksu_allow(db, "servicemanager", KERNEL_SU_DOMAIN, "file", "open");
ksu_allow(db, ALL, KERNEL_SU_DOMAIN, "fifo_file", "getattr"); ksu_allow(db, "servicemanager", KERNEL_SU_DOMAIN, "file", "read");
ksu_allow(db, "servicemanager", KERNEL_SU_DOMAIN, "process", "getattr");
ksu_allow(db, ALL, KERNEL_SU_DOMAIN, "process", "sigchld");
// bootctl // allowLog
ksu_allow(db, "hwservicemanager", KERNEL_SU_DOMAIN, "dir", "search"); ksu_allow(db, "logd", KERNEL_SU_DOMAIN, "dir", "search");
ksu_allow(db, "hwservicemanager", KERNEL_SU_DOMAIN, "file", "read"); ksu_allow(db, "logd", KERNEL_SU_DOMAIN, "file", "read");
ksu_allow(db, "hwservicemanager", KERNEL_SU_DOMAIN, "file", "open"); ksu_allow(db, "logd", KERNEL_SU_DOMAIN, "file", "open");
ksu_allow(db, "hwservicemanager", KERNEL_SU_DOMAIN, "process", ksu_allow(db, "logd", KERNEL_SU_DOMAIN, "file", "getattr");
"getattr");
// For mounting loop devices, mirrors, tmpfs // dumpsys
ksu_allow(db, "kernel", ALL, "file", "read"); ksu_allow(db, ALL, KERNEL_SU_DOMAIN, "fd", "use");
ksu_allow(db, "kernel", ALL, "file", "write"); ksu_allow(db, ALL, KERNEL_SU_DOMAIN, "fifo_file", "write");
ksu_allow(db, ALL, KERNEL_SU_DOMAIN, "fifo_file", "read");
ksu_allow(db, ALL, KERNEL_SU_DOMAIN, "fifo_file", "open");
ksu_allow(db, ALL, KERNEL_SU_DOMAIN, "fifo_file", "getattr");
// Allow all binder transactions // bootctl
ksu_allow(db, ALL, KERNEL_SU_DOMAIN, "binder", ALL); ksu_allow(db, "hwservicemanager", KERNEL_SU_DOMAIN, "dir", "search");
ksu_allow(db, "hwservicemanager", KERNEL_SU_DOMAIN, "file", "read");
ksu_allow(db, "hwservicemanager", KERNEL_SU_DOMAIN, "file", "open");
ksu_allow(db, "hwservicemanager", KERNEL_SU_DOMAIN, "process",
"getattr");
// For mounting loop devices, mirrors, tmpfs
ksu_allow(db, "kernel", ALL, "file", "read");
ksu_allow(db, "kernel", ALL, "file", "write");
// Allow all binder transactions
ksu_allow(db, ALL, KERNEL_SU_DOMAIN, "binder", ALL);
// Allow system server kill su process // 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", "getpgid");
ksu_allow(db, "system_server", KERNEL_SU_DOMAIN, "process", "sigkill"); ksu_allow(db, "system_server", KERNEL_SU_DOMAIN, "process", "sigkill");
rcu_read_unlock(); // https://android-review.googlesource.com/c/platform/system/logging/+/3725346
ksu_dontaudit(db, "untrusted_app", KERNEL_SU_DOMAIN, "dir", "getattr");
mutex_unlock(&ksu_rules);
} }
#define MAX_SEPOL_LEN 128 #define MAX_SEPOL_LEN 128
@@ -137,399 +145,333 @@ void apply_kernelsu_rules()
#define CMD_TYPE_CHANGE 8 #define CMD_TYPE_CHANGE 8
#define CMD_GENFSCON 9 #define CMD_GENFSCON 9
#ifdef CONFIG_64BIT
struct sepol_data { struct sepol_data {
u32 cmd; u32 cmd;
u32 subcmd; u32 subcmd;
u64 field_sepol1; char __user *sepol1;
u64 field_sepol2; char __user *sepol2;
u64 field_sepol3; char __user *sepol3;
u64 field_sepol4; char __user *sepol4;
u64 field_sepol5; char __user *sepol5;
u64 field_sepol6; char __user *sepol6;
u64 field_sepol7; char __user *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, static int get_object(char *buf, char __user *user_object, size_t buf_sz,
char **object) char **object)
{ {
if (!user_object) { if (!user_object) {
*object = ALL; *object = ALL;
return 0; return 0;
} }
if (strncpy_from_user(buf, user_object, buf_sz) < 0) { if (strncpy_from_user(buf, user_object, buf_sz) < 0) {
return -1; return -EINVAL;
} }
*object = buf; *object = buf;
return 0; return 0;
} }
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0))
extern int avc_ss_reset(u32 seqno);
#else
extern int avc_ss_reset(struct selinux_avc *avc, u32 seqno);
#endif
// reset avc cache table, otherwise the new rules will not take effect if already denied // reset avc cache table, otherwise the new rules will not take effect if already denied
static void reset_avc_cache() static void reset_avc_cache()
{ {
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0)) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0))
avc_ss_reset(0); avc_ss_reset(0);
selnl_notify_policyload(0); selnl_notify_policyload(0);
selinux_status_update_policyload(0); selinux_status_update_policyload(0);
#else #else
struct selinux_avc *avc = selinux_state.avc; struct selinux_avc *avc = selinux_state.avc;
avc_ss_reset(avc, 0); avc_ss_reset(avc, 0);
selnl_notify_policyload(0); selnl_notify_policyload(0);
selinux_status_update_policyload(&selinux_state, 0); selinux_status_update_policyload(&selinux_state, 0);
#endif #endif
selinux_xfrm_notify_policyload(); selinux_xfrm_notify_policyload();
} }
int handle_sepolicy(unsigned long arg3, void __user *arg4) int handle_sepolicy(unsigned long arg3, void __user *arg4)
{ {
if (!arg4) { struct policydb *db;
return -1;
}
if (!getenforce()) { if (!arg4) {
pr_info("SELinux permissive or disabled when handle policy!\n"); return -EINVAL;
} }
u32 cmd, subcmd;
char __user *sepol1, *sepol2, *sepol3, *sepol4, *sepol5, *sepol6, *sepol7;
#if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT) if (!getenforce()) {
if (unlikely(ksu_is_compat)) { pr_info("SELinux permissive or disabled when handle policy!\n");
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;
}
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(); struct sepol_data data;
if (copy_from_user(&data, arg4, sizeof(struct sepol_data))) {
pr_err("sepol: copy sepol_data failed.\n");
return -EINVAL;
}
struct policydb *db = get_policydb(); u32 cmd = data.cmd;
u32 subcmd = data.subcmd;
int ret = -1; mutex_lock(&ksu_rules);
if (cmd == CMD_NORMAL_PERM) {
char src_buf[MAX_SEPOL_LEN];
char tgt_buf[MAX_SEPOL_LEN];
char cls_buf[MAX_SEPOL_LEN];
char perm_buf[MAX_SEPOL_LEN];
char *s, *t, *c, *p; db = get_policydb();
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, sepol2, sizeof(tgt_buf), &t) < 0) { int ret = -EINVAL;
pr_err("sepol: copy tgt failed.\n"); if (cmd == CMD_NORMAL_PERM) {
goto exit; char src_buf[MAX_SEPOL_LEN];
} char tgt_buf[MAX_SEPOL_LEN];
char cls_buf[MAX_SEPOL_LEN];
char perm_buf[MAX_SEPOL_LEN];
if (get_object(cls_buf, sepol3, sizeof(cls_buf), &c) < 0) { char *s, *t, *c, *p;
pr_err("sepol: copy cls failed.\n"); if (get_object(src_buf, data.sepol1, sizeof(src_buf), &s) < 0) {
goto exit; pr_err("sepol: copy src failed.\n");
} goto exit;
}
if (get_object(perm_buf, sepol4, sizeof(perm_buf), &p) < if (get_object(tgt_buf, data.sepol2, sizeof(tgt_buf), &t) < 0) {
0) { pr_err("sepol: copy tgt failed.\n");
pr_err("sepol: copy perm failed.\n"); goto exit;
goto exit; }
}
bool success = false; if (get_object(cls_buf, data.sepol3, sizeof(cls_buf), &c) < 0) {
if (subcmd == 1) { pr_err("sepol: copy cls failed.\n");
success = ksu_allow(db, s, t, c, p); goto exit;
} else if (subcmd == 2) { }
success = ksu_deny(db, s, t, c, p);
} else if (subcmd == 3) {
success = ksu_auditallow(db, s, t, c, p);
} else if (subcmd == 4) {
success = ksu_dontaudit(db, s, t, c, p);
} else {
pr_err("sepol: unknown subcmd: %d\n", subcmd);
}
ret = success ? 0 : -1;
} else if (cmd == CMD_XPERM) { if (get_object(perm_buf, data.sepol4, sizeof(perm_buf), &p) <
char src_buf[MAX_SEPOL_LEN]; 0) {
char tgt_buf[MAX_SEPOL_LEN]; pr_err("sepol: copy perm failed.\n");
char cls_buf[MAX_SEPOL_LEN]; goto exit;
}
char __maybe_unused bool success = false;
operation[MAX_SEPOL_LEN]; // it is always ioctl now! if (subcmd == 1) {
char perm_set[MAX_SEPOL_LEN]; success = ksu_allow(db, s, t, c, p);
} else if (subcmd == 2) {
success = ksu_deny(db, s, t, c, p);
} else if (subcmd == 3) {
success = ksu_auditallow(db, s, t, c, p);
} else if (subcmd == 4) {
success = ksu_dontaudit(db, s, t, c, p);
} else {
pr_err("sepol: unknown subcmd: %d\n", subcmd);
}
ret = success ? 0 : -EINVAL;
char *s, *t, *c; } else if (cmd == CMD_XPERM) {
if (get_object(src_buf, sepol1, sizeof(src_buf), &s) < 0) { char src_buf[MAX_SEPOL_LEN];
pr_err("sepol: copy src failed.\n"); char tgt_buf[MAX_SEPOL_LEN];
goto exit; char cls_buf[MAX_SEPOL_LEN];
}
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, sepol3, sizeof(cls_buf), &c) < 0) {
pr_err("sepol: copy cls failed.\n");
goto exit;
}
if (strncpy_from_user(operation, sepol4,
sizeof(operation)) < 0) {
pr_err("sepol: copy operation failed.\n");
goto exit;
}
if (strncpy_from_user(perm_set, sepol5, sizeof(perm_set)) <
0) {
pr_err("sepol: copy perm_set failed.\n");
goto exit;
}
bool success = false; char __maybe_unused
if (subcmd == 1) { operation[MAX_SEPOL_LEN]; // it is always ioctl now!
success = ksu_allowxperm(db, s, t, c, perm_set); char perm_set[MAX_SEPOL_LEN];
} else if (subcmd == 2) {
success = ksu_auditallowxperm(db, s, t, c, perm_set);
} else if (subcmd == 3) {
success = ksu_dontauditxperm(db, s, t, c, perm_set);
} else {
pr_err("sepol: unknown subcmd: %d\n", subcmd);
}
ret = success ? 0 : -1;
} else if (cmd == CMD_TYPE_STATE) {
char src[MAX_SEPOL_LEN];
if (strncpy_from_user(src, sepol1, sizeof(src)) < 0) { char *s, *t, *c;
pr_err("sepol: copy src failed.\n"); if (get_object(src_buf, data.sepol1, sizeof(src_buf), &s) < 0) {
goto exit; pr_err("sepol: copy src failed.\n");
} goto exit;
}
if (get_object(tgt_buf, data.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) {
pr_err("sepol: copy cls failed.\n");
goto exit;
}
if (strncpy_from_user(operation, data.sepol4,
sizeof(operation)) < 0) {
pr_err("sepol: copy operation failed.\n");
goto exit;
}
if (strncpy_from_user(perm_set, data.sepol5, sizeof(perm_set)) <
0) {
pr_err("sepol: copy perm_set failed.\n");
goto exit;
}
bool success = false; bool success = false;
if (subcmd == 1) { if (subcmd == 1) {
success = ksu_permissive(db, src); success = ksu_allowxperm(db, s, t, c, perm_set);
} else if (subcmd == 2) { } else if (subcmd == 2) {
success = ksu_enforce(db, src); success = ksu_auditallowxperm(db, s, t, c, perm_set);
} else { } else if (subcmd == 3) {
pr_err("sepol: unknown subcmd: %d\n", subcmd); success = ksu_dontauditxperm(db, s, t, c, perm_set);
} } else {
if (success) pr_err("sepol: unknown subcmd: %d\n", subcmd);
ret = 0; }
ret = success ? 0 : -EINVAL;
} else if (cmd == CMD_TYPE_STATE) {
char src[MAX_SEPOL_LEN];
} else if (cmd == CMD_TYPE || cmd == CMD_TYPE_ATTR) { if (strncpy_from_user(src, data.sepol1, sizeof(src)) < 0) {
char type[MAX_SEPOL_LEN]; pr_err("sepol: copy src failed.\n");
char attr[MAX_SEPOL_LEN]; goto exit;
}
if (strncpy_from_user(type, sepol1, sizeof(type)) < 0) { bool success = false;
pr_err("sepol: copy type failed.\n"); if (subcmd == 1) {
goto exit; success = ksu_permissive(db, src);
} } else if (subcmd == 2) {
if (strncpy_from_user(attr, sepol2, sizeof(attr)) < 0) { success = ksu_enforce(db, src);
pr_err("sepol: copy attr failed.\n"); } else {
goto exit; pr_err("sepol: unknown subcmd: %d\n", subcmd);
} }
if (success)
ret = 0;
bool success = false; } else if (cmd == CMD_TYPE || cmd == CMD_TYPE_ATTR) {
if (cmd == CMD_TYPE) { char type[MAX_SEPOL_LEN];
success = ksu_type(db, type, attr); char attr[MAX_SEPOL_LEN];
} else {
success = ksu_typeattribute(db, type, attr);
}
if (!success) {
pr_err("sepol: %d failed.\n", cmd);
goto exit;
}
ret = 0;
} else if (cmd == CMD_ATTR) { if (strncpy_from_user(type, data.sepol1, sizeof(type)) < 0) {
char attr[MAX_SEPOL_LEN]; pr_err("sepol: copy type failed.\n");
goto exit;
}
if (strncpy_from_user(attr, data.sepol2, sizeof(attr)) < 0) {
pr_err("sepol: copy attr failed.\n");
goto exit;
}
if (strncpy_from_user(attr, sepol1, sizeof(attr)) < 0) { bool success = false;
pr_err("sepol: copy attr failed.\n"); if (cmd == CMD_TYPE) {
goto exit; success = ksu_type(db, type, attr);
} } else {
if (!ksu_attribute(db, attr)) { success = ksu_typeattribute(db, type, attr);
pr_err("sepol: %d failed.\n", cmd); }
goto exit; if (!success) {
} pr_err("sepol: %d failed.\n", cmd);
ret = 0; goto exit;
}
ret = 0;
} else if (cmd == CMD_TYPE_TRANSITION) { } else if (cmd == CMD_ATTR) {
char src[MAX_SEPOL_LEN]; char attr[MAX_SEPOL_LEN];
char tgt[MAX_SEPOL_LEN];
char cls[MAX_SEPOL_LEN];
char default_type[MAX_SEPOL_LEN];
char object[MAX_SEPOL_LEN];
if (strncpy_from_user(src, sepol1, sizeof(src)) < 0) { if (strncpy_from_user(attr, data.sepol1, sizeof(attr)) < 0) {
pr_err("sepol: copy src failed.\n"); pr_err("sepol: copy attr failed.\n");
goto exit; goto exit;
} }
if (strncpy_from_user(tgt, sepol2, sizeof(tgt)) < 0) { if (!ksu_attribute(db, attr)) {
pr_err("sepol: copy tgt failed.\n"); pr_err("sepol: %d failed.\n", cmd);
goto exit; goto exit;
} }
if (strncpy_from_user(cls, sepol3, sizeof(cls)) < 0) { ret = 0;
pr_err("sepol: copy cls failed.\n");
goto exit;
}
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 (sepol5 == NULL) {
real_object = NULL;
} else {
if (strncpy_from_user(object, sepol5,
sizeof(object)) < 0) {
pr_err("sepol: copy object failed.\n");
goto exit;
}
real_object = object;
}
bool success = ksu_type_transition(db, src, tgt, cls, } else if (cmd == CMD_TYPE_TRANSITION) {
default_type, real_object); char src[MAX_SEPOL_LEN];
if (success) char tgt[MAX_SEPOL_LEN];
ret = 0; char cls[MAX_SEPOL_LEN];
char default_type[MAX_SEPOL_LEN];
char object[MAX_SEPOL_LEN];
} else if (cmd == CMD_TYPE_CHANGE) { if (strncpy_from_user(src, data.sepol1, sizeof(src)) < 0) {
char src[MAX_SEPOL_LEN]; pr_err("sepol: copy src failed.\n");
char tgt[MAX_SEPOL_LEN]; goto exit;
char cls[MAX_SEPOL_LEN]; }
char default_type[MAX_SEPOL_LEN]; if (strncpy_from_user(tgt, data.sepol2, sizeof(tgt)) < 0) {
pr_err("sepol: copy tgt failed.\n");
goto exit;
}
if (strncpy_from_user(cls, data.sepol3, sizeof(cls)) < 0) {
pr_err("sepol: copy cls failed.\n");
goto exit;
}
if (strncpy_from_user(default_type, data.sepol4,
sizeof(default_type)) < 0) {
pr_err("sepol: copy default_type failed.\n");
goto exit;
}
char *real_object;
if (data.sepol5 == NULL) {
real_object = NULL;
} else {
if (strncpy_from_user(object, data.sepol5,
sizeof(object)) < 0) {
pr_err("sepol: copy object failed.\n");
goto exit;
}
real_object = object;
}
if (strncpy_from_user(src, sepol1, sizeof(src)) < 0) { bool success = ksu_type_transition(db, src, tgt, cls,
pr_err("sepol: copy src failed.\n"); default_type, real_object);
goto exit; if (success)
} ret = 0;
if (strncpy_from_user(tgt, sepol2, sizeof(tgt)) < 0) {
pr_err("sepol: copy tgt failed.\n");
goto exit;
}
if (strncpy_from_user(cls, sepol3, sizeof(cls)) < 0) {
pr_err("sepol: copy cls failed.\n");
goto exit;
}
if (strncpy_from_user(default_type, sepol4,
sizeof(default_type)) < 0) {
pr_err("sepol: copy default_type failed.\n");
goto exit;
}
bool success = false;
if (subcmd == 1) {
success = ksu_type_change(db, src, tgt, cls,
default_type);
} else if (subcmd == 2) {
success = ksu_type_member(db, src, tgt, cls,
default_type);
} else {
pr_err("sepol: unknown subcmd: %d\n", subcmd);
}
if (success)
ret = 0;
} else if (cmd == CMD_GENFSCON) {
char name[MAX_SEPOL_LEN];
char path[MAX_SEPOL_LEN];
char context[MAX_SEPOL_LEN];
if (strncpy_from_user(name, sepol1, sizeof(name)) < 0) {
pr_err("sepol: copy name failed.\n");
goto exit;
}
if (strncpy_from_user(path, sepol2, sizeof(path)) < 0) {
pr_err("sepol: copy path failed.\n");
goto exit;
}
if (strncpy_from_user(context, sepol3, sizeof(context)) <
0) {
pr_err("sepol: copy context failed.\n");
goto exit;
}
if (!ksu_genfscon(db, name, path, context)) { } else if (cmd == CMD_TYPE_CHANGE) {
pr_err("sepol: %d failed.\n", cmd); char src[MAX_SEPOL_LEN];
goto exit; char tgt[MAX_SEPOL_LEN];
} char cls[MAX_SEPOL_LEN];
ret = 0; char default_type[MAX_SEPOL_LEN];
} else {
pr_err("sepol: unknown cmd: %d\n", cmd); if (strncpy_from_user(src, data.sepol1, sizeof(src)) < 0) {
} pr_err("sepol: copy src failed.\n");
goto exit;
}
if (strncpy_from_user(tgt, data.sepol2, sizeof(tgt)) < 0) {
pr_err("sepol: copy tgt failed.\n");
goto exit;
}
if (strncpy_from_user(cls, data.sepol3, sizeof(cls)) < 0) {
pr_err("sepol: copy cls failed.\n");
goto exit;
}
if (strncpy_from_user(default_type, data.sepol4,
sizeof(default_type)) < 0) {
pr_err("sepol: copy default_type failed.\n");
goto exit;
}
bool success = false;
if (subcmd == 1) {
success = ksu_type_change(db, src, tgt, cls,
default_type);
} else if (subcmd == 2) {
success = ksu_type_member(db, src, tgt, cls,
default_type);
} else {
pr_err("sepol: unknown subcmd: %d\n", subcmd);
}
if (success)
ret = 0;
} else if (cmd == CMD_GENFSCON) {
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) {
pr_err("sepol: copy name failed.\n");
goto exit;
}
if (strncpy_from_user(path, data.sepol2, sizeof(path)) < 0) {
pr_err("sepol: copy path failed.\n");
goto exit;
}
if (strncpy_from_user(context, data.sepol3, sizeof(context)) <
0) {
pr_err("sepol: copy context failed.\n");
goto exit;
}
if (!ksu_genfscon(db, name, path, context)) {
pr_err("sepol: %d failed.\n", cmd);
goto exit;
}
ret = 0;
} else {
pr_err("sepol: unknown cmd: %d\n", cmd);
}
exit: exit:
rcu_read_unlock(); mutex_unlock(&ksu_rules);
// only allow and xallow needs to reset avc cache, but we cannot do that because // only allow and xallow needs to reset avc cache, but we cannot do that because
// we are in atomic context. so we just reset it every time. // we are in atomic context. so we just reset it every time.
reset_avc_cache(); reset_avc_cache();
return ret; return ret;
} }

View File

@@ -1,4 +1,6 @@
#include "selinux.h" #include "selinux.h"
#include "linux/cred.h"
#include "linux/sched.h"
#include "objsec.h" #include "objsec.h"
#include "linux/version.h" #include "linux/version.h"
#include "../klog.h" // IWYU pragma: keep #include "../klog.h" // IWYU pragma: keep
@@ -7,124 +9,146 @@
static int transive_to_domain(const char *domain) static int transive_to_domain(const char *domain)
{ {
struct cred *cred; struct cred *cred;
struct task_security_struct *tsec; struct task_security_struct *tsec;
u32 sid; u32 sid;
int error; int error;
cred = (struct cred *)__task_cred(current); cred = (struct cred *)__task_cred(current);
tsec = cred->security; tsec = cred->security;
if (!tsec) { if (!tsec) {
pr_err("tsec == NULL!\n"); pr_err("tsec == NULL!\n");
return -1; return -1;
} }
error = security_secctx_to_secid(domain, strlen(domain), &sid); error = security_secctx_to_secid(domain, strlen(domain), &sid);
if (error) { if (error) {
pr_info("security_secctx_to_secid %s -> sid: %d, error: %d\n", pr_info("security_secctx_to_secid %s -> sid: %d, error: %d\n",
domain, sid, error); domain, sid, error);
} }
if (!error) { if (!error) {
tsec->sid = sid; tsec->sid = sid;
tsec->create_sid = 0; tsec->create_sid = 0;
tsec->keycreate_sid = 0; tsec->keycreate_sid = 0;
tsec->sockcreate_sid = 0; tsec->sockcreate_sid = 0;
} }
return error; return error;
} }
void setup_selinux(const char *domain) void setup_selinux(const char *domain)
{ {
if (transive_to_domain(domain)) { if (transive_to_domain(domain)) {
pr_err("transive domain failed.\n"); pr_err("transive domain failed.\n");
return; return;
} }
/* we didn't need this now, we have change selinux rules when boot!
if (!is_domain_permissive) {
if (set_domain_permissive() == 0) {
is_domain_permissive = true;
}
}*/
} }
void setenforce(bool enforce) void setenforce(bool enforce)
{ {
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
selinux_state.enforcing = enforce; selinux_state.enforcing = enforce;
#endif #endif
} }
bool getenforce() bool getenforce()
{ {
#ifdef CONFIG_SECURITY_SELINUX_DISABLE #ifdef CONFIG_SECURITY_SELINUX_DISABLE
if (selinux_state.disabled) { if (selinux_state.disabled) {
return false; return false;
} }
#endif #endif
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
return selinux_state.enforcing; return selinux_state.enforcing;
#else #else
return true; return true;
#endif #endif
} }
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)) && \ #if LINUX_VERSION_CODE < KERNEL_VERSION(6, 14, 0)
!defined(KSU_COMPAT_HAS_CURRENT_SID) struct lsm_context {
/* char *context;
* get the subjective security ID of the current task u32 len;
*/ };
static inline u32 current_sid(void)
static int __security_secid_to_secctx(u32 secid, struct lsm_context *cp)
{ {
const struct task_security_struct *tsec = current_security(); return security_secid_to_secctx(secid, &cp->context, &cp->len);
return tsec->sid;
} }
static void __security_release_secctx(struct lsm_context *cp)
{
return security_release_secctx(cp->context, cp->len);
}
#else
#define __security_secid_to_secctx security_secid_to_secctx
#define __security_release_secctx security_release_secctx
#endif #endif
bool is_task_ksu_domain(const struct cred* cred)
{
struct lsm_context ctx;
bool result;
if (!cred) {
return false;
}
const struct task_security_struct *tsec = selinux_cred(cred);
if (!tsec) {
return false;
}
int err = __security_secid_to_secctx(tsec->sid, &ctx);
if (err) {
return false;
}
result = strncmp(KERNEL_SU_DOMAIN, ctx.context, ctx.len) == 0;
__security_release_secctx(&ctx);
return result;
}
bool is_ksu_domain() bool is_ksu_domain()
{ {
char *domain; current_sid();
u32 seclen; return is_task_ksu_domain(current_cred());
bool result;
int err = security_secid_to_secctx(current_sid(), &domain, &seclen);
if (err) {
return false;
}
result = strncmp(KERNEL_SU_DOMAIN, domain, seclen) == 0;
security_release_secctx(domain, seclen);
return result;
} }
bool is_zygote(void *sec) bool is_context(const struct cred* cred, const char* context)
{ {
struct task_security_struct *tsec = (struct task_security_struct *)sec; if (!cred) {
if (!tsec) { return false;
return false; }
} const struct task_security_struct * tsec = selinux_cred(cred);
char *domain; if (!tsec) {
u32 seclen; return false;
bool result; }
int err = security_secid_to_secctx(tsec->sid, &domain, &seclen); struct lsm_context ctx;
if (err) { bool result;
return false; int err = __security_secid_to_secctx(tsec->sid, &ctx);
} if (err) {
result = strncmp("u:r:zygote:s0", domain, seclen) == 0; return false;
security_release_secctx(domain, seclen); }
return result; result = strncmp(context, ctx.context, ctx.len) == 0;
__security_release_secctx(&ctx);
return result;
} }
#define DEVPTS_DOMAIN "u:object_r:ksu_file:s0" bool is_zygote(const struct cred* cred)
u32 ksu_get_devpts_sid()
{ {
u32 devpts_sid = 0; return is_context(cred, "u:r:zygote:s0");
int err = security_secctx_to_secid(DEVPTS_DOMAIN, strlen(DEVPTS_DOMAIN), }
&devpts_sid);
if (err) { bool is_init(const struct cred* cred) {
pr_info("get devpts sid err %d\n", err); return is_context(cred, "u:r:init:s0");
} }
return devpts_sid;
#define KSU_FILE_DOMAIN "u:object_r:ksu_file:s0"
u32 ksu_get_ksu_file_sid()
{
u32 ksu_file_sid = 0;
int err = security_secctx_to_secid(KSU_FILE_DOMAIN, strlen(KSU_FILE_DOMAIN),
&ksu_file_sid);
if (err) {
pr_info("get ksufile sid err %d\n", err);
}
return ksu_file_sid;
} }

View File

@@ -3,6 +3,7 @@
#include "linux/types.h" #include "linux/types.h"
#include "linux/version.h" #include "linux/version.h"
#include "linux/cred.h"
void setup_selinux(const char *); void setup_selinux(const char *);
@@ -10,12 +11,18 @@ void setenforce(bool);
bool getenforce(); bool getenforce();
bool is_task_ksu_domain(const struct cred* cred);
bool is_ksu_domain(); bool is_ksu_domain();
bool is_zygote(void *cred); bool is_zygote(const struct cred* cred);
bool is_init(const struct cred* cred);
void apply_kernelsu_rules(); void apply_kernelsu_rules();
u32 ksu_get_devpts_sid(); u32 ksu_get_ksu_file_sid();
int handle_sepolicy(unsigned long arg3, void __user *arg4);
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@@ -15,32 +15,32 @@ bool ksu_exists(struct policydb *db, const char *type);
// Access vector rules // Access vector rules
bool ksu_allow(struct policydb *db, const char *src, const char *tgt, bool ksu_allow(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *perm); const char *cls, const char *perm);
bool ksu_deny(struct policydb *db, const char *src, const char *tgt, bool ksu_deny(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *perm); const char *cls, const char *perm);
bool ksu_auditallow(struct policydb *db, const char *src, const char *tgt, bool ksu_auditallow(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *perm); const char *cls, const char *perm);
bool ksu_dontaudit(struct policydb *db, const char *src, const char *tgt, bool ksu_dontaudit(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *perm); const char *cls, const char *perm);
// Extended permissions access vector rules // Extended permissions access vector rules
bool ksu_allowxperm(struct policydb *db, const char *src, const char *tgt, bool ksu_allowxperm(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *range); const char *cls, const char *range);
bool ksu_auditallowxperm(struct policydb *db, const char *src, const char *tgt, bool ksu_auditallowxperm(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *range); const char *cls, const char *range);
bool ksu_dontauditxperm(struct policydb *db, const char *src, const char *tgt, bool ksu_dontauditxperm(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *range); const char *cls, const char *range);
// Type rules // Type rules
bool ksu_type_transition(struct policydb *db, const char *src, const char *tgt, bool ksu_type_transition(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *def, const char *obj); const char *cls, const char *def, const char *obj);
bool ksu_type_change(struct policydb *db, const char *src, const char *tgt, bool ksu_type_change(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *def); const char *cls, const char *def);
bool ksu_type_member(struct policydb *db, const char *src, const char *tgt, bool ksu_type_member(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *def); const char *cls, const char *def);
// File system labeling // File system labeling
bool ksu_genfscon(struct policydb *db, const char *fs_name, const char *path, bool ksu_genfscon(struct policydb *db, const char *fs_name, const char *path,
const char *ctx); const char *ctx);
#endif #endif

171
kernel/setuid_hook.c Normal file
View File

@@ -0,0 +1,171 @@
#include <linux/compiler.h>
#include <linux/sched/signal.h>
#include <linux/slab.h>
#include <linux/task_work.h>
#include <linux/thread_info.h>
#include <linux/seccomp.h>
#include <linux/bpf.h>
#include <linux/capability.h>
#include <linux/cred.h>
#include <linux/dcache.h>
#include <linux/err.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/init_task.h>
#include <linux/kernel.h>
#include <linux/kprobes.h>
#include <linux/mm.h>
#include <linux/mount.h>
#include <linux/namei.h>
#include <linux/nsproxy.h>
#include <linux/path.h>
#include <linux/printk.h>
#include <linux/sched.h>
#include <linux/security.h>
#include <linux/stddef.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <linux/uidgid.h>
#include <linux/version.h>
#include <linux/binfmts.h>
#include <linux/tty.h>
#include "allowlist.h"
#include "setuid_hook.h"
#include "feature.h"
#include "klog.h" // IWYU pragma: keep
#include "manager.h"
#include "selinux/selinux.h"
#include "seccomp_cache.h"
#include "supercalls.h"
#include "syscall_hook_manager.h"
#include "kernel_umount.h"
#include "app_profile.h"
static bool ksu_enhanced_security_enabled = false;
static int enhanced_security_feature_get(u64 *value)
{
*value = ksu_enhanced_security_enabled ? 1 : 0;
return 0;
}
static int enhanced_security_feature_set(u64 value)
{
bool enable = value != 0;
ksu_enhanced_security_enabled = enable;
pr_info("enhanced_security: set to %d\n", enable);
return 0;
}
static const struct ksu_feature_handler enhanced_security_handler = {
.feature_id = KSU_FEATURE_ENHANCED_SECURITY,
.name = "enhanced_security",
.get_handler = enhanced_security_feature_get,
.set_handler = enhanced_security_feature_set,
};
static inline bool is_allow_su()
{
if (is_manager()) {
// we are manager, allow!
return true;
}
return ksu_is_allow_uid_for_current(current_uid().val);
}
int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid)
{
uid_t new_uid = ruid;
uid_t old_uid = current_uid().val;
pr_info("handle_setresuid from %d to %d\n", old_uid, new_uid);
// if old process is root, ignore it.
if (old_uid != 0 && ksu_enhanced_security_enabled) {
// disallow any non-ksu domain escalation from non-root to root!
// euid is what we care about here as it controls permission
if (unlikely(euid == 0)) {
if (!is_ksu_domain()) {
pr_warn("find suspicious EoP: %d %s, from %d to %d\n",
current->pid, current->comm, old_uid, new_uid);
force_sig(SIGKILL);
return 0;
}
}
// disallow appuid decrease to any other uid if it is not allowed to su
if (is_appuid(old_uid)) {
if (euid < current_euid().val && !ksu_is_allow_uid_for_current(old_uid)) {
pr_warn("find suspicious EoP: %d %s, from %d to %d\n",
current->pid, current->comm, old_uid, new_uid);
force_sig(SIGKILL);
return 0;
}
}
return 0;
}
// if on private space, see if its possibly the manager
if (new_uid > PER_USER_RANGE && new_uid % PER_USER_RANGE == ksu_get_manager_uid()) {
ksu_set_manager_uid(new_uid);
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
if (ksu_get_manager_uid() == new_uid) {
pr_info("install fd for manager: %d\n", new_uid);
ksu_install_fd();
spin_lock_irq(&current->sighand->siglock);
ksu_seccomp_allow_cache(current->seccomp.filter, __NR_reboot);
ksu_set_task_tracepoint_flag(current);
spin_unlock_irq(&current->sighand->siglock);
return 0;
}
if (ksu_is_allow_uid_for_current(new_uid)) {
if (current->seccomp.mode == SECCOMP_MODE_FILTER &&
current->seccomp.filter) {
spin_lock_irq(&current->sighand->siglock);
ksu_seccomp_allow_cache(current->seccomp.filter, __NR_reboot);
spin_unlock_irq(&current->sighand->siglock);
}
ksu_set_task_tracepoint_flag(current);
} else {
ksu_clear_task_tracepoint_flag_if_needed(current);
}
#else
if (ksu_is_allow_uid_for_current(new_uid)) {
spin_lock_irq(&current->sighand->siglock);
disable_seccomp();
spin_unlock_irq(&current->sighand->siglock);
if (ksu_get_manager_uid() == new_uid) {
pr_info("install fd for ksu manager(uid=%d)\n",
new_uid);
ksu_install_fd();
}
return 0;
}
#endif
// Handle kernel umount
ksu_handle_umount(old_uid, new_uid);
return 0;
}
void ksu_setuid_hook_init(void)
{
ksu_kernel_umount_init();
if (ksu_register_feature_handler(&enhanced_security_handler)) {
pr_err("Failed to register enhanced security feature handler\n");
}
}
void ksu_setuid_hook_exit(void)
{
pr_info("ksu_core_exit\n");
ksu_kernel_umount_exit();
ksu_unregister_feature_handler(KSU_FEATURE_ENHANCED_SECURITY);
}

14
kernel/setuid_hook.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef __KSU_H_KSU_CORE
#define __KSU_H_KSU_CORE
#include <linux/init.h>
#include <linux/types.h>
#include "apk_sign.h"
#include <linux/thread_info.h>
void ksu_setuid_hook_init(void);
void ksu_setuid_hook_exit(void);
int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid);
#endif

View File

@@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
set -eu set -eu
GKI_ROOT=$(pwd) KERNEL_ROOT=$(pwd)
display_usage() { display_usage() {
echo "Usage: $0 [--cleanup | <commit-or-tag>]" echo "Usage: $0 [--cleanup | <commit-or-tag>]"
@@ -12,10 +12,10 @@ display_usage() {
} }
initialize_variables() { initialize_variables() {
if test -d "$GKI_ROOT/common/drivers"; then if test -d "$KERNEL_ROOT/common/drivers"; then
DRIVER_DIR="$GKI_ROOT/common/drivers" DRIVER_DIR="$KERNEL_ROOT/common/drivers"
elif test -d "$GKI_ROOT/drivers"; then elif test -d "$KERNEL_ROOT/drivers"; then
DRIVER_DIR="$GKI_ROOT/drivers" DRIVER_DIR="$KERNEL_ROOT/drivers"
else else
echo '[ERROR] "drivers/" directory not found.' echo '[ERROR] "drivers/" directory not found.'
exit 127 exit 127
@@ -30,22 +30,21 @@ perform_cleanup() {
echo "[+] Cleaning up..." echo "[+] Cleaning up..."
[ -L "$DRIVER_DIR/kernelsu" ] && rm "$DRIVER_DIR/kernelsu" && echo "[-] Symlink removed." [ -L "$DRIVER_DIR/kernelsu" ] && rm "$DRIVER_DIR/kernelsu" && echo "[-] Symlink removed."
grep -q "kernelsu" "$DRIVER_MAKEFILE" && sed -i '/kernelsu/d' "$DRIVER_MAKEFILE" && echo "[-] Makefile reverted." grep -q "kernelsu" "$DRIVER_MAKEFILE" && sed -i '/kernelsu/d' "$DRIVER_MAKEFILE" && echo "[-] Makefile reverted."
grep -q "drivers/kernelsu/Kconfig" "$DRIVER_KCONFIG" && sed -i '/drivers\/kernelsu\/Kconfig/d' "$DRIVER_KCONFIG" && echo "[-] Kconfig reverted." grep -q "kernelsu" "$DRIVER_KCONFIG" && sed -i '/kernelsu/d' "$DRIVER_KCONFIG" && echo "[-] Kconfig reverted."
if [ -d "$GKI_ROOT/KernelSU" ]; then if [ -d "$KERNEL_ROOT/KernelSU" ]; then
rm -rf "$GKI_ROOT/KernelSU" && echo "[-] KernelSU directory deleted." rm -rf "$KERNEL_ROOT/KernelSU" && echo "[-] KernelSU directory deleted."
fi fi
} }
# Sets up or update KernelSU environment # Sets up or update KernelSU environment
setup_kernelsu() { setup_kernelsu() {
echo "[+] Setting up KernelSU..." echo "[+] Setting up KernelSU..."
# Clone the repository and rename it to KernelSU # Clone the repository
if [ ! -d "$GKI_ROOT/KernelSU" ]; then if [ ! -d "$KERNEL_ROOT/KernelSU" ]; then
git clone https://github.com/SukiSU-Ultra/SukiSU-Ultra SukiSU-Ultra git clone https://github.com/SukiSU-Ultra/SukiSU-Ultra KernelSU
mv SukiSU-Ultra KernelSU echo "[+] Repository cloned."
echo "[+] Repository cloned and renamed to KernelSU."
fi fi
cd "$GKI_ROOT/KernelSU" cd "$KERNEL_ROOT/KernelSU"
git stash && echo "[-] Stashed current changes." git stash && echo "[-] Stashed current changes."
if [ "$(git status | grep -Po 'v\d+(\.\d+)*' | head -n1)" ]; then if [ "$(git status | grep -Po 'v\d+(\.\d+)*' | head -n1)" ]; then
git checkout main && echo "[-] Switched to main branch." git checkout main && echo "[-] Switched to main branch."
@@ -57,11 +56,11 @@ setup_kernelsu() {
git checkout "$1" && echo "[-] Checked out $1." || echo "[-] Checkout default branch" git checkout "$1" && echo "[-] Checked out $1." || echo "[-] Checkout default branch"
fi fi
cd "$DRIVER_DIR" cd "$DRIVER_DIR"
ln -sf "$(realpath --relative-to="$DRIVER_DIR" "$GKI_ROOT/KernelSU/kernel")" "kernelsu" && echo "[+] Symlink created." ln -sf "$(realpath --relative-to="$DRIVER_DIR" "$KERNEL_ROOT/KernelSU/kernel")" "kernelsu" && echo "[+] Symlink created."
# Add entries in Makefile and Kconfig if not already existing # Add entries in Makefile and Kconfig if not already existing
grep -q "kernelsu" "$DRIVER_MAKEFILE" || printf "\nobj-\$(CONFIG_KSU) += kernelsu/\n" >> "$DRIVER_MAKEFILE" && echo "[+] Modified Makefile." grep -q "kernelsu" "$DRIVER_MAKEFILE" || echo 'obj-$(CONFIG_KSU) += kernelsu/' >> "$DRIVER_MAKEFILE" && echo "[+] Modified Makefile."
grep -q "source \"drivers/kernelsu/Kconfig\"" "$DRIVER_KCONFIG" || sed -i "/endmenu/i\source \"drivers/kernelsu/Kconfig\"" "$DRIVER_KCONFIG" && echo "[+] Modified Kconfig." grep -q 'source "drivers/kernelsu/Kconfig"' "$DRIVER_KCONFIG" || sed -i '/endmenu/i\source "drivers/kernelsu/Kconfig"' "$DRIVER_KCONFIG" && echo "[+] Modified Kconfig."
echo '[+] Done.' echo '[+] Done.'
} }
@@ -77,4 +76,4 @@ elif [ "$1" = "--cleanup" ]; then
else else
initialize_variables initialize_variables
setup_kernelsu "$@" setup_kernelsu "$@"
fi fi

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