Compare commits

..

295 Commits

Author SHA1 Message Date
Amicia De Rune
acc37fb387 manager: Update ID language translation (#239)
Signed-off-by: RooGhz720 <rooghz720@gmail.com>

Signed-off-by: RooGhz720 <rooghz720@gmail.com>
2023-02-14 13:02:16 +08:00
tiann
f50b4dfe34 ksud: fmt 2023-02-14 12:59:21 +08:00
tiann
9ce7351aaa ksud: support check_sepolicy in scripts 2023-02-14 12:57:08 +08:00
tiann
c691a1adb2 manager: Add reboot shortcut for module screen 2023-02-14 12:01:05 +08:00
tiann
9a2a21ec5d manager: Add more info to bugreport 2023-02-14 11:44:57 +08:00
tiann
a9fd0aa132 manager: Add kernel version to bugreport 2023-02-14 11:40:24 +08:00
tiann
198674d889 manager: show manager version 2023-02-14 11:37:37 +08:00
tiann
203a5683ac manager: show safemode in homescreen 2023-02-14 11:29:16 +08:00
tiann
eeb8cda175 manager: show module state in safemode 2023-02-13 23:33:56 +08:00
tiann
b268971323 ksud: support module disable in safemode 2023-02-13 23:33:56 +08:00
weishu
051fc53a4f kernel: count time of volumedown to enter safemode 2023-02-13 22:01:59 +07:00
tiann
55602f1f16 manager: ui state for safemode 2023-02-13 22:41:32 +08:00
tiann
42428345ff ksud: check kernel safemode 2023-02-13 22:28:43 +08:00
weishu
ca950d909b kernel: press KEY_VOLUMEDOWN over 2 seconds will enter safemode and disable all modules
Co-authored-by: Ylarod <me@ylarod.cn>
2023-02-13 21:23:28 +07:00
weishu
20ff530962 kernel: fix sepolicy apply may not work #227
Co-authored-by: sekaiacg <sekaiacg@gmail.com>
2023-02-13 09:12:31 +07:00
tiann
a5dbbf4881 Revert "[add device]: GKI 1.0 (#236)"
This reverts commit e91b1fc89a.
2023-02-13 09:38:03 +08:00
github-actions[bot]
e91b1fc89a [add device]: GKI 1.0 (#236)
GKI 1.0 has been added to the website.
Related issue: https://github.com/tiann/KernelSU/issues/235

---------

Co-authored-by: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: weishu <twsxtd@gmail.com>
2023-02-12 18:44:31 +08:00
tiann
4e35e4ae86 ksud: fix vendor only overlay not working 2023-02-12 18:29:27 +08:00
Aquarius223
6d15cb7e33 kernel: Fix f6967d2c lost parameters after ack-linux 4.14.y (>=163) (#234)
* [android-4.14-stable tree:
https://github.com/aosp-mirror/kernel_common/commit/5d0939e1]

Change-Id: Ice92dd83df4c4f1ae272156cb57f95998e45819f

Co-authored-by: stic-server-open <1138705738@qq.com>
2023-02-12 18:11:28 +08:00
tiann
095acad8a6 ksud: Fix mount ext4 failed of sys-mount 2023-02-12 18:07:50 +08:00
skbeh
c187d1ad8a ksud: remove tailing "/" from PATH (#230) 2023-02-12 18:07:07 +08:00
weishu
f6967d2cfb kernel: reset avc cache for sepolicy
Co-authored-by: sekaiacg <sekaiacg@gmail.com>
2023-02-12 13:09:00 +07:00
weishu
388d2b0b59 kernel: disable inofity for fd opened for manager 2023-02-12 12:15:58 +07:00
github-actions[bot]
d9aecbcbca [add device]: (#229)
has been added to the website.
Related issue: https://github.com/tiann/KernelSU/issues/228

Co-authored-by: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-11 19:55:23 +08:00
rxuglr
eabdf3e78c manager: Add Russian language (#225) 2023-02-11 15:26:55 +08:00
tiann
a1fb7c5fdf ksud: don't hardcode system unzip becuase we use busybox now 2023-02-10 18:51:22 +08:00
f19
89394245b1 fix KSU_GIT_VERSION is not defined while importing KSU by 'git submodule add' (#224)
.git is a text file while the module is imported by 'git submodule add'.
2023-02-10 16:34:47 +08:00
Re*Index. (ot_inc)
91f1eb2d6a Added Japanese language to KernelSU Manager (#223)
Japanese translation added.
2023-02-09 23:51:53 +08:00
tiann
ab5f6db54b website: Update installation 2023-02-09 14:04:41 +08:00
tiann
626642af76 ksud: e2fsck before resize2fs 2023-02-09 13:53:07 +08:00
tiann
473f02396f website: Update installation 2023-02-09 10:51:16 +08:00
tiann
aa4b1bf9d8 website: Update installation instruction 2023-02-09 09:28:16 +08:00
tiann
8e5a72fc35 ci: Fix release build 2023-02-08 23:58:47 +08:00
weishu
7302653879 Add release ci (#218) 2023-02-08 22:31:43 +08:00
github-actions[bot]
b2b563547c [add device]: (#220)
has been added to the website.
Related issue: https://github.com/tiann/KernelSU/issues/219

Co-authored-by: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-08 22:18:05 +08:00
tiann
cc29ad151a ksud: Add KSU_KERNEL_VER_CODE 2023-02-08 15:09:36 +08:00
tiann
a4a93d8945 ksud: clippy 2023-02-08 12:33:00 +08:00
tiann
3389cd0aea ksud: Fix module operation order 2023-02-08 12:26:33 +08:00
tiann
d26956ff72 ksud: Fix confliction with stock system overlayfs 2023-02-08 12:14:31 +08:00
Aquarius223
66284bfbe3 kernel: Correctly judge the version of selinux_state (#214)
* Merged related changes in android-common-kernel-4.14.163 [1] Handle
correct checks for older versions (below 4.14.163, 4.9, 4.4)
* fixes 14be7562, it is required in 4.14.163 kernel, it is not needed in
4.14.163 and later

[1]: https://github.com/MiCode/Xiaomi_Kernel_OpenSource/commits/1cfd8419

Change-Id: Iade104312d058a249667ca836259d5608418bb55

Co-authored-by: admin <paper@localhost>
2023-02-07 15:02:48 +08:00
初羽
14be75629b kernel: selinux: Fix build error (#213)
* d77ab8d although fixed some typo, but since there is no include avc.h,
this will cause the build to fail
* Error:


/mnt/HDD/fish/aospa/kernel/msm-4.9/drivers/staging/ksu/selinux/selinux.c:60:2:
error: use of undeclared identifier 'selinux_enforcing'
        selinux_enforcing = enforce;
        ^

/mnt/HDD/fish/aospa/kernel/msm-4.9/drivers/staging/ksu/selinux/selinux.c:81:9:
error: use of undeclared identifier 'selinux_enforcing'
        return selinux_enforcing;
               ^
2 errors generated.

Change-Id: I4cc8917b2b73ca467873222e02d498da8718988e
2023-02-07 09:50:55 +08:00
小さい猫
d77ab8dbff kernel: selinux: fix more typos introduced in #166 (#212)
i didn't realize these typos in #181

Signed-off-by: Ookiineko <chiisaineko@protonmail.com>
2023-02-06 16:31:26 +08:00
weishu
c2ac548ac7 kernel: allow use without git submodule 2023-02-06 15:30:58 +07:00
tiann
ad4d8e939e ksud: clippy 2023-02-06 09:16:15 +08:00
tiann
aa7a00b299 ksud: don't mount module when in safe mode 2023-02-06 08:58:02 +08:00
tiann
1ff421365e ksud: pass KSU_VER and KSU_VER_CODE to installer script 2023-02-06 08:53:18 +08:00
weishu
0a12d0139d kernel: make sure KernelSU is a submodule to avoding incorrect git version 2023-02-05 16:31:50 +07:00
Daybit
181ab4f545 [add device]:Pixel4XL (#210)
[add device]:Pixel4XL
2023-02-05 13:21:40 +08:00
github-actions[bot]
3e29e98f2c [add device]: (#209)
has been added to the website.
Related issue: https://github.com/tiann/KernelSU/issues/208

Co-authored-by: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-05 11:42:58 +08:00
Amicia De Rune
a66c1de660 manager: update translation ID language (#207)
Signed-off-by: RooGhz720 <rooghz720@gmail.com>

Signed-off-by: RooGhz720 <rooghz720@gmail.com>
2023-02-05 07:15:21 +08:00
f19
0c322a33bc kernel: fix filp_open on older kernel's kworker (#205)
On older kernel, kworker missing keyring from init process , and this
keyring is related to FBE , which causes filp_open return ENOKEY or
other errors.To fix this,just install init's keyring to per
kworkers.This works on Kernel 4.4 and 4.9.
2023-02-05 07:14:59 +08:00
小さい猫
cd33a6dd07 website: document the replacement of do_faccessat for some non-GKI (#206)
Signed-off-by: Ookiineko <chiisaineko@protonmail.com>
2023-02-04 21:56:04 +08:00
github-actions[bot]
c1dceaf11f [add device]: (#204)
has been added to the website.
Related issue: https://github.com/tiann/KernelSU/issues/203

Co-authored-by: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-04 15:35:26 +08:00
skbeh
3181dd17bc ci: add CI for clippy, rustfmt and shell scripts (#193) 2023-02-04 13:52:20 +08:00
VINC3NT
c93fa1af59 [add device]: Redmi K40s / POCO F4 (#201) 2023-02-04 13:36:01 +08:00
skbeh
9f4a8d3dfc ksud, kernel: update explanation and fix some issues (#194) 2023-02-04 13:16:51 +08:00
weishu
4da829792f kernel: unify version 2023-02-03 23:01:02 +07:00
github-actions[bot]
1a073224c3 [add device]: Redmi K40 / POCO F3 (#198)
Redmi K40 / POCO F3 has been added to the website.
Related issue: https://github.com/tiann/KernelSU/issues/197

Co-authored-by: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-03 23:33:36 +08:00
tiann
175de861bf ksud: Fix incorrect dependency 2023-02-03 23:19:22 +08:00
tiann
aa73c34db2 ksud: unify version 2023-02-03 21:02:11 +08:00
github-actions[bot]
ed2176af8c [add device]: (#196)
has been added to the website.
Related issue: https://github.com/tiann/KernelSU/issues/195

Co-authored-by: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-03 19:12:44 +08:00
tiann
49f7d56fdd manager: Add send log 2023-02-03 18:14:42 +08:00
tiann
71cc166f72 ksud: Fix macOS compile 2023-02-03 14:46:48 +08:00
tiann
8ee00839dc ksud: Fix script exec 2023-02-03 14:26:26 +08:00
github-actions[bot]
6239662a7f [add device]: Redmi Note 9 Pro/ Mi 10T Lite/ Mi 10i (#190)
Redmi Note 9 Pro/ Mi 10T Lite/ Mi 10i has been added to the website.
Related issue: https://github.com/tiann/KernelSU/issues/189

Co-authored-by: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-03 14:12:24 +08:00
Huy Minh
216c2aa2cd website: vi_VN: Update FAQs (#191) 2023-02-03 14:03:05 +08:00
tiann
70b8b43b48 ksud: support sepolicy check 2023-02-03 13:16:17 +08:00
tiann
430c2e709f website: Add some faq 2023-02-03 11:11:41 +08:00
tiann
b975950b07 ksud: fix module update 2023-02-03 10:05:09 +08:00
tiann
ed42cf42d2 ksud: restore syscon before module install script; this revert 2a4675e25b 2023-02-03 10:00:52 +08:00
tiann
d80c282644 ksud: tweaks for setcon 2023-02-03 09:55:03 +08:00
tiann
a05edb3872 manager: coming soon for system writable 2023-02-03 09:45:42 +08:00
tiann
43b8987b4b manager: open installation guide when install 2023-02-03 09:45:42 +08:00
skbeh
219ea1c458 ksud: fix issues found by clippy (#167)
These issues are mostly found by `cargo clippy -- -W clippy::pedantic`.
2023-02-03 09:45:07 +08:00
skbeh
bea93f6ad7 ksud: compress embed assets (#186) 2023-02-03 09:31:32 +08:00
耀風
e4267848f0 manager: Update Traditional Chinese (#185) 2023-02-03 08:37:07 +08:00
Huy Minh
bc5953b510 manager: vi_VN: small edit (#184) 2023-02-03 05:15:32 +08:00
Arthur
e41b7cd117 website: fix description error (#183) 2023-02-03 05:14:36 +08:00
Nguyễn Long
cab78e7893 manager: add vi translation (#182)
Signed-off-by: HoangLong-Lumi <hoanglong.lumi404@gmail.com>
2023-02-02 23:39:10 +08:00
小さい猫
199f5cc223 fix some typos introduced in #166 (#181)
Signed-off-by: Ookiineko <chiisaineko@protonmail.com>
Co-authored-by: f19 <58457605+F-19-F@users.noreply.github.com>
Co-authored-by: Scirese <nuclearlight91@gmail.com>
2023-02-02 23:38:04 +08:00
Amicia De Rune
962649f7ca manager: add id translation (#179)
Signed-off-by: RooGhz720 <rooghz720@gmail.com>
2023-02-02 22:40:33 +08:00
tiann
7b32c0e37b ksud: opti module mount 2023-02-02 21:56:08 +08:00
tiann
12f353a1ae ksud: Add bin path to script PATH 2023-02-02 21:42:04 +08:00
tiann
c26e170c87 ksud: default umask 022(0644 for file) 2023-02-02 21:24:11 +08:00
tiann
6a706de09e ksud: use busybox to exec all shell scripts 2023-02-02 20:37:17 +08:00
tiann
2a4675e25b ksud: set /system permission after installation script 2023-02-02 20:37:17 +08:00
tiann
0bc36b3299 ksud: fix incorrecy RAII 2023-02-02 20:37:17 +08:00
tiann
dc902b16d4 ksud: copy when rename failed 2023-02-02 20:37:17 +08:00
tiann
86998a032e ksud: fallback to system mount when rust lib mount failed 2023-02-02 20:37:17 +08:00
github-actions[bot]
1727ec41c4 [add device]: OnePlus 8 Serials (#178)
OnePlus 8 Serials has been added to the website.
Related issue: https://github.com/tiann/KernelSU/issues/177

Co-authored-by: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-02 20:10:51 +08:00
tiann
3eb812be5b ksud: Fix module may mount failed 2023-02-02 14:02:02 +08:00
Amicia De Rune
64c2f6ba5c website: update translation in ID language (#176)
Signed-off-by: RooGhz720 <rooghz720@gmail.com>

Signed-off-by: RooGhz720 <rooghz720@gmail.com>
2023-02-02 13:59:10 +08:00
WeeAris
2db7da0766 website:fix devices info error (#175)
Fix devices info error for unofficially supported devices.
#173
2023-02-02 11:23:21 +08:00
weishu
d1e7bad18f kernel: version 15 2023-02-02 09:05:37 +07:00
tiann
d7cef25665 manager: Superuser support refresh and hide system apps 2023-02-02 09:59:40 +08:00
tiann
23f41145b0 ksud: Fix module resize error 2023-02-02 09:25:41 +08:00
tiann
a969af8159 relicense kernel source code to GPL-v2 2023-02-02 09:04:07 +08:00
tiann
001fa00355 ksud: Add logs for module installation 2023-02-02 08:58:34 +08:00
tiann
a6dddd32b3 website: fix build err 2023-02-02 08:40:28 +08:00
tiann
cd825e34da ksud: support common post-fs-data.d and service.d 2023-02-02 08:39:26 +08:00
github-actions[bot]
2bba088319 [add device]: non-GKI devices, 4.19.x kernel, sm8250, repo for AOSP only. (#171)
non-GKI devices, 4.19.x kernel, sm8250, repo for AOSP only. has been
added to the website.
Related issue: https://github.com/tiann/KernelSU/issues/170

Co-authored-by: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-02 03:20:19 +08:00
Amicia De Rune
4905bd9bb8 website: fix missing directory in ID language (#169)
sry missing /guide/

Signed-off-by: RooGhz720 <rooghz720@gmail.com>

Signed-off-by: RooGhz720 <rooghz720@gmail.com>
2023-02-02 03:19:27 +08:00
Amicia De Rune
3f625a000b website: fix missing pages in ID language (#168)
Signed-off-by: RooGhz720 <rooghz720@gmail.com>

Signed-off-by: RooGhz720 <rooghz720@gmail.com>
2023-02-01 22:41:53 +08:00
tiann
3bfee10a0d ksud: set SELinux context for /vendor 2023-02-01 21:10:16 +08:00
tiann
d5a05da5b8 ci: don't build kernel when ksud changes 2023-02-01 21:01:32 +08:00
tiann
d8042a36c3 ksud: fix post-fs-data.sh and service.sh may be not executed 2023-02-01 20:28:38 +08:00
tiann
85bf01eb65 ksud: use logcat log 2023-02-01 20:28:38 +08:00
f19
4f2b8b7077 kernel: backport to 4.4 (#166)
These changes make KernelSU work on kernel4.4
[link](https://github.com/F-19-F/android_kernel_oneplus_msm8998).
LINUX_VERSION_CODE macro changes have been vertied on 4.4 4.9 4.14.
For kernel 4.4,just pick two commits
* [introduce
KernelSU](2993524f2f)
* [allow init exec ksud under
nosuid](3df9df42a6)
2023-02-01 19:48:36 +08:00
tiann
417ff8a6c5 ksud: fix module installation failed when size < 1M 2023-02-01 19:30:39 +08:00
tiann
681c4a3f0d ksud: minor tweaks 2023-02-01 19:12:25 +08:00
tiann
619dd1ace1 ksud: make it compilable for non-android 2023-02-01 19:04:33 +08:00
tiann
1cd18a643d ksud: some refactor 2023-02-01 18:33:38 +08:00
tiann
3519d61636 ksud: format code 2023-02-01 17:59:16 +08:00
skbeh
46913671a8 kernel, ksud: collect binaries into /data/adb/ksu (#161) 2023-02-01 17:58:58 +08:00
tiann
b7ff6b1a51 ksud: support module sepolicy.rule 2023-01-31 21:58:59 +08:00
weishu
62be9eb589 kernel: version 14 2023-01-31 20:55:25 +07:00
weishu
ab6d483c32 kernel: fix sepolicy rule which contains * 2023-01-31 20:51:02 +07:00
weishu
2d77f84736 kernel: bump version 13 2023-01-31 19:21:21 +07:00
tiann
c2f7963a43 ci: Add android13-5.10.149 2023-01-31 20:19:36 +08:00
weishu
b9e27621ee kernel: support sepolicy 2023-01-31 18:54:31 +07:00
skbeh
2766e24007 ci: replace actions-rs/cargo with naive command (#162)
This avoids node 12 warnings.

Co-authored-by: Ylarod <me@ylarod.cn>
2023-01-31 19:11:00 +08:00
Ylarod
45911ac3c4 ci: trigger ci if yml changes in pr (#163) 2023-01-31 19:06:11 +08:00
tiann
ad89c5a80f ksud: fix compile for x86_64 2023-01-31 19:00:58 +08:00
tiann
3413f4a4fe ksud: sepolicy support 2023-01-31 18:47:43 +08:00
Ylarod
2a88cca50c ci: update kernel build, remove embed ksud (#159) 2023-01-31 10:37:54 +08:00
skbeh
634978c14f ksud: remove subprocess dependency (#156) 2023-01-30 20:14:27 +08:00
Ylarod
093f7d9758 website: fix typo (#158) 2023-01-30 20:06:09 +08:00
Ylarod
40960f60f8 ci: handle add device automatically (#157) 2023-01-30 19:41:46 +08:00
The_second_Tom
25a4c2930a website: add Xiaomi 8 (dipper) (#151)
Add kernelsu support for MI 8 (dipper)
2023-01-30 15:04:59 +08:00
Sakura桜
342344db0c website: Remove "For LineageOS" on MI 8 SE (#150)
Change _MI8SE(sirius) for LineageOS_ To _Xiaomi MI 8 SE(sirius)_

With a lot of tests, it also can use on Crdroid, PixelExperience and so
on.
2023-01-30 15:04:03 +08:00
skbeh
7785d2a3f8 ksud: replace some utils with rust libraries (#142) 2023-01-30 12:57:25 +08:00
tarsin
bd6b0d3d12 Proper way to fix #107 (#148) 2023-01-30 09:53:24 +08:00
Amicia De Rune
a871b92dc9 website: add xiaomi redmi note 10 pro (sweet) (#147) 2023-01-30 08:19:37 +08:00
Aquarius223
47d15c47f3 website: Merged MI 6 and MIX 2 information into one line (#146)
Change-Id: Ide86c6ea2256b06390852d73dc0b79bc8ced4792

Co-authored-by: admin <paper@localhost>
2023-01-30 08:19:09 +08:00
tiann
684283c585 manager: fix uninstall button is overlayed. close #107 2023-01-29 21:31:20 +08:00
tiann
d2d9b0eaad ksud: fix broken /system/vendor when it is a symlink 2023-01-29 21:27:29 +08:00
SlackerState
22e6b1eec5 website:add RedmiK30 4G(phoenix) (#144)
add RedmiK30 4G(phoenix)
2023-01-29 20:27:25 +08:00
Aquarius223
f6301c5a7c website: Add Xiaomi MI 6 (sagit) and Xiaomi MIX 2 (chiron) (#143)
Change-Id: I1d68b41d74c9cf237b834d96c53a5949add2f4ba

Co-authored-by: stic-server-open <1138705738@qq.com>
2023-01-29 19:06:23 +08:00
Sakura桜
b191415173 Add MI8SE (#141) 2023-01-29 16:21:33 +08:00
Ylarod
59542bc99a add issue template (#139) 2023-01-29 16:14:23 +08:00
tiann
0e4b5b3765 website: fix device list link broken 2023-01-29 16:12:22 +08:00
Ylarod
a986251773 ci: fix kernel build (#137) 2023-01-29 13:00:47 +08:00
tiann
0e651fdc99 website: opti device list 2023-01-29 12:59:37 +08:00
Ylarod
b1e279bd2a ci: update build (#129)
1. update kernel ci
2. fix manager build
2023-01-29 11:25:10 +08:00
tarsin
e76cf08934 Fix Navbar color (#136) 2023-01-29 10:32:34 +08:00
tarsin
4cf930a9dc Update unofficially-support-devices.md (#135)
Add cas
2023-01-29 08:46:59 +08:00
Huy Minh
599723515e docs: vi_VN: Translate some strings (#134)
Signed-off-by: Huy Minh <buingoc67@gmail.com>
2023-01-28 23:11:40 +08:00
Huy Minh
e1e8d53da5 docs: Adding Android-x86 kernel supported by me (#133)
Chinese translated using Google Translate
2023-01-28 22:36:44 +08:00
Huy Minh
20a2c0092e docs: vi_VN: translate unofficially supported devices (#131) 2023-01-28 22:15:18 +08:00
tiann
a40ad07e2b website: repo list for munch 2023-01-28 21:13:48 +08:00
Ylarod
65d80aad03 docs: add unofficially-support-devices (#128) 2023-01-28 20:41:23 +08:00
Ylarod
905c041a76 ci: common kernel build and embed ksud (#127) 2023-01-28 12:24:43 +08:00
tiann
0dae6ebaee docs: simplify 2023-01-28 09:33:03 +08:00
Ylarod
d41954b09c website: update description 2023-01-27 16:58:52 +08:00
tiann
6e8771b8d9 manager: check overlayfs support 2023-01-26 17:27:16 +08:00
weishu
cf5bcc09e8 kernel: version 12 2023-01-26 16:16:00 +07:00
weishu
413a8d0a2f kernel: support selinux state transition 2023-01-26 16:05:14 +07:00
weishu
1852652029 kernel: add sepolicy calls 2023-01-26 16:05:14 +07:00
tiann
76c88a72c6 manager: fix ksud installation failed at first boot. 2023-01-26 15:51:59 +08:00
tiann
f6c249bd77 ksud: fix compile for non-android 2023-01-26 15:05:20 +08:00
Ylarod
ee7065bc12 kernel: minor fix (#122) 2023-01-26 14:55:41 +08:00
Ylarod
8446f07a91 kernel: update debug warning (#121) 2023-01-26 14:32:52 +08:00
Ylarod
09b9aefed7 ci: use custom key to sign official bootimgs (#120)
We can get pub key hash by 
```
avbtool info_image --image boot.img
```
2023-01-26 13:40:07 +08:00
tiann
f810ce2d0d manager: remove libksu 2023-01-26 12:36:25 +08:00
tiann
ed86635b3c ksud: add su 2023-01-26 12:28:55 +08:00
tiann
080aeee5e3 ksud: make other os build happy 2023-01-26 12:12:25 +08:00
tiann
2ebb363350 website: fix symbol 2023-01-26 11:50:15 +08:00
tiann
da38815ce0 website: no need to bother sucompat now 2023-01-26 11:37:34 +08:00
Ylarod
db600d5ea0 kernel: precise trigger timing of post-fs-data (#118)
* kernel: add report_event cmd

* ksud: report event

* kernel: trigger on_post_fs_data

* ksud: comment unused code

* [skip ci] run clang-format

Signed-off-by: Ylarod <me@ylarod.cn>

* ci: use custom key to sign official bootimgs

* format ksud

* reject non root

* remove

Signed-off-by: Ylarod <me@ylarod.cn>
2023-01-26 11:29:02 +08:00
Ylarod
22b66b6672 kernel: opt allowlist persist and log (#119)
* kernel: persist on need

* kernel: opt log for ksu_allow_uid
2023-01-26 08:55:27 +08:00
Ylarod
06aaae1335 kernel: fix missing log tag (#117) 2023-01-25 22:24:00 +08:00
Ylarod
810087b2a7 kernel: bump version to 11 2023-01-25 21:55:47 +08:00
Ylarod
2f970f7ab8 kernel: refact (#113)
* refact

* sort inlude

* update

* unregister execve kprobe

* update log

* don't unregister if not in kprobe

* opt for no kprobe

* opt for no kprobe

* stop debug

* don't forget to call ksu_uid_observer_exit

* rename core to core_hook

* direct call do_persistent_allow_list

* add prefix

* use getter, add warn

* add wrapper

* run clang-format

clang-format --style="{BasedOnStyle: InheritParentConfig, SortIncludes: true}" -i kernel/**/*.[ch]

* try fix wsa x64 build
2023-01-25 21:53:19 +08:00
Ylarod
5fb8316e46 ksud: update help and add default pkg name (#115) 2023-01-25 20:45:49 +08:00
Huy Minh
57806df17e website : vi_VN : Update non-GKI integration translate (#116) 2023-01-25 20:45:35 +08:00
tiann
0857cf8835 ksud: minor tweaks 2023-01-25 19:01:51 +08:00
weishu
64d78c31bc ksud: support set-manager (#114)
* ksud: support set-manager

* ksud: rework apk sign

Co-authored-by: Ylarod <me@ylarod.cn>
2023-01-25 17:55:08 +08:00
Ylarod
47a736f567 kernel: allow to change manager in debug mode (#111) 2023-01-25 14:50:44 +08:00
Ylarod
423f4aaf1f kernel: add missing header (#110) 2023-01-24 22:32:16 +08:00
weishu
1d55c987a6 kernel: bump version to 10 2023-01-24 19:49:08 +07:00
weishu
e5044b4b6f kernel: selinux support add new type and add builtin unconstrained file type 2023-01-24 19:48:41 +07:00
weishu
fbd7d0f90d kernel: enable sucompat iff KPROBES enabled, close #100 2023-01-24 14:38:33 +07:00
セリカ・シルフィル
87d05fbbdc website:Remind readers how to resolve dependencies for KPROBES (#106)
website:Remind readers how to resolve  dependencies for KPROBES

Power by DeepL and Google Translate
2023-01-24 15:10:44 +08:00
tiann
1475a85c58 ksud: dummy mount stdout and stderr 2023-01-24 15:06:50 +08:00
tiann
b4bc2e66e6 ksud: auto resize image based on module size 2023-01-24 15:00:31 +08:00
tiann
780a42d823 ksud: dummy mount output 2023-01-24 13:28:06 +08:00
tiann
3ca9537d8a ksud: retry for mount 2023-01-24 13:26:40 +08:00
Ylarod
4c28932c4c kernel: run ksu_kprobe_init if build as module (#109) 2023-01-24 08:42:25 +08:00
Abhiram
6bccd757fd Add support for predictive back gesture (#105)
Reference: https://developer.android.com/guide/navigation/predictive-back-gesture#opt-predictive
2023-01-23 18:39:38 +08:00
AngelaCool
00630cb4f3 manager: Add monochrome themed icon on Android 12+ (#104) 2023-01-23 10:26:12 +08:00
Ylarod
254d19f8a3 Revert "README: Added the information for the support of Linux 4.9 (#103)"
This reverts commit f8583fbef0.
2023-01-22 13:11:33 +08:00
SlightlyLookAround
f8583fbef0 README: Added the information for the support of Linux 4.9 (#103)
- And Linux 4.14 is same. See the disscusion of https://www.coolapk.com/feed/42545715.

Signed-off-by: Calling <KeternalGithub@163.com>

Signed-off-by: Calling <KeternalGithub@163.com>
2023-01-22 12:23:39 +08:00
SlightlyLookAround
fe11fcd6c6 kernel: Migrate the reference of task_stack() (#102)
- task_stack() had been separated when it was in Linux 4.11, so let's do
  our migration when KernelSU facing the old version of kernel.
- See f3ac606719

Signed-off-by: Calling <KeternalGithub@163.com>

Signed-off-by: Calling <KeternalGithub@163.com>
2023-01-22 11:32:28 +08:00
Huy Minh
c27302136c Website : vi_VN : Capitalize "guide" in Vietnamese (#101) 2023-01-21 22:41:52 +08:00
Abhiram
fbbe2166e6 [skip ci] bump actions/upload-artifact to v3 (#99) 2023-01-21 20:35:28 +08:00
weishu
6e02cbde8a Add SELinux status (#98)
* manager: Get SELinux status and display it at home

Signed-off-by: xiaoleGun <1592501605@qq.com>
Co-authored-by: xiaoleGun <1592501605@qq.com>
2023-01-21 18:58:33 +08:00
Abhiram
aced1088f7 Update link to workflow page (#97) 2023-01-21 17:59:31 +08:00
Ylarod
ec41eec1a0 website: fix id_ID 2023-01-21 15:34:36 +08:00
Anggit Febriantoro
505b5ea767 website: add id_ID translation (#96)
* website: add id_ID translation

* website: fix leftover id_ID translation
2023-01-21 15:32:55 +08:00
Ylarod
08165211eb website: update vi_VN translation 2023-01-21 14:54:12 +08:00
Huy Minh
ec0158e2e8 website: add vi_VN translation (#91)
Signed-off-by: hmtheboy154 <buingoc67@gmail.com>

Signed-off-by: hmtheboy154 <buingoc67@gmail.com>
2023-01-21 06:37:36 +08:00
tiann
b7bed72c6d website: fix typo 2023-01-20 21:24:09 +08:00
tiann
553b26c1cb website: fix title 2023-01-20 21:10:26 +08:00
tiann
58dc00c17c website: fix faq 2023-01-20 21:05:43 +08:00
tiann
e79e4fa05e website: add faq 2023-01-20 21:02:55 +08:00
Ylarod
95ea1b2dfb website: bump vitepress to 1.0.0-alpha.40 2023-01-20 21:00:10 +08:00
Ylarod
a408a46168 website: add favicon 2023-01-20 18:49:39 +08:00
Ylarod
bc539569e1 website: add missing c 2023-01-20 18:42:28 +08:00
Ylarod
7a275e8e2a website: fixup 2023-01-20 18:40:47 +08:00
tiann
87fcfdf9e6 website: instruction for non gki build 2023-01-20 18:31:22 +08:00
tiann
664981628a website: Add instruction for non gki build 2023-01-20 18:28:15 +08:00
Ylarod
a255a5e3c1 website: add zh_CN translation (#88)
* website: bump vitepress to 1.0.0-alpha.38

* i18n: add zh-CN translation
2023-01-20 10:55:38 +08:00
weishu
c252492a42 kernel: add __init for init funcs 2023-01-19 16:38:53 +07:00
秋秋
b328fd96bc ci: fix WSA ccache (#85) 2023-01-19 17:36:31 +08:00
weishu
2844df865b kernel: use rename lsm hook 2023-01-19 16:34:21 +07:00
weishu
da377a9fa9 kernel: fix unused-variable 2023-01-19 13:54:42 +07:00
weishu
deac6163d6 kernel: 1. use prctl lsm hook; 2. refine sucompat hook 2023-01-19 13:31:55 +07:00
weishu
448fcc07e7 kernel: fix typo 2023-01-18 18:57:37 +07:00
weishu
830c27361e kernel: unify workqueue 2023-01-18 18:37:27 +07:00
Ylarod
5b2efd65b1 kernel: add null check (#84) 2023-01-18 17:05:40 +08:00
Ylarod
2724c6211a kernel: put original group_info (#82) 2023-01-18 07:59:26 +08:00
Ylarod
9a3451a8ae [skip ci] ci: don't save cache in pr (#81) 2023-01-17 22:40:31 +08:00
Ylarod
3d5effb678 kernel: fix panic in #79 (#80) 2023-01-17 21:51:19 +08:00
秋秋
965412377d ci: use ccache (#78) 2023-01-17 19:56:39 +08:00
Ylarod
d8009500a4 ci: fix error 2023-01-17 17:05:12 +08:00
Ylarod
7347ae2301 [skip ci] fix typo 2023-01-17 16:23:59 +08:00
Ylarod
babd6edbc2 [skip ci] check BOT_TOKEN before step run 2023-01-17 16:20:36 +08:00
weishu
2a1e91cb34 kernel: don't use 0(root uid) as manager init uid 2023-01-17 13:49:30 +07:00
weishu
ab36e1fa0c kernel: add uid observer, correctly prune uid allowlist when app is installed/uninstalled. 2023-01-17 12:44:38 +07:00
Ylarod
2ab60750d4 ci: update msg (#76) 2023-01-16 19:18:42 +08:00
Ylarod
b9dd673518 ci: add version to tg msg (#75) 2023-01-16 18:15:35 +08:00
weishu
bf3edfd0ef kernel: fix init_groups not exist int 5.15 2023-01-16 16:33:51 +07:00
weishu
710b933b08 kernel: fix am/pm error in app's su 2023-01-16 15:48:40 +07:00
weishu
ece66a3c38 kernel: setgroup to root for su 2023-01-16 15:43:14 +07:00
tiann
ebfa64cc08 ksud: support ext partition overlay 2023-01-16 16:06:39 +08:00
tiann
10000c098d ksud: e2fsck return 1 is ok 2023-01-16 16:06:39 +08:00
tiann
7c585905ac ksud: fix log 2023-01-16 16:06:39 +08:00
tiann
1ca06e1f1a manager: don't show manager in superuser 2023-01-16 16:06:39 +08:00
Ylarod
fb73a7f83e kernel: fix typo 2023-01-16 12:42:40 +08:00
Ylarod
2362a8d169 ci: build manager if ksud change 2023-01-16 12:34:48 +08:00
tiann
f98066cb99 ksud: support services. close #60 2023-01-16 12:22:47 +08:00
weishu
2222a999b9 kernel: version 9 2023-01-16 11:20:27 +07:00
weishu
00b1d7538d kernel: support ksud services 2023-01-16 11:19:59 +07:00
weishu
886c7d97a6 kernel: fix stack frame size exceeds 2023-01-16 10:21:10 +07:00
tiann
ae8a5d047b misc: remove tools dir 2023-01-15 20:12:28 +08:00
Scirese
4f99d865cb kernel: make kernel correctly response CMD_GRANT_ROOT (#73) 2023-01-15 20:11:21 +08:00
Ylarod
a30aab1da6 [skip ci] minor fixup (#72)
1. update README_CN.md
2. indent fixup
2023-01-15 17:05:08 +08:00
Huy Minh
bff4303dbb Add 4.14 to the supported kernel and declare supported ABIs (#71) 2023-01-15 15:45:10 +08:00
chen2021-web
2359b16526 backport to 4.14 (#59) 2023-01-15 15:34:15 +08:00
Ylarod
fb4b9d0173 [skip ci] ci: don't upload in pr (#70) 2023-01-15 14:46:34 +08:00
Ylarod
aafa24094c [skip ci] ci: setup mutex for uploading (#69) 2023-01-15 12:44:56 +08:00
Ylarod
c3f462d260 [skip ci] kernel: allow override EXPECTED_* by env (#67)
The original one can only override by `make EXPECTED_SIZE=123 EXPECTED_HASH=123`
2023-01-15 08:29:29 +08:00
tiann
97de71d09e website: Add gitignore 2023-01-14 23:20:37 +08:00
weishu
5a8acea84e Add website (#65) 2023-01-14 23:18:11 +08:00
Scirese
8274f6a1ff userspace/su: implement basic features (#62) 2023-01-14 22:42:45 +08:00
Scirese
0b86cd69fc [skip ci] kernel: allow root processes to get version (#63) 2023-01-14 21:52:57 +08:00
Ylarod
5e77d1cd5b kernel: add CONFIG_KSU_DEBUG (#19)
* Kconfig: add KSU_DEBUG

* print alert on debug mode

* allow shell by default

* store signature to var on debug mode

* format

* export as module_param

* rename apk_sign to kernelsu
2023-01-14 21:45:34 +08:00
Ylarod
50f44fff9e kernel: export customized symbols (#58) 2023-01-14 10:43:16 +08:00
longhuan1999
21b0d6ceaf Update build-WSA-5.10.117-kernel.yml (#56) 2023-01-13 21:20:05 +08:00
Ylarod
6e483a025d ci: fix typo (#57) 2023-01-13 21:09:37 +08:00
Ylarod
a748bed807 ci: opt manager (#55)
* ci: opt manager

* lint: don't check release build
2023-01-13 21:06:55 +08:00
Ylarod
177d6dba15 kernel: add prefix for functions in sepolicy (#49)
* kernel: add prefix for functions in sepolicy

* ci: fix 5.15 compile error
2023-01-13 20:05:52 +08:00
Ylarod
dd905a1852 ci: speed up build-ksud again (#54) 2023-01-13 19:50:42 +08:00
Ylarod
5bad1d0b53 ci: speed up build-ksud (#53) 2023-01-13 18:47:31 +08:00
韵の祈
3577b91a3c manager: Optimize ModuleScreen UI (#51)
* manager: fix moduleList is empty cannot parse to jsonArray

* manager: Optimize ModuleScreen UI

* manager: Optimize switch position
2023-01-13 17:48:36 +08:00
huangsijun17
ece1cbe48e Update README_CN.md (#50)
修正标点核错别字。
2023-01-13 13:59:26 +08:00
longhuan1999
f75ca3a4f1 kernel: Change CI build for WSA-5.10.117 (#48) 2023-01-12 21:32:17 +08:00
秋秋
e173081cae kernel: We don't like dirty (#46) 2023-01-12 17:19:54 +08:00
セリカ・シルフィル
954e06bbcc Make setup script support non-GKI kernel (#47) 2023-01-12 17:09:55 +08:00
セリカ・シルフィル
bf87b134de Fix error for some non-GKI kernel source code (#45)
Idea from @Dreamail
2023-01-12 15:11:51 +08:00
Ylarod
acd6f44c7e ci: update message hint (#44) 2023-01-12 09:21:01 +08:00
Ylarod
e37d97c7c7 ci: push to telegram (#43)
* ci: push to telegram

* support topic

* check BOT_TOKEN in build-su

* update script
2023-01-11 22:47:31 +08:00
Ylarod
4f9feeff19 ci: fix su (#42) 2023-01-11 20:21:53 +08:00
longhuan1999
761f68b24f kernel: Add CI build for WSA-android12-5.10.117 (#41) 2023-01-11 14:32:51 +08:00
Scirese
d9f656031d Readme: Add disclaimer and Chinese README (#40) 2023-01-11 08:12:02 +08:00
Ylarod
848712e417 kernel: fix warning (#37) 2023-01-11 05:22:58 +08:00
weishu
0e0a812a9c kernel: backport to 4.19 (#36) 2023-01-10 23:20:32 +08:00
Ylarod
26f80b7107 kernel: improve include (#35) 2023-01-10 19:44:43 +08:00
weishu
a2ec618c49 kernel: fix typo for PT_PARAM_REG 2023-01-09 07:24:23 +07:00
weishu
43bea50605 kernel: fix syscall_work version 2023-01-07 20:11:33 +07:00
weishu
94d0d5ac6b kernel: syscall_work is introduced above 5.10 2023-01-07 20:07:16 +07:00
tiann
7c3a78b83f ksud: Only use resetprop, remove magisk binary 2023-01-07 19:40:15 +08:00
YuKongA
0c6de7a1ed kernel: CI build for 5.15.y (#30) 2023-01-07 16:39:19 +08:00
weishu
36aff66835 kernel: add PT_REGS_PARAM6 2023-01-06 21:51:09 +07:00
tiann
63ebec2f76 ci: we need full history to generate app version code 2023-01-06 16:43:07 +08:00
weishu
d9542d6a9c Fix ci for manager (#28) 2023-01-06 16:18:17 +08:00
tiann
09d9e4aa02 manager: Add versionCode to avoid downgrade 2023-01-06 14:16:57 +08:00
tiann
7140f04243 manager: Add git commit to version 2023-01-06 14:09:50 +08:00
tiann
76ff69dedb ksud: trim command output 2023-01-06 13:10:27 +08:00
tiann
1c4e51aec5 ksud: support post-fs-data.sh run as daemon.
1. We should make the `post-fs-data.sh` use itself a process group, otherwise it will receive signal from other process and make it exit accidentally.
2. And we should also switch child process' cgroup out of parent process, otherwise it would be kill by cgroup.
2023-01-06 12:59:21 +08:00
残页
7942f4c495 ksud: use the same variable type in scripts (#26)
When executing module install scripts, KSU is set to "true"; when executing module post-fs-data scripts, KSU is set to "1". This may cause confusions so use the same value instead.
2023-01-06 11:49:13 +08:00
tiann
bc9daf1583 ksud: block stderr of installer script 2023-01-05 18:47:05 +08:00
Huy Minh
89288a0c59 Kconfig : Make KSU depends on OVERLAY_FS (#25)
As KernelSU now support modules and mounting system as R/W using overlayfs, it's time to require overlayfs when trying to compile it.
2023-01-05 17:48:22 +08:00
tiann
ea3cfbd0ca ksud: fix selinux unlabeled of modules dir 2023-01-05 16:58:00 +08:00
tiann
06cc677278 manager: allow absent versionCode, version, author for module prop 2023-01-05 15:27:33 +08:00
168 changed files with 11407 additions and 1491 deletions

33
.github/ISSUE_TEMPLATE/add_device.yml vendored Normal file
View File

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

32
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,32 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

10
.github/ISSUE_TEMPLATE/custom.md vendored Normal file
View File

@@ -0,0 +1,10 @@
---
name: Custom issue template
about: Describe this issue template's purpose here.
title: ''
labels: ''
assignees: ''
---

View File

@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -0,0 +1,48 @@
From f1e398602b989ac197cdd0fda4a7c4c323b03eb9 Mon Sep 17 00:00:00 2001
From: DozNaka <dozdguide@gmail.com>
Date: Mon, 11 Apr 2022 20:43:45 -0400
Subject: [PATCH] Makefile: Use CCACHE for faster compilation
---
Makefile | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/Makefile b/Makefile
index e8b8d5894..51e8aac6e 100644
--- a/Makefile
+++ b/Makefile
@@ -442,21 +442,21 @@ KBUILD_HOSTLDLIBS := $(HOST_LFS_LIBS) $(HOSTLDLIBS)
# Make variables (CC, etc...)
CPP = $(CC) -E
ifneq ($(LLVM),)
-CC = clang
-LD = ld.lld
-AR = llvm-ar
+CC = $(CCACHE) clang
+LD = $(CCACHE) ld.lld
+AR = $(CCACHE) llvm-ar
NM = llvm-nm
-OBJCOPY = llvm-objcopy
-OBJDUMP = llvm-objdump
+OBJCOPY = $(CCACHE) llvm-objcopy
+OBJDUMP = $(CCACHE) llvm-objdump
READELF = llvm-readelf
STRIP = llvm-strip
else
-CC = $(CROSS_COMPILE)gcc
-LD = $(CROSS_COMPILE)ld
-AR = $(CROSS_COMPILE)ar
+CC = $(CCACHE) $(CROSS_COMPILE)gcc
+LD = $(CCACHE) $(CROSS_COMPILE)ld
+AR = $(CCACHE) $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
-OBJCOPY = $(CROSS_COMPILE)objcopy
-OBJDUMP = $(CROSS_COMPILE)objdump
+OBJCOPY = $(CCACHE) $(CROSS_COMPILE)objcopy
+OBJDUMP = $(CCACHE) $(CROSS_COMPILE)objdump
READELF = $(CROSS_COMPILE)readelf
STRIP = $(CROSS_COMPILE)strip
endif
--
2.37.2

View File

@@ -0,0 +1,43 @@
From dbdd2906c0b3a967ca28c6b870b46f905c170661 Mon Sep 17 00:00:00 2001
From: Park Ju Hyung <qkrwngud825@gmail.com>
Date: Wed, 13 Mar 2019 13:36:37 +0900
Subject: [PATCH] setlocalversion: don't check for uncommitted changes
I ofter push after the build is done and I hate seeing "-dirty"
Signed-off-by: Park Ju Hyung <qkrwngud825@gmail.com>
Signed-off-by: Danny Lin <danny@kdrag0n.dev>
Signed-off-by: Divyanshu-Modi <divyan.m05@gmail.com>
Change-Id: I240c516520879da680794fd144b1f273f9e21e13
Signed-off-by: Divyanshu-Modi <divyan.m05@gmail.com>
---
scripts/setlocalversion | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/scripts/setlocalversion b/scripts/setlocalversion
index 842936656b84..ef27a273ebf5 100755
--- a/scripts/setlocalversion
+++ b/scripts/setlocalversion
@@ -107,19 +107,6 @@ scm_version()
printf -- '-svn%s' "$(git svn find-rev $head)"
fi
- # Check for uncommitted changes.
- # First, with git-status, but --no-optional-locks is only
- # supported in git >= 2.14, so fall back to git-diff-index if
- # it fails. Note that git-diff-index does not refresh the
- # index, so it may give misleading results. See
- # git-update-index(1), git-diff-index(1), and git-status(1).
- if {
- git --no-optional-locks status -uno --porcelain 2>/dev/null ||
- git diff-index --name-only HEAD
- } | grep -qvE '^(.. )?scripts/package'; then
- printf '%s' -dirty
- fi
-
# All done with git
return
fi
--
2.37.2

View File

@@ -0,0 +1,48 @@
From f1e398602b989ac197cdd0fda4a7c4c323b03eb9 Mon Sep 17 00:00:00 2001
From: DozNaka <dozdguide@gmail.com>
Date: Mon, 11 Apr 2022 20:43:45 -0400
Subject: [PATCH] Makefile: Use CCACHE for faster compilation
---
Makefile | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/Makefile b/Makefile
index e8b8d5894..51e8aac6e 100644
--- a/Makefile
+++ b/Makefile
@@ -442,21 +442,21 @@ KBUILD_HOSTLDLIBS := $(HOST_LFS_LIBS) $(HOSTLDLIBS)
# Make variables (CC, etc...)
CPP = $(CC) -E
ifneq ($(LLVM),)
-CC = clang
-LD = ld.lld
-AR = llvm-ar
+CC = $(CCACHE) clang
+LD = $(CCACHE) ld.lld
+AR = $(CCACHE) llvm-ar
NM = llvm-nm
-OBJCOPY = llvm-objcopy
-OBJDUMP = llvm-objdump
+OBJCOPY = $(CCACHE) llvm-objcopy
+OBJDUMP = $(CCACHE) llvm-objdump
READELF = llvm-readelf
STRIP = llvm-strip
else
-CC = $(CROSS_COMPILE)gcc
-LD = $(CROSS_COMPILE)ld
-AR = $(CROSS_COMPILE)ar
+CC = $(CCACHE) $(CROSS_COMPILE)gcc
+LD = $(CCACHE) $(CROSS_COMPILE)ld
+AR = $(CCACHE) $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
-OBJCOPY = $(CROSS_COMPILE)objcopy
-OBJDUMP = $(CROSS_COMPILE)objdump
+OBJCOPY = $(CCACHE) $(CROSS_COMPILE)objcopy
+OBJDUMP = $(CCACHE) $(CROSS_COMPILE)objdump
READELF = $(CROSS_COMPILE)readelf
STRIP = $(CROSS_COMPILE)strip
endif
--
2.37.2

View File

@@ -0,0 +1,46 @@
From bbb9e7fb1ccadac47b58ba615e6874ddeaa9e628 Mon Sep 17 00:00:00 2001
From: Park Ju Hyung <qkrwngud825@gmail.com>
Date: Wed, 13 Mar 2019 13:36:37 +0900
Subject: [PATCH] setlocalversion: don't check for uncommitted changes
I ofter push after the build is done and I hate seeing "-dirty"
Signed-off-by: Park Ju Hyung <qkrwngud825@gmail.com>
Signed-off-by: Danny Lin <danny@kdrag0n.dev>
Signed-off-by: Divyanshu-Modi <divyan.m05@gmail.com>
Change-Id: I240c516520879da680794fd144b1f273f9e21e13
Signed-off-by: Divyanshu-Modi <divyan.m05@gmail.com>
---
scripts/setlocalversion | 16 ----------------
1 file changed, 16 deletions(-)
diff --git a/scripts/setlocalversion b/scripts/setlocalversion
index 1b733ae4c..2a3ea7684 100755
--- a/scripts/setlocalversion
+++ b/scripts/setlocalversion
@@ -90,22 +90,6 @@ scm_version()
printf '%s%s' -g "$(echo $head | cut -c1-12)"
fi
- # Check for uncommitted changes.
- # This script must avoid any write attempt to the source tree,
- # which might be read-only.
- # You cannot use 'git describe --dirty' because it tries to
- # create .git/index.lock .
- # First, with git-status, but --no-optional-locks is only
- # supported in git >= 2.14, so fall back to git-diff-index if
- # it fails. Note that git-diff-index does not refresh the
- # index, so it may give misleading results. See
- # git-update-index(1), git-diff-index(1), and git-status(1).
- if {
- git --no-optional-locks status -uno --porcelain 2>/dev/null ||
- git diff-index --name-only HEAD
- } | read dummy; then
- printf '%s' -dirty
- fi
fi
}
--
2.37.2

56
.github/scripts/build_a12.sh vendored Normal file
View File

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

43
.github/scripts/build_a13.sh vendored Normal file
View File

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

59
.github/workflows/add-device.yml vendored Normal file
View File

@@ -0,0 +1,59 @@
name: handle-add-device-issue
on:
issues:
types: [labeled]
jobs:
handle-add-device:
if: github.event.label.name == 'add-device'
runs-on: ubuntu-latest
env:
ISSUE_CONTENT: ${{ github.event.issue.body }}
steps:
- uses: actions/checkout@v3
- name: Parse issue body
id: handle-add-device
run: |
python3 scripts/add_device_handler.py website/docs/repos.json || true
- name: Commit
if: steps.handle-add-device.outputs.success == 'true'
run: |
git config --local user.name "GitHub Actions"
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add website/docs/repos.json
git commit -m "add device: ${{ steps.handle-add-device.outputs.device }}"
- name: Make pull request
if: steps.handle-add-device.outputs.success == 'true'
id: cpr
uses: peter-evans/create-pull-request@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: "[add device]: ${{ steps.handle-add-device.outputs.device }}"
title: "[add device]: ${{ steps.handle-add-device.outputs.device }}"
body: |
${{ steps.handle-add-device.outputs.device }} has been added to the website.
Related issue: ${{ github.event.issue.html_url }}
branch: "add-device-${{ github.event.issue.number }}"
labels: add-device
delete-branch: true
- name: Check outputs
if: ${{ steps.cpr.outputs.pull-request-number }}
run: |
echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}"
- uses: ben-z/actions-comment-on-issue@1.0.2
if: ${{ steps.cpr.outputs.pull-request-number }}
with:
message: "Automatically created pull request: ${{ steps.cpr.outputs.pull-request-url }}"
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: ben-z/actions-comment-on-issue@1.0.2
if: steps.handle-add-device.outputs.success != 'true'
with:
message: "Cannot create pull request. Please check the issue content. Or you can create a pull request manually."
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: close issue
uses: peter-evans/close-issue@v1
with:
issue-number: ${{ github.event.issue.number }}
token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -0,0 +1,99 @@
name: Build WSA-5.10.117-Kernel
on:
push:
branches: [ "main" ]
paths:
- '.github/workflows/build-WSA-5.10.117-kernel.yml'
- 'kernel/**'
pull_request:
branches: [ "main" ]
paths:
- 'kernel/**'
workflow_call:
jobs:
build:
strategy:
matrix:
include:
- version: 5.10.117.2
arch: "x86_64"
out_file: "arch/x86/boot/bzImage"
kernel_make_cmd: "bzImage"
make_config: "config-wsa"
date: "20220906"
- version: 5.10.117.2
arch: "arm64"
out_file: "arch/arm64/boot/Image"
kernel_make_cmd: "ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu Image"
make_config: "config-wsa-arm64"
date: "20220906"
name: Build WSA-Kernel-${{ matrix.version }}-${{ matrix.arch }}
runs-on: ubuntu-18.04
env:
CCACHE_COMPILERCHECK: "%compiler% -dumpmachine; %compiler% -dumpversion"
CCACHE_NOHASHDIR: "true"
CCACHE_MAXSIZE: "2G"
CCACHE_HARDLINK: "true"
steps:
- uses: hendrikmuhs/ccache-action@v1.2
with:
key: ccache-WSA-Kernel-${{ matrix.version }}-${{ matrix.arch }}
append-timestamp: false
save: ${{ github.event_name != 'pull_request' }}
- uses: actions/checkout@v3
with:
path: KernelSU
- name: Install LLVM
run: |
sudo apt install -y --no-install-recommends bc bison build-essential ca-certificates flex git gnupg libelf-dev libssl-dev lsb-release software-properties-common wget libncurses-dev binutils-aarch64-linux-gnu gcc-aarch64-linux-gnu nuget
export LLVM_VERSION=10
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh $LLVM_VERSION
rm ./llvm.sh
sudo ln -s --force /usr/bin/clang-$LLVM_VERSION /usr/bin/clang
sudo ln -s --force /usr/bin/ld.lld-$LLVM_VERSION /usr/bin/ld.lld
sudo ln -s --force /usr/bin/llvm-objdump-$LLVM_VERSION /usr/bin/llvm-objdump
sudo ln -s --force /usr/bin/llvm-ar-$LLVM_VERSION /usr/bin/llvm-ar
sudo ln -s --force /usr/bin/llvm-nm-$LLVM_VERSION /usr/bin/llvm-nm
sudo ln -s --force /usr/bin/llvm-strip-$LLVM_VERSION /usr/bin/llvm-strip
sudo ln -s --force /usr/bin/llvm-objcopy-$LLVM_VERSION /usr/bin/llvm-objcopy
sudo ln -s --force /usr/bin/llvm-readelf-$LLVM_VERSION /usr/bin/llvm-readelf
sudo ln -s --force /usr/bin/clang++-$LLVM_VERSION /usr/bin/clang++
- name: Download kernel source
run: |
cd $GITHUB_WORKSPACE
KERNEL_ROOT=$GITHUB_WORKSPACE/WSA-Linux-Kernel
echo "[+] 克隆远程仓库 WSA-Linux-Kernel..."
git clone https://github.com/microsoft/WSA-Linux-Kernel
cd WSA-Linux-Kernel && git checkout android-lts/latte/${{ matrix.version }}
echo "[+] 切换到分支 android-lts/latte/${{ matrix.version }}"
echo "[+] 导入 KernelSU"
echo "[+] KERNEL_ROOT: $KERNEL_ROOT"
echo "[+] 复制 kernel su driver 到路径:$KERNEL_ROOT/drivers"
ln -sf $GITHUB_WORKSPACE/KernelSU/kernel $KERNEL_ROOT/drivers/kernelsu
DRIVER_MAKEFILE=$KERNEL_ROOT/drivers/Makefile
echo "[+] 添加 kernel su driver 到文件:$DRIVER_MAKEFILE"
grep -q "kernelsu" $DRIVER_MAKEFILE || echo "obj-y += kernelsu/" >> $DRIVER_MAKEFILE
echo "[+] KernelSU 导入完成"
cd $KERNEL_ROOT && git apply $GITHUB_WORKSPACE/KernelSU/.github/patches/5.10/*.patch
cd -
- name: Build Kernel
working-directory: WSA-Linux-Kernel
run: |
KERNEL_ROOT=$GITHUB_WORKSPACE/WSA-Linux-Kernel
echo "[+] 构建 kernel"
cp configs/wsa/${{ matrix.make_config }}-5.10 $KERNEL_ROOT/.config
echo "[+] 复制配置文件 configs/wsa/${{ matrix.make_config }}-5.10 到 $KERNEL_ROOT/.config"
echo "执行: make -j`nproc` LLVM=1 ${{ matrix.kernel_make_cmd }}"
make -j`nproc` LLVM=1 ${{ matrix.kernel_make_cmd }} CCACHE="/usr/bin/ccache"
- name: Upload kernel-${{ matrix.arch }}-${{ matrix.version }}
uses: actions/upload-artifact@v3
with:
name: kernel-WSA-${{ matrix.arch }}-${{ matrix.version }}-${{ matrix.date }}
path: WSA-Linux-Kernel/${{ matrix.out_file }}

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

@@ -0,0 +1,117 @@
name: Build Kernel - Android 12
on:
push:
branches: ["main", "ci"]
paths:
- ".github/workflows/build-kernel-a12.yml"
- ".github/workflows/gki-kernel.yml"
- ".github/scripts/build_a12.sh"
- "kernel/**"
pull_request:
branches: ["main"]
paths:
- ".github/workflows/build-kernel-a12.yml"
- ".github/workflows/gki-kernel.yml"
- ".github/scripts/build-a12.sh"
- "kernel/**"
workflow_call:
jobs:
build-kernel:
if: github.event_name != 'pull_request'
strategy:
matrix:
include:
- sub_level: 66
os_patch_level: 2021-11
- sub_level: 81
os_patch_level: 2022-03
- sub_level: 101
os_patch_level: 2022-05
- sub_level: 110
os_patch_level: 2022-07
- sub_level: 136
os_patch_level: 2022-11
uses: ./.github/workflows/gki-kernel.yml
secrets: inherit
with:
version: android12-5.10
version_name: android12-5.10.${{ matrix.sub_level }}
tag: android12-5.10-${{ matrix.os_patch_level }}
os_patch_level: ${{ matrix.os_patch_level }}
patch_path: "5.10"
upload-artifacts:
needs: build-kernel
runs-on: ubuntu-latest
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' || github.ref == 'refs/heads/ci' }}
env:
CHAT_ID: ${{ secrets.CHAT_ID }}
CACHE_CHAT_ID: ${{ secrets.CACHE_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@v3
- uses: actions/checkout@v3
with:
path: KernelSU
fetch-depth: 0
- name: List artifacts
run: |
tree
- name: Download prebuilt toolchain
run: |
AOSP_MIRROR=https://android.googlesource.com
BRANCH=master-kernel-build-2022
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 python-telegram-bot
- 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: Setup mutex for uploading
uses: ben-z/gh-action-mutex@v1.0-alpha-7
- 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@v3
with:
name: boot-images-android12
path: Image-android12*/*.img.gz
check-build-kernel:
if: github.event_name == 'pull_request'
uses: ./.github/workflows/gki-kernel.yml
with:
version: android12-5.10
version_name: android12-5.10.101
tag: android12-5.10-2022-05
os_patch_level: 2022-05
patch_path: "5.10"

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

@@ -0,0 +1,126 @@
name: Build Kernel - Android 13
on:
push:
branches: ["main", "ci"]
paths:
- ".github/workflows/build-kernel-a13.yml"
- ".github/workflows/gki-kernel.yml"
- ".github/scripts/build_a13.sh"
- "kernel/**"
pull_request:
branches: ["main"]
paths:
- ".github/workflows/build-kernel-a13.yml"
- ".github/workflows/gki-kernel.yml"
- ".github/scripts/build-a13.sh"
- "kernel/**"
workflow_call:
jobs:
build-kernel:
if: github.event_name != 'pull_request'
strategy:
matrix:
include:
- version: "5.10"
sub_level: 107
os_patch_level: 2022-11
- version: "5.10"
sub_level: 149
os_patch_level: 2023-01
- version: "5.15"
sub_level: 41
os_patch_level: 2022-11
- version: "5.15"
sub_level: 74
os_patch_level: 2022-12
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 }}
patch_path: ${{ matrix.version }}
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 }}
CACHE_CHAT_ID: ${{ secrets.CACHE_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@v3
- uses: actions/checkout@v3
with:
path: KernelSU
fetch-depth: 0
- name: List artifacts
run: |
tree
- name: Download prebuilt toolchain
run: |
AOSP_MIRROR=https://android.googlesource.com
BRANCH=master-kernel-build-2022
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 python-telegram-bot
- 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: Setup mutex for uploading
uses: ben-z/gh-action-mutex@v1.0-alpha-7
- 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@v3
with:
name: boot-images-android13
path: Image-android13*/*.img.gz
check-build-kernel:
if: github.event_name == 'pull_request'
strategy:
matrix:
include:
- version: "5.10"
sub_level: 107
os_patch_level: 2022-11
- version: "5.15"
sub_level: 41
os_patch_level: 2022-11
uses: ./.github/workflows/gki-kernel.yml
with:
version: android13-${{ matrix.version }}
version_name: android13-${{ matrix.version }}.${{ matrix.sub_level }}
tag: android13-${{ matrix.version }}-${{ matrix.os_patch_level }}
patch_path: ${{ matrix.version }}

View File

@@ -1,103 +0,0 @@
name: Build Kernel
on:
push:
branches: [ "main" ]
paths:
- '.github/workflows/build-kernel.yml'
- 'kernel/**'
pull_request:
branches: [ "main" ]
paths:
- 'kernel/**'
jobs:
build:
strategy:
matrix:
include:
- version: android12-5.10-66
tag: android12-5.10-2021-11
os_version: 12.0.0
os_patch_level: 2021-11
- version: android12-5.10-81
tag: android12-5.10-2022-03
os_version: 12.0.0
os_patch_level: 2022-03
- version: android12-5.10-101
tag: android12-5.10-2022-05
os_version: 12.0.0
os_patch_level: 2022-05
- version: android12-5.10-110
tag: android12-5.10-2022-07
os_version: 12.0.0
os_patch_level: 2022-07
- version: android12-5.10-136
tag: android12-5.10-2022-11
os_version: 12.0.0
os_patch_level: 2022-11
name: Build aarch64-${{ matrix.version }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
path: KernelSU
- name: Download kernel source
run: |
cd $GITHUB_WORKSPACE
git clone https://gerrit.googlesource.com/git-repo
mkdir android-kernel && cd android-kernel
../git-repo/repo init -u https://android.googlesource.com/kernel/manifest -b common-${{ matrix.tag }}
../git-repo/repo sync
echo "[+] KernelSU setup"
GKI_ROOT=$(pwd)
echo "[+] GKI_ROOT: $GKI_ROOT"
echo "[+] Copy kernel su driver to $GKI_ROOT/common/drivers"
ln -sf $GITHUB_WORKSPACE/KernelSU/kernel $GKI_ROOT/common/drivers/kernelsu
echo "[+] Add kernel su driver to Makefile"
DRIVER_MAKEFILE=$GKI_ROOT/common/drivers/Makefile
grep -q "kernelsu" $DRIVER_MAKEFILE || echo "obj-y += kernelsu/" >> $DRIVER_MAKEFILE
echo "[+] KernelSU setup Done."
curl -Lo gki-kernel.zip https://dl.google.com/android/gki/gki-certified-boot-${{ matrix.tag }}_r1.zip
unzip gki-kernel.zip
tools/mkbootimg/unpack_bootimg.py --boot_img=$(find . -maxdepth 1 -name "*.img")
- name: Build boot.img
working-directory: android-kernel
run: BUILD_BOOT_IMG=1 SKIP_VENDOR_BOOT=1 KERNEL_BINARY=Image GKI_RAMDISK_PREBUILT_BINARY=out/ramdisk AVB_SIGN_BOOT_IMG=1 AVB_BOOT_PARTITION_SIZE=$((64*1024*1024)) AVB_BOOT_ALGORITHM=SHA256_RSA2048 AVB_BOOT_KEY=prebuilts/kernel-build-tools/linux-x86/share/avb/testkey_rsa2048.pem BOOT_IMAGE_HEADER_VERSION=4 LTO=thin BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh
- name: Build boot-lz4.img
working-directory: android-kernel
run: |
tools/mkbootimg/mkbootimg.py --header_version 4 --kernel ./out/android12-5.10/dist/Image.lz4 --ramdisk out/ramdisk --output ./out/android12-5.10/dist/boot-lz4.img --os_version ${{ matrix.os_version }} --os_patch_level ${{ matrix.os_patch_level }}
./build/build-tools/path/linux-x86/avbtool add_hash_footer --partition_name boot --partition_size $((64*1024*1024)) --image out/android12-5.10/dist/boot-lz4.img --algorithm SHA256_RSA2048 --key ./prebuilts/kernel-build-tools/linux-x86/share/avb/testkey_rsa2048.pem
- name: Build boot-gz.img
working-directory: android-kernel
run: |
cat out/android12-5.10/dist/Image | ./prebuilts/build-tools/path/linux-x86/gzip -n -f -9 > out/android12-5.10/dist/Image.gz
tools/mkbootimg/mkbootimg.py --header_version 4 --kernel ./out/android12-5.10/dist/Image.gz --ramdisk out/ramdisk --output ./out/android12-5.10/dist/boot-gz.img --os_version ${{ matrix.os_version }} --os_patch_level ${{ matrix.os_patch_level }}
./build/build-tools/path/linux-x86/avbtool add_hash_footer --partition_name boot --partition_size $((64*1024*1024)) --image out/android12-5.10/dist/boot-gz.img --algorithm SHA256_RSA2048 --key ./prebuilts/kernel-build-tools/linux-x86/share/avb/testkey_rsa2048.pem
- name: Upload Image.gz
uses: actions/upload-artifact@v3
with:
name: kernel-aarch64-${{ matrix.version }}-Image.gz
path: android-kernel/out/*/dist/Image.gz
- name: Upload boot.img
uses: actions/upload-artifact@v3
with:
name: kernel-aarch64-${{ matrix.version }}-boot.img
path: android-kernel/out/*/dist/boot.img
- name: Upload boot-lz4.img
uses: actions/upload-artifact@v3
with:
name: kernel-aarch64-${{ matrix.version }}-boot-lz4.img
path: android-kernel/out/*/dist/boot-lz4.img
- name: Upload boot-gz.img
uses: actions/upload-artifact@v3
with:
name: kernel-aarch64-${{ matrix.version }}-boot-gz.img
path: android-kernel/out/*/dist/boot-gz.img

25
.github/workflows/build-ksud.yml vendored Normal file
View File

@@ -0,0 +1,25 @@
name: Build KSUD
on:
push:
branches: [ "main", "ci" ]
paths:
- '.github/workflows/build-ksud.yml'
- '.github/workflows/ksud.yml'
- 'userspace/ksud/**'
pull_request:
branches: [ "main" ]
paths:
- '.github/workflows/build-ksud.yml'
- '.github/workflows/ksud.yml'
- 'userspace/ksud/**'
jobs:
build:
strategy:
matrix:
include:
- target: aarch64-linux-android
- target: x86_64-linux-android
- target: x86_64-pc-windows-gnu # only for build
uses: ./.github/workflows/ksud.yml
with:
target: ${{ matrix.target }}

View File

@@ -5,24 +5,50 @@ on:
paths:
- '.github/workflows/build-manager.yml'
- 'manager/**'
- 'userspace/ksud/**'
pull_request:
branches: [ "main" ]
paths:
- 'manager/**'
workflow_call:
jobs:
build:
build-ksud:
strategy:
matrix:
include:
- target: aarch64-linux-android
- target: x86_64-linux-android
uses: ./.github/workflows/ksud.yml
with:
target: ${{ matrix.target }}
build-manager:
needs: build-ksud
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./manager
steps:
- uses: actions/checkout@v3
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: set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
cache: gradle
- uses: nttld/setup-ndk@v1
with:
ndk-version: r25b
local-cache: true
- name: Extract keystore
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' }}
run: |
@@ -33,13 +59,49 @@ jobs:
echo KEYSTORE_FILE='../key.jks' >> sign.properties
echo ${{ secrets.KEYSTORE }} | base64 --decode > key.jks
fi
- name: Download arm64 ksud
uses: actions/download-artifact@v3
with:
name: ksud-aarch64-linux-android
path: .
- name: Download x86_64 ksud
uses: actions/download-artifact@v3
with:
name: ksud-x86_64-linux-android
path: .
- name: Copy ksud to app jniLibs
run: |
mkdir -p app/src/main/jniLibs/arm64-v8a
mkdir -p app/src/main/jniLibs/x86_64
cp -f ../aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud.so
cp -f ../x86_64-linux-android/release/ksud ../manager/app/src/main/jniLibs/x86_64/libksud.so
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew build
run: ./gradlew clean assembleRelease
- name: Upload build artifact
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: manager
path: manager/app/build/outputs/apk/release/*.apk
- name: Setup mutex for uploading
uses: ben-z/gh-action-mutex@v1.0-alpha-7
if: github.event_name != 'pull_request' && steps.need_upload.outputs.UPLOAD == 'true'
- name: Upload to telegram
if: github.event_name != 'pull_request' && steps.need_upload.outputs.UPLOAD == 'true'
env:
CHAT_ID: ${{ secrets.CHAT_ID }}
CACHE_CHAT_ID: ${{ secrets.CACHE_CHAT_ID }}
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
MESSAGE_THREAD_ID: ${{ secrets.MESSAGE_THREAD_ID }}
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
COMMIT_URL: ${{ github.event.head_commit.url }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
TITLE: Manager
run: |
if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then
export VERSION=$(git rev-list --count HEAD)
APK=$(find ./app/build/outputs/apk/release -name "*.apk")
pip3 install python-telegram-bot
python3 $GITHUB_WORKSPACE/scripts/ksubot.py $APK
fi

62
.github/workflows/build-su.yml vendored Normal file
View File

@@ -0,0 +1,62 @@
name: Build SU
on:
push:
branches: [ "main" ]
paths:
- '.github/workflows/build-su.yml'
- 'userspace/**'
- 'scripts/ksubot.py'
pull_request:
branches: [ "main" ]
paths:
- 'userspace/**'
jobs:
build-su:
name: Build userspace su
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
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
- uses: nttld/setup-ndk@v1
with:
ndk-version: r25b
local-cache: true
- name: Build su
working-directory: ./userspace/su
run: ndk-build
- name: Upload a Build Artifact
uses: actions/upload-artifact@v3
with:
name: su
path: ./userspace/su/libs
- name: Setup mutex for uploading
uses: ben-z/gh-action-mutex@v1.0-alpha-7
if: github.event_name != 'pull_request' && steps.need_upload.outputs.UPLOAD == 'true'
- name: Upload to telegram
if: github.event_name != 'pull_request' && steps.need_upload.outputs.UPLOAD == 'true'
env:
CHAT_ID: ${{ secrets.CHAT_ID }}
CACHE_CHAT_ID: ${{ secrets.CACHE_CHAT_ID }}
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
MESSAGE_THREAD_ID: ${{ secrets.MESSAGE_THREAD_ID }}
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
COMMIT_URL: ${{ github.event.head_commit.url }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
TITLE: SU
run: |
if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then
export VERSION=$(git rev-list --count HEAD)
pip3 install python-telegram-bot
mv ./userspace/su/libs/arm64-v8a/su su-arm64
mv ./userspace/su/libs/x86_64/su su-x86_64
python3 scripts/ksubot.py su-arm64 su-x86_64
fi

View File

@@ -1,29 +0,0 @@
name: Build Userspace
on:
push:
branches: [ "main" ]
paths:
- '.github/workflows/build-userspace.yml'
- 'userspace/**'
pull_request:
branches: [ "main" ]
paths:
- 'userspace/**'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: nttld/setup-ndk@v1
with:
ndk-version: r25b
local-cache: true
- name: Build with NDK
working-directory: ./userspace
run: ndk-build
- name: Upload a Build Artifact
uses: actions/upload-artifact@v3
with:
name: su
path: ./userspace/libs

22
.github/workflows/clippy-pr.yml vendored Normal file
View File

@@ -0,0 +1,22 @@
name: Clippy check for pull request
on:
pull_request:
branches:
- 'main'
paths:
- '.github/workflows/clippy-pr.yml'
- 'userspace/ksud/**'
permissions:
checks: write
jobs:
clippy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: giraffate/clippy-action@v1
with:
workdir: userspace/ksud

30
.github/workflows/clippy.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
name: Clippy check
on:
push:
branches:
- 'main'
paths:
- '.github/workflows/clippy.yml'
- 'userspace/ksud/**'
env:
RUSTFLAGS: '-Dwarnings'
jobs:
clippy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: Swatinem/rust-cache@v2
with:
workspaces: userspace/ksud
- name: Install cross
run: cargo install cross
- name: Run clippy
run: |
cross clippy --manifest-path userspace/ksud/Cargo.toml --target aarch64-linux-android
cross clippy --manifest-path userspace/ksud/Cargo.toml --target x86_64-linux-android

37
.github/workflows/deploy-website.yml vendored Normal file
View File

@@ -0,0 +1,37 @@
name: Deploy Website
on:
push:
branches:
- main
- website
paths:
- '.github/workflows/deploy-website.yml'
- 'website/**'
jobs:
deploy:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./website
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-node@v3
with:
node-version: 16
cache: yarn
cache-dependency-path: website/yarn.lock
- run: yarn install --frozen-lockfile
- name: Build
run: yarn docs:build
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: website/docs/.vitepress/dist
cname: kernelsu.org # if wanna deploy to custom domain

152
.github/workflows/gki-kernel.yml vendored Normal file
View File

@@ -0,0 +1,152 @@
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: true
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
secrets:
BOOT_SIGN_KEY:
required: false
CHAT_ID:
required: false
CACHE_CHAT_ID:
required: false
BOT_TOKEN:
required: false
MESSAGE_THREAD_ID:
required: false
jobs:
build:
name: Build ${{ inputs.version_name }}
runs-on: ubuntu-latest
env:
CCACHE_COMPILERCHECK: "%compiler% -dumpmachine; %compiler% -dumpversion"
CCACHE_NOHASHDIR: "true"
CCACHE_MAXSIZE: "2G"
CCACHE_HARDLINK: "true"
steps:
- uses: actions/checkout@v3
with:
path: KernelSU
fetch-depth: 0
- uses: hendrikmuhs/ccache-action@v1.2
if: inputs.use_cache == true
with:
key: ccache-aarch64-${{ inputs.version_name }}
append-timestamp: false
save: ${{ github.event_name != 'pull_request' }}
- 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: |
cd $GITHUB_WORKSPACE
git clone https://gerrit.googlesource.com/git-repo
mkdir android-kernel && cd android-kernel
../git-repo/repo init --depth=1 --u https://android.googlesource.com/kernel/manifest -b common-${{ inputs.tag }}
../git-repo/repo sync -j$(nproc --all)
- name: Setup KernelSU
env:
PATCH_PATH: ${{ inputs.patch_path }}
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
grep -q "kernelsu" $DRIVER_MAKEFILE || echo "obj-y += kernelsu/" >> $DRIVER_MAKEFILE
echo "[+] Apply KernelSU patches"
cd $GKI_ROOT/common/ && git apply $GITHUB_WORKSPACE/KernelSU/.github/patches/$PATCH_PATH/*.patch
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: Build boot.img
working-directory: android-kernel
run: CCACHE="/usr/bin/ccache" LTO=thin BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh
- name: Prepare artifacts
id: prepareArtifacts
run: |
OUTDIR=android-kernel/out/${{ inputs.version }}/dist
mkdir output
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/
- name: Upload Image and Image.gz
uses: actions/upload-artifact@v3
with:
name: Image-${{ inputs.version_name }}_${{ inputs.os_patch_level }}
path: ./output/*
- name: Upload AnyKernel3
uses: actions/upload-artifact@v3
with:
name: AnyKernel3-${{ inputs.version_name }}_${{ inputs.os_patch_level }}
path: ./AnyKernel3/*

34
.github/workflows/ksud.yml vendored Normal file
View File

@@ -0,0 +1,34 @@
name: Build ksud
on:
workflow_call:
inputs:
target:
required: true
type: string
use_cache:
required: false
type: boolean
default: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: Swatinem/rust-cache@v2
with:
workspaces: userspace/ksud
cache-targets: false
- name: Install cross
run: cargo install cross
- name: Build ksud
run: cross build --target ${{ inputs.target }} --release --manifest-path ./userspace/ksud/Cargo.toml
- name: Upload ksud artifact
uses: actions/upload-artifact@v3
with:
name: ksud-${{ inputs.target }}
path: userspace/ksud/target/**/release/ksud

56
.github/workflows/release.yml vendored Normal file
View File

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

33
.github/workflows/rustfmt.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
name: Rustfmt check
on:
push:
branches:
- 'main'
paths:
- '.github/workflows/rustfmt.yml'
- 'userspace/ksud/**'
pull_request:
branches:
- 'main'
paths:
- '.github/workflows/rustfmt.yml'
- 'userspace/ksud/**'
permissions:
checks: write
jobs:
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@nightly
with:
components: rustfmt
- uses: LoliGothick/rustfmt-check@v0.2
with:
token: ${{ github.token }}
options: --manifest-path userspace/ksud/Cargo.toml

27
.github/workflows/shellcheck.yml vendored Normal file
View File

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

View File

@@ -1,32 +1,38 @@
**English** | [中文](README_CN.md)
# KernelSU
A Kernel based root solution for Android GKI.
A Kernel based root solution for Android devices.
## Features
1. Kernel-based `su` and root access management.
2. Module system based on overlayfs.
## Compatibility State
KernelSU officially supports Android GKI 2.0 devices(with kernel 5.10+), old kernels(4.14+) is also compatiable, but you need to build kernel yourself.
WSA and containter-based Android should also work with KernelSU integrated.
And the current supported ABIs are : `arm64-v8a` and `x86_64`
## Usage
1. Flash a custom kernel with KernelSU, you can build it yourself or [download it from CI](https://github.com/tiann/KernelSU/actions/workflows/build-kernel.yml).
2. Install Manager App and enjoy :)
[Installation](https://kernelsu.org/guide/installation.html)
## Build
### Build GKI Kernel
1. Download the GKI source first, you can refer the [GKI build instruction](https://source.android.com/docs/setup/build/building-kernels)
2. cd `<GKI kernel source dir>`
3. `curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -`
4. Build the kernel.
### Build the Manager App
Android Studio / Gradle
[How to build?](https://kernelsu.org/guide/how-to-build.html)
### Discussion
[@KernelSU](https://t.me/KernelSU)
- Telegram: [@KernelSU](https://t.me/KernelSU)
## License
[GPL-3](http://www.gnu.org/copyleft/gpl.html)
- Files under `kernel` directory are [GPL-2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
- All other parts except `kernel` directory are [GPL-3](https://www.gnu.org/licenses/gpl-3.0.html)
## Credits

42
README_CN.md Normal file
View File

@@ -0,0 +1,42 @@
[English](README.md) | **中文**
# KernelSU
一个 Android 上基于内核的 root 方案。
## 特性
- 基于内核的 su 和权限管理。
- 基于 overlayfs 的模块系统。
## 兼容状态
KernelSU 官方支持 GKI 2.0 的设备内核版本5.10以上旧内核也是兼容的最低4.14+),不过需要自己编译内核。
WSA 和运行在容器上的 Android 也可以与 KernelSU 一起工作。
目前支持架构 : `arm64-v8a``x86_64`
## 使用方法
[安装教程](https://kernelsu.org/zh_CN/guide/installation.html)
## 构建
[如何构建?](https://kernelsu.org/zh_CN/guide/how-to-build.html)
### 讨论
- Telegram: [@KernelSU](https://t.me/KernelSU)
## 许可证
- 目录 `kernel` 下所有文件为 [GPL-2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
-`kernel` 目录的其他部分均为 [GPL-3](https://www.gnu.org/licenses/gpl-3.0.html)
## 鸣谢
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/)KernelSU 的灵感。
- [true](https://github.com/brevent/genuine/)apk v2 签名验证。
- [Diamorphine](https://github.com/m0nad/Diamorphine):一些 rootkit 技巧。
- [Magisk](https://github.com/topjohnwu/Magisk)sepolicy 的实现。

View File

@@ -1,3 +1,4 @@
Diagnostics:
UnusedIncludes: Strict
ClangTidy:
Remove: bugprone-sizeof-expression

View File

@@ -2,5 +2,13 @@ config KSU
tristate "KernelSU module"
default y
depends on KPROBES
depends on OVERLAY_FS
help
This is the KSU privilege driver for android system.
config KSU_DEBUG
tristate "KernelSU module debug mode"
default n
depends on KSU
help
This enables debug mode for KSU

339
kernel/LICENSE Normal file
View File

@@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@@ -1,14 +1,33 @@
obj-y += ksu.o
obj-y += allowlist.o
obj-y += apk_sign.o
kernelsu-objs := apk_sign.o
obj-y += kernelsu.o
obj-y += module_api.o
obj-y += sucompat.o
obj-y += uid_observer.o
obj-y += manager.o
obj-y += core_hook.o
obj-y += ksud.o
obj-y += embed_ksud.o
obj-y += kernel_compat.o
obj-y += selinux/
# .git is a text file while the module is imported by 'git submodule add'.
ifeq ($(shell test -e $(srctree)/$(src)/../.git; echo $$?),0)
# We must use the absolute path to git, otherwise the build will fail if git is not in the PATH
KSU_GIT_VERSION := $(shell cd $(srctree)/$(src);/usr/bin/git rev-list --count HEAD)
ccflags-y += -DKSU_GIT_VERSION=$(KSU_GIT_VERSION)
endif
ifndef EXPECTED_SIZE
EXPECTED_SIZE := 0x033b
endif
ifndef EXPECTED_HASH
EXPECTED_HASH := 0xb0b91415
endif
ccflags-y += -DEXPECTED_SIZE=$(EXPECTED_SIZE)
ccflags-y += -DEXPECTED_HASH=$(EXPECTED_HASH)
ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat
ccflags-y += -Wno-macro-redefined -Wno-declaration-after-statement
ccflags-y += -Wno-macro-redefined -Wno-declaration-after-statement

View File

@@ -1,30 +1,19 @@
#include <linux/cpu.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/kprobes.h>
#include <linux/memory.h>
#include <linux/module.h>
#include <linux/printk.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/uaccess.h>
#include <linux/uidgid.h>
#include <linux/fdtable.h>
#include <linux/fs.h>
#include <linux/fs_struct.h>
#include <linux/namei.h>
#include <linux/rcupdate.h>
#include <linux/delay.h> // msleep
#include "klog.h"
#include "linux/delay.h"
#include "linux/fs.h"
#include "linux/kernel.h"
#include "linux/list.h"
#include "linux/printk.h"
#include "linux/slab.h"
#include "linux/version.h"
#include "klog.h" // IWYU pragma: keep
#include "selinux/selinux.h"
#include "kernel_compat.h"
#define FILE_MAGIC 0x7f4b5355 // ' KSU', u32
#define FILE_FORMAT_VERSION 1 // u32
static DEFINE_MUTEX(allowlist_mutex);
struct perm_data {
struct list_head list;
uid_t uid;
@@ -33,15 +22,25 @@ struct perm_data {
static struct list_head allow_list;
#define KERNEL_SU_ALLOWLIST "/data/adb/.ksu_allowlist"
#define KERNEL_SU_ALLOWLIST "/data/adb/ksu/.allowlist"
static struct workqueue_struct *ksu_workqueue;
static struct work_struct ksu_save_work;
static struct work_struct ksu_load_work;
bool persistent_allow_list(void);
bool ksu_allow_uid(uid_t uid, bool allow)
void ksu_show_allow_list(void)
{
struct perm_data *p = NULL;
struct list_head *pos = NULL;
pr_info("ksu_show_allow_list");
list_for_each (pos, &allow_list) {
p = list_entry(pos, struct perm_data, list);
pr_info("uid :%d, allow: %d\n", p->uid, p->allow);
}
}
bool ksu_allow_uid(uid_t uid, bool allow, bool persist)
{
// find the node first!
struct perm_data *p = NULL;
@@ -49,7 +48,6 @@ bool ksu_allow_uid(uid_t uid, bool allow)
bool result = false;
list_for_each (pos, &allow_list) {
p = list_entry(pos, struct perm_data, list);
pr_info("ksu_allow_uid :%d, allow: %d\n", p->uid, p->allow);
if (uid == p->uid) {
p->allow = allow;
result = true;
@@ -70,8 +68,8 @@ bool ksu_allow_uid(uid_t uid, bool allow)
result = true;
exit:
persistent_allow_list();
if (persist)
persistent_allow_list();
return result;
}
@@ -121,7 +119,7 @@ void do_persistent_allow_list(struct work_struct *work)
struct perm_data *p = NULL;
struct list_head *pos = NULL;
loff_t off = 0;
KWORKER_INSTALL_KEYRING();
struct file *fp =
filp_open(KERNEL_SU_ALLOWLIST, O_WRONLY | O_CREAT, 0644);
@@ -131,12 +129,12 @@ void do_persistent_allow_list(struct work_struct *work)
}
// store magic and version
if (kernel_write(fp, &magic, sizeof(magic), &off) != sizeof(magic)) {
if (kernel_write_compat(fp, &magic, sizeof(magic), &off) != sizeof(magic)) {
pr_err("save_allow_list write magic failed.\n");
goto exit;
}
if (kernel_write(fp, &version, sizeof(version), &off) !=
if (kernel_write_compat(fp, &version, sizeof(version), &off) !=
sizeof(version)) {
pr_err("save_allow_list write version failed.\n");
goto exit;
@@ -146,8 +144,8 @@ void do_persistent_allow_list(struct work_struct *work)
p = list_entry(pos, struct perm_data, list);
pr_info("save allow list uid :%d, allow: %d\n", p->uid,
p->allow);
kernel_write(fp, &p->uid, sizeof(p->uid), &off);
kernel_write(fp, &p->allow, sizeof(p->allow), &off);
kernel_write_compat(fp, &p->uid, sizeof(p->uid), &off);
kernel_write_compat(fp, &p->allow, sizeof(p->allow), &off);
}
exit:
@@ -161,14 +159,14 @@ void do_load_allow_list(struct work_struct *work)
struct file *fp = NULL;
u32 magic;
u32 version;
fp = filp_open("/data/adb/", O_RDONLY, 0);
KWORKER_INSTALL_KEYRING();
fp = filp_open("/data/adb", O_RDONLY, 0);
if (IS_ERR(fp)) {
int errno = PTR_ERR(fp);
pr_err("load_allow_list open '/data/adb': %d\n", PTR_ERR(fp));
if (errno == -ENOENT) {
msleep(2000);
queue_work(ksu_workqueue, &ksu_load_work);
ksu_queue_work(&ksu_load_work);
return;
} else {
pr_info("load_allow list dir exist now!");
@@ -181,18 +179,29 @@ void do_load_allow_list(struct work_struct *work)
fp = filp_open(KERNEL_SU_ALLOWLIST, O_RDONLY, 0);
if (IS_ERR(fp)) {
#ifdef CONFIG_KSU_DEBUG
int errno = PTR_ERR(fp);
if (errno == -ENOENT) {
ksu_allow_uid(2000, true,
true); // allow adb shell by default
} else {
pr_err("load_allow_list open file failed: %d\n",
PTR_ERR(fp));
}
#else
pr_err("load_allow_list open file failed: %d\n", PTR_ERR(fp));
#endif
return;
}
// verify magic
if (kernel_read(fp, &magic, sizeof(magic), &off) != sizeof(magic) ||
if (kernel_read_compat(fp, &magic, sizeof(magic), &off) != sizeof(magic) ||
magic != FILE_MAGIC) {
pr_err("allowlist file invalid: %d!\n", magic);
goto exit;
}
if (kernel_read(fp, &version, sizeof(version), &off) !=
if (kernel_read_compat(fp, &version, sizeof(version), &off) !=
sizeof(version)) {
pr_err("allowlist read version: %d failed\n", version);
goto exit;
@@ -203,59 +212,78 @@ void do_load_allow_list(struct work_struct *work)
while (true) {
u32 uid;
bool allow = false;
ret = kernel_read(fp, &uid, sizeof(uid), &off);
ret = kernel_read_compat(fp, &uid, sizeof(uid), &off);
if (ret <= 0) {
pr_info("load_allow_list read err: %d\n", ret);
break;
}
ret = kernel_read(fp, &allow, sizeof(allow), &off);
ret = kernel_read_compat(fp, &allow, sizeof(allow), &off);
pr_info("load_allow_uid: %d, allow: %d\n", uid, allow);
ksu_allow_uid(uid, allow);
ksu_allow_uid(uid, allow, false);
}
exit:
ksu_show_allow_list();
filp_close(fp, 0);
}
static int init_work(void)
void ksu_prune_allowlist(bool (*is_uid_exist)(uid_t, void *), void *data)
{
ksu_workqueue = alloc_workqueue("kernelsu_work_queue", 0, 0);
INIT_WORK(&ksu_save_work, do_persistent_allow_list);
INIT_WORK(&ksu_load_work, do_load_allow_list);
return 0;
struct perm_data *np = NULL;
struct perm_data *n = NULL;
bool modified = false;
// TODO: use RCU!
mutex_lock(&allowlist_mutex);
list_for_each_entry_safe (np, n, &allow_list, list) {
uid_t uid = np->uid;
if (!is_uid_exist(uid, data)) {
modified = true;
pr_info("prune uid: %d\n", uid);
list_del(&np->list);
kfree(np);
}
}
mutex_unlock(&allowlist_mutex);
if (modified) {
persistent_allow_list();
}
}
// make sure allow list works cross boot
bool persistent_allow_list(void)
{
queue_work(ksu_workqueue, &ksu_save_work);
return true;
return ksu_queue_work(&ksu_save_work);
}
bool ksu_load_allow_list(void)
{
queue_work(ksu_workqueue, &ksu_load_work);
return true;
return ksu_queue_work(&ksu_load_work);
}
bool ksu_allowlist_init(void)
void ksu_allowlist_init(void)
{
INIT_LIST_HEAD(&allow_list);
init_work();
// start load allow list, we load it before app_process exec now, refer: sucompat#execve_handler_pre
// ksu_load_allow_list();
return true;
INIT_WORK(&ksu_save_work, do_persistent_allow_list);
INIT_WORK(&ksu_load_work, do_load_allow_list);
}
bool ksu_allowlist_exit(void)
void ksu_allowlist_exit(void)
{
destroy_workqueue(ksu_workqueue);
struct perm_data *np = NULL;
struct perm_data *n = NULL;
return true;
do_persistent_allow_list(NULL);
// free allowlist
mutex_lock(&allowlist_mutex);
list_for_each_entry_safe (np, n, &allow_list, list) {
list_del(&np->list);
kfree(np);
}
mutex_unlock(&allowlist_mutex);
}

View File

@@ -1,16 +1,22 @@
#ifndef __KSU_H_ALLOWLIST
#define __KSU_H_ALLOWLIST
bool ksu_allowlist_init();
#include "linux/types.h"
bool ksu_allowlist_exit();
void ksu_allowlist_init(void);
bool ksu_is_allow_uid(uid_t uid);
bool ksu_allow_uid(uid_t uid, bool allow);
bool ksu_get_allow_list(int *array, int *length, bool allow);
void ksu_allowlist_exit(void);
bool ksu_load_allow_list(void);
void ksu_show_allow_list(void);
bool ksu_is_allow_uid(uid_t uid);
bool ksu_allow_uid(uid_t uid, bool allow, bool persist);
bool ksu_get_allow_list(int *array, int *length, bool allow);
void ksu_prune_allowlist(bool (*is_uid_exist)(uid_t, void *), void *data);
#endif

View File

@@ -1,10 +1,12 @@
#include <linux/fs.h>
#include "linux/fs.h"
#include "linux/moduleparam.h"
#include "apk_sign.h"
#include "klog.h"
#include "klog.h" // IWYU pragma: keep
#include "kernel_compat.h"
static int check_v2_signature(char *path, unsigned expected_size,
unsigned expected_hash)
static __always_inline int
check_v2_signature(char *path, unsigned expected_size, unsigned expected_hash)
{
unsigned char buffer[0x11] = { 0 };
u32 size4;
@@ -19,15 +21,18 @@ static int check_v2_signature(char *path, unsigned expected_size,
return PTR_ERR(fp);
}
// disable inotify for this file
fp->f_mode |= FMODE_NONOTIFY;
sign = 1;
// https://en.wikipedia.org/wiki/Zip_(file_format)#End_of_central_directory_record_(EOCD)
for (int i = 0;; ++i) {
unsigned short n;
pos = generic_file_llseek(fp, -i - 2, SEEK_END);
kernel_read(fp, &n, 2, &pos);
kernel_read_compat(fp, &n, 2, &pos);
if (n == i) {
pos -= 22;
kernel_read(fp, &size4, 4, &pos);
kernel_read_compat(fp, &size4, 4, &pos);
if ((size4 ^ 0xcafebabeu) == 0xccfbf1eeu) {
break;
}
@@ -40,17 +45,17 @@ static int check_v2_signature(char *path, unsigned expected_size,
pos += 12;
// offset
kernel_read(fp, &size4, 0x4, &pos);
kernel_read_compat(fp, &size4, 0x4, &pos);
pos = size4 - 0x18;
kernel_read(fp, &size8, 0x8, &pos);
kernel_read(fp, buffer, 0x10, &pos);
kernel_read_compat(fp, &size8, 0x8, &pos);
kernel_read_compat(fp, buffer, 0x10, &pos);
if (strcmp((char *)buffer, "APK Sig Block 42")) {
goto clean;
}
pos = size4 - (size8 + 0x8);
kernel_read(fp, &size_of_block, 0x8, &pos);
kernel_read_compat(fp, &size_of_block, 0x8, &pos);
if (size_of_block != size8) {
goto clean;
}
@@ -58,47 +63,47 @@ static int check_v2_signature(char *path, unsigned expected_size,
for (;;) {
uint32_t id;
uint32_t offset;
kernel_read(fp, &size8, 0x8, &pos); // sequence length
kernel_read_compat(fp, &size8, 0x8, &pos); // sequence length
if (size8 == size_of_block) {
break;
}
kernel_read(fp, &id, 0x4, &pos); // id
kernel_read_compat(fp, &id, 0x4, &pos); // id
offset = 4;
pr_info("id: 0x%08x\n", id);
if ((id ^ 0xdeadbeefu) == 0xafa439f5u ||
(id ^ 0xdeadbeefu) == 0x2efed62f) {
kernel_read(fp, &size4, 0x4,
kernel_read_compat(fp, &size4, 0x4,
&pos); // signer-sequence length
kernel_read(fp, &size4, 0x4, &pos); // signer length
kernel_read(fp, &size4, 0x4,
kernel_read_compat(fp, &size4, 0x4, &pos); // signer length
kernel_read_compat(fp, &size4, 0x4,
&pos); // signed data length
offset += 0x4 * 3;
kernel_read(fp, &size4, 0x4,
kernel_read_compat(fp, &size4, 0x4,
&pos); // digests-sequence length
pos += size4;
offset += 0x4 + size4;
kernel_read(fp, &size4, 0x4,
kernel_read_compat(fp, &size4, 0x4,
&pos); // certificates length
kernel_read(fp, &size4, 0x4,
kernel_read_compat(fp, &size4, 0x4,
&pos); // certificate length
offset += 0x4 * 2;
#if 0
int hash = 1;
signed char c;
for (unsigned i = 0; i < size4; ++i) {
kernel_read(fp, &c, 0x1, &pos);
hash = 31 * hash + c;
}
offset += size4;
pr_info(" size: 0x%04x, hash: 0x%08x\n", size4, ((unsigned) hash) ^ 0x14131211u);
int hash = 1;
signed char c;
for (unsigned i = 0; i < size4; ++i) {
kernel_read_compat(fp, &c, 0x1, &pos);
hash = 31 * hash + c;
}
offset += size4;
pr_info(" size: 0x%04x, hash: 0x%08x\n", size4, ((unsigned) hash) ^ 0x14131211u);
#else
if (size4 == expected_size) {
int hash = 1;
signed char c;
for (unsigned i = 0; i < size4; ++i) {
kernel_read(fp, &c, 0x1, &pos);
kernel_read_compat(fp, &c, 0x1, &pos);
hash = 31 * hash + c;
}
offset += size4;
@@ -121,7 +126,54 @@ clean:
return sign;
}
#ifdef CONFIG_KSU_DEBUG
unsigned ksu_expected_size = EXPECTED_SIZE;
unsigned ksu_expected_hash = EXPECTED_HASH;
#include "manager.h"
static int set_expected_size(const char *val, const struct kernel_param *kp)
{
int rv = param_set_uint(val, kp);
ksu_invalidate_manager_uid();
pr_info("ksu_expected_size set to %x", ksu_expected_size);
return rv;
}
static int set_expected_hash(const char *val, const struct kernel_param *kp)
{
int rv = param_set_uint(val, kp);
ksu_invalidate_manager_uid();
pr_info("ksu_expected_hash set to %x", ksu_expected_hash);
return rv;
}
static struct kernel_param_ops expected_size_ops = {
.set = set_expected_size,
.get = param_get_uint,
};
static struct kernel_param_ops expected_hash_ops = {
.set = set_expected_hash,
.get = param_get_uint,
};
module_param_cb(ksu_expected_size, &expected_size_ops, &ksu_expected_size,
S_IRUSR | S_IWUSR);
module_param_cb(ksu_expected_hash, &expected_hash_ops, &ksu_expected_hash,
S_IRUSR | S_IWUSR);
int is_manager_apk(char *path)
{
return check_v2_signature(path, ksu_expected_size, ksu_expected_hash);
}
#else
int is_manager_apk(char *path)
{
return check_v2_signature(path, EXPECTED_SIZE, EXPECTED_HASH);
}
}
#endif

View File

@@ -2,6 +2,6 @@
#define __KSU_H_APK_V2_SIGN
// return 0 if signature match
int is_manager_apk(char* path);
int is_manager_apk(char *path);
#endif

View File

@@ -1,6 +1,8 @@
#ifndef __KSU_H_ARCH
#define __KSU_H_ARCH
#include "linux/version.h"
#if defined(__aarch64__)
#define __PT_PARM1_REG regs[0]
@@ -8,13 +10,18 @@
#define __PT_PARM3_REG regs[2]
#define __PT_PARM4_REG regs[3]
#define __PT_PARM5_REG regs[4]
#define __PT_PARM6_REG regs[5]
#define __PT_RET_REG regs[30]
#define __PT_FP_REG regs[29] /* Works only with CONFIG_FRAME_POINTER */
#define __PT_RC_REG regs[0]
#define __PT_SP_REG sp
#define __PT_IP_REG pc
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
#define PRCTL_SYMBOL "__arm64_sys_prctl"
#else
#define PRCTL_SYMBOL "sys_prctl"
#endif
#elif defined(__x86_64__)
@@ -25,13 +32,17 @@
#define __PT_PARM4_REG r10
// #define __PT_PARM4_REG cx
#define __PT_PARM5_REG r8
#define __PT_PARM6_REG r9
#define __PT_RET_REG sp
#define __PT_FP_REG bp
#define __PT_RC_REG ax
#define __PT_SP_REG sp
#define __PT_IP_REG ip
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
#define PRCTL_SYMBOL "__x64_sys_prctl"
#else
#define PRCTL_SYMBOL "sys_prctl"
#endif
#else
#error "Unsupported arch"
@@ -47,10 +58,11 @@
#define PT_REGS_PARM3(x) (__PT_REGS_CAST(x)->__PT_PARM3_REG)
#define PT_REGS_PARM4(x) (__PT_REGS_CAST(x)->__PT_PARM4_REG)
#define PT_REGS_PARM5(x) (__PT_REGS_CAST(x)->__PT_PARM5_REG)
#define PT_REGS_PARM6(x) (__PT_REGS_CAST(x)->__PT_PARM6_REG)
#define PT_REGS_RET(x) (__PT_REGS_CAST(x)->__PT_RET_REG)
#define PT_REGS_FP(x) (__PT_REGS_CAST(x)->__PT_FP_REG)
#define PT_REGS_RC(x) (__PT_REGS_CAST(x)->__PT_RC_REG)
#define PT_REGS_SP(x) (__PT_REGS_CAST(x)->__PT_SP_REG)
#define PT_REGS_IP(x) (__PT_REGS_CAST(x)->__PT_IP_REG)
#endif
#endif

431
kernel/core_hook.c Normal file
View File

@@ -0,0 +1,431 @@
#include "linux/cred.h"
#include "linux/err.h"
#include "linux/init.h"
#include "linux/kernel.h"
#include "linux/kprobes.h"
#include "linux/lsm_hooks.h"
#include "linux/printk.h"
#include "linux/uaccess.h"
#include "linux/uidgid.h"
#include "linux/version.h"
#include "linux/fs.h"
#include "linux/namei.h"
#include "linux/rcupdate.h"
#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 "uid_observer.h"
#include "kernel_compat.h"
extern int handle_sepolicy(unsigned long arg3, void __user *arg4);
static inline bool is_allow_su()
{
if (is_manager()) {
// we are manager, allow!
return true;
}
return ksu_is_allow_uid(current_uid().val);
}
static struct group_info root_groups = { .usage = ATOMIC_INIT(2) };
void escape_to_root(void)
{
struct cred *cred;
cred = (struct cred *)__task_cred(current);
memset(&cred->uid, 0, sizeof(cred->uid));
memset(&cred->gid, 0, sizeof(cred->gid));
memset(&cred->suid, 0, sizeof(cred->suid));
memset(&cred->euid, 0, sizeof(cred->euid));
memset(&cred->egid, 0, sizeof(cred->egid));
memset(&cred->fsuid, 0, sizeof(cred->fsuid));
memset(&cred->fsgid, 0, sizeof(cred->fsgid));
memset(&cred->cap_inheritable, 0xff, sizeof(cred->cap_inheritable));
memset(&cred->cap_permitted, 0xff, sizeof(cred->cap_permitted));
memset(&cred->cap_effective, 0xff, sizeof(cred->cap_effective));
memset(&cred->cap_bset, 0xff, sizeof(cred->cap_bset));
memset(&cred->cap_ambient, 0xff, sizeof(cred->cap_ambient));
// 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
current->seccomp.mode = 0;
current->seccomp.filter = NULL;
// setgroup to root
if (cred->group_info)
put_group_info(cred->group_info);
cred->group_info = get_group_info(&root_groups);
setup_selinux();
}
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 (strcmp(buf, "/system/packages.list")) {
return 0;
}
pr_info("renameat: %s -> %s, new path: %s", old_dentry->d_iname,
new_dentry->d_iname, buf);
update_uid();
return 0;
}
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;
}
pr_info("option: 0x%x, cmd: %ld\n", option, arg2);
if (arg2 == CMD_BECOME_MANAGER) {
// quick check
if (is_manager()) {
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
pr_err("become_manager: prctl reply error\n");
}
return 0;
}
if (ksu_is_manager_uid_valid()) {
pr_info("manager already exist: %d\n",
ksu_get_manager_uid());
return 0;
}
// someone wants to be root manager, just check it!
// arg3 should be `/data/data/<manager_package_name>`
char param[128];
const char *prefix = "/data/data/";
if (copy_from_user(param, arg3, sizeof(param))) {
pr_err("become_manager: copy param err\n");
return 0;
}
if (startswith(param, (char *)prefix) != 0) {
pr_info("become_manager: invalid param: %s\n", param);
return 0;
}
// stat the param, app must have permission to do this
// otherwise it may fake the path!
struct path path;
if (kern_path(param, LOOKUP_DIRECTORY, &path)) {
pr_err("become_manager: kern_path err\n");
return 0;
}
if (path.dentry->d_inode->i_uid.val != current_uid().val) {
pr_err("become_manager: path uid != current uid\n");
path_put(&path);
return 0;
}
char *pkg = param + strlen(prefix);
pr_info("become_manager: param pkg: %s\n", pkg);
bool success = become_manager(pkg);
if (success) {
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
pr_err("become_manager: prctl reply error\n");
}
}
path_put(&path);
return 0;
}
if (arg2 == CMD_GRANT_ROOT) {
if (is_allow_su()) {
pr_info("allow root for: %d\n", current_uid());
escape_to_root();
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
pr_err("grant_root: prctl reply error\n");
}
} else {
pr_info("deny root for: %d\n", current_uid());
// add it to deny list!
ksu_allow_uid(current_uid().val, false, true);
}
return 0;
}
// Both root manager and root processes should be allowed to get version
if (arg2 == CMD_GET_VERSION) {
if (is_manager() || 0 == current_uid().val) {
u32 version = KERNEL_SU_VERSION;
if (copy_to_user(arg3, &version, sizeof(version))) {
pr_err("prctl reply error, cmd: %d\n", arg2);
return 0;
}
}
}
if (arg2 == CMD_REPORT_EVENT) {
if (0 != current_uid().val) {
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");
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");
}
break;
}
default:
break;
}
return 0;
}
if (arg2 == CMD_SET_SEPOLICY) {
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;
}
// all other cmds are for 'root manager'
if (!is_manager()) {
pr_info("Only manager can do cmd: %d\n", arg2);
return 0;
}
// we are already manager
if (arg2 == CMD_ALLOW_SU || arg2 == CMD_DENY_SU) {
bool allow = arg2 == CMD_ALLOW_SU;
bool success = false;
uid_t uid = (uid_t)arg3;
success = ksu_allow_uid(uid, allow, true);
if (success) {
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
pr_err("prctl reply error, cmd: %d\n", arg2);
}
}
ksu_show_allow_list();
} else 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: %d\n",
arg2);
}
} else {
pr_err("prctl copy allowlist error\n");
}
}
}
return 0;
}
// Init functons
static int handler_pre(struct kprobe *p, struct pt_regs *regs)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
struct pt_regs *real_regs = (struct pt_regs *)PT_REGS_PARM1(regs);
#else
struct pt_regs *real_regs = regs;
#endif
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);
unsigned long arg4 = (unsigned long)PT_REGS_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_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;
}
// kernel 4.4 and 4.9
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
static int ksu_key_permission(key_ref_t key_ref,
const struct cred *cred,
unsigned perm)
{
if (init_session_keyring != NULL)
{
return 0;
}
if (strcmp(current->comm, "init"))
{
// we are only interested in `init` process
return 0;
}
init_session_keyring = cred->session_keyring;
pr_info("kernel_compat: got init_session_keyring");
return 0;
}
#endif
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 struct security_hook_list ksu_hooks[] = {
LSM_HOOK_INIT(task_prctl, ksu_task_prctl),
LSM_HOOK_INIT(inode_rename, ksu_inode_rename),
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
LSM_HOOK_INIT(key_permission, ksu_key_permission)
#endif
};
void __init ksu_lsm_hook_init(void)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
security_add_hooks(ksu_hooks, ARRAY_SIZE(ksu_hooks), "ksu");
#else
// https://elixir.bootlin.com/linux/v4.10.17/source/include/linux/lsm_hooks.h#L1892
security_add_hooks(ksu_hooks, ARRAY_SIZE(ksu_hooks));
#endif
}
void __init ksu_core_init(void)
{
#ifndef MODULE
pr_info("ksu_lsm_hook_init\n");
ksu_lsm_hook_init();
#else
pr_info("ksu_kprobe_init\n");
ksu_kprobe_init();
#endif
}
void ksu_core_exit(void)
{
#ifndef MODULE
pr_info("ksu_kprobe_exit\n");
ksu_kprobe_exit();
#endif
}

9
kernel/core_hook.h Normal file
View File

@@ -0,0 +1,9 @@
#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

5
kernel/embed_ksud.c Normal file
View File

@@ -0,0 +1,5 @@
// WARNING: THIS IS A STUB FILE
// This file will be regenerated by CI
unsigned int ksud_size = 0;
const char ksud[0] = {};

2
kernel/export_symbol.txt Normal file
View File

@@ -0,0 +1,2 @@
register_kprobe
unregister_kprobe

24
kernel/include/ksu_hook.h Normal file
View File

@@ -0,0 +1,24 @@
#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);
#endif

34
kernel/kernel_compat.c Normal file
View File

@@ -0,0 +1,34 @@
#include "linux/version.h"
#include "linux/fs.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
#include "linux/key.h"
#include "linux/errno.h"
struct key *init_session_keyring = NULL;
#endif
ssize_t kernel_read_compat(struct file *p, void *buf, size_t count, loff_t *pos){
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
return kernel_read(p, buf, count, pos);
#else
loff_t offset = pos ? *pos : 0;
ssize_t result = kernel_read(p, offset, (char *)buf, count);
if (pos && result > 0)
{
*pos = offset + result;
}
return result;
#endif
}
ssize_t kernel_write_compat(struct file *p, const void *buf, size_t count, loff_t *pos){
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
return kernel_write(p, buf, count, pos);
#else
loff_t offset = pos ? *pos : 0;
ssize_t result = kernel_write(p, buf, count, offset);
if (pos && result > 0)
{
*pos = offset + result;
}
return result;
#endif
}

42
kernel/kernel_compat.h Normal file
View File

@@ -0,0 +1,42 @@
#ifndef __KSU_H_KERNEL_COMPAT
#define __KSU_H_KERNEL_COMPAT
#include "linux/fs.h"
#include "linux/key.h"
#include "linux/version.h"
extern struct key *init_session_keyring;
extern ssize_t kernel_read_compat(struct file *p, void *buf, size_t count, loff_t *pos);
extern ssize_t kernel_write_compat(struct file *p, const void *buf, size_t count, loff_t *pos);
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
static inline int install_session_keyring(struct key *keyring)
{
struct cred *new;
int ret;
new = prepare_creds();
if (!new)
return -ENOMEM;
ret = install_session_keyring_to_cred(new, keyring);
if (ret < 0) {
abort_creds(new);
return ret;
}
return commit_creds(new);
}
#define KWORKER_INSTALL_KEYRING() \
static bool keyring_installed = false; \
if (init_session_keyring != NULL && !keyring_installed) \
{ \
install_session_keyring(init_session_keyring); \
keyring_installed = true; \
}
#else
#define KWORKER_INSTALL_KEYRING()
#endif
#endif

View File

@@ -1,6 +1,8 @@
#ifndef __KSU_H_KLOG
#define __KSU_H_KLOG
#include <linux/printk.h>
#ifdef pr_fmt
#undef pr_fmt
#define pr_fmt(fmt) "KernelSU: " fmt

View File

@@ -1,334 +1,86 @@
#include "linux/gfp.h"
#include "linux/uidgid.h"
#include <linux/cpu.h>
#include <linux/memory.h>
#include <linux/uaccess.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kprobes.h>
#include <linux/printk.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <asm-generic/errno-base.h>
#include "linux/fs.h"
#include "linux/module.h"
#include "linux/workqueue.h"
#include <linux/rcupdate.h>
#include <linux/fdtable.h>
#include <linux/fs.h>
#include <linux/fs_struct.h>
#include <linux/namei.h>
#include <linux/delay.h> // mslepp
#include "selinux/selinux.h"
#include "klog.h"
#include "apk_sign.h"
#include "allowlist.h"
#include "arch.h"
#include "core_hook.h"
#include "klog.h" // IWYU pragma: keep
#include "ksu.h"
#include "uid_observer.h"
#define KERNEL_SU_VERSION 8
static struct workqueue_struct *ksu_workqueue;
#define KERNEL_SU_OPTION 0xDEADBEEF
#define CMD_GRANT_ROOT 0
#define CMD_BECOME_MANAGER 1
#define CMD_GET_VERSION 2
#define CMD_ALLOW_SU 3
#define CMD_DENY_SU 4
#define CMD_GET_ALLOW_LIST 5
#define CMD_GET_DENY_LIST 6
void escape_to_root()
bool ksu_queue_work(struct work_struct *work)
{
struct cred *cred;
return queue_work(ksu_workqueue, work);
}
cred = (struct cred *)__task_cred(current);
extern int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
void *argv, void *envp, int *flags);
memset(&cred->uid, 0, sizeof(cred->uid));
memset(&cred->gid, 0, sizeof(cred->gid));
memset(&cred->suid, 0, sizeof(cred->suid));
memset(&cred->euid, 0, sizeof(cred->euid));
memset(&cred->egid, 0, sizeof(cred->egid));
memset(&cred->fsuid, 0, sizeof(cred->fsuid));
memset(&cred->fsgid, 0, sizeof(cred->fsgid));
memset(&cred->cap_inheritable, 0xff, sizeof(cred->cap_inheritable));
memset(&cred->cap_permitted, 0xff, sizeof(cred->cap_permitted));
memset(&cred->cap_effective, 0xff, sizeof(cred->cap_effective));
memset(&cred->cap_bset, 0xff, sizeof(cred->cap_bset));
memset(&cred->cap_ambient, 0xff, sizeof(cred->cap_ambient));
extern int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
void *argv, void *envp, int *flags);
// disable seccomp
#ifdef CONFIG_GENERIC_ENTRY
current_thread_info()->syscall_work &= ~SYSCALL_WORK_SECCOMP;
#else
current_thread_info()->flags &= ~(TIF_SECCOMP | _TIF_SECCOMP);
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_enable_sucompat();
extern void ksu_enable_ksud();
int __init kernelsu_init(void)
{
#ifdef CONFIG_KSU_DEBUG
pr_alert("*************************************************************");
pr_alert("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **");
pr_alert("** **");
pr_alert("** You are running DEBUG version of KernelSU **");
pr_alert("** **");
pr_alert("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **");
pr_alert("*************************************************************");
#endif
current->seccomp.mode = 0;
current->seccomp.filter = NULL;
setup_selinux();
}
ksu_core_init();
int startswith(char *s, char *prefix)
{
return strncmp(s, prefix, strlen(prefix));
}
int endswith(const char *s, const char *t)
{
size_t slen = strlen(s);
size_t tlen = strlen(t);
if (tlen > slen)
return 1;
return strcmp(s + slen - tlen, t);
}
static uid_t __manager_uid;
static bool is_manager()
{
return __manager_uid == current_uid().val;
}
static bool become_manager(char *pkg)
{
struct fdtable *files_table;
int i = 0;
struct path files_path;
char *cwd;
char *buf;
bool result = false;
// must be zygote's direct child, otherwise any app can fork a new process and open manager's apk
if (task_uid(current->real_parent).val != 0) {
pr_info("parent is not zygote!\n");
return false;
}
if (__manager_uid != 0) {
pr_info("manager already exist: %d\n", __manager_uid);
return is_manager();
}
buf = (char *)kmalloc(PATH_MAX, GFP_ATOMIC);
if (!buf) {
pr_err("kalloc path failed.\n");
return false;
}
files_table = files_fdtable(current->files);
// todo: use iterate_fd
while (files_table->fd[i] != NULL) {
files_path = files_table->fd[i]->f_path;
if (!d_is_reg(files_path.dentry)) {
i++;
continue;
}
cwd = d_path(&files_path, buf, PATH_MAX);
if (startswith(cwd, "/data/app/") == 0 &&
endswith(cwd, "/base.apk") == 0) {
// we have found the apk!
pr_info("found apk: %s", cwd);
if (!strstr(cwd, pkg)) {
pr_info("apk path not match package name!\n");
i++;
continue;
}
if (is_manager_apk(cwd) == 0) {
// check passed
uid_t uid = current_uid().val;
pr_info("manager uid: %d\n", uid);
__manager_uid = uid;
result = true;
goto clean;
} else {
pr_info("manager signature invalid!");
}
break;
}
i++;
}
clean:
kfree(buf);
return result;
}
static bool is_allow_su()
{
uid_t uid = current_uid().val;
if (uid == __manager_uid) {
// we are manager, allow!
return true;
}
return ksu_is_allow_uid(uid);
}
extern void enable_sucompat();
static int handler_pre(struct kprobe *p, struct pt_regs *regs)
{
struct pt_regs *real_regs = (struct pt_regs *)PT_REGS_PARM1(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);
unsigned long arg4 = (unsigned long)PT_REGS_PARM4(real_regs);
unsigned long arg5 = (unsigned long)PT_REGS_PARM5(real_regs);
// 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;
}
pr_info("option: 0x%x, cmd: %ld\n", option, arg2);
if (arg2 == CMD_BECOME_MANAGER) {
// someone wants to be root manager, just check it!
// arg3 should be `/data/data/<manager_package_name>`
char param[128];
const char *prefix = "/data/data/";
if (copy_from_user(param, arg3, sizeof(param))) {
pr_err("become_manager: copy param err\n");
return 0;
}
if (startswith(param, (char *)prefix) != 0) {
pr_info("become_manager: invalid param: %s\n", param);
return 0;
}
// stat the param, app must have permission to do this
// otherwise it may fake the path!
struct path path;
if (kern_path(param, LOOKUP_DIRECTORY, &path)) {
pr_err("become_manager: kern_path err\n");
return 0;
}
if (path.dentry->d_inode->i_uid.val != current_uid().val) {
pr_err("become_manager: path uid != current uid\n");
path_put(&path);
return 0;
}
char *pkg = param + strlen(prefix);
pr_info("become_manager: param pkg: %s\n", pkg);
bool success = become_manager(pkg);
if (success) {
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
pr_err("become_manager: prctl reply error\n");
}
}
path_put(&path);
return 0;
}
if (arg2 == CMD_GRANT_ROOT) {
if (is_allow_su()) {
pr_info("allow root for: %d\n", current_uid());
escape_to_root();
} else {
pr_info("deny root for: %d\n", current_uid());
// add it to deny list!
ksu_allow_uid(current_uid().val, false);
}
return 0;
}
// all other cmds are for 'root manager'
if (!is_manager()) {
pr_info("Only manager can do cmd: %d\n", arg2);
return 0;
}
// we are already manager
if (arg2 == CMD_ALLOW_SU || arg2 == CMD_DENY_SU) {
bool allow = arg2 == CMD_ALLOW_SU;
bool success = false;
uid_t uid = (uid_t)arg3;
success = ksu_allow_uid(uid, allow);
if (success) {
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
pr_err("prctl reply error, cmd: %d\n", arg2);
}
}
} else 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: %d\n",
arg2);
}
} else {
pr_err("prctl copy allowlist error\n");
}
}
} else if (arg2 == CMD_GET_VERSION) {
u32 version = KERNEL_SU_VERSION;
if (copy_to_user(arg3, &version, sizeof(version))) {
pr_err("prctl reply error, cmd: %d\n", arg2);
}
}
return 0;
}
static struct kprobe kp = {
.symbol_name = PRCTL_SYMBOL,
.pre_handler = handler_pre,
};
int kernelsu_init(void)
{
int rc = 0;
ksu_workqueue = alloc_workqueue("kernelsu_work_queue", 0, 0);
ksu_allowlist_init();
rc = register_kprobe(&kp);
if (rc) {
pr_info("prctl kprobe failed: %d, please check your kernel config.\n",
rc);
return rc;
}
ksu_uid_observer_init();
enable_sucompat();
#ifdef CONFIG_KPROBES
ksu_enable_sucompat();
ksu_enable_ksud();
#else
#warning("KPROBES is disabled, KernelSU may not work, please check https://kernelsu.org/guide/how-to-integrate-for-non-gki.html")
#endif
return 0;
}
void kernelsu_exit(void)
{
// should never happen...
unregister_kprobe(&kp);
ksu_allowlist_exit();
ksu_uid_observer_exit();
destroy_workqueue(ksu_workqueue);
ksu_core_exit();
}
module_init(kernelsu_init);
module_exit(kernelsu_exit);
#ifndef CONFIG_KPROBES
#error("`CONFIG_KPROBES` must be enabled for KernelSU!")
#endif
MODULE_LICENSE("GPL");
MODULE_AUTHOR("weishu");
MODULE_DESCRIPTION("Android GKI KernelSU");
MODULE_IMPORT_NS(
VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); // 5+才需要导出命名空间
MODULE_DESCRIPTION("Android KernelSU");
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver);
#endif

45
kernel/ksu.h Normal file
View File

@@ -0,0 +1,45 @@
#ifndef __KSU_H_KSU
#define __KSU_H_KSU
#include "linux/workqueue.h"
#ifndef KSU_GIT_VERSION
#warning "KSU_GIT_VERSION not defined! It is better to make KernelSU a git submodule!"
#define KERNEL_SU_VERSION (16)
#else
#define KERNEL_SU_VERSION (10000 + KSU_GIT_VERSION + 200) // major * 10000 + git version + 200 for historical reasons
#endif
#define KERNEL_SU_OPTION 0xDEADBEEF
#define CMD_GRANT_ROOT 0
#define CMD_BECOME_MANAGER 1
#define CMD_GET_VERSION 2
#define CMD_ALLOW_SU 3
#define CMD_DENY_SU 4
#define CMD_GET_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 EVENT_POST_FS_DATA 1
#define EVENT_BOOT_COMPLETED 2
bool ksu_queue_work(struct work_struct *work);
static inline int startswith(char *s, char *prefix)
{
return strncmp(s, prefix, strlen(prefix));
}
static inline int endswith(const char *s, const char *t)
{
size_t slen = strlen(s);
size_t tlen = strlen(t);
if (tlen > slen)
return 1;
return strcmp(s + slen - tlen, t);
}
#endif

370
kernel/ksud.c Normal file
View File

@@ -0,0 +1,370 @@
#include "asm/current.h"
#include "linux/cred.h"
#include "linux/dcache.h"
#include "linux/err.h"
#include "linux/fs.h"
#include "linux/input-event-codes.h"
#include "linux/kprobes.h"
#include "linux/printk.h"
#include "linux/types.h"
#include "linux/uaccess.h"
#include "linux/version.h"
#include "linux/workqueue.h"
#include "linux/input.h"
#include "allowlist.h"
#include "arch.h"
#include "klog.h" // IWYU pragma: keep
#include "ksud.h"
#include "selinux/selinux.h"
static const char KERNEL_SU_RC[] =
"\n"
"on post-fs-data\n"
// We should wait for the post-fs-data finish
" exec u:r:su:s0 root -- " KSUD_PATH " post-fs-data\n"
"\n"
"on nonencrypted\n"
" exec u:r:su:s0 root -- " KSUD_PATH " services\n"
"\n"
"on property:vold.decrypt=trigger_restart_framework\n"
" exec u:r:su:s0 root -- " KSUD_PATH " services\n"
"\n"
"on property:sys.boot_completed=1\n"
" exec u:r:su:s0 root -- " KSUD_PATH " boot-completed\n"
"\n"
"\n";
static void stop_vfs_read_hook();
static void stop_execve_hook();
static void stop_input_hook();
#ifdef CONFIG_KPROBES
static struct work_struct stop_vfs_read_work;
static struct work_struct stop_execve_hook_work;
static struct work_struct stop_input_hook_work;
#else
static bool vfs_read_hook = true;
static bool execveat_hook = true;
static bool input_hook = true;
#endif
void on_post_fs_data(void)
{
static bool done = false;
if (done) {
pr_info("on_post_fs_data already done");
return;
}
done = true;
pr_info("ksu_load_allow_list");
ksu_load_allow_list();
// sanity check, this may influence the performance
stop_input_hook();
}
int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
void *argv, void *envp, int *flags)
{
#ifndef CONFIG_KPROBES
if (!execveat_hook) {
return 0;
}
#endif
struct filename *filename;
static const char app_process[] = "/system/bin/app_process";
static bool first_app_process = true;
static const char system_bin_init[] = "/system/bin/init";
static int init_count = 0;
if (!filename_ptr)
return 0;
filename = *filename_ptr;
if (IS_ERR(filename)) {
return 0;
}
if (!memcmp(filename->name, system_bin_init,
sizeof(system_bin_init) - 1)) {
// /system/bin/init executed
if (++init_count == 2) {
// 1: /system/bin/init selinux_setup
// 2: /system/bin/init second_stage
pr_info("/system/bin/init second_stage executed\n");
apply_kernelsu_rules();
}
}
if (first_app_process &&
!memcmp(filename->name, app_process, sizeof(app_process) - 1)) {
first_app_process = false;
pr_info("exec app_process, /data prepared!\n");
on_post_fs_data(); // we keep this for old ksud
stop_execve_hook();
}
return 0;
}
int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
size_t *count_ptr, loff_t **pos)
{
#ifndef CONFIG_KPROBES
if (!vfs_read_hook) {
return 0;
}
#endif
struct file *file;
char __user *buf;
size_t count;
if (strcmp(current->comm, "init")) {
// we are only interest in `init` process
return 0;
}
file = *file_ptr;
if (IS_ERR(file)) {
return 0;
}
if (!d_is_reg(file->f_path.dentry)) {
return 0;
}
const char *short_name = file->f_path.dentry->d_name.name;
if (strcmp(short_name, "atrace.rc")) {
// we are only interest `atrace.rc` file name file
return 0;
}
char path[256];
char *dpath = d_path(&file->f_path, path, sizeof(path));
if (IS_ERR(dpath)) {
return 0;
}
if (strcmp(dpath, "/system/etc/init/atrace.rc")) {
return 0;
}
// we only process the first read
static bool rc_inserted = false;
if (rc_inserted) {
// we don't need this kprobe, unregister it!
stop_vfs_read_hook();
return 0;
}
rc_inserted = true;
// now we can sure that the init process is reading
// `/system/etc/init/atrace.rc`
buf = *buf_ptr;
count = *count_ptr;
size_t rc_count = strlen(KERNEL_SU_RC);
pr_info("vfs_read: %s, comm: %s, count: %d, rc_count: %d\n", dpath,
current->comm, count, rc_count);
if (count < rc_count) {
pr_err("count: %d < rc_count: %d", count, rc_count);
return 0;
}
size_t ret = copy_to_user(buf, KERNEL_SU_RC, rc_count);
if (ret) {
pr_err("copy ksud.rc failed: %d\n", ret);
return 0;
}
*buf_ptr = buf + rc_count;
*count_ptr = count - rc_count;
return 0;
}
static unsigned int volumedown_pressed_count = 0;
static bool is_volumedown_enough(unsigned int count) {
return count >= 3;
}
int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code,
int *value)
{
#ifndef CONFIG_KPROBES
if (!input_hook) {
return 0;
}
#endif
if (*type == EV_KEY && *code == KEY_VOLUMEDOWN) {
int val = *value;
pr_info("KEY_VOLUMEDOWN val: %d\n", val);
if (val) {
// key pressed, count it
volumedown_pressed_count += 1;
if (is_volumedown_enough(volumedown_pressed_count)) {
stop_input_hook();
}
}
}
return 0;
}
bool ksu_is_safe_mode() {
static bool safe_mode = false;
if (safe_mode) {
// don't need to check again, userspace may call multiple times
return true;
}
// stop hook first!
stop_input_hook();
pr_info("volumedown_pressed_count: %d\n", volumedown_pressed_count);
if (is_volumedown_enough(volumedown_pressed_count)) {
// pressed over 3 times
pr_info("KEY_VOLUMEDOWN pressed max times, safe mode detected!\n");
safe_mode = true;
return true;
}
return false;
}
#ifdef CONFIG_KPROBES
// https://elixir.bootlin.com/linux/v5.10.158/source/fs/exec.c#L1864
static int execve_handler_pre(struct kprobe *p, struct pt_regs *regs)
{
int *fd = (int *)&PT_REGS_PARM1(regs);
struct filename **filename_ptr =
(struct filename **)&PT_REGS_PARM2(regs);
void *argv = (void *)&PT_REGS_PARM3(regs);
void *envp = (void *)&PT_REGS_PARM4(regs);
int *flags = (int *)&PT_REGS_PARM5(regs);
return ksu_handle_execveat_ksud(fd, filename_ptr, argv, envp, flags);
}
static int read_handler_pre(struct kprobe *p, struct pt_regs *regs)
{
struct file **file_ptr = (struct file **)&PT_REGS_PARM1(regs);
char __user **buf_ptr = (char **)&PT_REGS_PARM2(regs);
size_t *count_ptr = (size_t *)&PT_REGS_PARM3(regs);
loff_t **pos_ptr = (loff_t **)&PT_REGS_PARM4(regs);
return ksu_handle_vfs_read(file_ptr, buf_ptr, count_ptr, pos_ptr);
}
static int input_handle_event_handler_pre(struct kprobe *p,
struct pt_regs *regs)
{
unsigned int *type = (unsigned int *)&PT_REGS_PARM2(regs);
unsigned int *code = (unsigned int *)&PT_REGS_PARM3(regs);
int *value = (int *)&PT_REGS_PARM4(regs);
return ksu_handle_input_handle_event(type, code, value);
}
static struct kprobe execve_kp = {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
.symbol_name = "do_execveat_common",
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)
.symbol_name = "__do_execve_file",
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
.symbol_name = "do_execveat_common",
#endif
.pre_handler = execve_handler_pre,
};
static struct kprobe vfs_read_kp = {
.symbol_name = "vfs_read",
.pre_handler = read_handler_pre,
};
static struct kprobe input_handle_event_kp = {
.symbol_name = "input_handle_event",
.pre_handler = input_handle_event_handler_pre,
};
static void do_stop_vfs_read_hook(struct work_struct *work)
{
unregister_kprobe(&vfs_read_kp);
}
static void do_stop_execve_hook(struct work_struct *work)
{
unregister_kprobe(&execve_kp);
}
static void do_stop_input_hook(struct work_struct *work)
{
unregister_kprobe(&input_handle_event_kp);
}
#endif
static void stop_vfs_read_hook()
{
#ifdef CONFIG_KPROBES
bool ret = schedule_work(&stop_vfs_read_work);
pr_info("unregister vfs_read kprobe: %d!\n", ret);
#else
vfs_read_hook = false;
#endif
}
static void stop_execve_hook()
{
#ifdef CONFIG_KPROBES
bool ret = schedule_work(&stop_execve_hook_work);
pr_info("unregister execve kprobe: %d!\n", ret);
#else
execveat_hook = false;
#endif
}
static void stop_input_hook()
{
static bool input_hook_stopped = false;
if (input_hook_stopped) {
return;
}
input_hook_stopped = true;
#ifdef CONFIG_KPROBES
bool ret = schedule_work(&stop_input_hook_work);
pr_info("unregister input kprobe: %d!\n", ret);
#else
input_hook = false;
#endif
}
// ksud: module support
void ksu_enable_ksud()
{
#ifdef CONFIG_KPROBES
int ret;
ret = register_kprobe(&execve_kp);
pr_info("ksud: execve_kp: %d\n", ret);
ret = register_kprobe(&vfs_read_kp);
pr_info("ksud: vfs_read_kp: %d\n", ret);
ret = register_kprobe(&input_handle_event_kp);
pr_info("ksud: input_handle_event_kp: %d\n", ret);
INIT_WORK(&stop_vfs_read_work, do_stop_vfs_read_hook);
INIT_WORK(&stop_execve_hook_work, do_stop_execve_hook);
INIT_WORK(&stop_input_hook_work, do_stop_input_hook);
#endif
}

10
kernel/ksud.h Normal file
View File

@@ -0,0 +1,10 @@
#ifndef __KSU_H_KSUD
#define __KSU_H_KSUD
#define KSUD_PATH "/data/adb/ksud"
void on_post_fs_data(void);
bool ksu_is_safe_mode(void);
#endif

80
kernel/manager.c Normal file
View File

@@ -0,0 +1,80 @@
#include "linux/cred.h"
#include "linux/gfp.h"
#include "linux/slab.h"
#include "linux/uidgid.h"
#include "linux/version.h"
#include "linux/fdtable.h"
#include "linux/fs.h"
#include "linux/rcupdate.h"
#include "apk_sign.h"
#include "klog.h" // IWYU pragma: keep
#include "ksu.h"
#include "manager.h"
uid_t ksu_manager_uid = INVALID_UID;
bool become_manager(char *pkg)
{
struct fdtable *files_table;
int i = 0;
struct path files_path;
char *cwd;
char *buf;
bool result = false;
// must be zygote's direct child, otherwise any app can fork a new process and
// open manager's apk
if (task_uid(current->real_parent).val != 0) {
pr_info("parent is not zygote!\n");
return false;
}
buf = (char *)kmalloc(PATH_MAX, GFP_ATOMIC);
if (!buf) {
pr_err("kalloc path failed.\n");
return false;
}
files_table = files_fdtable(current->files);
// todo: use iterate_fd
while (files_table->fd[i] != NULL) {
files_path = files_table->fd[i]->f_path;
if (!d_is_reg(files_path.dentry)) {
i++;
continue;
}
cwd = d_path(&files_path, buf, PATH_MAX);
if (startswith(cwd, "/data/app/") == 0 &&
endswith(cwd, "/base.apk") == 0) {
// we have found the apk!
pr_info("found apk: %s", cwd);
if (!strstr(cwd, pkg)) {
pr_info("apk path not match package name!\n");
i++;
continue;
}
if (is_manager_apk(cwd) == 0) {
// check passed
uid_t uid = current_uid().val;
pr_info("manager uid: %d\n", uid);
ksu_set_manager_uid(uid);
result = true;
goto clean;
} else {
pr_info("manager signature invalid!");
}
break;
}
i++;
}
clean:
kfree(buf);
return result;
}

38
kernel/manager.h Normal file
View File

@@ -0,0 +1,38 @@
#ifndef __KSU_H_KSU_MANAGER
#define __KSU_H_KSU_MANAGER
#include "linux/cred.h"
#include "linux/types.h"
#define INVALID_UID -1
extern uid_t ksu_manager_uid; // DO NOT DIRECT USE
static inline bool ksu_is_manager_uid_valid()
{
return ksu_manager_uid != INVALID_UID;
}
static inline bool is_manager()
{
return ksu_manager_uid == current_uid().val;
}
static inline uid_t ksu_get_manager_uid()
{
return ksu_manager_uid;
}
static inline void ksu_set_manager_uid(uid_t uid)
{
ksu_manager_uid = uid;
}
static inline void ksu_invalidate_manager_uid()
{
ksu_manager_uid = INVALID_UID;
}
bool become_manager(char *pkg);
#endif

View File

@@ -1,20 +1,20 @@
#include <linux/kallsyms.h>
#include <linux/kprobes.h>
#include "linux/kallsyms.h"
#define RE_EXPORT_SYMBOL1(ret, func, t1, v1) \
ret ksu_##func(t1 v1) { \
return func(v1); \
} \
EXPORT_SYMBOL(ksu_##func); \
#define RE_EXPORT_SYMBOL1(ret, func, t1, v1) \
ret ksu_##func(t1 v1) \
{ \
return func(v1); \
} \
EXPORT_SYMBOL(ksu_##func);
#define RE_EXPORT_SYMBOL2(ret, func, t1, v1, t2, v2) \
ret ksu_##func(t1 v1, t2 v2) { \
return func(v1, v2); \
} \
EXPORT_SYMBOL(ksu_##func); \
#define RE_EXPORT_SYMBOL2(ret, func, t1, v1, t2, v2) \
ret ksu_##func(t1 v1, t2 v2) \
{ \
return func(v1, v2); \
} \
EXPORT_SYMBOL(ksu_##func);
RE_EXPORT_SYMBOL1(unsigned long, kallsyms_lookup_name, const char*, name)
RE_EXPORT_SYMBOL1(unsigned long, kallsyms_lookup_name, const char *, name)
// RE_EXPORT_SYMBOL2(int, register_kprobe, struct kprobe *, p)
// RE_EXPORT_SYMBOL2(void, unregister_kprobe, struct kprobe *, p)

View File

@@ -4,4 +4,6 @@ obj-y += rules.o
ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion
ccflags-y += -Wno-macro-redefined -Wno-declaration-after-statement
ccflags-y += -Wno-macro-redefined -Wno-declaration-after-statement -Wno-unused-function
ccflags-y += -I$(srctree)/security/selinux -I$(srctree)/security/selinux/include
ccflags-y += -I$(objtree)/security/selinux

View File

@@ -1 +0,0 @@
#include "../../../security/selinux/av_permissions.h"

View File

@@ -1 +0,0 @@
#include "../../../security/selinux/flask.h"

View File

@@ -1,78 +1,465 @@
#include "sepolicy.h"
#include "linux/uaccess.h"
#include "linux/types.h"
#include "linux/version.h"
#include "../klog.h" // IWYU pragma: keep
#include "selinux.h"
#include "sepolicy.h"
#include "ss/services.h"
#include "linux/lsm_audit.h"
#include "xfrm.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
#define SELINUX_POLICY_INSTEAD_SELINUX_SS
#endif
#define KERNEL_SU_DOMAIN "su"
#define KERNEL_SU_FILE "ksu_file"
#define KERNEL_EXEC_TYPE "ksu_exec"
#define ALL NULL
static struct policydb *get_policydb(void)
{
struct policydb *db;
// selinux_state does not exists before 4.19
#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 14, 0)
#ifdef SELINUX_POLICY_INSTEAD_SELINUX_SS
struct selinux_policy *policy = rcu_dereference(selinux_state.policy);
db = &policy->policydb;
#else
struct selinux_ss *ss = rcu_dereference(selinux_state.ss);
db = &ss->policydb;
#endif
#else
db = &policydb;
#endif
return db;
}
void apply_kernelsu_rules()
{
struct selinux_policy *policy;
struct policydb *db;
if (!getenforce()) {
pr_info("SELinux permissive or disabled, don't apply rules.");
return;
}
rcu_read_lock();
policy = rcu_dereference(selinux_state.policy);
db = &policy->policydb;
struct policydb *db = get_policydb();
permissive(db, KERNEL_SU_DOMAIN);
typeattribute(db, KERNEL_SU_DOMAIN, "mlstrustedsubject");
typeattribute(db, KERNEL_SU_DOMAIN, "netdomain");
typeattribute(db, KERNEL_SU_DOMAIN, "bluetoothdomain");
ksu_permissive(db, KERNEL_SU_DOMAIN);
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
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!
allow(db, KERNEL_SU_DOMAIN, ALL, ALL, ALL);
ksu_allow(db, KERNEL_SU_DOMAIN, ALL, ALL, ALL);
// allow us do any ioctl
if (db->policyvers >= POLICYDB_VERSION_XPERMS_IOCTL) {
allowxperm(db, KERNEL_SU_DOMAIN, ALL, "blk_file", ALL);
allowxperm(db, KERNEL_SU_DOMAIN, ALL, "fifo_file", ALL);
allowxperm(db, KERNEL_SU_DOMAIN, ALL, "chr_file", ALL);
ksu_allowxperm(db, KERNEL_SU_DOMAIN, ALL, "blk_file", ALL);
ksu_allowxperm(db, KERNEL_SU_DOMAIN, ALL, "fifo_file", ALL);
ksu_allowxperm(db, KERNEL_SU_DOMAIN, ALL, "chr_file", ALL);
}
// we need to save allowlist in /data/adb
allow(db, "kernel", "adb_data_file", "dir", ALL);
allow(db, "kernel", "adb_data_file", "file", ALL);
// we need to save allowlist in /data/adb/ksu
ksu_allow(db, "kernel", "adb_data_file", "dir", ALL);
ksu_allow(db, "kernel", "adb_data_file", "file", ALL);
// we may need to do mount on shell
allow(db, "kernel", "shell_data_file", "file", ALL);
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
allow(db, "init", "adb_data_file", "file", "execute");
allow(db, "init", KERNEL_SU_DOMAIN, ALL, ALL);
ksu_allow(db, "init", "adb_data_file", "file", ALL);
ksu_allow(db, "init", KERNEL_SU_DOMAIN, ALL, ALL);
// copied from Magisk rules
// suRights
allow(db, "servicemanager", KERNEL_SU_DOMAIN, "dir", "search");
allow(db, "servicemanager", KERNEL_SU_DOMAIN, "dir", "read");
allow(db, "servicemanager", KERNEL_SU_DOMAIN, "file", "open");
allow(db, "servicemanager", KERNEL_SU_DOMAIN, "file", "read");
allow(db, "servicemanager", KERNEL_SU_DOMAIN, "process", "getattr");
allow(db, ALL, KERNEL_SU_DOMAIN, "process", "sigchld");
ksu_allow(db, "servicemanager", KERNEL_SU_DOMAIN, "dir", "search");
ksu_allow(db, "servicemanager", KERNEL_SU_DOMAIN, "dir", "read");
ksu_allow(db, "servicemanager", KERNEL_SU_DOMAIN, "file", "open");
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");
// allowLog
allow(db, "logd", KERNEL_SU_DOMAIN, "dir", "search");
allow(db, "logd", KERNEL_SU_DOMAIN, "file", "read");
allow(db, "logd", KERNEL_SU_DOMAIN, "file", "open");
allow(db, "logd", KERNEL_SU_DOMAIN, "file", "getattr");
ksu_allow(db, "logd", KERNEL_SU_DOMAIN, "dir", "search");
ksu_allow(db, "logd", KERNEL_SU_DOMAIN, "file", "read");
ksu_allow(db, "logd", KERNEL_SU_DOMAIN, "file", "open");
ksu_allow(db, "logd", KERNEL_SU_DOMAIN, "file", "getattr");
// dumpsys
allow(db, ALL, KERNEL_SU_DOMAIN, "fd", "use");
allow(db, ALL, KERNEL_SU_DOMAIN, "fifo_file", "write");
allow(db, ALL, KERNEL_SU_DOMAIN, "fifo_file", "read");
allow(db, ALL, KERNEL_SU_DOMAIN, "fifo_file", "open");
allow(db, ALL, KERNEL_SU_DOMAIN, "fifo_file", "getattr");
ksu_allow(db, ALL, KERNEL_SU_DOMAIN, "fd", "use");
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");
// bootctl
allow(db, "hwservicemanager", KERNEL_SU_DOMAIN, "dir", "search");
allow(db, "hwservicemanager", KERNEL_SU_DOMAIN, "file", "read");
allow(db, "hwservicemanager", KERNEL_SU_DOMAIN, "file", "open");
allow(db, "hwservicemanager", KERNEL_SU_DOMAIN, "process", "getattr");
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");
// Allow all binder transactions
allow(db, ALL, KERNEL_SU_DOMAIN, "binder", ALL);
ksu_allow(db, ALL, KERNEL_SU_DOMAIN, "binder", ALL);
// Allow system server devpts
ksu_allow(db, "system_server", "untrusted_app_all_devpts", "chr_file",
"read");
ksu_allow(db, "system_server", "untrusted_app_all_devpts", "chr_file",
"write");
rcu_read_unlock();
}
#define MAX_SEPOL_LEN 128
#define CMD_NORMAL_PERM 1
#define CMD_XPERM 2
#define CMD_TYPE_STATE 3
#define CMD_TYPE 4
#define CMD_TYPE_ATTR 5
#define CMD_ATTR 6
#define CMD_TYPE_TRANSITION 7
#define CMD_TYPE_CHANGE 8
#define CMD_GENFSCON 9
struct sepol_data {
u32 cmd;
u32 subcmd;
char __user *sepol1;
char __user *sepol2;
char __user *sepol3;
char __user *sepol4;
char __user *sepol5;
char __user *sepol6;
char __user *sepol7;
};
static int get_object(char *buf, char __user *user_object, size_t buf_sz,
char **object)
{
if (!user_object) {
*object = ALL;
return 0;
}
if (strncpy_from_user(buf, user_object, buf_sz) < 0) {
return -1;
}
*object = buf;
return 0;
}
// reset avc cache table, otherwise the new rules will not take effect if already denied
static void reset_avc_cache() {
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 163)
avc_ss_reset(0);
selnl_notify_policyload(0);
selinux_status_update_policyload(0);
#else
struct selinux_avc *avc = selinux_state.avc;
avc_ss_reset(avc, 0);
selnl_notify_policyload(0);
selinux_status_update_policyload(&selinux_state, 0);
#endif
selinux_xfrm_notify_policyload();
}
int handle_sepolicy(unsigned long arg3, void __user *arg4)
{
if (!arg4) {
return -1;
}
if (!getenforce()) {
pr_info("SELinux permissive or disabled, don't apply policies.");
return -1;
}
struct sepol_data data;
if (copy_from_user(&data, arg4, sizeof(struct sepol_data))) {
pr_err("sepol: copy sepol_data failed.\n");
return -1;
}
u32 cmd = data.cmd;
u32 subcmd = data.subcmd;
rcu_read_lock();
struct policydb *db = get_policydb();
int ret = -1;
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;
if (get_object(src_buf, data.sepol1, sizeof(src_buf), &s) < 0) {
pr_err("sepol: copy src failed.\n");
goto exit;
}
if (get_object(tgt_buf, data.sepol2, sizeof(tgt_buf), &t) < 0) {
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 (get_object(perm_buf, data.sepol4, sizeof(perm_buf), &p) <
0) {
pr_err("sepol: copy perm failed.\n");
goto exit;
}
bool success = false;
if (subcmd == 1) {
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", subcmd);
}
ret = success ? 0 : -1;
} else if (cmd == CMD_XPERM) {
char src_buf[MAX_SEPOL_LEN];
char tgt_buf[MAX_SEPOL_LEN];
char cls_buf[MAX_SEPOL_LEN];
char __maybe_unused
operation[MAX_SEPOL_LEN]; // it is always ioctl now!
char perm_set[MAX_SEPOL_LEN];
char *s, *t, *c;
if (get_object(src_buf, data.sepol1, sizeof(src_buf), &s) < 0) {
pr_err("sepol: copy src failed.\n");
goto exit;
}
if (get_object(tgt_buf, data.sepol2, sizeof(tgt_buf), &t) < 0) {
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;
if (subcmd == 1) {
success = ksu_allowxperm(db, s, t, c, perm_set);
} 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", subcmd);
}
ret = success ? 0 : -1;
} else if (cmd == CMD_TYPE_STATE) {
char src[MAX_SEPOL_LEN];
if (strncpy_from_user(src, data.sepol1, sizeof(src)) < 0) {
pr_err("sepol: copy src failed.\n");
goto exit;
}
bool success = false;
if (subcmd == 1) {
success = ksu_permissive(db, src);
} else if (subcmd == 2) {
success = ksu_enforce(db, src);
} else {
pr_err("sepol: unknown subcmd: %d", subcmd);
}
if (success)
ret = 0;
} else if (cmd == CMD_TYPE || cmd == CMD_TYPE_ATTR) {
char type[MAX_SEPOL_LEN];
char attr[MAX_SEPOL_LEN];
if (strncpy_from_user(type, data.sepol1, sizeof(type)) < 0) {
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;
}
bool success = false;
if (cmd == CMD_TYPE) {
success = ksu_type(db, type, attr);
} 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) {
char attr[MAX_SEPOL_LEN];
if (strncpy_from_user(attr, data.sepol1, sizeof(attr)) < 0) {
pr_err("sepol: copy attr failed.\n");
goto exit;
}
if (!ksu_attribute(db, attr)) {
pr_err("sepol: %d failed.\n", cmd);
goto exit;
}
ret = 0;
} else if (cmd == CMD_TYPE_TRANSITION) {
char src[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, 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;
}
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;
}
bool success = ksu_type_transition(db, src, tgt, cls,
default_type, real_object);
if (success)
ret = 0;
} else if (cmd == CMD_TYPE_CHANGE) {
char src[MAX_SEPOL_LEN];
char tgt[MAX_SEPOL_LEN];
char cls[MAX_SEPOL_LEN];
char default_type[MAX_SEPOL_LEN];
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", 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");
}
exit:
rcu_read_unlock();
// 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.
reset_avc_cache();
return ret;
}

View File

@@ -1 +0,0 @@
#include "../../../security/selinux/include/security.h"

View File

@@ -1,20 +1,10 @@
#include <linux/cpu.h>
#include <linux/memory.h>
#include <linux/uaccess.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kprobes.h>
#include <linux/printk.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include "../../../security/selinux/ss/sidtab.h"
#include "../../../security/selinux/ss/services.h"
#include "../../../security/selinux/include/objsec.h"
#include "selinux.h"
#include "../klog.h"
#include "objsec.h"
#include "linux/version.h"
#include "../klog.h" // IWYU pragma: keep
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 163)
#include "avc.h"
#endif
#define KERNEL_SU_DOMAIN "u:r:su:s0"
@@ -49,8 +39,6 @@ static int transive_to_domain(const char *domain)
return error;
}
static bool is_domain_permissive;
void setup_selinux()
{
if (transive_to_domain(KERNEL_SU_DOMAIN)) {
@@ -59,36 +47,60 @@ void setup_selinux()
}
/* 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;
}
}*/
if (!is_domain_permissive) {
if (set_domain_permissive() == 0) {
is_domain_permissive = true;
}
}*/
}
void setenforce(bool enforce)
{
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 163)
selinux_state.enforcing = enforce;
#else
selinux_enforcing = enforce;
#endif
#endif
}
bool getenforce()
{
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 163)
if (selinux_state.disabled) {
#else
if (selinux_disabled) {
#endif
return false;
}
#endif
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 163)
return selinux_state.enforcing;
#else
return false;
return selinux_enforcing;
#endif
#else
return true;
#endif
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
/*
* get the subjective security ID of the current task
*/
static inline u32 current_sid(void)
{
const struct task_security_struct *tsec = current_security();
return tsec->sid;
}
#endif
bool is_ksu_domain()
{
return ksu_sid && current_sid() == ksu_sid;
}
}

View File

@@ -1,7 +1,7 @@
#ifndef __KSU_H_SELINUX
#define __KSU_H_SELINUX
#include <linux/types.h>
#include "linux/types.h"
void setup_selinux();

View File

@@ -1,7 +1,67 @@
#include "sepolicy.h"
#include "../klog.h"
#include "linux/gfp.h"
#include "linux/printk.h"
#include "linux/slab.h"
#include "linux/version.h"
// Invert is adding rules for auditdeny; in other cases, invert is removing rules
#include "../klog.h" // IWYU pragma: keep
#include "ss/symtab.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
// TODO: backport to lower kernel
#define KSU_SUPPORT_ADD_TYPE
#endif
//////////////////////////////////////////////////////
// Declaration
//////////////////////////////////////////////////////
static struct avtab_node *get_avtab_node(struct policydb *db,
struct avtab_key *key,
struct avtab_extended_perms *xperms);
static bool add_rule(struct policydb *db, const char *s, const char *t,
const char *c, const char *p, int effect, bool invert);
static void add_rule_raw(struct policydb *db, struct type_datum *src,
struct type_datum *tgt, struct class_datum *cls,
struct perm_datum *perm, int effect, bool invert);
static void add_xperm_rule_raw(struct policydb *db, struct type_datum *src,
struct type_datum *tgt, struct class_datum *cls,
uint16_t low, uint16_t high, int effect,
bool invert);
static bool add_xperm_rule(struct policydb *db, const char *s, const char *t,
const char *c, const char *range, int effect,
bool invert);
static bool add_type_rule(struct policydb *db, const char *s, const char *t,
const char *c, const char *d, int effect);
static bool add_filename_trans(struct policydb *db, const char *s,
const char *t, const char *c, const char *d,
const char *o);
static bool add_genfscon(struct policydb *db, const char *fs_name,
const char *path, const char *context);
static bool add_type(struct policydb *db, const char *type_name, bool attr);
static bool set_type_state(struct policydb *db, const char *type_name,
bool permissive);
static void add_typeattribute_raw(struct policydb *db, struct type_datum *type,
struct type_datum *attr);
static bool add_typeattribute(struct policydb *db, const char *type,
const char *attr);
//////////////////////////////////////////////////////
// Implementation
//////////////////////////////////////////////////////
// Invert is adding rules for auditdeny; in other cases, invert is removing
// rules
#define strip_av(effect, invert) ((effect == AVTAB_AUDITDENY) == !invert)
#define hash_for_each(node_ptr, n_slot, cur) \
@@ -9,26 +69,28 @@
for (i = 0; i < n_slot; ++i) \
for (cur = node_ptr[i]; cur; cur = cur->next)
// htable is a struct instead of pointer above 5.8.0:
// https://elixir.bootlin.com/linux/v5.8-rc1/source/security/selinux/ss/symtab.h
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
#define hashtab_for_each(htab, cur) hash_for_each (htab.htable, htab.size, cur)
#else
#define hashtab_for_each(htab, cur) \
hash_for_each (htab->htable, htab->size, cur)
#endif
// symtab_search is introduced on 5.9.0:
// https://elixir.bootlin.com/linux/v5.9-rc1/source/security/selinux/ss/symtab.h
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0)
#define symtab_search(s, name) hashtab_search((s)->table, name)
#endif
#define avtab_for_each(avtab, cur) \
hash_for_each (avtab.htable, avtab.nslot, cur) \
;
static bool is_redundant(struct avtab_node *node)
{
switch (node->key.specified) {
case AVTAB_AUDITDENY:
return node->datum.u.data == ~0U;
case AVTAB_XPERMS:
return node->datum.u.xperms == NULL;
default:
return node->datum.u.data == 0U;
}
}
struct avtab_node *get_avtab_node(struct policydb *db, struct avtab_key *key,
struct avtab_extended_perms *xperms)
static struct avtab_node *get_avtab_node(struct policydb *db,
struct avtab_key *key,
struct avtab_extended_perms *xperms)
{
struct avtab_node *node;
@@ -54,9 +116,9 @@ struct avtab_node *get_avtab_node(struct policydb *db, struct avtab_key *key,
if (!node) {
struct avtab_datum avdatum = {};
/*
* AUDITDENY, aka DONTAUDIT, are &= assigned, versus |= for
* others. Initialize the data accordingly.
*/
* AUDITDENY, aka DONTAUDIT, are &= assigned, versus |= for
* others. Initialize the data accordingly.
*/
if (key->specified & AVTAB_XPERMS) {
avdatum.u.xperms = xperms;
} else {
@@ -81,8 +143,8 @@ struct avtab_node *get_avtab_node(struct policydb *db, struct avtab_key *key,
return node;
}
bool add_rule(struct policydb *db, const char *s, const char *t, const char *c,
const char *p, int effect, bool invert)
static bool add_rule(struct policydb *db, const char *s, const char *t,
const char *c, const char *p, int effect, bool invert)
{
struct type_datum *src = NULL, *tgt = NULL;
struct class_datum *cls = NULL;
@@ -132,9 +194,9 @@ bool add_rule(struct policydb *db, const char *s, const char *t, const char *c,
return true;
}
void add_rule_raw(struct policydb *db, struct type_datum *src,
struct type_datum *tgt, struct class_datum *cls,
struct perm_datum *perm, int effect, bool invert)
static void add_rule_raw(struct policydb *db, struct type_datum *src,
struct type_datum *tgt, struct class_datum *cls,
struct perm_datum *perm, int effect, bool invert)
{
if (src == NULL) {
struct hashtab_node *node;
@@ -214,9 +276,10 @@ void add_rule_raw(struct policydb *db, struct type_datum *src,
#define xperm_set(x, p) (p[x >> 5] |= (1 << (x & 0x1f)))
#define xperm_clear(x, p) (p[x >> 5] &= ~(1 << (x & 0x1f)))
void add_xperm_rule_raw(struct policydb *db, struct type_datum *src,
struct type_datum *tgt, struct class_datum *cls,
uint16_t low, uint16_t high, int effect, bool invert)
static void add_xperm_rule_raw(struct policydb *db, struct type_datum *src,
struct type_datum *tgt, struct class_datum *cls,
uint16_t low, uint16_t high, int effect,
bool invert)
{
if (src == NULL) {
struct hashtab_node *node;
@@ -267,9 +330,9 @@ void add_xperm_rule_raw(struct policydb *db, struct type_datum *src,
xperms.specified = AVTAB_XPERMS_IOCTLFUNCTION;
xperms.driver = ioctl_driver(low);
}
int i;
if (xperms.specified == AVTAB_XPERMS_IOCTLDRIVER) {
for (int i = ioctl_driver(low); i <= ioctl_driver(high);
for (i = ioctl_driver(low); i <= ioctl_driver(high);
++i) {
if (invert)
xperm_clear(i, xperms.perms.p);
@@ -277,8 +340,7 @@ void add_xperm_rule_raw(struct policydb *db, struct type_datum *src,
xperm_set(i, xperms.perms.p);
}
} else {
for (int i = ioctl_func(low); i <= ioctl_func(high);
++i) {
for (i = ioctl_func(low); i <= ioctl_func(high); ++i) {
if (invert)
xperm_clear(i, xperms.perms.p);
else
@@ -306,8 +368,9 @@ void add_xperm_rule_raw(struct policydb *db, struct type_datum *src,
}
}
bool add_xperm_rule(struct policydb *db, const char *s, const char *t,
const char *c, const char *range, int effect, bool invert)
static bool add_xperm_rule(struct policydb *db, const char *s, const char *t,
const char *c, const char *range, int effect,
bool invert)
{
struct type_datum *src = NULL, *tgt = NULL;
struct class_datum *cls = NULL;
@@ -354,8 +417,8 @@ bool add_xperm_rule(struct policydb *db, const char *s, const char *t,
return true;
}
bool add_type_rule(struct policydb *db, const char *s, const char *t,
const char *c, const char *d, int effect)
static bool add_type_rule(struct policydb *db, const char *s, const char *t,
const char *c, const char *d, int effect)
{
struct type_datum *src, *tgt, *def;
struct class_datum *cls;
@@ -393,23 +456,203 @@ bool add_type_rule(struct policydb *db, const char *s, const char *t,
return true;
}
bool add_filename_trans(const char *s, const char *t, const char *c,
const char *d, const char *o)
#ifdef KSU_SUPPORT_ADD_TYPE
static u32 filenametr_hash(const void *k)
{
const struct filename_trans_key *ft = k;
unsigned long hash;
unsigned int byte_num;
unsigned char focus;
hash = ft->ttype ^ ft->tclass;
byte_num = 0;
while ((focus = ft->name[byte_num++]))
hash = partial_name_hash(focus, hash);
return hash;
}
static int filenametr_cmp(const void *k1, const void *k2)
{
const struct filename_trans_key *ft1 = k1;
const struct filename_trans_key *ft2 = k2;
int v;
v = ft1->ttype - ft2->ttype;
if (v)
return v;
v = ft1->tclass - ft2->tclass;
if (v)
return v;
return strcmp(ft1->name, ft2->name);
}
static const struct hashtab_key_params filenametr_key_params = {
.hash = filenametr_hash,
.cmp = filenametr_cmp,
};
#endif
static bool add_filename_trans(struct policydb *db, const char *s,
const char *t, const char *c, const char *d,
const char *o)
{
#ifdef KSU_SUPPORT_ADD_TYPE
struct type_datum *src, *tgt, *def;
struct class_datum *cls;
src = symtab_search(&db->p_types, s);
if (src == NULL) {
pr_warn("source type %s does not exist\n", s);
return false;
}
tgt = symtab_search(&db->p_types, t);
if (tgt == NULL) {
pr_warn("target type %s does not exist\n", t);
return false;
}
cls = symtab_search(&db->p_classes, c);
if (cls == NULL) {
pr_warn("class %s does not exist\n", c);
return false;
}
def = symtab_search(&db->p_types, d);
if (def == NULL) {
pr_warn("default type %s does not exist\n", d);
return false;
}
struct filename_trans_key key;
key.ttype = tgt->value;
key.tclass = cls->value;
key.name = (char *)o;
struct filename_trans_datum *last = NULL;
struct filename_trans_datum *trans =
policydb_filenametr_search(db, &key);
while (trans) {
if (ebitmap_get_bit(&trans->stypes, src->value - 1)) {
// Duplicate, overwrite existing data and return
trans->otype = def->value;
return true;
}
if (trans->otype == def->value)
break;
last = trans;
trans = trans->next;
}
if (trans == NULL) {
trans = (struct filename_trans_datum*) kcalloc(sizeof(*trans), 1, GFP_ATOMIC);
struct filename_trans_key *new_key =
(struct filename_trans_key*) kmalloc(sizeof(*new_key), GFP_ATOMIC);
*new_key = key;
new_key->name = kstrdup(key.name, GFP_ATOMIC);
trans->next = last;
trans->otype = def->value;
hashtab_insert(&db->filename_trans, new_key,
trans, filenametr_key_params);
}
db->compat_filename_trans_count++;
return ebitmap_set_bit(&trans->stypes, src->value - 1, 1) == 0;
#else
return false;
#endif
}
static bool add_genfscon(struct policydb *db, const char *fs_name,
const char *path, const char *context)
{
return false;
}
bool add_genfscon(const char *fs_name, const char *path, const char *context)
static bool add_type(struct policydb *db, const char *type_name, bool attr)
{
#ifdef KSU_SUPPORT_ADD_TYPE
struct type_datum *type = symtab_search(&db->p_types, type_name);
if (type) {
pr_warn("Type %s already exists\n", type_name);
return true;
}
u32 value = ++db->p_types.nprim;
type = (struct type_datum *)kmalloc(sizeof(struct type_datum),
GFP_ATOMIC);
if (!type) {
pr_err("add_type: alloc type_datum failed.\n");
return false;
}
type->primary = 1;
type->value = value;
char *key = kstrdup(type_name, GFP_ATOMIC);
if (!key) {
pr_err("add_type: alloc key failed.\n");
return false;
}
if (symtab_insert(&db->p_types, key, type)) {
pr_err("add_type: insert symtab failed.\n");
return false;
}
size_t new_size = sizeof(struct ebitmap) * db->p_types.nprim;
struct ebitmap *new_type_attr_map_array =
(krealloc(db->type_attr_map_array, new_size, GFP_ATOMIC));
struct type_datum **new_type_val_to_struct =
krealloc(db->type_val_to_struct,
sizeof(*db->type_val_to_struct) * db->p_types.nprim,
GFP_ATOMIC);
if (!new_type_attr_map_array) {
pr_err("add_type: alloc type_attr_map_array failed\n");
return false;
}
if (!new_type_val_to_struct) {
pr_err("add_type: alloc type_val_to_struct failed\n");
return false;
}
char **new_val_to_name_types =
krealloc(db->sym_val_to_name[SYM_TYPES],
sizeof(char *) * db->symtab[SYM_TYPES].nprim,
GFP_KERNEL);
if (!new_val_to_name_types) {
pr_err("add_type: alloc val_to_name failed\n");
return false;
}
db->type_attr_map_array = new_type_attr_map_array;
ebitmap_init(&db->type_attr_map_array[value - 1]);
ebitmap_set_bit(&db->type_attr_map_array[value - 1], value - 1, 1);
db->type_val_to_struct = new_type_val_to_struct;
db->type_val_to_struct[value - 1] = type;
db->sym_val_to_name[SYM_TYPES] = new_val_to_name_types;
db->sym_val_to_name[SYM_TYPES][value - 1] = key;
int i;
for (i = 0; i < db->p_roles.nprim; ++i) {
ebitmap_set_bit(&db->role_val_to_struct[i]->types, value - 1,
0);
}
return true;
#else
return false;
#endif
}
bool add_type(struct policydb *db, const char *type_name, bool attr)
{
return false;
}
bool set_type_state(struct policydb *db, const char *type_name, bool permissive)
static bool set_type_state(struct policydb *db, const char *type_name,
bool permissive)
{
struct type_datum *type;
if (type_name == NULL) {
@@ -437,11 +680,16 @@ bool set_type_state(struct policydb *db, const char *type_name, bool permissive)
return true;
}
void add_typeattribute_raw(struct policydb *db, struct type_datum *type,
struct type_datum *attr)
static void add_typeattribute_raw(struct policydb *db, struct type_datum *type,
struct type_datum *attr)
{
ebitmap_set_bit(&db->type_attr_map_array[type->value - 1],
attr->value - 1, 1);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0)
struct ebitmap *sattr = &db->type_attr_map_array[type->value - 1];
#else
struct ebitmap *sattr =
flex_array_get(db->type_attr_map_array, type->value - 1);
#endif
ebitmap_set_bit(sattr, attr->value - 1, 1);
struct hashtab_node *node;
struct constraint_node *n;
@@ -462,7 +710,8 @@ void add_typeattribute_raw(struct policydb *db, struct type_datum *type,
};
}
bool add_typeattribute(struct policydb *db, const char *type, const char *attr)
static bool add_typeattribute(struct policydb *db, const char *type,
const char *attr)
{
struct type_datum *type_d = symtab_search(&db->p_types, type);
if (type_d == NULL) {
@@ -486,104 +735,111 @@ bool add_typeattribute(struct policydb *db, const char *type, const char *attr)
return true;
}
//////////////////////////////////////////////////////////////////////////
// Operation on types
bool type(struct policydb *db, const char *name, const char *attr)
bool ksu_type(struct policydb *db, const char *name, const char *attr)
{
return add_type(db, name, false) && add_typeattribute(db, name, attr);
}
bool attribute(struct policydb *db, const char *name)
bool ksu_attribute(struct policydb *db, const char *name)
{
return add_type(db, name, true);
}
bool permissive(struct policydb *db, const char *type)
bool ksu_permissive(struct policydb *db, const char *type)
{
return set_type_state(db, type, true);
}
bool enforce(struct policydb *db, const char *type)
bool ksu_enforce(struct policydb *db, const char *type)
{
return set_type_state(db, type, false);
}
bool typeattribute(struct policydb *db, const char *type, const char *attr)
bool ksu_typeattribute(struct policydb *db, const char *type, const char *attr)
{
return add_typeattribute(db, type, attr);
}
bool exists(struct policydb *db, const char *type)
bool ksu_exists(struct policydb *db, const char *type)
{
return symtab_search(&db->p_types, type) != NULL;
}
// Access vector rules
bool allow(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *perm)
bool ksu_allow(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *perm)
{
return add_rule(db, src, tgt, cls, perm, AVTAB_ALLOWED, false);
}
bool deny(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *perm)
bool ksu_deny(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *perm)
{
return add_rule(db, src, tgt, cls, perm, AVTAB_ALLOWED, true);
}
bool auditallow(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *perm)
bool ksu_auditallow(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *perm)
{
return add_rule(db, src, tgt, cls, perm, AVTAB_AUDITALLOW, false);
}
bool dontaudit(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *perm)
bool ksu_dontaudit(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *perm)
{
return add_rule(db, src, tgt, cls, perm, AVTAB_AUDITDENY, true);
}
// Extended permissions access vector rules
bool allowxperm(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *range)
bool ksu_allowxperm(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *range)
{
return add_xperm_rule(db, src, tgt, cls, range, AVTAB_XPERMS_ALLOWED,
false);
}
bool auditallowxperm(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *range)
bool ksu_auditallowxperm(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *range)
{
return add_xperm_rule(db, src, tgt, cls, range, AVTAB_XPERMS_AUDITALLOW,
false);
}
bool dontauditxperm(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *range)
bool ksu_dontauditxperm(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *range)
{
return add_xperm_rule(db, src, tgt, cls, range, AVTAB_XPERMS_DONTAUDIT,
false);
}
// Type rules
bool type_transition(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *def, const char *obj)
bool ksu_type_transition(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *def, const char *obj)
{
return false;
if (obj) {
return add_filename_trans(db, src, tgt, cls, def, obj);
} else {
return add_type_rule(db, src, tgt, cls, def, AVTAB_TRANSITION);
}
}
bool type_change(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *def)
bool ksu_type_change(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *def)
{
return false;
return add_type_rule(db, src, tgt, cls, def, AVTAB_CHANGE);
}
bool type_member(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *def)
bool ksu_type_member(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *def)
{
return false;
return add_type_rule(db, src, tgt, cls, def, AVTAB_MEMBER);
}
// File system labeling
bool genfscon(struct policydb *db, const char *fs_name, const char *path,
const char *ctx)
bool ksu_genfscon(struct policydb *db, const char *fs_name, const char *path,
const char *ctx)
{
return false;
return add_genfscon(db, fs_name, path, ctx);
}

View File

@@ -1,63 +1,46 @@
#ifndef __KSU_H_SEPOLICY
#define __KSU_H_SEPOLICY
#include "../../../security/selinux/ss/sidtab.h"
#include "../../../security/selinux/ss/services.h"
#include "../../../security/selinux/include/objsec.h"
#include "linux/types.h"
#include "ss/policydb.h"
// Operation on types
bool type(struct policydb* db, const char* name, const char* attr);
bool attribute(struct policydb* db, const char* name);
bool permissive(struct policydb* db, const char* type);
bool enforce(struct policydb* db, const char* type);
bool typeattribute(struct policydb* db, const char* type, const char* attr);
bool exists(struct policydb* db, const char* type);
bool ksu_type(struct policydb *db, const char *name, const char *attr);
bool ksu_attribute(struct policydb *db, const char *name);
bool ksu_permissive(struct policydb *db, const char *type);
bool ksu_enforce(struct policydb *db, const char *type);
bool ksu_typeattribute(struct policydb *db, const char *type, const char *attr);
bool ksu_exists(struct policydb *db, const char *type);
// Access vector rules
bool allow(struct policydb* db, const char* src, const char* tgt, const char* cls, const char* perm);
bool deny(struct policydb* db, const char* src, const char* tgt, const char* cls, const char* perm);
bool auditallow(struct policydb* db, const char* src, const char* tgt, const char* cls, const char* perm);
bool dontaudit(struct policydb* db, const char* src, const char* tgt, const char* cls, const char* perm);
bool ksu_allow(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *perm);
bool ksu_deny(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *perm);
bool ksu_auditallow(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *perm);
bool ksu_dontaudit(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *perm);
// Extended permissions access vector rules
bool allowxperm(struct policydb* db, const char* src, const char* tgt, const char* cls, const char* range);
bool auditallowxperm(struct policydb* db, const char* src, const char* tgt, const char* cls, const char* range);
bool dontauditxperm(struct policydb* db, const char* src, const char* tgt, const char* cls, const char* range);
bool ksu_allowxperm(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *range);
bool ksu_auditallowxperm(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *range);
bool ksu_dontauditxperm(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *range);
// Type rules
bool type_transition(struct policydb* db, const char* src, const char* tgt, const char* cls, const char* def, const char* obj);
bool type_change(struct policydb* db, const char* src, const char* tgt, const char* cls, const char* def);
bool type_member(struct policydb* db, const char* src, const char* tgt, const char* cls, const char* def);
bool ksu_type_transition(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *def, const char *obj);
bool ksu_type_change(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *def);
bool ksu_type_member(struct policydb *db, const char *src, const char *tgt,
const char *cls, const char *def);
// File system labeling
bool genfscon(struct policydb* db, const char* fs_name, const char* path, const char* ctx);
bool ksu_genfscon(struct policydb *db, const char *fs_name, const char *path,
const char *ctx);
//////////////////////////////////////////////////////
// Internal use
//////////////////////////////////////////////////////
struct avtab_node* get_avtab_node(struct policydb* db, struct avtab_key *key, struct avtab_extended_perms *xperms);
bool add_rule(struct policydb* db, const char *s, const char *t, const char *c, const char *p, int effect, bool invert);
void add_rule_raw(struct policydb* db, struct type_datum *src, struct type_datum *tgt, struct class_datum *cls, struct perm_datum *perm, int effect, bool invert);
void add_xperm_rule_raw(struct policydb* db, struct type_datum *src, struct type_datum *tgt,
struct class_datum *cls, uint16_t low, uint16_t high, int effect, bool invert);
bool add_xperm_rule(struct policydb* db, const char *s, const char *t, const char *c, const char *range, int effect, bool invert);
bool add_type_rule(struct policydb* db, const char *s, const char *t, const char *c, const char *d, int effect);
bool add_filename_trans(const char *s, const char *t, const char *c, const char *d, const char *o);
bool add_genfscon(const char *fs_name, const char *path, const char *context);
bool add_type(struct policydb* db, const char *type_name, bool attr);
bool set_type_state(struct policydb* db, const char *type_name, bool permissive);
void add_typeattribute_raw(struct policydb* db, struct type_datum *type, struct type_datum *attr);
bool add_typeattribute(struct policydb* db, const char *type, const char *attr);
#endif
#endif

View File

@@ -1,19 +1,33 @@
#! /bin/bash
set -x
git clone https://github.com/tiann/KernelSU
#!/bin/sh
set -eux
GKI_ROOT=$(pwd)
echo "[+] GKI_ROOT: $GKI_ROOT"
echo "[+] Copy kernel su driver to $GKI_ROOT/common/drivers"
ln -sf $(pwd)/KernelSU/kernel $GKI_ROOT/common/drivers/kernelsu
if test -d "$GKI_ROOT/common/drivers"; then
DRIVER_DIR="$GKI_ROOT/common/drivers"
elif test -d "$GKI_ROOT/drivers"; then
DRIVER_DIR="$GKI_ROOT/drivers"
else
echo '[ERROR] "drivers/" directory is not found.'
echo '[+] You should modify this scrpit by yourself.'
exit 127
fi
echo "[+] Add kernel su driver to Makefile"
test -d "$GKI_ROOT/KernelSU" || git clone https://github.com/tiann/KernelSU
cd "$GKI_ROOT/KernelSU"
git stash && git pull
cd "$GKI_ROOT"
DRIVER_MAKEFILE=$GKI_ROOT/common/drivers/Makefile
grep -q "kernelsu" $DRIVER_MAKEFILE || echo "obj-y += kernelsu/" >> $DRIVER_MAKEFILE
echo "[+] GKI_ROOT: $GKI_ROOT"
echo "[+] Copy kernel su driver to $DRIVER_DIR"
echo "[+] Done."
test -e "$DRIVER_DIR/kernelsu" || ln -sf "$GKI_ROOT/KernelSU/kernel" "$DRIVER_DIR/kernelsu"
echo '[+] Add kernel su driver to Makefile'
DRIVER_MAKEFILE=$DRIVER_DIR/Makefile
grep -q "kernelsu" "$DRIVER_MAKEFILE" || echo "obj-y += kernelsu/" >>"$DRIVER_MAKEFILE"
echo '[+] Done.'

View File

@@ -1,34 +1,20 @@
#include "asm/current.h"
#include "linux/cred.h"
#include "linux/err.h"
#include "linux/fs.h"
#include "linux/kprobes.h"
#include "linux/types.h"
#include "linux/uaccess.h"
#include "linux/version.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
#include "linux/sched/task_stack.h"
#else
#include "linux/sched.h"
#endif
#include <linux/gfp.h>
#include <linux/workqueue.h>
#include <asm/current.h>
#include <linux/cred.h>
#include <linux/dcache.h>
#include <linux/err.h>
#include <linux/limits.h>
#include <linux/cpu.h>
#include <linux/memory.h>
#include <linux/uaccess.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kprobes.h>
#include <linux/printk.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/sched/task_stack.h>
#include <linux/slab.h>
#include <asm-generic/errno-base.h>
#include <linux/rcupdate.h>
#include <linux/fdtable.h>
#include <linux/fs.h>
#include <linux/fs_struct.h>
#include <linux/namei.h>
#include "klog.h"
#include "arch.h"
#include "allowlist.h"
#include "selinux/selinux.h"
#include "arch.h"
#include "klog.h" // IWYU pragma: keep
#define SU_PATH "/system/bin/su"
#define SH_PATH "/system/bin/sh"
@@ -37,7 +23,8 @@ extern void escape_to_root();
static void __user *userspace_stack_buffer(const void *d, size_t len)
{
/* To avoid having to mmap a page in userspace, just write below the stack pointer. */
/* To avoid having to mmap a page in userspace, just write below the stack
* pointer. */
char __user *p = (void __user *)current_user_stack_pointer() - len;
return copy_to_user(p, d, len) ? NULL : p;
@@ -50,7 +37,8 @@ static char __user *sh_user_path(void)
return userspace_stack_buffer(sh_path, sizeof(sh_path));
}
static int faccessat_handler_pre(struct kprobe *p, struct pt_regs *regs)
int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
int *flags)
{
struct filename *filename;
const char su[] = SU_PATH;
@@ -59,14 +47,14 @@ static int faccessat_handler_pre(struct kprobe *p, struct pt_regs *regs)
return 0;
}
filename = getname(PT_REGS_PARM2(regs));
filename = getname(*filename_user);
if (IS_ERR(filename)) {
return 0;
}
if (!memcmp(filename->name, su, sizeof(su))) {
pr_info("faccessat su->sh!\n");
PT_REGS_PARM2(regs) = sh_user_path();
*filename_user = sh_user_path();
}
putname(filename);
@@ -74,7 +62,7 @@ static int faccessat_handler_pre(struct kprobe *p, struct pt_regs *regs)
return 0;
}
static int newfstatat_handler_pre(struct kprobe *p, struct pt_regs *regs)
int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags)
{
// const char sh[] = SH_PATH;
struct filename *filename;
@@ -84,14 +72,18 @@ static int newfstatat_handler_pre(struct kprobe *p, struct pt_regs *regs)
return 0;
}
filename = getname(PT_REGS_PARM2(regs));
if (!filename_user) {
return 0;
}
filename = getname(*filename_user);
if (IS_ERR(filename)) {
return 0;
}
if (!memcmp(filename->name, su, sizeof(su))) {
pr_info("newfstatat su->sh!\n");
PT_REGS_PARM2(regs) = sh_user_path();
*filename_user = sh_user_path();
}
putname(filename);
@@ -99,40 +91,21 @@ static int newfstatat_handler_pre(struct kprobe *p, struct pt_regs *regs)
return 0;
}
// https://elixir.bootlin.com/linux/v5.10.158/source/fs/exec.c#L1864
static int execve_handler_pre(struct kprobe *p, struct pt_regs *regs)
int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
void *argv, void *envp, int *flags)
{
struct filename *filename;
const char sh[] = SH_PATH;
const char su[] = SU_PATH;
static const char app_process[] = "/system/bin/app_process";
static bool first_app_process = true;
static const char system_bin_init[] = "/system/bin/init";
static int init_count = 0;
if (!filename_ptr)
return 0;
filename = PT_REGS_PARM2(regs);
filename = *filename_ptr;
if (IS_ERR(filename)) {
return 0;
}
if (!memcmp(filename->name, system_bin_init, sizeof(system_bin_init) - 1)) {
// /system/bin/init executed
if (++init_count == 2) {
// 1: /system/bin/init selinux_setup
// 2: /system/bin/init second_stage
pr_info("/system/bin/init second_stage executed\n");
apply_kernelsu_rules();
}
}
if (first_app_process &&
!memcmp(filename->name, app_process, sizeof(app_process) - 1)) {
first_app_process = false;
pr_info("exec app_process, /data prepared!\n");
ksu_load_allow_list();
}
if (!ksu_is_allow_uid(current_uid().val)) {
return 0;
}
@@ -147,136 +120,88 @@ static int execve_handler_pre(struct kprobe *p, struct pt_regs *regs)
return 0;
}
static const char KERNEL_SU_RC[] =
"\n"
#ifdef CONFIG_KPROBES
"on post-fs-data\n"
// We should wait for the post-fs-data finish
" exec u:r:su:s0 root -- /data/adb/ksud post-fs-data\n"
"\n"
"on property:sys.boot_completed=1\n"
" exec u:r:su:s0 root -- /data/adb/ksud boot-completed\n"
"\n"
"\n"
;
static void unregister_vfs_read_kp();
static struct work_struct unregister_vfs_read_work;
static int read_handler_pre(struct kprobe *p, struct pt_regs *regs)
static int faccessat_handler_pre(struct kprobe *p, struct pt_regs *regs)
{
struct file *file;
char __user *buf;
size_t count;
int *dfd = (int *)PT_REGS_PARM1(regs);
const char __user **filename_user = (const char **)&PT_REGS_PARM2(regs);
int *mode = (int *)&PT_REGS_PARM3(regs);
int *flags = (int *)&PT_REGS_PARM4(regs);
if (strcmp(current->comm, "init")) {
// we are only interest in `init` process
return 0;
}
return ksu_handle_faccessat(dfd, filename_user, mode, flags);
}
file = PT_REGS_PARM1(regs);
if (IS_ERR(file)) {
return 0;
}
static int newfstatat_handler_pre(struct kprobe *p, struct pt_regs *regs)
{
int *dfd = (int *)&PT_REGS_PARM1(regs);
const char __user **filename_user = (const char **)&PT_REGS_PARM2(regs);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
// static int vfs_statx(int dfd, const char __user *filename, int flags, struct kstat *stat, u32 request_mask)
int *flags = (int *)&PT_REGS_PARM3(regs);
#else
// int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,int flag)
int *flags = (int *)&PT_REGS_PARM4(regs);
#endif
if (!d_is_reg(file->f_path.dentry)) {
return 0;
}
return ksu_handle_stat(dfd, filename_user, flags);
}
const char *short_name = file->f_path.dentry->d_name.name;
if (strcmp(short_name, "atrace.rc")) {
// we are only interest `atrace.rc` file name file
return 0;
}
char path[PATH_MAX];
char* dpath = d_path(&file->f_path, path, PATH_MAX);
if (IS_ERR(dpath)) {
return 0;
}
// https://elixir.bootlin.com/linux/v5.10.158/source/fs/exec.c#L1864
static int execve_handler_pre(struct kprobe *p, struct pt_regs *regs)
{
int *fd = (int *)&PT_REGS_PARM1(regs);
struct filename **filename_ptr =
(struct filename **)&PT_REGS_PARM2(regs);
void *argv = (void *)&PT_REGS_PARM3(regs);
void *envp = (void *)&PT_REGS_PARM4(regs);
int *flags = (int *)&PT_REGS_PARM5(regs);
if (strcmp(dpath, "/system/etc/init/atrace.rc")) {
return 0;
}
// we only process the first read
static bool rc_inserted = false;
if (rc_inserted) {
// we don't need this kprobe, unregister it!
unregister_vfs_read_kp();
return 0;
}
rc_inserted = true;
// now we can sure that the init process is reading `/system/etc/init/atrace.rc`
buf = PT_REGS_PARM2(regs);
count = PT_REGS_PARM3(regs);
size_t rc_count = strlen(KERNEL_SU_RC);
pr_info("vfs_read: %s, comm: %s, count: %d, rc_count: %d\n", dpath, current->comm, count, rc_count);
if (count < rc_count) {
pr_err("count: %d < rc_count: %d", count, rc_count);
return 0;
}
size_t ret = copy_to_user(buf, KERNEL_SU_RC, rc_count);
if (ret) {
pr_err("copy ksud.rc failed: %d\n", ret);
return 0;
}
PT_REGS_PARM2(regs) = buf + rc_count;
PT_REGS_PARM3(regs) = count - rc_count;
return 0;
return ksu_handle_execveat_sucompat(fd, filename_ptr, argv, envp,
flags);
}
static struct kprobe faccessat_kp = {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)
.symbol_name = "do_faccessat",
#else
.symbol_name = "sys_faccessat",
#endif
.pre_handler = faccessat_handler_pre,
};
static struct kprobe newfstatat_kp = {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
.symbol_name = "vfs_statx",
#else
.symbol_name = "vfs_fstatat",
#endif
.pre_handler = newfstatat_handler_pre,
};
static struct kprobe execve_kp = {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
.symbol_name = "do_execveat_common",
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)
.symbol_name = "__do_execve_file",
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
.symbol_name = "do_execveat_common",
#endif
.pre_handler = execve_handler_pre,
};
static struct kprobe vfs_read_kp = {
.symbol_name = "vfs_read",
.pre_handler = read_handler_pre,
};
static void do_unregister_vfs_read_kp(struct work_struct *work) {
unregister_kprobe(&vfs_read_kp);
}
static void unregister_vfs_read_kp() {
bool ret = schedule_work(&unregister_vfs_read_work);
pr_info("unregister vfs_read kprobe: %d!\n", ret);
}
#endif
// sucompat: permited process can execute 'su' to gain root access.
void enable_sucompat()
void ksu_enable_sucompat()
{
#ifdef CONFIG_KPROBES
int ret;
ret = register_kprobe(&execve_kp);
pr_info("execve_kp: %d\n", ret);
pr_info("sucompat: execve_kp: %d\n", ret);
ret = register_kprobe(&newfstatat_kp);
pr_info("newfstatat_kp: %d\n", ret);
pr_info("sucompat: newfstatat_kp: %d\n", ret);
ret = register_kprobe(&faccessat_kp);
pr_info("faccessat_kp: %d\n", ret);
ret = register_kprobe(&vfs_read_kp);
pr_info("vfs_read_kp: %d\n", ret);
INIT_WORK(&unregister_vfs_read_work, do_unregister_vfs_read_kp);
pr_info("sucompat: faccessat_kp: %d\n", ret);
#endif
}

136
kernel/uid_observer.c Normal file
View File

@@ -0,0 +1,136 @@
#include "linux/err.h"
#include "linux/fs.h"
#include "linux/list.h"
#include "linux/slab.h"
#include "linux/string.h"
#include "linux/types.h"
#include "linux/version.h"
#include "linux/workqueue.h"
#include "allowlist.h"
#include "klog.h" // IWYU pragma: keep
#include "ksu.h"
#include "manager.h"
#include "uid_observer.h"
#include "kernel_compat.h"
#define SYSTEM_PACKAGES_LIST_PATH "/data/system/packages.list"
static struct work_struct ksu_update_uid_work;
struct uid_data {
struct list_head list;
u32 uid;
};
static bool is_uid_exist(uid_t uid, void *data)
{
struct list_head *list = (struct list_head *)data;
struct uid_data *np;
bool exist = false;
list_for_each_entry (np, list, list) {
if (np->uid == uid) {
exist = true;
break;
}
}
return exist;
}
static void do_update_uid(struct work_struct *work)
{
KWORKER_INSTALL_KEYRING();
struct file *fp = filp_open(SYSTEM_PACKAGES_LIST_PATH, O_RDONLY, 0);
if (IS_ERR(fp)) {
pr_err("do_update_uid, open " SYSTEM_PACKAGES_LIST_PATH
" failed: %d\n",
ERR_PTR(fp));
return;
}
struct list_head uid_list;
INIT_LIST_HEAD(&uid_list);
char chr = 0;
loff_t pos = 0;
loff_t line_start = 0;
char buf[128];
for (;;) {
ssize_t count = kernel_read_compat(fp, &chr, sizeof(chr), &pos);
if (count != sizeof(chr))
break;
if (chr != '\n')
continue;
count = kernel_read_compat(fp, buf, sizeof(buf), &line_start);
struct uid_data *data =
kmalloc(sizeof(struct uid_data), GFP_ATOMIC);
if (!data) {
goto out;
}
char *tmp = buf;
const char *delim = " ";
strsep(&tmp, delim); // skip package
char *uid = strsep(&tmp, delim);
if (!uid) {
pr_err("update_uid: uid is NULL!\n");
continue;
}
u32 res;
if (kstrtou32(uid, 10, &res)) {
pr_err("update_uid: uid parse err\n");
continue;
}
data->uid = res;
list_add_tail(&data->list, &uid_list);
// reset line start
line_start = pos;
}
// now update uid list
struct uid_data *np;
struct uid_data *n;
// first, check if manager_uid exist!
bool manager_exist = false;
list_for_each_entry (np, &uid_list, list) {
if (np->uid == ksu_get_manager_uid()) {
manager_exist = true;
break;
}
}
if (!manager_exist && ksu_is_manager_uid_valid()) {
pr_info("manager is uninstalled, invalidate it!\n");
ksu_invalidate_manager_uid();
}
// then prune the allowlist
ksu_prune_allowlist(is_uid_exist, &uid_list);
out:
// free uid_list
list_for_each_entry_safe (np, n, &uid_list, list) {
list_del(&np->list);
kfree(np);
}
filp_close(fp, 0);
}
void update_uid()
{
ksu_queue_work(&ksu_update_uid_work);
}
int ksu_uid_observer_init()
{
INIT_WORK(&ksu_update_uid_work, do_update_uid);
return 0;
}
int ksu_uid_observer_exit()
{
return 0;
}

10
kernel/uid_observer.h Normal file
View File

@@ -0,0 +1,10 @@
#ifndef __KSU_H_UID_OBSERVER
#define __KSU_H_UID_OBSERVER
int ksu_uid_observer_init();
int ksu_uid_observer_exit();
void update_uid();
#endif

View File

@@ -9,6 +9,8 @@ plugins {
android {
namespace = "me.weishu.kernelsu"
ndkVersion = "25.1.8937393"
defaultConfig {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
@@ -17,6 +19,10 @@ android {
}
}
lint {
checkReleaseBuilds = false
}
buildFeatures {
compose = true
}

View File

@@ -11,6 +11,7 @@
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:enableOnBackInvokedCallback="true"
android:extractNativeLibs="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
@@ -31,6 +32,16 @@
android:name="android.app.lib_name"
android:value="" />
</activity>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
</application>
</manifest>

View File

@@ -15,6 +15,4 @@ add_library(kernelsu
find_library(log-lib log)
target_link_libraries(kernelsu ${log-lib})
add_executable(libksu.so su.c)
target_link_libraries(kernelsu ${log-lib})

View File

@@ -61,3 +61,9 @@ Java_me_weishu_kernelsu_Natives_allowRoot(JNIEnv *env, jclass clazz, jint uid, j
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_me_weishu_kernelsu_Natives_isSafeMode(JNIEnv *env, jclass clazz) {
return is_safe_mode();
}

View File

@@ -19,6 +19,7 @@
#define CMD_DENY_SU 4
#define CMD_GET_ALLOW_LIST 5
#define CMD_GET_DENY_LIST 6
#define CMD_CHECK_SAFEMODE 9
static bool ksuctl(int cmd, void* arg1, void* arg2) {
int32_t result = 0;
@@ -51,4 +52,8 @@ bool get_allow_list(int *uids, int *size) {
bool get_deny_list(int *uids, int *size) {
return ksuctl(CMD_GET_DENY_LIST, uids, size);
}
bool is_safe_mode() {
return ksuctl(CMD_CHECK_SAFEMODE, nullptr, nullptr);
}

View File

@@ -15,4 +15,6 @@ bool get_allow_list(int *uids, int *size);
bool get_deny_list(int *uids, int *size);
bool is_safe_mode();
#endif //KERNELSU_KSU_H

View File

@@ -3,7 +3,6 @@ package me.weishu.kernelsu
import android.app.Application
import coil.Coil
import coil.ImageLoader
import me.weishu.kernelsu.ui.util.install
import me.zhanghai.android.appiconloader.coil.AppIconFetcher
import me.zhanghai.android.appiconloader.coil.AppIconKeyer
@@ -25,8 +24,6 @@ class KernelSUApplication : Application() {
}
.build()
)
install()
}

View File

@@ -21,4 +21,6 @@ public final class Natives {
public static native int[] getDenyList();
public static native boolean allowRoot(int uid, boolean allow);
public static native boolean isSafeMode();
}

View File

@@ -10,8 +10,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Search
import androidx.compose.material.icons.filled.*
import androidx.compose.material.icons.outlined.ArrowBack
import androidx.compose.material3.*
import androidx.compose.runtime.*
@@ -22,9 +21,11 @@ import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import me.weishu.kernelsu.R
private const val TAG = "SearchBar"
@@ -36,7 +37,8 @@ fun SearchAppBar(
onSearchTextChange: (String) -> Unit,
onClearClick: () -> Unit,
onBackClick: (() -> Unit)? = null,
onConfirm: (() -> Unit)? = null
onConfirm: (() -> Unit)? = null,
dropdownContent: @Composable (() -> Unit)? = null,
) {
val keyboardController = LocalSoftwareKeyboardController.current
val focusRequester = remember { FocusRequester() }
@@ -116,6 +118,11 @@ fun SearchAppBar(
content = { Icon(Icons.Filled.Search, null) }
)
}
if (dropdownContent != null) {
dropdownContent()
}
}
)
}

View File

@@ -22,9 +22,9 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.ramcosta.composedestinations.annotation.Destination
@@ -34,9 +34,10 @@ import kotlinx.coroutines.launch
import me.weishu.kernelsu.*
import me.weishu.kernelsu.R
import me.weishu.kernelsu.ui.screen.destinations.SettingScreenDestination
import me.weishu.kernelsu.ui.util.LinkifyText
import me.weishu.kernelsu.ui.util.LocalSnackbarHost
import me.weishu.kernelsu.ui.util.reboot
import me.weishu.kernelsu.ui.util.getSELinuxStatus
import me.weishu.kernelsu.ui.util.install
@OptIn(ExperimentalMaterial3Api::class)
@RootNavGraph(start = true)
@@ -59,6 +60,9 @@ fun HomeScreen(navigator: DestinationsNavigator) {
) {
val kernelVersion = getKernelVersion()
val isManager = Natives.becomeManager(ksuApp.packageName)
SideEffect {
if (isManager) install()
}
val ksuVersion = if (isManager) Natives.getVersion() else null
StatusCard(kernelVersion, ksuVersion)
@@ -127,21 +131,29 @@ private fun StatusCard(kernelVersion: KernelVersion, ksuVersion: Int?) {
else MaterialTheme.colorScheme.errorContainer
})
) {
val uriHandler = LocalUriHandler.current
Row(
modifier = Modifier
.fillMaxWidth()
.clickable {
// TODO: Install kernel
if (kernelVersion.isGKI() && ksuVersion == null) {
uriHandler.openUri("https://kernelsu.org/guide/installation.html")
}
}
.padding(24.dp),
verticalAlignment = Alignment.CenterVertically
) {
when {
ksuVersion != null -> {
val appendText = if (Natives.isSafeMode()) {
" [${stringResource(id = R.string.safe_mode)}]"
} else {
""
}
Icon(Icons.Outlined.CheckCircle, stringResource(R.string.home_working))
Column(Modifier.padding(start = 20.dp)) {
Text(
text = stringResource(R.string.home_working),
text = stringResource(R.string.home_working) + appendText,
style = MaterialTheme.typography.titleMedium
)
Spacer(Modifier.height(4.dp))
@@ -210,10 +222,7 @@ private fun InfoCard() {
InfoCardItem(stringResource(R.string.home_kernel), uname.release)
Spacer(Modifier.height(24.dp))
InfoCardItem(stringResource(R.string.home_arch), uname.machine)
Spacer(Modifier.height(24.dp))
InfoCardItem(stringResource(R.string.home_version), uname.version)
InfoCardItem(stringResource(R.string.home_manager_version), getManagerVersion(context))
Spacer(Modifier.height(24.dp))
InfoCardItem(stringResource(R.string.home_api), Build.VERSION.SDK_INT.toString())
@@ -227,6 +236,9 @@ private fun InfoCard() {
Spacer(Modifier.height(24.dp))
InfoCardItem(stringResource(R.string.home_securitypatch), Build.VERSION.SECURITY_PATCH)
Spacer(Modifier.height(24.dp))
InfoCardItem(stringResource(R.string.home_selinux_status), getSELinuxStatus())
val copiedMessage = stringResource(R.string.home_copied_to_clipboard)
TextButton(
modifier = Modifier.align(Alignment.End),
@@ -241,6 +253,11 @@ private fun InfoCard() {
}
}
fun getManagerVersion(context: Context) : String {
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
return "${packageInfo.versionName} (${packageInfo.versionCode})"
}
@Preview
@Composable
private fun StatusCardPreview() {

View File

@@ -16,6 +16,7 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
@@ -30,9 +31,7 @@ import kotlinx.coroutines.launch
import me.weishu.kernelsu.Natives
import me.weishu.kernelsu.R
import me.weishu.kernelsu.ui.screen.destinations.InstallScreenDestination
import me.weishu.kernelsu.ui.util.LocalSnackbarHost
import me.weishu.kernelsu.ui.util.toggleModule
import me.weishu.kernelsu.ui.util.uninstallModule
import me.weishu.kernelsu.ui.util.*
import me.weishu.kernelsu.ui.viewmodel.ModuleViewModel
@OptIn(ExperimentalMaterial3Api::class)
@@ -50,11 +49,14 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
}
}
Scaffold(
topBar = {
TopBar()
},
floatingActionButton = {
val isSafeMode = Natives.isSafeMode()
Scaffold(topBar = {
TopBar()
}, floatingActionButton = if (isSafeMode) {
{ /* Empty */ }
} else {
{
val moduleInstall = stringResource(id = R.string.module_install)
val selectZipLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult()
@@ -80,8 +82,8 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
icon = { Icon(Icons.Filled.Add, moduleInstall) },
text = { Text(text = moduleInstall) },
)
},
) { innerPadding ->
}
}) { innerPadding ->
val failedEnable = stringResource(R.string.module_failed_to_enable)
val failedDisable = stringResource(R.string.module_failed_to_disable)
val failedUninstall = stringResource(R.string.module_uninstall_failed)
@@ -95,14 +97,21 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
return@Scaffold
}
SwipeRefresh(
state = swipeState,
onRefresh = {
state = swipeState, onRefresh = {
scope.launch { viewModel.fetchModuleList() }
},
modifier = Modifier
}, modifier = Modifier
.padding(innerPadding)
.padding(16.dp)
.fillMaxSize()
) {
val isOverlayAvailable = overlayFsAvailable()
if (!isOverlayAvailable) {
swipeState.isRefreshing = false
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Text(stringResource(R.string.module_overlay_fs_not_available))
}
return@SwipeRefresh
}
val isEmpty = viewModel.moduleList.isEmpty()
if (isEmpty) {
swipeState.isRefreshing = false
@@ -110,42 +119,59 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
Text(stringResource(R.string.module_empty))
}
} else {
LazyColumn {
LazyColumn(verticalArrangement = Arrangement.spacedBy(15.dp),
contentPadding = remember { PaddingValues(bottom = 16.dp + 56.dp /* Scaffold Fab Spacing + Fab container height */) }) {
items(viewModel.moduleList) { module ->
var isChecked by rememberSaveable(module) { mutableStateOf(module.enabled) }
ModuleItem(module,
isChecked,
onUninstall = {
scope.launch {
val result = uninstallModule(module.id)
if (result) {
viewModel.fetchModuleList()
}
snackBarHost.showSnackbar(
if (result) {
successUninstall.format(module.name)
} else {
failedUninstall.format(module.name)
}
)
}
},
onCheckChanged = {
val success = toggleModule(module.id, !isChecked)
val reboot = stringResource(id = R.string.reboot)
val rebootToApply = stringResource(id = R.string.reboot_to_apply)
ModuleItem(module, isChecked, onUninstall = {
scope.launch {
val success = uninstallModule(module.id)
if (success) {
isChecked = it
scope.launch {
viewModel.fetchModuleList()
}
} else scope.launch {
val message = if (isChecked) failedDisable else failedEnable
snackBarHost.showSnackbar(message.format(module.name))
viewModel.fetchModuleList()
}
})
val message = if (success) {
successUninstall.format(module.name)
} else {
failedUninstall.format(module.name)
}
val actionLabel = if (success) {
reboot
} else {
null
}
val result = snackBarHost.showSnackbar(
message, actionLabel = actionLabel
)
if (result == SnackbarResult.ActionPerformed) {
reboot()
}
}
}, onCheckChanged = {
val success = toggleModule(module.id, !isChecked)
if (success) {
isChecked = it
scope.launch {
viewModel.fetchModuleList()
val result = snackBarHost.showSnackbar(
rebootToApply, actionLabel = reboot
)
if (result == SnackbarResult.ActionPerformed) {
reboot()
}
}
} else scope.launch {
val message = if (isChecked) failedDisable else failedEnable
snackBarHost.showSnackbar(message.format(module.name))
}
})
// fix last item shadow incomplete in LazyColumn
Spacer(Modifier.height(1.dp))
}
}
}
}
}
}
@@ -153,9 +179,7 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun TopBar() {
TopAppBar(
title = { Text(stringResource(R.string.module)) }
)
TopAppBar(title = { Text(stringResource(R.string.module)) })
}
@Composable
@@ -166,62 +190,69 @@ private fun ModuleItem(
onCheckChanged: (Boolean) -> Unit
) {
ElevatedCard(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp),
colors =
CardDefaults.elevatedCardColors(containerColor = MaterialTheme.colorScheme.surface)
modifier = Modifier.fillMaxWidth(),
colors = CardDefaults.elevatedCardColors(containerColor = MaterialTheme.colorScheme.surface)
) {
val textDecoration = if (!module.remove) null else TextDecoration.LineThrough
Column(modifier = Modifier.padding(16.dp, 16.dp, 16.dp, 0.dp)) {
Row {
Column {
Column(modifier = Modifier.padding(24.dp, 16.dp, 24.dp, 0.dp)) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
) {
val moduleVersion = stringResource(id = R.string.module_version)
val moduleAuthor = stringResource(id = R.string.module_author)
Column(modifier = Modifier.fillMaxWidth(0.8f)) {
Text(
text = module.name,
fontSize = MaterialTheme.typography.titleLarge.fontSize,
fontFamily = MaterialTheme.typography.titleLarge.fontFamily,
fontSize = MaterialTheme.typography.titleMedium.fontSize,
fontWeight = FontWeight.SemiBold,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
fontFamily = MaterialTheme.typography.titleMedium.fontFamily,
textDecoration = textDecoration,
)
Row {
Text(
text = module.version,
fontFamily = MaterialTheme.typography.titleMedium.fontFamily,
fontSize = MaterialTheme.typography.titleMedium.fontSize,
textDecoration = textDecoration
)
Text(
text = "$moduleVersion: ${module.version}",
fontSize = MaterialTheme.typography.bodySmall.fontSize,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
textDecoration = textDecoration
)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = module.author,
fontFamily = MaterialTheme.typography.titleMedium.fontFamily,
fontSize = MaterialTheme.typography.titleMedium.fontSize,
textDecoration = textDecoration
)
}
Text(
text = "$moduleAuthor: ${module.author}",
fontSize = MaterialTheme.typography.bodySmall.fontSize,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
textDecoration = textDecoration
)
}
Spacer(modifier = Modifier.weight(1f))
Switch(
enabled = !module.update,
checked = isChecked,
onCheckedChange = onCheckChanged
)
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.End,
) {
Switch(
enabled = !module.update,
checked = isChecked,
onCheckedChange = onCheckChanged
)
}
}
Spacer(modifier = Modifier.height(12.dp))
Text(
text = module.description,
fontFamily = MaterialTheme.typography.bodyMedium.fontFamily,
fontSize = MaterialTheme.typography.bodyMedium.fontSize,
lineHeight = MaterialTheme.typography.bodyMedium.lineHeight,
fontWeight = MaterialTheme.typography.bodyMedium.fontWeight,
fontSize = MaterialTheme.typography.bodySmall.fontSize,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
fontWeight = MaterialTheme.typography.bodySmall.fontWeight,
overflow = TextOverflow.Ellipsis,
maxLines = 4,
textDecoration = textDecoration

View File

@@ -1,22 +1,27 @@
package me.weishu.kernelsu.ui.screen
import android.content.Intent
import android.net.Uri
import android.widget.Toast
import androidx.compose.foundation.layout.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Info
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.content.FileProvider
import com.alorma.compose.settings.ui.*
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import me.weishu.kernelsu.ui.util.getBugreportFile
import me.weishu.kernelsu.BuildConfig
import me.weishu.kernelsu.R
import me.weishu.kernelsu.ui.util.LinkifyText
/**
* @author weishu
* @date 2023/1/1.
@@ -61,12 +66,36 @@ fun SettingScreen(navigator: DestinationsNavigator) {
Column(modifier = Modifier.padding(paddingValues)) {
val context = LocalContext.current
SettingsSwitch(
title = {
Text(stringResource(id = R.string.settings_system_rw))
},
subtitle = {
Text(stringResource(id = R.string.settings_system_rw_summary))
},
onCheckedChange = {
Toast.makeText(context, "coming soon", Toast.LENGTH_SHORT).show()
}
)
SettingsMenuLink(title = {
Text(stringResource(id = R.string.send_log))
},
onClick = {
val bugreport = getBugreportFile(context)
val uri: Uri = FileProvider.getUriForFile(context, "${BuildConfig.APPLICATION_ID}.fileprovider", bugreport)
val shareIntent = Intent(Intent.ACTION_SEND)
shareIntent.putExtra(Intent.EXTRA_STREAM, uri)
shareIntent.setDataAndType(uri, "application/zip")
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
context.startActivity(
Intent.createChooser(
shareIntent,
context.getString(R.string.send_log)
)
)
}
)
SettingsMenuLink(title = {

View File

@@ -1,14 +1,10 @@
package me.weishu.kernelsu.ui.screen
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.util.Log
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
@@ -17,17 +13,8 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import coil.ImageLoader
import coil.compose.AsyncImage
import coil.compose.rememberAsyncImagePainter
import coil.compose.rememberImagePainter
import coil.decode.DataSource
import coil.fetch.DrawableResult
import coil.fetch.FetchResult
import coil.fetch.Fetcher
import coil.request.CachePolicy
import coil.request.ImageRequest
import coil.request.Options
import com.google.accompanist.swiperefresh.SwipeRefresh
import com.google.accompanist.swiperefresh.rememberSwipeRefreshState
import com.ramcosta.composedestinations.annotation.Destination
@@ -37,7 +24,6 @@ import me.weishu.kernelsu.R
import me.weishu.kernelsu.ui.component.SearchAppBar
import me.weishu.kernelsu.ui.util.LocalSnackbarHost
import me.weishu.kernelsu.ui.viewmodel.SuperUserViewModel
import me.zhanghai.android.appiconloader.coil.AppIconKeyer
import java.util.*
@OptIn(ExperimentalMaterial3Api::class)
@@ -60,7 +46,44 @@ fun SuperUserScreen() {
title = { Text(stringResource(R.string.superuser)) },
searchText = viewModel.search,
onSearchTextChange = { viewModel.search = it },
onClearClick = { viewModel.search = "" }
onClearClick = { viewModel.search = "" },
dropdownContent = {
var showDropdown by remember { mutableStateOf(false) }
IconButton(
onClick = { showDropdown = true },
) {
Icon(
imageVector = Icons.Filled.MoreVert,
contentDescription = stringResource(id = R.string.settings)
)
DropdownMenu(expanded = showDropdown, onDismissRequest = {
showDropdown = false
}) {
DropdownMenuItem(text = {
Text(stringResource(R.string.refresh))
}, onClick = {
scope.launch {
viewModel.fetchAppList()
}
showDropdown = false
})
DropdownMenuItem(text = {
Text(
if (viewModel.showSystemApps) {
stringResource(R.string.hide_system_apps)
} else {
stringResource(R.string.show_system_apps)
}
)
}, onClick = {
viewModel.showSystemApps = !viewModel.showSystemApps
showDropdown = false
})
}
}
},
)
}
) { innerPadding ->

View File

@@ -10,6 +10,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.unit.dp
import androidx.core.view.ViewCompat
import com.google.accompanist.systemuicontroller.rememberSystemUiController
@@ -47,6 +48,12 @@ fun KernelSUTheme(
color = colorScheme.surface,
darkIcons = !darkTheme
)
// To match the App Navbar color
systemUiController.setNavigationBarColor(
color = colorScheme.surfaceColorAtElevation(8.dp),
darkIcons = !darkTheme,
)
}
MaterialTheme(
@@ -54,4 +61,4 @@ fun KernelSUTheme(
typography = Typography,
content = content
)
}
}

View File

@@ -23,11 +23,11 @@ private fun getKsuDaemonPath(): String {
fun createRootShell(): Shell {
Shell.enableVerboseLogging = BuildConfig.DEBUG
val su = ksuApp.applicationInfo.nativeLibraryDir + File.separator + "libksu.so"
val builder = Shell.Builder.create()
return try {
builder.build(su)
builder.build(getKsuDaemonPath(), "debug", "su")
} catch (e: Throwable) {
Log.e(TAG, "su failed: ", e)
builder.build("sh")
}
}
@@ -47,7 +47,7 @@ fun listModules(): String {
val shell = createRootShell()
val out = shell.newJob().add("${getKsuDaemonPath()} module list").to(ArrayList(), null).exec().out
return out.joinToString("\n")
return out.joinToString("\n").ifBlank { "[]" }
}
fun toggleModule(id: String, enable: Boolean): Boolean {
@@ -102,4 +102,10 @@ fun reboot(reason: String = "") {
ShellUtils.fastCmd(shell, "/system/bin/input keyevent 26")
}
ShellUtils.fastCmd(shell, "/system/bin/svc power reboot $reason || /system/bin/reboot $reason")
}
fun overlayFsAvailable(): Boolean {
val shell = createRootShell()
// check /proc/filesystems
return ShellUtils.fastCmdResult(shell, "cat /proc/filesystems | grep overlay")
}

View File

@@ -0,0 +1,78 @@
package me.weishu.kernelsu.ui.util
import android.content.Context
import android.os.Build
import android.system.Os
import me.weishu.kernelsu.Natives
import me.weishu.kernelsu.ui.screen.getManagerVersion
import java.io.File
import java.io.FileWriter
import java.io.PrintWriter
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
fun getBugreportFile(context: Context): File {
val bugreportDir = File(context.cacheDir, "bugreport")
bugreportDir.mkdirs()
val dmesgFile = File(bugreportDir, "dmesg.txt")
val logcatFile = File(bugreportDir, "logcat.txt")
val tombstonesFile = File(bugreportDir, "tombstones.tar.gz")
val dropboxFile = File(bugreportDir, "dropbox.tar.gz")
val mountsFile = File(bugreportDir, "mounts.txt")
val fileSystemsFile = File(bugreportDir, "filesystems.txt")
val ksuFileTree = File(bugreportDir, "ksu_tree.txt")
val shell = createRootShell()
shell.newJob().add("dmesg > ${dmesgFile.absolutePath}").exec()
shell.newJob().add("logcat -d > ${logcatFile.absolutePath}").exec()
shell.newJob().add("tar -czf ${tombstonesFile.absolutePath} /data/tombstones").exec()
shell.newJob().add("tar -czf ${dropboxFile.absolutePath} /data/system/dropbox").exec()
shell.newJob().add("cat /proc/mounts > ${mountsFile.absolutePath}").exec()
shell.newJob().add("cat /proc/filesystems > ${fileSystemsFile.absolutePath}").exec()
shell.newJob().add("ls -alRZ /data/adb/ksu > ${ksuFileTree.absolutePath}").exec()
// basic information
val buildInfo = File(bugreportDir, "basic.txt")
PrintWriter(FileWriter(buildInfo)).use { pw ->
pw.println("Kernel: ${System.getProperty("os.version")}")
pw.println("BRAND: " + Build.BRAND)
pw.println("MODEL: " + Build.MODEL)
pw.println("PRODUCT: " + Build.PRODUCT)
pw.println("MANUFACTURER: " + Build.MANUFACTURER)
pw.println("SDK: " + Build.VERSION.SDK_INT)
pw.println("PREVIEW_SDK: " + Build.VERSION.PREVIEW_SDK_INT)
pw.println("FINGERPRINT: " + Build.FINGERPRINT)
pw.println("DEVICE: " + Build.DEVICE)
pw.println("Manager: " + getManagerVersion(context))
val uname = Os.uname()
pw.println("KernelRelease: ${uname.release}")
pw.println("KernelVersion: ${uname.version}")
pw.println("Mahcine: ${uname.machine}")
pw.println("Nodename: ${uname.nodename}")
pw.println("Sysname: ${uname.sysname}")
val ksuKernel = Natives.getVersion()
pw.println("KernelSU: $ksuKernel")
val safeMode = Natives.isSafeMode()
pw.println("SafeMode: $safeMode")
}
// modules
val modulesFile = File(bugreportDir, "modules.json")
modulesFile.writeText(listModules())
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH_mm")
val current = LocalDateTime.now().format(formatter)
val targetFile = File(context.cacheDir, "KernelSU_bugreport_${current}.tar.gz")
shell.newJob().add("tar czf ${targetFile.absolutePath} -C ${bugreportDir.absolutePath} .").exec()
shell.newJob().add("rm -rf ${bugreportDir.absolutePath}").exec()
shell.newJob().add("chmod 0644 ${targetFile.absolutePath}").exec()
return targetFile;
}

View File

@@ -0,0 +1,32 @@
package me.weishu.kernelsu.ui.util
import androidx.compose.ui.res.stringResource
import androidx.compose.runtime.Composable
import com.topjohnwu.superuser.Shell
import me.weishu.kernelsu.R
@Composable
fun getSELinuxStatus(): String {
val shell = Shell.Builder.create()
.setFlags(Shell.FLAG_REDIRECT_STDERR)
.build("sh")
val list = ArrayList<String>()
val result = shell.newJob().add("getenforce").to(list, list).exec()
val output = result.out.joinToString("\n").trim()
if (result.isSuccess) {
return when (output) {
"Enforcing" -> stringResource(R.string.selinux_status_enforcing)
"Permissive" -> stringResource(R.string.selinux_status_permissive)
"Disabled" -> stringResource(R.string.selinux_status_disabled)
else -> stringResource(R.string.selinux_status_unknown)
}
}
return if (output.endsWith("Permission denied")) {
stringResource(R.string.selinux_status_enforcing)
} else {
stringResource(R.string.selinux_status_unknown)
}
}

View File

@@ -63,9 +63,9 @@ class ModuleViewModel : ViewModel() {
ModuleInfo(
obj.getString("id"),
obj.getString("name"),
obj.getString("author"),
obj.getString("version"),
obj.getInt("versionCode"),
obj.optString("author", "Unknown"),
obj.optString("version", "Unknown"),
obj.optInt("versionCode", 0),
obj.getString("description"),
obj.getBoolean("enabled"),
obj.getBoolean("update"),

View File

@@ -35,6 +35,7 @@ class SuperUserViewModel : ViewModel() {
)
var search by mutableStateOf("")
var showSystemApps by mutableStateOf(false)
var isRefreshing by mutableStateOf(false)
private set
@@ -53,7 +54,11 @@ class SuperUserViewModel : ViewModel() {
val appList by derivedStateOf {
sortedList.filter {
it.label.contains(search) || it.packageName.contains(search) || HanziToPinyin.getInstance().toPinyinString(it.label).contains(search)
it.label.contains(search) || it.packageName.contains(search) || HanziToPinyin.getInstance()
.toPinyinString(it.label).contains(search)
}.filter {
it.uid == 2000 // Always show shell
|| showSystemApps || it.icon.applicationInfo.flags.and(ApplicationInfo.FLAG_SYSTEM) == 0
}
}
@@ -77,7 +82,7 @@ class SuperUserViewModel : ViewModel() {
onAllowList = uid in allowList,
onDenyList = uid in denyList
)
}
}.filter { it.packageName != ksuApp.packageName }
Log.i(TAG, "load cost: ${SystemClock.elapsedRealtime() - start}")
}
}

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<group
android:scaleX="0.135"
android:scaleY="0.135">
<path
android:fillColor="#ffffff"
android:pathData="M 0 0 H 800 V 800 H 0 V 0 Z" />
</group>
</vector>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<group
android:scaleX="0.135"
android:scaleY="0.135">
<path
android:pathData="M 259 259 H 541 V 541 H 259 V 259 Z"
android:strokeWidth="18"
android:strokeColor="#1e110d" />
<path
android:fillColor="#1e110d"
android:pathData="M 257 257 H 407 V 407 H 257 V 257 Z" />
<path
android:fillColor="#1e110d"
android:pathData="M 393 393 H 543 V 543 H 393 V 393 Z" />
</group>
</vector>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<group
android:scaleX="0.135"
android:scaleY="0.135">
<path
android:pathData="M 259 259 H 541 V 541 H 259 V 259 Z"
android:strokeWidth="18"
android:strokeColor="#000000" />
<path
android:fillColor="#000000"
android:pathData="M 257 257 H 407 V 407 H 257 V 257 Z" />
<path
android:fillColor="#000000"
android:pathData="M 393 393 H 543 V 543 H 393 V 393 Z" />
</group>
</vector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
</adaptive-icon>

View File

@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="home">Beranda</string>
<string name="home_not_installed">Tidak terinstall</string>
<string name="home_click_to_install">Klik untuk menginstall</string>
<string name="home_working">Bekerja</string>
<string name="home_working_version">Versi: %d</string>
<string name="home_unsupported">Tidak didukung</string>
<string name="home_unsupported_reason">Saat ini kernelSu hanya mendukung GKI kernel</string>
<string name="home_copied_to_clipboard">Salin ke clipboard</string>
<string name="home_support">Dukungan</string>
<string name="home_kernel">Kernel</string>
<string name="home_arch">Arch</string>
<string name="home_manager_version">Versi</string>
<string name="home_api">API Level</string>
<string name="home_abi">ABI</string>
<string name="home_fingerprint">Fingerprint</string>
<string name="home_securitypatch">Patch keamanan</string>
<string name="home_selinux_status">Status SElinux</string>
<string name="selinux_status_disabled">Cacat</string>
<string name="selinux_status_enforcing">Enforcing</string>
<string name="selinux_status_permissive">Permissive</string>
<string name="selinux_status_unknown">Tidak tersedia</string>
<string name="superuser">Superuser</string>
<string name="superuser_failed_to_grant_root">Gagal mengizinkan root untuk %d</string>
<string name="module_failed_to_enable">Gagal mengaktifkan module: %s</string>
<string name="module_failed_to_disable">Gagal menonaktifkan module: %s</string>
<string name="module_empty">Tidak ada module terpasang</string>
<string name="module">Module</string>
<string name="uninstall">Hapus</string>
<string name="module_install">Pasang</string>
<string name="install">Pasang</string>
<string name="reboot">Reboot perangkat</string>
<string name="settings">Pengaturan</string>
<string name="reboot_userspace">Soft Reboot</string>
<string name="reboot_recovery">Reboot ke Recovery</string>
<string name="reboot_bootloader">Reboot ke Bootloader</string>
<string name="reboot_download">Reboot ke Download</string>
<string name="reboot_edl">Reboot ke EDL</string>
<string name="settings_system_rw">Buat system agar dapat ditulis sebagai OverlayFs</string>
<string name="settings_system_rw_summary">restart perangkat setelah mengaktifkan fitur ini</string>
<string name="about">Tentang</string>
<string name="require_kernel_version_8">Membutuhkan KernelSU Versi 8+</string>
<string name="module_uninstall_success">%s terhapus</string>
<string name="module_uninstall_failed">Gagal untuk menghapus: %s</string>
<string name="module_version">Versi</string>
<string name="module_author">Pembuat</string>
<string name="module_overlay_fs_not_available">overlayfs tidak tersedia, module tidak bekerja!</string>
<string name="refresh">Segarkan</string>
<string name="show_system_apps">Tampilkan system apps</string>
<string name="hide_system_apps">Sembunyikan system apps</string>
<string name="send_log">Kirim logs</string>
<string name="safe_mode_disable_module">Mode Safe, semua module dinonaktifkan</string>
</resources>

View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="safe_mode">セーフモード</string>
<string name="home">ホーム</string>
<string name="home_not_installed">未インストール</string>
<string name="home_click_to_install">タップでインストール</string>
<string name="home_working">動作中</string>
<string name="home_working_version">バージョン: %d</string>
<string name="home_unsupported">非対応</string>
<string name="home_unsupported_reason">KernelSUは現在、GKI Kernelのみサポートをしています</string>
<string name="home_copied_to_clipboard">クリップボードにコピーしました</string>
<string name="home_support">対応</string>
<string name="home_kernel">カーネル</string>
<string name="home_arch">アーキテクチャ</string>
<string name="home_manager_version">バージョン</string>
<string name="home_api">APIレベル</string>
<string name="home_abi">ABI</string>
<string name="home_fingerprint">フィンガープリント</string>
<string name="home_securitypatch">セキュリティパッチ</string>
<string name="home_selinux_status">SELinuxの状態</string>
<string name="selinux_status_disabled">無効</string>
<string name="selinux_status_enforcing">Enforcing</string>
<string name="selinux_status_permissive">Permissive</string>
<string name="selinux_status_unknown">不明</string>
<string name="superuser">スーパーユーザー</string>
<string name="superuser_failed_to_grant_root">%dの権限の付与に失敗しました</string>
<string name="module_failed_to_enable">モジュールの有効化に失敗: %s</string>
<string name="module_failed_to_disable">モジュールの無効化に失敗: %s</string>
<string name="module_empty">モジュールはインストールされていません</string>
<string name="module">モジュール</string>
<string name="uninstall">アンインストール</string>
<string name="module_install">インストール</string>
<string name="install">インストール</string>
<string name="reboot">再起動</string>
<string name="settings">設定</string>
<string name="reboot_userspace">ソフトリブート</string>
<string name="reboot_recovery">リカバリーで再起動</string>
<string name="reboot_bootloader">Bootloaderで再起動</string>
<string name="reboot_download">ダウンロードモードで再起動</string>
<string name="reboot_edl">EDLで再起動</string>
<string name="settings_system_rw">システムを書き込み可能にする</string>
<string name="settings_system_rw_summary">OverlayFSを使用してシステムパーティション内部を書き込み可能にします。この機能は再起動後に有効になります。</string>
<string name="about">アプリについて</string>
<string name="require_kernel_version_8">KernelSU バージョン8以降が必要です</string>
<string name="module_uninstall_success">%sをアンインストールしました</string>
<string name="module_uninstall_failed">アンインストールに失敗: %s</string>
<string name="module_version">バージョン</string>
<string name="module_author">作者</string>
<string name="module_overlay_fs_not_available">OverlayFSが有効でないためモジュールは動作しません</string>
<string name="refresh">更新</string>
<string name="show_system_apps">システムアプリを表示</string>
<string name="hide_system_apps">システムアプリを非表示</string>
<string name="send_log">ログを送信</string>
<string name="reboot_to_apply">再起動して有効にする</string>
</resources>

View File

@@ -0,0 +1,58 @@
<resources>
<string name="home">Главная</string>
<string name="home_not_installed">Не установлен</string>
<string name="home_click_to_install">Нажмите чтобы установить</string>
<string name="home_working">Работает</string>
<string name="home_working_version">Версия: %d</string>
<string name="home_unsupported">Не поддерживается</string>
<string name="home_unsupported_reason">KernelSU поддерживает только GKI ядра</string>
<string name="home_copied_to_clipboard">Скопировано в буфер обмена</string>
<string name="home_support">Поддержка</string>
<string name="home_kernel">Ядро</string>
<string name="home_arch">Архитектура</string>
<string name="home_manager_version">Версия</string>
<string name="home_api">Уровень API</string>
<string name="home_abi">ABI</string>
<string name="home_fingerprint">Подпись</string>
<string name="home_securitypatch">Патч Безопасности</string>
<string name="home_selinux_status">Состояние SELinux</string>
<string name="selinux_status_disabled">Выключен</string>
<string name="selinux_status_enforcing">Принудительный</string>
<string name="selinux_status_permissive">Разрешающий</string>
<string name="selinux_status_unknown">Неизвестно</string>
<string name="superuser">Superuser</string>
<string name="superuser_failed_to_grant_root">Failed to grant root for %d</string>
<string name="module_failed_to_enable">Не удалось включить модуль: %s</string>
<string name="module_failed_to_disable">Не удалось отключить модуль: %s</string>
<string name="module_empty">Нет установленных модулей</string>
<string name="module">Модули</string>
<string name="uninstall">Удалить</string>
<string name="module_install">Установить</string>
<string name="install">Установить</string>
<string name="reboot">Перезагрузка</string>
<string name="settings">Настройки</string>
<string name="reboot_userspace">Soft Reboot</string>
<string name="reboot_recovery">Reboot to Recovery</string>
<string name="reboot_bootloader">Reboot to Bootloader</string>
<string name="reboot_download">Reboot to Download</string>
<string name="reboot_edl">Reboot to EDL</string>
<string name="settings_system_rw">Сделать систему доступной для записи</string>
<string name="settings_system_rw_summary">Использовать overlayfs, чтобы сделать системный раздел доступным для записи, необходима перезагрузка.</string>
<string name="about">О KernelSU</string>
<string name="require_kernel_version_8">Требуется KernelSU версии 8 и выше</string>
<string name="module_uninstall_success">%s удален</string>
<string name="module_uninstall_failed">Не удалось удалить: %s</string>
<string name="module_version">Версия</string>
<string name="module_author">Автор</string>
<string name="module_overlay_fs_not_available">overlayfs выключен, модуль не будет работать!</string>
<string name="refresh">Обновить</string>
<string name="show_system_apps">Показать системные приложения</string>
<string name="hide_system_apps">Скрыть системные приложения</string>
<string name="send_log">Отправить лог</string>
<string name="safe_mode">Безопасный режим</string>
<string name="reboot_to_apply">Перезагрузите, чтобы вступить в силу</string>
</resources>

View File

@@ -0,0 +1,53 @@
<resources>
<string name="home">Trang chủ</string>
<string name="home_not_installed">Chưa được cài đặt</string>
<string name="home_click_to_install">Nhấn đề cài dặt</string>
<string name="home_working">Đang chạy</string>
<string name="home_working_version">Phiên bản: %d</string>
<string name="home_unsupported">Không hỗ trợ</string>
<string name="home_unsupported_reason">KernelSU hiện tại chỉ hỗ trợ kernel GKI</string>
<string name="home_copied_to_clipboard">Sao chép vào clipboard</string>
<string name="home_support">Ủng hộ</string>
<string name="home_kernel">Kernel</string>
<string name="home_arch">Kiến trúc</string>
<string name="home_manager_version">Phiên bản</string>
<string name="home_api">Cấp độ API</string>
<string name="home_abi">ABI</string>
<string name="home_fingerprint">Fingerprint</string>
<string name="home_securitypatch">Bản vá bảo mật</string>
<string name="home_selinux_status">Trạng thái SELinux</string>
<string name="selinux_status_disabled">Vô hiệu hóa</string>
<string name="selinux_status_enforcing">Thực thi</string>
<string name="selinux_status_permissive">Cho phép</string>
<string name="selinux_status_unknown">Không rõ</string>
<string name="superuser">Superuser</string>
<string name="superuser_failed_to_grant_root">Không thể cấp quyền root cho %d</string>
<string name="module_failed_to_enable">Không thể kích hoạt mô-đun: %s</string>
<string name="module_failed_to_disable">Không thể vô hiệu hóa mô-đun: %s</string>
<string name="module_empty">Chưa có mô-đun nào được cài đặt</string>
<string name="module">Mô-đun</string>
<string name="uninstall">Gỡ cài đặt</string>
<string name="module_install">Cài đặt</string>
<string name="install">Cài đặt</string>
<string name="reboot">Khởi động lại</string>
<string name="settings">Thiết lập</string>
<string name="reboot_userspace">Khởi động mềm</string>
<string name="reboot_recovery">Khởi động lại vào Recovery</string>
<string name="reboot_bootloader">Khởi động lại vào Bootloader</string>
<string name="reboot_download">Khởi động lại vào Download Mode</string>
<string name="reboot_edl">Khởi động vào EDL</string>
<string name="settings_system_rw">Cho phép ghi vào phân vùng system</string>
<string name="settings_system_rw_summary">Sử dụng overlayfs để làm cho phân vùng system có thể ghi được, khởi động lại để áp dụng</string>
<string name="about">Thông tin</string>
<string name="require_kernel_version_8">Yêu cầu KernelSU phiên bản 8+</string>
<string name="module_uninstall_success">%s đã được gỡ cài đặt</string>
<string name="module_uninstall_failed">Lỗi khi gỡ cài đặt: %s</string>
<string name="module_version">Phiên bản</string>
<string name="module_author">Tác giả</string>
<string name="module_overlay_fs_not_available">Không tìm thấy overlayfs, mô-đun sẽ không thể hoạt động!</string>
<string name="refresh">Làm mới</string>
<string name="show_system_apps">Hiển thị ứng dụng hệ thống</string>
<string name="hide_system_apps">Ẩn ứng dụng hệ thống</string>
<string name="safe_mode">Chế độ an toàn</string>
<string name="reboot_to_apply">Khởi động lại để có hiệu lực</string>
</resources>

View File

@@ -11,11 +11,16 @@
<string name="home_support">支持</string>
<string name="home_kernel">内核版本</string>
<string name="home_arch">设备架构</string>
<string name="home_version">系统版本</string>
<string name="home_manager_version">管理器版本</string>
<string name="home_api">API 版本</string>
<string name="home_abi">ABI 支持</string>
<string name="home_fingerprint">系统指纹</string>
<string name="home_securitypatch">安全补丁</string>
<string name="home_selinux_status">SELinux 状态</string>
<string name="selinux_status_disabled">被禁用</string>
<string name="selinux_status_enforcing">强制执行</string>
<string name="selinux_status_permissive">宽容模式</string>
<string name="selinux_status_unknown">未知</string>
<string name="superuser">超级用户</string>
<string name="superuser_failed_to_grant_root">无法为 %d 授予 Root</string>
<string name="module_failed_to_enable">无法启用模块: %s</string>
@@ -36,4 +41,15 @@
<string name="settings_system_rw_summary">使用 overlayfs 使系统分区可写, 重启生效</string>
<string name="about">关于</string>
<string name="require_kernel_version_8">需要 KernelSU 版本 8+</string>
<string name="module_uninstall_success">%s 已卸载</string>
<string name="module_uninstall_failed">卸载失败: %s</string>
<string name="module_version">版本</string>
<string name="module_author">作者</string>
<string name="module_overlay_fs_not_available">内核不支持 overlayfs模块功能无法运作</string>
<string name="refresh">刷新</string>
<string name="show_system_apps">显示系统应用</string>
<string name="hide_system_apps">隐藏系统应用</string>
<string name="send_log">发送日志</string>
<string name="safe_mode">安全模式</string>
<string name="reboot_to_apply">重启生效</string>
</resources>

View File

@@ -11,11 +11,16 @@
<string name="home_support">支持</string>
<string name="home_kernel">内核版本</string>
<string name="home_arch">设备架构</string>
<string name="home_version">系统版本</string>
<string name="home_manager_version">管理器版本</string>
<string name="home_api">API 版本</string>
<string name="home_abi">ABI 支持</string>
<string name="home_fingerprint">系统指纹</string>
<string name="home_securitypatch">安全补丁</string>
<string name="home_selinux_status">SELinux 狀態</string>
<string name="selinux_status_disabled">被禁用</string>
<string name="selinux_status_enforcing">強制執行</string>
<string name="selinux_status_permissive">寬容模式</string>
<string name="selinux_status_unknown">未知</string>
<string name="superuser">超級用戶</string>
<string name="superuser_failed_to_grant_root">无法为 %d 授予 Root</string>
<string name="module_failed_to_enable">无法启用模块: %s</string>
@@ -36,4 +41,11 @@
<string name="settings_system_rw_summary">使用 overlayfs 使系统分区可写, 重启生效</string>
<string name="about">关于</string>
<string name="require_kernel_version_8">需要 KernelSU 版本 8+</string>
<string name="module_uninstall_success">%s 已卸載</string>
<string name="module_uninstall_failed">卸載失敗: %s</string>
<string name="module_version">版本</string>
<string name="module_author">作者</string>
<string name="module_overlay_fs_not_available">內核不支持 overlayfs模塊功能無法運作</string>
<string name="safe_mode">安全模式</string>
<string name="reboot_to_apply">重啟生效</string>
</resources>

View File

@@ -1,39 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="home"></string>
<string name="home"></string>
<string name="home_not_installed">未安裝</string>
<string name="home_click_to_install">点击安装</string>
<string name="home_click_to_install">點擊安裝</string>
<string name="home_working">工作中</string>
<string name="home_working_version">版本: %d</string>
<string name="home_unsupported">不支</string>
<string name="home_unsupported_reason">KernelSU 在只支 GKI </string>
<string name="home_unsupported">不支</string>
<string name="home_unsupported_reason">KernelSU 在只支 GKI </string>
<string name="home_copied_to_clipboard">已複製到剪貼簿</string>
<string name="home_support"></string>
<string name="home_kernel">核版本</string>
<string name="home_arch">设备架构</string>
<string name="home_version">系统版本</string>
<string name="home_support"></string>
<string name="home_kernel">核版本</string>
<string name="home_arch">設備架構</string>
<string name="home_manager_version">管理器版本</string>
<string name="home_api">API 版本</string>
<string name="home_abi">ABI 支</string>
<string name="home_fingerprint">统指纹</string>
<string name="home_securitypatch">安全补丁</string>
<string name="home_abi">ABI 支</string>
<string name="home_fingerprint">統指紋</string>
<string name="home_securitypatch">安全性更新</string>
<string name="home_selinux_status">SELinux 狀態</string>
<string name="selinux_status_disabled">被停用</string>
<string name="selinux_status_enforcing">強制執行</string>
<string name="selinux_status_permissive">寬容模式</string>
<string name="selinux_status_unknown">未知</string>
<string name="superuser">超級用戶</string>
<string name="superuser_failed_to_grant_root">无法为 %d 授 Root</string>
<string name="module_failed_to_enable">无法启用模: %s</string>
<string name="module_failed_to_disable">法禁用模: %s</string>
<string name="module_empty">有安装模块</string>
<string name="module"></string>
<string name="uninstall">卸载</string>
<string name="module_install"></string>
<string name="install"></string>
<string name="reboot"></string>
<string name="superuser_failed_to_grant_root">無法為 %d 授 Root</string>
<string name="module_failed_to_enable">無法啟用模: %s</string>
<string name="module_failed_to_disable">法禁用模: %s</string>
<string name="module_empty">有安裝模組</string>
<string name="module"></string>
<string name="uninstall">解除安裝</string>
<string name="module_install"></string>
<string name="install"></string>
<string name="reboot">新開機</string>
<string name="settings">設定</string>
<string name="reboot_userspace">软重启</string>
<string name="reboot_recovery">到 Recovery</string>
<string name="reboot_bootloader">到 BootLoader</string>
<string name="reboot_download">到 Download</string>
<string name="reboot_edl">到 EDL</string>
<string name="settings_system_rw">使系统可写</string>
<string name="settings_system_rw_summary">使用 overlayfs 使系统分区可写, 重启生效</string>
<string name="about">关于</string>
<string name="reboot_userspace">重新啟動</string>
<string name="reboot_recovery">新啟動到 Recovery</string>
<string name="reboot_bootloader">新啟動到 BootLoader</string>
<string name="reboot_download">新啟用到 Download</string>
<string name="reboot_edl">新啟用到 EDL</string>
<string name="settings_system_rw">讓系統可以寫入</string>
<string name="settings_system_rw_summary">使用 overlayfs 使系統分區可以寫入,重新啟動後生效</string>
<string name="about">關於</string>
<string name="require_kernel_version_8">需要 KernelSU 版本 8+</string>
<string name="module_uninstall_success">%s 已解除安裝</string>
<string name="module_uninstall_failed">解除安裝失敗: %s</string>
<string name="module_version">版本</string>
<string name="module_author">作者</string>
<string name="module_overlay_fs_not_available">內核不支持 overlayfs模組功能不能運作</string>
<string name="refresh">重新整理</string>
<string name="show_system_apps">顯示系統應用程式</string>
<string name="hide_system_apps">隱藏系統應用程式</string>
<string name="safe_mode">安全模式</string>
<string name="reboot_to_apply">重啟生效</string>
</resources>

View File

@@ -13,12 +13,17 @@
<string name="home_kernel">Kernel</string>
<string name="home_arch">Arch</string>
<string name="home_version">Version</string>
<string name="home_manager_version">Manager Version</string>
<string name="home_api">API Level</string>
<string name="home_abi">ABI</string>
<string name="home_fingerprint">Fingerprint</string>
<string name="home_securitypatch">Security Patch</string>
<string name="home_selinux_status">SELinux status</string>
<string name="selinux_status_disabled">Disabled</string>
<string name="selinux_status_enforcing">Enforcing</string>
<string name="selinux_status_permissive">Permissive</string>
<string name="selinux_status_unknown">Unknown</string>
<string name="superuser">Superuser</string>
<string name="superuser_failed_to_grant_root">Failed to grant root for %d</string>
<string name="module_failed_to_enable">Failed to enable module: %s</string>
@@ -42,5 +47,14 @@
<string name="require_kernel_version_8">Require KernelSU version 8+</string>
<string name="module_uninstall_success">%s uninstalled</string>
<string name="module_uninstall_failed">Failed to uninstall: %s</string>
<string name="module_version">Version</string>
<string name="module_author">Author</string>
<string name="module_overlay_fs_not_available">overlayfs is not available, module cannot work!</string>
<string name="refresh">Refresh</string>
<string name="show_system_apps">Show system apps</string>
<string name="hide_system_apps">Hide system apps</string>
<string name="send_log">Send Log</string>
<string name="safe_mode">Safe mode</string>
<string name="reboot_to_apply">Reboot to take effect</string>
</resources>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
<cache-path name="cache" path="."/>
<root-path name="root" path="." />
</paths>

View File

@@ -2,6 +2,7 @@ import com.android.build.api.dsl.ApplicationExtension
import com.android.build.gradle.BaseExtension
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.konan.properties.Properties
import java.io.ByteArrayOutputStream
plugins {
id("com.android.application") apply false
@@ -25,13 +26,41 @@ val androidCompileSdk = 33
val androidBuildToolsVersion = "33.0.1"
val androidSourceCompatibility = JavaVersion.VERSION_11
val androidTargetCompatibility = JavaVersion.VERSION_11
val managerVersionCode = 10302
val managerVersionName = "0.3.2"
val managerVersionCode = getVersionCode()
val managerVersionName = getVersionName()
tasks.register<Delete>("clean") {
delete(rootProject.buildDir)
}
fun getGitCommitCount(): Int {
val out = ByteArrayOutputStream()
exec {
commandLine("git", "rev-list", "--count", "HEAD")
standardOutput = out
}
return out.toString().trim().toInt()
}
fun getGitDescribe(): String {
val out = ByteArrayOutputStream()
exec {
commandLine("git", "describe", "--tags", "--always")
standardOutput = out
}
return out.toString().trim()
}
fun getVersionCode(): Int {
val commitCount = getGitCommitCount()
val major = 1
return major * 10000 + commitCount + 200
}
fun getVersionName(): String {
return getGitDescribe()
}
fun Project.configureBaseExtension() {
extensions.findByType<BaseExtension>()?.run {
compileSdkVersion(androidCompileSdk)

10
scripts/abi_gki_all.py Normal file
View File

@@ -0,0 +1,10 @@
from xml.dom.minidom import parse
import xml.dom.minidom
import sys
DOMTree = xml.dom.minidom.parse(sys.argv[1])
symbols = DOMTree.getElementsByTagName("elf-symbol")
print("[abi_symbol_list]")
for symbol in symbols:
print(" " + symbol.getAttribute("name"))

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