Compare commits

...

85 Commits

Author SHA1 Message Date
tiann
76b1165572 kernel: fix incorrect invalidate for manager in work profile 2023-04-21 14:45:47 +08:00
tiann
80c85b3bb9 manager: update libsu to make it work in work profile standalone! 2023-04-21 14:34:40 +08:00
Amicia De Rune
900652a82b update id translation (#412)
Signed-off-by: RooGhz720 <rooghz720@gmail.com>
2023-04-21 10:26:14 +08:00
Jia-Bin
6cbef7d987 Update Traditional Chinese (#413)
Update Traditional Chinese
Optimize the text for easier reading
2023-04-21 10:25:46 +08:00
TireX228
01d66834f0 manager: Update Russian language (#411) 2023-04-20 19:15:14 +08:00
Trịnh Văn Lợi
a40eae9b8c Update vi strings (#408) 2023-04-20 16:16:08 +08:00
github-actions[bot]
23b46bde2b [add device]: (#410)
has been added to the website.
Related issue: https://github.com/tiann/KernelSU/issues/409

Co-authored-by: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-20 16:15:28 +08:00
tiann
b38ada30e6 manager: remove html-text dependency 2023-04-20 15:46:05 +08:00
3452841752 selinux: use grep to check api supports (#402)
This checks `selinux_state` and `current_sid` supports in a raw way.
Feels more reliable than the version checks.

Supersedes #401, fixes #280, fixes #400.
2023-04-20 15:22:03 +08:00
tiann
3b9cab3432 manager: refine about dialog 2023-04-20 15:20:10 +08:00
tiann
2f6df20085 manager: remake home page 2023-04-20 13:52:56 +08:00
tiann
609ea40d1c manager: show loading dialog when collect bugreport 2023-04-20 11:40:09 +08:00
tiann
515a309831 Revert "ci: Add version to build artifacts"
This reverts commit 0b4f4683b3.
2023-04-20 10:55:41 +08:00
tiann
02c2228ab7 Revert "ci: Fix img upload"
This reverts commit ea93140b8a.
2023-04-20 10:55:41 +08:00
Trịnh Văn Lợi
ca246ba67d Update vi strings (#406) 2023-04-20 10:01:03 +08:00
easterNday
f9008b67c4 [add device]: Xiaomi 10S (#405)
增加小米10S的非GKi内核KSU支持。
2023-04-19 23:22:19 +08:00
tiann
e228197906 Revert "manager: manager: disable user scroll when refreshing"
This reverts commit d86b524558.
2023-04-19 21:16:23 +08:00
tiann
d98e324618 manager: upgrade compose dependencies to fix some weird bugs. close #367 2023-04-19 21:15:59 +08:00
Igor Sorocean
1880fdfda9 Update ro strings (#403) 2023-04-19 21:10:08 +08:00
tiann
d86b524558 manager: manager: disable user scroll when refreshing 2023-04-19 18:14:09 +08:00
tiann
70fa38a589 manager: upgrade AGP 2023-04-19 18:10:48 +08:00
tiann
ea93140b8a ci: Fix img upload 2023-04-19 14:02:39 +08:00
tiann
45c229dc9f kernel: fix snprintf 2023-04-18 19:38:58 +08:00
tiann
2b5ac95165 manager: Fix snprintf 2023-04-18 19:35:42 +08:00
Howard Wu
38c65e7e4b [skip ci] ci: fix job name typo (#398) 2023-04-18 18:44:04 +08:00
tiann
f40eaf4499 manager: Fix loading state 2023-04-18 18:42:41 +08:00
tiann
3a667ef389 manager: allow become_manager in work profile. 2023-04-18 18:40:32 +08:00
tiann
f35e03d816 kernel: allow manager to be installed in work profile 2023-04-18 18:32:33 +08:00
tiann
2bfd4d71d8 manager: use ParceledListSlice to transport List<PackageInfo>, avoiding TransactionTooLargeException. 2023-04-18 18:04:49 +08:00
tiann
2bc84014c2 manager: supports grant root access to cross profile. close #271 2023-04-18 17:38:48 +08:00
tiann
a3c72c22c1 manager: add selinux state to bugreport. 2023-04-18 14:47:21 +08:00
tiann
ddf2b7e9ff manager: add allowlist to bugreport. 2023-04-18 14:47:21 +08:00
tiann
04d1bee7b4 manager: remove directory tree in bugreport. 2023-04-18 14:47:21 +08:00
tiann
0c9ecf3abc kernel: always apply sepolicy rules even if selinux is permissive 2023-04-18 14:15:37 +08:00
Kung-chih
c8b4798b61 Update zh-rHK and zh-rTW (#396) 2023-04-18 13:25:55 +08:00
tiann
550c8ae45d Revert "ksud: update faked Magisk version to 26.1 to make some modules happy"
This reverts commit 48cd6e112b.
2023-04-18 13:24:35 +08:00
tiann
0b4f4683b3 ci: Add version to build artifacts 2023-04-18 13:24:35 +08:00
tiann
5504b0dd29 Revert "kernel: don't save allowlist in worker"
This reverts commit c569d803c5.
2023-04-18 13:19:49 +08:00
tiann
f0dcddd391 kernel: don't show log when get allowlist 2023-04-18 13:19:49 +08:00
Howard Wu
75be1e1bd6 ci: avoid ccache key conflict (#397) 2023-04-18 12:12:03 +08:00
tiann
c569d803c5 kernel: don't save allowlist in worker 2023-04-18 09:18:06 +08:00
tiann
48cd6e112b ksud: update faked Magisk version to 26.1 to make some modules happy 2023-04-17 23:20:10 +08:00
tiann
d41354e1d7 manager: show confirm dialog when grant root to app. 2023-04-17 18:19:33 +08:00
tiann
9a5e36c0a4 ksud: remove unused dependency 2023-04-17 18:19:18 +08:00
5ec1cff
f963e40a5f ksud: fix bind mount failed again (#395)
This fixes https://github.com/Dr-TSNG/ZygiskOnKernelSU/issues/18
2023-04-17 12:05:13 +08:00
tiann
f1e2402316 ksud: avoid using master commit dependency 2023-04-17 11:37:54 +08:00
tiann
31bb8c75f5 ksud: fix clippy 2023-04-16 22:14:53 +08:00
tiann
fb4ab44aa5 manager: add bootlog for bugreport 2023-04-15 17:45:20 +08:00
tiann
71216b1458 ksud: catch bootlog when post-fs-data 2023-04-15 17:45:20 +08:00
aiamadeus
c969ff4011 website: fix web link address of taichi (#391)
Co-authored-by: AmadeusGhost <42570690+AmadeusGhost@users.noreply.github.com>
2023-04-15 15:32:07 +08:00
tiann
dc45eb6ed4 kernel: Make sure logd has started before post-fs-data. 2023-04-15 00:17:28 +08:00
tiann
29aaaae4b4 ksud: fix clippy 2023-04-14 23:06:11 +08:00
tiann
1fe53b9549 ci: run clippy with release build 2023-04-14 22:59:29 +08:00
weishu
6274dbebc0 Ci (#390) 2023-04-14 22:55:43 +08:00
weishu
a1cd3ab6fa ci: update clippy check (#389) 2023-04-14 22:42:25 +08:00
5ec1cff
c058cb8848 ksud: refactor module mount (#384) 2023-04-14 22:30:34 +08:00
セリカ・シルフィル
029061177b kernel: Fix pull when we are not currently on a branch (#388)
Before fix:
```
[celica@arch msm-5.4]$ curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -
++ pwd
+ GKI_ROOT=/home/celica/workdir/mvaisakh-kernel/kernel/msm-5.4
+ echo '[+] GKI_ROOT: /home/celica/workdir/mvaisakh-kernel/kernel/msm-5.4'
[+] GKI_ROOT: /home/celica/workdir/mvaisakh-kernel/kernel/msm-5.4
+ test -d /home/celica/workdir/mvaisakh-kernel/kernel/msm-5.4/common/drivers
+ test -d /home/celica/workdir/mvaisakh-kernel/kernel/msm-5.4/drivers
+ DRIVER_DIR=/home/celica/workdir/mvaisakh-kernel/kernel/msm-5.4/drivers
+ test -d /home/celica/workdir/mvaisakh-kernel/kernel/msm-5.4/KernelSU
+ cd /home/celica/workdir/mvaisakh-kernel/kernel/msm-5.4/KernelSU
+ git stash
没有要保存的本地修改
+ git pull
您当前不在一个分支上。
请指定您要合并哪一个分支。
详见 git-pull(1)。

    git pull <远程> <分支>
```

After fix:
```
[celica@arch msm-5.4]$ curl -LSs "https://raw.githubusercontent.com/natsumerinchan/KernelSU/main/kernel/setup.sh" | bash -s main
++ pwd
+ GKI_ROOT=/home/celica/workdir/mvaisakh-kernel/kernel/msm-5.4
+ echo '[+] GKI_ROOT: /home/celica/workdir/mvaisakh-kernel/kernel/msm-5.4'
[+] GKI_ROOT: /home/celica/workdir/mvaisakh-kernel/kernel/msm-5.4
+ test -d /home/celica/workdir/mvaisakh-kernel/kernel/msm-5.4/common/drivers
+ test -d /home/celica/workdir/mvaisakh-kernel/kernel/msm-5.4/drivers
+ DRIVER_DIR=/home/celica/workdir/mvaisakh-kernel/kernel/msm-5.4/drivers
+ test -d /home/celica/workdir/mvaisakh-kernel/kernel/msm-5.4/KernelSU
+ cd /home/celica/workdir/mvaisakh-kernel/kernel/msm-5.4/KernelSU
+ git stash
没有要保存的本地修改
++ git status
++ grep -Po 'v\d+(\.\d+)*'
++ head -n1
+ '[' v0.5.2 ']'
+ git checkout main
之前的 HEAD 位置是 0bda101 ci: fix WSA upload path (#372)
切换到分支 'main'
您的分支与上游分支 'origin/main' 一致。
+ git pull
已经是最新的。
+ '[' -z main ']'
+ git checkout main
已经位于 'main'
您的分支与上游分支 'origin/main' 一致。
+ cd /home/celica/workdir/mvaisakh-kernel/kernel/msm-5.4
+ echo '[+] GKI_ROOT: /home/celica/workdir/mvaisakh-kernel/kernel/msm-5.4'
[+] GKI_ROOT: /home/celica/workdir/mvaisakh-kernel/kernel/msm-5.4
+ echo '[+] Copy kernel su driver to /home/celica/workdir/mvaisakh-kernel/kernel/msm-5.4/drivers'
[+] Copy kernel su driver to /home/celica/workdir/mvaisakh-kernel/kernel/msm-5.4/drivers
+ test -e /home/celica/workdir/mvaisakh-kernel/kernel/msm-5.4/drivers/kernelsu
+ echo '[+] Add kernel su driver to Makefile'
[+] Add kernel su driver to Makefile
+ DRIVER_MAKEFILE=/home/celica/workdir/mvaisakh-kernel/kernel/msm-5.4/drivers/Makefile
+ grep -q kernelsu /home/celica/workdir/mvaisakh-kernel/kernel/msm-5.4/drivers/Makefile
+ echo '[+] Done.'
[+] Done.
```
2023-04-14 15:31:30 +08:00
セリカ・シルフィル
9c8e813642 Kernel: Fix "bash: line 21: $1: unbound variable" (#385) 2023-04-13 22:15:17 +08:00
Coconut
7be61b9657 Make Huawei 4.9 Kernel compiler Happy and Does not affect other kernels (#374)
Adapt to SELinux with Huawei 4.9.xxx kernel without affecting other
mainstream kernels
2023-04-13 17:08:05 +08:00
セリカ・シルフィル
2f67d24ec9 kernel: Support switch branch or tag (#382) 2023-04-13 14:40:56 +08:00
Amicia De Rune
17d6f1cdf1 manager: update translation (#381)
Signed-off-by: RooGhz720 <rooghz720@gmail.com>
2023-04-13 13:19:39 +08:00
Terminator850
a0c34b40c6 Ensure the stability of use (#380)
I think we can add tag selection commands in the setup.sh script, such
as git checkout v0.5.1, to ensure the stability of use #379
2023-04-13 12:30:32 +08:00
tiann
00856f8cb9 misc: add .clang-format 2023-04-13 10:41:49 +08:00
Mike Evans
3df6387ee0 promotion: KernelSU integrated Bool-X kernel for raphael (#378)
Hi, I have made yet another KernelSU integrated kernel for Redmi #K20Pro
(#Raphael), based on a popular custom & optimized kernel called Bool-X
in the community.

Forked source code:
https://github.com/etnperlong/kernel_xiaomi_raphael_bool-x/tree/13.0-ksu
upstream source: https://github.com/onettboots/bool-x_xiaomi_raphael
(thanks to @onettboots)

I have tested the KernelSU feature on this kernel, everything works
fine.
2023-04-13 08:07:23 +08:00
Howard Wu
fe1c826b1b ci: Install dependency python-telegram-bot (#373) 2023-04-12 20:37:41 +08:00
Howard Wu
0bda101d4d ci: fix WSA upload path (#372) 2023-04-12 18:31:59 +08:00
Howard Wu
5e738129d9 ci: WSA build fix typo (#370) 2023-04-12 17:52:24 +08:00
tiann
39b5014add ksud: ensure parent dir when create file 2023-04-12 17:45:56 +08:00
tiann
3c6560ade9 ksud: format anyhow error 2023-04-12 13:21:13 +08:00
tiann
183d1a91c1 ksud: add error context to log 2023-04-12 13:17:13 +08:00
tiann
d711ab8b1f Revert "ksud: sort the stock mounts correctly."
This reverts commit 273a0b0b99.
2023-04-12 13:12:10 +08:00
Howard Wu
6c1a48952e WSA Kernel update to 5.15 (#369)
Checks: https://github.com/Howard20181/KernelSU/actions/runs/4672228625
2023-04-12 12:16:56 +08:00
chen2021-web
a343aa5eb0 Try to solve 4.14 build don't pass problem (#368) 2023-04-11 23:13:34 +08:00
tiann
273a0b0b99 ksud: sort the stock mounts correctly. 2023-04-11 21:23:30 +08:00
tiann
2f1e64dc1b ksud: make compiler happy 2023-04-11 20:45:21 +08:00
tiann
a46d4ecd3e ksud: use move mount instead of remount for stock mounts
Because some stock mounts are difficult to remount it back, so we bind mount it to somewhere else before overlayfs mount. And then use move mount to mount it back.
2023-04-11 20:32:08 +08:00
tiann
5f04954a5c ksud: don't umount stock overlayfs, just remount it 2023-04-11 16:24:02 +08:00
tiann
d065a7ca22 manager: don't create root shell everytime. this should close #361. MeiZu kernel seems cache something in execve syscall, which will cause double free in kernel. 2023-04-11 12:56:19 +08:00
Trịnh Văn Lợi
2f8373f9c5 Update strings.xml (#366)
Update missing translation
2023-04-11 11:05:35 +08:00
weishu
2d36e98246 kernel: make /system/bin/init second_stage more precisely (#357) 2023-04-11 10:55:17 +08:00
5ec1cff
f2d8f1ee60 kernel: fix search git in path (#363)
Prevent failing to get KSU_GIT_VERSION when PATH contains space.


[Details](https://github.com/5ec1cff/my-notes/blob/master/mi-kernel.md#%E4%B8%80%E4%B8%AA%E7%BC%BA%E5%B0%91%E5%BC%95%E5%8F%B7%E5%BC%95%E5%8F%91%E7%9A%84%E8%A1%80%E6%A1%88)
2023-04-09 17:16:35 +08:00
weishu
e7881c350c ksud: handle partition after REMOVE and REPLACE 2023-04-08 12:51:16 +08:00
Ylarod
ffe3e68c35 ksud: ensure ksud context when install (#356)
Incorrect se context will make module system broken
2023-04-07 12:46:59 +08:00
Xeonacid
4d6fafd778 website: fix typo (#354) 2023-04-06 22:40:47 +08:00
tiann
2bbf77ab4c ci: shortten image file name 2023-04-06 19:23:09 +08:00
63 changed files with 1847 additions and 542 deletions

View File

@@ -37,7 +37,7 @@ build_from_image() {
echo '[+] Compress images'
for image in boot*.img; do
$GZIP -n -f -9 "$image"
mv "$image".gz ksu-"$VERSION"-"$1"-"$image".gz
mv "$image".gz "${1//Image-/}"-"$image".gz
done
echo "[+] Images to upload"

View File

@@ -24,7 +24,7 @@ build_from_image() {
echo '[+] Compress images'
for image in boot*.img; do
$GZIP -n -f -9 "$image"
mv "$image".gz ksu-"$VERSION"-"$1"-"$image".gz
mv "$image".gz "${1//Image-/}"-"$image".gz
done
echo '[+] Images to upload'

View File

@@ -1,13 +1,14 @@
name: Build WSA-5.10.117-Kernel
name: Build Kernel - WSA
on:
push:
branches: ["main"]
paths:
- ".github/workflows/build-WSA-5.10.117-kernel.yml"
- ".github/workflows/build-kernel-wsa.yml"
- "kernel/**"
pull_request:
branches: ["main"]
paths:
- ".github/workflows/build-kernel-wsa.yml"
- "kernel/**"
workflow_call:
workflow_dispatch:
@@ -17,29 +18,44 @@ jobs:
strategy:
matrix:
arch: [x86_64, arm64]
version: [5.10.117.2]
version: ["5.10.117.2", "5.15.78.1"]
include:
- file_name: "bzImage"
make_config: "config-wsa"
arch: x86_64
- file_name: "Image"
- arch: x86_64
file_name: "bzImage"
- arch: arm64
file_name: "Image"
cross_compile: "aarch64-linux-gnu"
make_config: "config-wsa-arm64"
- version: "5.10.117.2"
arch: x86_64
make_config: config-wsa-5.10
- version: "5.10.117.2"
arch: arm64
make_config: config-wsa-arm64-5.10
- version: "5.15.78.1"
arch: x86_64
make_config: config-wsa-x64
- version: "5.15.78.1"
arch: arm64
make_config: config-wsa-arm64
- version: "5.10.117.2"
device_code: latte
kernel_version: "5.10"
- version: "5.15.78.1"
device_code: latte-2
kernel_version: "5.15"
name: Build WSA-Kernel-${{ matrix.version }}-${{ matrix.arch }}
runs-on: ubuntu-20.04
env:
CCACHE_COMPILERCHECK: "%compiler% -dumpmachine; %compiler% -dumpversion"
CCACHE_NOHASHDIR: "true"
CCACHE_MAXSIZE: "2G"
CCACHE_HARDLINK: "true"
steps:
- name: Install Build Tools
run: |
sudo apt update
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
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 gzip
export LLVM_VERSION=12
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
@@ -66,14 +82,15 @@ jobs:
uses: actions/checkout@v3
with:
repository: microsoft/WSA-Linux-Kernel
ref: android-lts/latte/${{ matrix.version }}
ref: android-lts/${{ matrix.device_code }}/${{ matrix.version }}
path: WSA-Linux-Kernel
- name: Setup Ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: WSA-Kernel-${{ matrix.version }}-${{ matrix.arch }}
save: ${{ github.event_name != 'pull_request' }}
save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
max-size: 2G
- name: Setup KernelSU
working-directory: WSA-Linux-Kernel
@@ -87,17 +104,47 @@ jobs:
DRIVER_MAKEFILE=$KERNEL_ROOT/drivers/Makefile
grep -q "kernelsu" $DRIVER_MAKEFILE || echo "obj-y += kernelsu/" >> $DRIVER_MAKEFILE
echo "[+] Apply KernelSU patches"
cd $KERNEL_ROOT && git apply $GITHUB_WORKSPACE/KernelSU/.github/patches/5.10/*.patch
cd $KERNEL_ROOT && git apply $GITHUB_WORKSPACE/KernelSU/.github/patches/${{ matrix.kernel_version }}/*.patch
echo "[+] KernelSU setup done."
cd $GITHUB_WORKSPACE/KernelSU
VERSION=$(($(git rev-list --count HEAD) + 10200))
echo "VERSION: $VERSION"
echo "kernelsu_version=$VERSION" >> $GITHUB_ENV
- name: Build Kernel
working-directory: WSA-Linux-Kernel
run: |
cp configs/wsa/${{ matrix.make_config }}-5.10 .config
cp configs/wsa/${{ matrix.make_config }} .config
make olddefconfig
make -j`nproc` LLVM=1 ARCH=${{ matrix.arch }} CROSS_COMPILE=${{ matrix.cross_compile }} ${{ matrix.file_name }} CCACHE="/usr/bin/ccache"
echo "file_path=WSA-Linux-Kernel/arch/${{ matrix.arch }}/boot/${{ matrix.file_name }}" >> $GITHUB_ENV
- name: Upload kernel-${{ matrix.arch }}-${{ matrix.version }}
uses: actions/upload-artifact@v3
with:
name: kernel-WSA-${{ matrix.arch }}-${{ matrix.version }}
path: WSA-Linux-Kernel/arch/${{ matrix.arch }}/boot/${{ matrix.file_name }}
path: "${{ env.file_path }}"
- name: Post to Telegram
if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' }}
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 }}
run: |
TITLE=kernel-${{ matrix.arch }}-WSA-${{ matrix.version }}
echo "[+] title: $TITLE"
export TITLE
export VERSION="${{ env.kernelsu_version }}"
echo "[+] Compress images"
gzip -n -f -9 "${{ env.file_path }}"
echo "[+] Image to upload"
ls -l "${{ env.file_path }}.gz"
if [ -n "${{ secrets.BOT_TOKEN }}" ]; then
pip3 install python-telegram-bot
python3 "$GITHUB_WORKSPACE/KernelSU/scripts/ksubot.py" "${{ env.file_path }}.gz"
fi

View File

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

View File

@@ -3,7 +3,13 @@ name: Clippy check
on:
push:
branches:
- 'main'
- main
paths:
- '.github/workflows/clippy.yml'
- 'userspace/ksud/**'
pull_request:
branches:
- main
paths:
- '.github/workflows/clippy.yml'
- 'userspace/ksud/**'
@@ -26,5 +32,5 @@ jobs:
- 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
cross clippy --manifest-path userspace/ksud/Cargo.toml --target aarch64-linux-android --release
cross clippy --manifest-path userspace/ksud/Cargo.toml --target x86_64-linux-android --release

View File

@@ -64,7 +64,6 @@ jobs:
env:
CCACHE_COMPILERCHECK: "%compiler% -dumpmachine; %compiler% -dumpversion"
CCACHE_NOHASHDIR: "true"
CCACHE_MAXSIZE: "2G"
CCACHE_HARDLINK: "true"
steps:
- uses: actions/checkout@v3
@@ -72,13 +71,6 @@ jobs:
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: |
@@ -124,6 +116,14 @@ jobs:
echo "[+] Add KernelSU symbols"
cat $KSU_ROOT/kernel/export_symbol.txt | awk '{sub("[ \t]+","");print " "$0}' >> $SYMBOL_LIST
- name: Setup ccache
if: inputs.use_cache == true
uses: hendrikmuhs/ccache-action@v1.2
with:
key: gki-kernel-aarch64-${{ inputs.version_name }}
max-size: 2G
save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
- 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
@@ -149,4 +149,4 @@ jobs:
uses: actions/upload-artifact@v3
with:
name: AnyKernel3-${{ inputs.version_name }}_${{ inputs.os_patch_level }}
path: ./AnyKernel3/*
path: ./AnyKernel3/*

View File

@@ -14,7 +14,7 @@ jobs:
build-a13-kernel:
uses: ./.github/workflows/build-kernel-a13.yml
build-wsa-kernel:
uses: ./.github/workflows/build-WSA-5.10.117-kernel.yml
uses: ./.github/workflows/build-kernel-wsa.yml
release:
needs:
- build-manager

548
kernel/.clang-format Normal file
View File

@@ -0,0 +1,548 @@
# SPDX-License-Identifier: GPL-2.0
#
# clang-format configuration file. Intended for clang-format >= 4.
#
# For more information, see:
#
# Documentation/process/clang-format.rst
# https://clang.llvm.org/docs/ClangFormat.html
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
#
---
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
#AlignEscapedNewlines: Left # Unknown to clang-format-4.0
AlignOperands: true
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
#AfterExternBlock: false # Unknown to clang-format-5.0
BeforeCatch: false
BeforeElse: false
IndentBraces: false
#SplitEmptyFunction: true # Unknown to clang-format-4.0
#SplitEmptyRecord: true # Unknown to clang-format-4.0
#SplitEmptyNamespace: true # Unknown to clang-format-4.0
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
#BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0
BreakBeforeTernaryOperators: false
BreakConstructorInitializersBeforeComma: false
#BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: false
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
#CompactNamespaces: false # Unknown to clang-format-4.0
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 8
Cpp11BracedListStyle: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
#FixNamespaceComments: false # Unknown to clang-format-4.0
# Taken from:
# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ \
# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \
# | sort | uniq
ForEachMacros:
- 'apei_estatus_for_each_section'
- 'ata_for_each_dev'
- 'ata_for_each_link'
- '__ata_qc_for_each'
- 'ata_qc_for_each'
- 'ata_qc_for_each_raw'
- 'ata_qc_for_each_with_internal'
- 'ax25_for_each'
- 'ax25_uid_for_each'
- '__bio_for_each_bvec'
- 'bio_for_each_bvec'
- 'bio_for_each_bvec_all'
- 'bio_for_each_integrity_vec'
- '__bio_for_each_segment'
- 'bio_for_each_segment'
- 'bio_for_each_segment_all'
- 'bio_list_for_each'
- 'bip_for_each_vec'
- 'bitmap_for_each_clear_region'
- 'bitmap_for_each_set_region'
- 'blkg_for_each_descendant_post'
- 'blkg_for_each_descendant_pre'
- 'blk_queue_for_each_rl'
- 'bond_for_each_slave'
- 'bond_for_each_slave_rcu'
- 'bpf_for_each_spilled_reg'
- 'btree_for_each_safe128'
- 'btree_for_each_safe32'
- 'btree_for_each_safe64'
- 'btree_for_each_safel'
- 'card_for_each_dev'
- 'cgroup_taskset_for_each'
- 'cgroup_taskset_for_each_leader'
- 'cpufreq_for_each_entry'
- 'cpufreq_for_each_entry_idx'
- 'cpufreq_for_each_valid_entry'
- 'cpufreq_for_each_valid_entry_idx'
- 'css_for_each_child'
- 'css_for_each_descendant_post'
- 'css_for_each_descendant_pre'
- 'device_for_each_child_node'
- 'dma_fence_chain_for_each'
- 'do_for_each_ftrace_op'
- 'drm_atomic_crtc_for_each_plane'
- 'drm_atomic_crtc_state_for_each_plane'
- 'drm_atomic_crtc_state_for_each_plane_state'
- 'drm_atomic_for_each_plane_damage'
- 'drm_client_for_each_connector_iter'
- 'drm_client_for_each_modeset'
- 'drm_connector_for_each_possible_encoder'
- 'drm_for_each_bridge_in_chain'
- 'drm_for_each_connector_iter'
- 'drm_for_each_crtc'
- 'drm_for_each_encoder'
- 'drm_for_each_encoder_mask'
- 'drm_for_each_fb'
- 'drm_for_each_legacy_plane'
- 'drm_for_each_plane'
- 'drm_for_each_plane_mask'
- 'drm_for_each_privobj'
- 'drm_mm_for_each_hole'
- 'drm_mm_for_each_node'
- 'drm_mm_for_each_node_in_range'
- 'drm_mm_for_each_node_safe'
- 'flow_action_for_each'
- 'for_each_active_dev_scope'
- 'for_each_active_drhd_unit'
- 'for_each_active_iommu'
- 'for_each_aggr_pgid'
- 'for_each_available_child_of_node'
- 'for_each_bio'
- 'for_each_board_func_rsrc'
- 'for_each_bvec'
- 'for_each_card_auxs'
- 'for_each_card_auxs_safe'
- 'for_each_card_components'
- 'for_each_card_dapms'
- 'for_each_card_pre_auxs'
- 'for_each_card_prelinks'
- 'for_each_card_rtds'
- 'for_each_card_rtds_safe'
- 'for_each_card_widgets'
- 'for_each_card_widgets_safe'
- 'for_each_cgroup_storage_type'
- 'for_each_child_of_node'
- 'for_each_clear_bit'
- 'for_each_clear_bit_from'
- 'for_each_cmsghdr'
- 'for_each_compatible_node'
- 'for_each_component_dais'
- 'for_each_component_dais_safe'
- 'for_each_comp_order'
- 'for_each_console'
- 'for_each_cpu'
- 'for_each_cpu_and'
- 'for_each_cpu_not'
- 'for_each_cpu_wrap'
- 'for_each_dapm_widgets'
- 'for_each_dev_addr'
- 'for_each_dev_scope'
- 'for_each_displayid_db'
- 'for_each_dma_cap_mask'
- 'for_each_dpcm_be'
- 'for_each_dpcm_be_rollback'
- 'for_each_dpcm_be_safe'
- 'for_each_dpcm_fe'
- 'for_each_drhd_unit'
- 'for_each_dss_dev'
- 'for_each_efi_memory_desc'
- 'for_each_efi_memory_desc_in_map'
- 'for_each_element'
- 'for_each_element_extid'
- 'for_each_element_id'
- 'for_each_endpoint_of_node'
- 'for_each_evictable_lru'
- 'for_each_fib6_node_rt_rcu'
- 'for_each_fib6_walker_rt'
- 'for_each_free_mem_pfn_range_in_zone'
- 'for_each_free_mem_pfn_range_in_zone_from'
- 'for_each_free_mem_range'
- 'for_each_free_mem_range_reverse'
- 'for_each_func_rsrc'
- 'for_each_hstate'
- 'for_each_if'
- 'for_each_iommu'
- 'for_each_ip_tunnel_rcu'
- 'for_each_irq_nr'
- 'for_each_link_codecs'
- 'for_each_link_cpus'
- 'for_each_link_platforms'
- 'for_each_lru'
- 'for_each_matching_node'
- 'for_each_matching_node_and_match'
- 'for_each_member'
- 'for_each_mem_region'
- 'for_each_memblock_type'
- 'for_each_memcg_cache_index'
- 'for_each_mem_pfn_range'
- '__for_each_mem_range'
- 'for_each_mem_range'
- '__for_each_mem_range_rev'
- 'for_each_mem_range_rev'
- 'for_each_migratetype_order'
- 'for_each_msi_entry'
- 'for_each_msi_entry_safe'
- 'for_each_net'
- 'for_each_net_continue_reverse'
- 'for_each_netdev'
- 'for_each_netdev_continue'
- 'for_each_netdev_continue_rcu'
- 'for_each_netdev_continue_reverse'
- 'for_each_netdev_feature'
- 'for_each_netdev_in_bond_rcu'
- 'for_each_netdev_rcu'
- 'for_each_netdev_reverse'
- 'for_each_netdev_safe'
- 'for_each_net_rcu'
- 'for_each_new_connector_in_state'
- 'for_each_new_crtc_in_state'
- 'for_each_new_mst_mgr_in_state'
- 'for_each_new_plane_in_state'
- 'for_each_new_private_obj_in_state'
- 'for_each_node'
- 'for_each_node_by_name'
- 'for_each_node_by_type'
- 'for_each_node_mask'
- 'for_each_node_state'
- 'for_each_node_with_cpus'
- 'for_each_node_with_property'
- 'for_each_nonreserved_multicast_dest_pgid'
- 'for_each_of_allnodes'
- 'for_each_of_allnodes_from'
- 'for_each_of_cpu_node'
- 'for_each_of_pci_range'
- 'for_each_old_connector_in_state'
- 'for_each_old_crtc_in_state'
- 'for_each_old_mst_mgr_in_state'
- 'for_each_oldnew_connector_in_state'
- 'for_each_oldnew_crtc_in_state'
- 'for_each_oldnew_mst_mgr_in_state'
- 'for_each_oldnew_plane_in_state'
- 'for_each_oldnew_plane_in_state_reverse'
- 'for_each_oldnew_private_obj_in_state'
- 'for_each_old_plane_in_state'
- 'for_each_old_private_obj_in_state'
- 'for_each_online_cpu'
- 'for_each_online_node'
- 'for_each_online_pgdat'
- 'for_each_pci_bridge'
- 'for_each_pci_dev'
- 'for_each_pci_msi_entry'
- 'for_each_pcm_streams'
- 'for_each_physmem_range'
- 'for_each_populated_zone'
- 'for_each_possible_cpu'
- 'for_each_present_cpu'
- 'for_each_prime_number'
- 'for_each_prime_number_from'
- 'for_each_process'
- 'for_each_process_thread'
- 'for_each_property_of_node'
- 'for_each_registered_fb'
- 'for_each_requested_gpio'
- 'for_each_requested_gpio_in_range'
- 'for_each_reserved_mem_range'
- 'for_each_reserved_mem_region'
- 'for_each_rtd_codec_dais'
- 'for_each_rtd_codec_dais_rollback'
- 'for_each_rtd_components'
- 'for_each_rtd_cpu_dais'
- 'for_each_rtd_cpu_dais_rollback'
- 'for_each_rtd_dais'
- 'for_each_set_bit'
- 'for_each_set_bit_from'
- 'for_each_set_clump8'
- 'for_each_sg'
- 'for_each_sg_dma_page'
- 'for_each_sg_page'
- 'for_each_sgtable_dma_page'
- 'for_each_sgtable_dma_sg'
- 'for_each_sgtable_page'
- 'for_each_sgtable_sg'
- 'for_each_sibling_event'
- 'for_each_subelement'
- 'for_each_subelement_extid'
- 'for_each_subelement_id'
- '__for_each_thread'
- 'for_each_thread'
- 'for_each_unicast_dest_pgid'
- 'for_each_wakeup_source'
- 'for_each_zone'
- 'for_each_zone_zonelist'
- 'for_each_zone_zonelist_nodemask'
- 'fwnode_for_each_available_child_node'
- 'fwnode_for_each_child_node'
- 'fwnode_graph_for_each_endpoint'
- 'gadget_for_each_ep'
- 'genradix_for_each'
- 'genradix_for_each_from'
- 'hash_for_each'
- 'hash_for_each_possible'
- 'hash_for_each_possible_rcu'
- 'hash_for_each_possible_rcu_notrace'
- 'hash_for_each_possible_safe'
- 'hash_for_each_rcu'
- 'hash_for_each_safe'
- 'hctx_for_each_ctx'
- 'hlist_bl_for_each_entry'
- 'hlist_bl_for_each_entry_rcu'
- 'hlist_bl_for_each_entry_safe'
- 'hlist_for_each'
- 'hlist_for_each_entry'
- 'hlist_for_each_entry_continue'
- 'hlist_for_each_entry_continue_rcu'
- 'hlist_for_each_entry_continue_rcu_bh'
- 'hlist_for_each_entry_from'
- 'hlist_for_each_entry_from_rcu'
- 'hlist_for_each_entry_rcu'
- 'hlist_for_each_entry_rcu_bh'
- 'hlist_for_each_entry_rcu_notrace'
- 'hlist_for_each_entry_safe'
- '__hlist_for_each_rcu'
- 'hlist_for_each_safe'
- 'hlist_nulls_for_each_entry'
- 'hlist_nulls_for_each_entry_from'
- 'hlist_nulls_for_each_entry_rcu'
- 'hlist_nulls_for_each_entry_safe'
- 'i3c_bus_for_each_i2cdev'
- 'i3c_bus_for_each_i3cdev'
- 'ide_host_for_each_port'
- 'ide_port_for_each_dev'
- 'ide_port_for_each_present_dev'
- 'idr_for_each_entry'
- 'idr_for_each_entry_continue'
- 'idr_for_each_entry_continue_ul'
- 'idr_for_each_entry_ul'
- 'in_dev_for_each_ifa_rcu'
- 'in_dev_for_each_ifa_rtnl'
- 'inet_bind_bucket_for_each'
- 'inet_lhash2_for_each_icsk_rcu'
- 'key_for_each'
- 'key_for_each_safe'
- 'klp_for_each_func'
- 'klp_for_each_func_safe'
- 'klp_for_each_func_static'
- 'klp_for_each_object'
- 'klp_for_each_object_safe'
- 'klp_for_each_object_static'
- 'kunit_suite_for_each_test_case'
- 'kvm_for_each_memslot'
- 'kvm_for_each_vcpu'
- 'list_for_each'
- 'list_for_each_codec'
- 'list_for_each_codec_safe'
- 'list_for_each_continue'
- 'list_for_each_entry'
- 'list_for_each_entry_continue'
- 'list_for_each_entry_continue_rcu'
- 'list_for_each_entry_continue_reverse'
- 'list_for_each_entry_from'
- 'list_for_each_entry_from_rcu'
- 'list_for_each_entry_from_reverse'
- 'list_for_each_entry_lockless'
- 'list_for_each_entry_rcu'
- 'list_for_each_entry_reverse'
- 'list_for_each_entry_safe'
- 'list_for_each_entry_safe_continue'
- 'list_for_each_entry_safe_from'
- 'list_for_each_entry_safe_reverse'
- 'list_for_each_prev'
- 'list_for_each_prev_safe'
- 'list_for_each_safe'
- 'llist_for_each'
- 'llist_for_each_entry'
- 'llist_for_each_entry_safe'
- 'llist_for_each_safe'
- 'mci_for_each_dimm'
- 'media_device_for_each_entity'
- 'media_device_for_each_intf'
- 'media_device_for_each_link'
- 'media_device_for_each_pad'
- 'nanddev_io_for_each_page'
- 'netdev_for_each_lower_dev'
- 'netdev_for_each_lower_private'
- 'netdev_for_each_lower_private_rcu'
- 'netdev_for_each_mc_addr'
- 'netdev_for_each_uc_addr'
- 'netdev_for_each_upper_dev_rcu'
- 'netdev_hw_addr_list_for_each'
- 'nft_rule_for_each_expr'
- 'nla_for_each_attr'
- 'nla_for_each_nested'
- 'nlmsg_for_each_attr'
- 'nlmsg_for_each_msg'
- 'nr_neigh_for_each'
- 'nr_neigh_for_each_safe'
- 'nr_node_for_each'
- 'nr_node_for_each_safe'
- 'of_for_each_phandle'
- 'of_property_for_each_string'
- 'of_property_for_each_u32'
- 'pci_bus_for_each_resource'
- 'pcm_for_each_format'
- 'ping_portaddr_for_each_entry'
- 'plist_for_each'
- 'plist_for_each_continue'
- 'plist_for_each_entry'
- 'plist_for_each_entry_continue'
- 'plist_for_each_entry_safe'
- 'plist_for_each_safe'
- 'pnp_for_each_card'
- 'pnp_for_each_dev'
- 'protocol_for_each_card'
- 'protocol_for_each_dev'
- 'queue_for_each_hw_ctx'
- 'radix_tree_for_each_slot'
- 'radix_tree_for_each_tagged'
- 'rbtree_postorder_for_each_entry_safe'
- 'rdma_for_each_block'
- 'rdma_for_each_port'
- 'rdma_umem_for_each_dma_block'
- 'resource_list_for_each_entry'
- 'resource_list_for_each_entry_safe'
- 'rhl_for_each_entry_rcu'
- 'rhl_for_each_rcu'
- 'rht_for_each'
- 'rht_for_each_entry'
- 'rht_for_each_entry_from'
- 'rht_for_each_entry_rcu'
- 'rht_for_each_entry_rcu_from'
- 'rht_for_each_entry_safe'
- 'rht_for_each_from'
- 'rht_for_each_rcu'
- 'rht_for_each_rcu_from'
- '__rq_for_each_bio'
- 'rq_for_each_bvec'
- 'rq_for_each_segment'
- 'scsi_for_each_prot_sg'
- 'scsi_for_each_sg'
- 'sctp_for_each_hentry'
- 'sctp_skb_for_each'
- 'shdma_for_each_chan'
- '__shost_for_each_device'
- 'shost_for_each_device'
- 'sk_for_each'
- 'sk_for_each_bound'
- 'sk_for_each_entry_offset_rcu'
- 'sk_for_each_from'
- 'sk_for_each_rcu'
- 'sk_for_each_safe'
- 'sk_nulls_for_each'
- 'sk_nulls_for_each_from'
- 'sk_nulls_for_each_rcu'
- 'snd_array_for_each'
- 'snd_pcm_group_for_each_entry'
- 'snd_soc_dapm_widget_for_each_path'
- 'snd_soc_dapm_widget_for_each_path_safe'
- 'snd_soc_dapm_widget_for_each_sink_path'
- 'snd_soc_dapm_widget_for_each_source_path'
- 'tb_property_for_each'
- 'tcf_exts_for_each_action'
- 'udp_portaddr_for_each_entry'
- 'udp_portaddr_for_each_entry_rcu'
- 'usb_hub_for_each_child'
- 'v4l2_device_for_each_subdev'
- 'v4l2_m2m_for_each_dst_buf'
- 'v4l2_m2m_for_each_dst_buf_safe'
- 'v4l2_m2m_for_each_src_buf'
- 'v4l2_m2m_for_each_src_buf_safe'
- 'virtio_device_for_each_vq'
- 'while_for_each_ftrace_op'
- 'xa_for_each'
- 'xa_for_each_marked'
- 'xa_for_each_range'
- 'xa_for_each_start'
- 'xas_for_each'
- 'xas_for_each_conflict'
- 'xas_for_each_marked'
- 'xbc_array_for_each_value'
- 'xbc_for_each_key_value'
- 'xbc_node_for_each_array_value'
- 'xbc_node_for_each_child'
- 'xbc_node_for_each_key_value'
- 'zorro_for_each_dev'
#IncludeBlocks: Preserve # Unknown to clang-format-5.0
IncludeCategories:
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
#IndentPPDirectives: None # Unknown to clang-format-5.0
IndentWidth: 8
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
#ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0
ObjCBlockIndentWidth: 8
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
# Taken from git's rules
#PenaltyBreakAssignment: 10 # Unknown to clang-format-4.0
PenaltyBreakBeforeFirstCallParameter: 30
PenaltyBreakComment: 10
PenaltyBreakFirstLessLess: 0
PenaltyBreakString: 10
PenaltyExcessCharacter: 100
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: false
SortIncludes: false
#SortUsingDeclarations: false # Unknown to clang-format-4.0
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
#SpaceBeforeCtorInitializerColon: true # Unknown to clang-format-5.0
#SpaceBeforeInheritanceColon: true # Unknown to clang-format-5.0
SpaceBeforeParens: ControlStatements
#SpaceBeforeRangeBasedForLoopColon: true # Unknown to clang-format-5.0
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp03
TabWidth: 8
UseTab: Always
...

View File

@@ -14,7 +14,7 @@ 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)
KSU_GIT_VERSION := $(shell cd $(srctree)/$(src); /usr/bin/env PATH=$$PATH:/usr/bin:/usr/local/bin git rev-list --count HEAD)
KSU_GIT_VERSION := $(shell cd $(srctree)/$(src); /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin git rev-list --count HEAD)
ccflags-y += -DKSU_GIT_VERSION=$(KSU_GIT_VERSION)
endif

View File

@@ -64,6 +64,8 @@ bool ksu_allow_uid(uid_t uid, bool allow, bool persist)
p->uid = uid;
p->allow = allow;
pr_info("allow_uid: %d, allow: %d", uid, allow);
list_add_tail(&p->list, &allow_list);
result = true;
@@ -102,7 +104,7 @@ bool ksu_get_allow_list(int *array, int *length, bool allow)
int i = 0;
list_for_each (pos, &allow_list) {
p = list_entry(pos, struct perm_data, list);
pr_info("get_allow_list uid: %d allow: %d\n", p->uid, p->allow);
// pr_info("get_allow_list uid: %d allow: %d\n", p->uid, p->allow);
if (p->allow == allow) {
array[i++] = p->uid;
}

View File

@@ -38,14 +38,16 @@ static inline bool is_allow_su()
return ksu_is_allow_uid(current_uid().val);
}
static inline bool is_isolated_uid(uid_t uid) {
#define FIRST_ISOLATED_UID 99000
#define LAST_ISOLATED_UID 99999
#define FIRST_APP_ZYGOTE_ISOLATED_UID 90000
#define LAST_APP_ZYGOTE_ISOLATED_UID 98999
uid_t appid = uid % 100000;
return (appid >= FIRST_ISOLATED_UID && appid <= LAST_ISOLATED_UID)
|| (appid >= FIRST_APP_ZYGOTE_ISOLATED_UID && appid <= LAST_APP_ZYGOTE_ISOLATED_UID);
static inline bool is_isolated_uid(uid_t uid)
{
#define FIRST_ISOLATED_UID 99000
#define LAST_ISOLATED_UID 99999
#define FIRST_APP_ZYGOTE_ISOLATED_UID 90000
#define LAST_APP_ZYGOTE_ISOLATED_UID 98999
uid_t appid = uid % 100000;
return (appid >= FIRST_ISOLATED_UID && appid <= LAST_ISOLATED_UID) ||
(appid >= FIRST_APP_ZYGOTE_ISOLATED_UID &&
appid <= LAST_APP_ZYGOTE_ISOLATED_UID);
}
static struct group_info root_groups = { .usage = ATOMIC_INIT(2) };
@@ -168,14 +170,25 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
}
// someone wants to be root manager, just check it!
// arg3 should be `/data/data/<manager_package_name>`
// arg3 should be `/data/user/<userId>/<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;
}
// for user 0, it is /data/data
// for user 999, it is /data/user/999
const char *prefix;
char prefixTmp[64];
int userId = current_uid().val / 100000;
if (userId == 0) {
prefix = "/data/data";
} else {
snprintf(prefixTmp, sizeof(prefixTmp), "/data/user/%d", userId);
prefix = prefixTmp;
}
if (startswith(param, (char *)prefix) != 0) {
pr_info("become_manager: invalid param: %s\n", param);
return 0;
@@ -335,28 +348,31 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
return 0;
}
static bool is_appuid(kuid_t uid) {
#define PER_USER_RANGE 100000
#define FIRST_APPLICATION_UID 10000
#define LAST_APPLICATION_UID 19999
static bool is_appuid(kuid_t uid)
{
#define PER_USER_RANGE 100000
#define FIRST_APPLICATION_UID 10000
#define LAST_APPLICATION_UID 19999
uid_t appid = uid.val % PER_USER_RANGE;
return appid >= FIRST_APPLICATION_UID && appid <= LAST_APPLICATION_UID;
}
static bool should_umount(struct path* path) {
static bool should_umount(struct path *path)
{
if (!path) {
return false;
}
if (path->mnt && path->mnt->mnt_sb && path->mnt->mnt_sb->s_type) {
const char* fstype = path->mnt->mnt_sb->s_type->name;
const char *fstype = path->mnt->mnt_sb->s_type->name;
return strcmp(fstype, "overlay") == 0;
}
return false;
}
static void try_umount(const char *mnt) {
static void try_umount(const char *mnt)
{
struct path path;
int err = kern_path(mnt, 0, &path);
if (err) {
@@ -376,7 +392,8 @@ static void try_umount(const char *mnt) {
#endif
}
int ksu_handle_setuid(struct cred *new, const struct cred *old) {
int ksu_handle_setuid(struct cred *new, const struct cred *old)
{
if (!new || !old) {
return 0;
}
@@ -509,7 +526,8 @@ static int ksu_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
}
static int ksu_task_fix_setuid(struct cred *new, const struct cred *old,
int flags) {
int flags)
{
return ksu_handle_setuid(new, old);
}

View File

@@ -23,6 +23,7 @@ static const char KERNEL_SU_RC[] =
"\n"
"on post-fs-data\n"
" start logd\n"
// We should wait for the post-fs-data finish
" exec u:r:su:s0 root -- " KSUD_PATH " post-fs-data\n"
"\n"
@@ -69,6 +70,69 @@ void on_post_fs_data(void)
stop_input_hook();
}
#define MAX_ARG_STRINGS 0x7FFFFFFF
struct user_arg_ptr {
#ifdef CONFIG_COMPAT
bool is_compat;
#endif
union {
const char __user *const __user *native;
#ifdef CONFIG_COMPAT
const compat_uptr_t __user *compat;
#endif
} ptr;
};
static const char __user *get_user_arg_ptr(struct user_arg_ptr argv, int nr)
{
const char __user *native;
#ifdef CONFIG_COMPAT
if (unlikely(argv.is_compat)) {
compat_uptr_t compat;
if (get_user(compat, argv.ptr.compat + nr))
return ERR_PTR(-EFAULT);
return compat_ptr(compat);
}
#endif
if (get_user(native, argv.ptr.native + nr))
return ERR_PTR(-EFAULT);
return native;
}
/*
* count() counts the number of strings in array ARGV.
*/
static int count(struct user_arg_ptr argv, int max)
{
int i = 0;
if (argv.ptr.native != NULL) {
for (;;) {
const char __user *p = get_user_arg_ptr(argv, i);
if (!p)
break;
if (IS_ERR(p))
return -EFAULT;
if (i >= max)
return -E2BIG;
++i;
if (fatal_signal_pending(current))
return -ERESTARTNOHAND;
cond_resched();
}
}
return i;
}
int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
void *argv, void *envp, int *flags)
{
@@ -82,7 +146,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
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;
static bool init_second_stage_executed = false;
if (!filename_ptr)
return 0;
@@ -95,18 +159,36 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
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();
struct user_arg_ptr *ptr = (struct user_arg_ptr*) argv;
int argc = count(*ptr, MAX_ARG_STRINGS);
pr_info("/system/bin/init argc: %d\n", argc);
if (argc > 1 && !init_second_stage_executed) {
const char __user *p = get_user_arg_ptr(*ptr, 1);
if (p && !IS_ERR(p)) {
char first_arg[16];
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
strncpy_from_user_nofault(first_arg, p, sizeof(first_arg));
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
strncpy_from_unsafe_user(first_arg, p, sizeof(first_arg));
#else
strncpy_from_user(first_arg, p, sizeof(first_arg));
#endif
pr_info("first arg: %s\n", first_arg);
if (!strcmp(first_arg, "second_stage")) {
pr_info("/system/bin/init second_stage executed\n");
apply_kernelsu_rules();
init_second_stage_executed = true;
}
} else {
pr_err("/system/bin/init parse args err!\n");
}
}
}
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");
pr_info("exec app_process, /data prepared, second_stage: %d\n", init_second_stage_executed);
on_post_fs_data(); // we keep this for old ksud
stop_execve_hook();
}

View File

@@ -2,6 +2,13 @@ obj-y += selinux.o
obj-y += sepolicy.o
obj-y += rules.o
ifeq ($(shell grep -q " current_sid(void)" $(srctree)/security/selinux/include/objsec.h; echo $$?),0)
ccflags-y += -DKSU_COMPAT_HAS_CURRENT_SID
endif
ifeq ($(shell grep -q "struct selinux_state " $(srctree)/security/selinux/include/security.h; echo $$?),0)
ccflags-y += -DKSU_COMPAT_HAS_SELINUX_STATE
endif
ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion
ccflags-y += -Wno-macro-redefined -Wno-declaration-after-statement -Wno-unused-function

View File

@@ -22,7 +22,7 @@ static struct policydb *get_policydb(void)
{
struct policydb *db;
// selinux_state does not exists before 4.19
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 337)
#ifdef KSU_COMPAT_USE_SELINUX_STATE
#ifdef SELINUX_POLICY_INSTEAD_SELINUX_SS
struct selinux_policy *policy = rcu_dereference(selinux_state.policy);
db = &policy->policydb;
@@ -31,7 +31,7 @@ static struct policydb *get_policydb(void)
db = &ss->policydb;
#endif
#else
db = &policydb;
db = &policydb;
#endif
return db;
}
@@ -39,8 +39,7 @@ static struct policydb *get_policydb(void)
void apply_kernelsu_rules()
{
if (!getenforce()) {
pr_info("SELinux permissive or disabled, don't apply rules.");
return;
pr_info("SELinux permissive or disabled, apply rules!");
}
rcu_read_lock();
@@ -169,8 +168,9 @@ static int get_object(char *buf, char __user *user_object, size_t buf_sz,
}
// reset avc cache table, otherwise the new rules will not take effect if already denied
static void reset_avc_cache() {
#if ((KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 163))) || (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 337))
static void reset_avc_cache()
{
#ifndef KSU_COMPAT_USE_SELINUX_STATE
avc_ss_reset(0);
selnl_notify_policyload(0);
selinux_status_update_policyload(0);
@@ -190,8 +190,7 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
}
if (!getenforce()) {
pr_info("SELinux permissive or disabled, don't apply policies.");
return 0;
pr_info("SELinux permissive or disabled when handle policy!\n");
}
struct sepol_data data;

View File

@@ -2,7 +2,7 @@
#include "objsec.h"
#include "linux/version.h"
#include "../klog.h" // IWYU pragma: keep
#if ((KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 163))) || (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 337))
#ifndef KSU_COMPAT_USE_SELINUX_STATE
#include "avc.h"
#endif
@@ -57,7 +57,7 @@ if (!is_domain_permissive) {
void setenforce(bool enforce)
{
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 163)) || ((KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 337)))
#ifdef KSU_COMPAT_USE_SELINUX_STATE
selinux_state.enforcing = enforce;
#else
selinux_enforcing = enforce;
@@ -68,7 +68,7 @@ void setenforce(bool enforce)
bool getenforce()
{
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 163)) || ((KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 337)))
#ifdef KSU_COMPAT_USE_SELINUX_STATE
if (selinux_state.disabled) {
#else
if (selinux_disabled) {
@@ -78,7 +78,7 @@ bool getenforce()
#endif
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 163)) || ((KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 337)))
#ifdef KSU_COMPAT_USE_SELINUX_STATE
return selinux_state.enforcing;
#else
return selinux_enforcing;
@@ -88,7 +88,7 @@ bool getenforce()
#endif
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 337)
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)) && !defined(KSU_COMPAT_HAS_CURRENT_SID)
/*
* get the subjective security ID of the current task
*/

View File

@@ -2,6 +2,11 @@
#define __KSU_H_SELINUX
#include "linux/types.h"
#include "linux/version.h"
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) || defined(KSU_COMPAT_HAS_SELINUX_STATE)
#define KSU_COMPAT_USE_SELINUX_STATE
#endif
void setup_selinux();

View File

@@ -9,6 +9,18 @@
#define KSU_SUPPORT_ADD_TYPE
/*
* Adapt to Huawei HISI kernel without affecting other kernels ,
* Huawei Hisi Kernel EBITMAP Enable or Disable Flag ,
* From ss/ebitmap.h
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0) && \
LINUX_VERSION_CODE <= KERNEL_VERSION(4, 9, 250)
#ifdef HISI_SELINUX_EBITMAP_RO
#define CONFIG_IS_HW_HISI
#endif
#endif
//////////////////////////////////////////////////////
// Declaration
//////////////////////////////////////////////////////
@@ -453,8 +465,9 @@ static bool add_type_rule(struct policydb *db, const char *s, const char *t,
return true;
}
// 5.9.0 : static inline int hashtab_insert(struct hashtab *h, void *key, void *datum, struct hashtab_key_params key_params)
// 5.8.0: int hashtab_insert(struct hashtab *h, void *k, void *d);
// 5.9.0 : static inline int hashtab_insert(struct hashtab *h, void *key, void
// *datum, struct hashtab_key_params key_params) 5.8.0: int
// hashtab_insert(struct hashtab *h, void *k, void *d);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
static u32 filenametr_hash(const void *k)
{
@@ -486,7 +499,6 @@ static int filenametr_cmp(const void *k1, const void *k2)
return v;
return strcmp(ft1->name, ft2->name);
}
static const struct hashtab_key_params filenametr_key_params = {
@@ -531,13 +543,13 @@ static bool add_filename_trans(struct policydb *db, const char *s,
struct filename_trans_datum *last = NULL;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
struct filename_trans_datum *trans =
policydb_filenametr_search(db, &key);
#else
#else
struct filename_trans_datum *trans =
hashtab_search(&db->filename_trans, &key);
#endif
#endif
while (trans) {
if (ebitmap_get_bit(&trans->stypes, src->value - 1)) {
// Duplicate, overwrite existing data and return
@@ -551,15 +563,17 @@ static bool add_filename_trans(struct policydb *db, const char *s,
}
if (trans == NULL) {
trans = (struct filename_trans_datum*) kcalloc(sizeof(*trans), 1, GFP_ATOMIC);
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);
(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);
hashtab_insert(&db->filename_trans, new_key, trans,
filenametr_key_params);
}
db->compat_filename_trans_count++;
@@ -575,13 +589,15 @@ static bool add_filename_trans(struct policydb *db, const char *s,
hashtab_search(db->filename_trans, &key);
if (trans == NULL) {
trans = (struct filename_trans_datum*) kcalloc(sizeof(*trans), 1, GFP_ATOMIC);
trans = (struct filename_trans_datum *)kcalloc(sizeof(*trans),
1, GFP_ATOMIC);
if (!trans) {
pr_err("add_filename_trans: Failed to alloc datum");
return false;
}
struct filename_trans *new_key =
(struct filename_trans*) kmalloc(sizeof(*new_key), GFP_ATOMIC);
(struct filename_trans *)kmalloc(sizeof(*new_key),
GFP_ATOMIC);
if (!new_key) {
pr_err("add_filename_trans: Failed to alloc new_key");
return false;
@@ -592,7 +608,8 @@ static bool add_filename_trans(struct policydb *db, const char *s,
hashtab_insert(db->filename_trans, new_key, trans);
}
return ebitmap_set_bit(&db->filename_trans_ttypes, src->value - 1, 1) == 0;
return ebitmap_set_bit(&db->filename_trans_ttypes, src->value - 1, 1) ==
0;
#endif
}
@@ -679,17 +696,70 @@ static bool add_type(struct policydb *db, const char *type_name, bool attr)
0);
}
return true;
#elif defined(CONFIG_IS_HW_HISI)
/*
* Huawei use type_attr_map and type_val_to_struct.
* And use ebitmap not flex_array.
*/
size_t new_size = sizeof(struct ebitmap) * db->p_types.nprim;
struct ebitmap *new_type_attr_map =
(krealloc(db->type_attr_map, 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) {
pr_err("add_type: alloc type_attr_map 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 = new_type_attr_map;
ebitmap_init(&db->type_attr_map[value - 1], HISI_SELINUX_EBITMAP_RO);
ebitmap_set_bit(&db->type_attr_map[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
// flex_array is not extensible, we need to create a new bigger one instead
struct flex_array *new_type_attr_map_array = flex_array_alloc(sizeof(struct ebitmap),
db->p_types.nprim, GFP_ATOMIC | __GFP_ZERO);
struct flex_array *new_type_attr_map_array =
flex_array_alloc(sizeof(struct ebitmap), db->p_types.nprim,
GFP_ATOMIC | __GFP_ZERO);
struct flex_array *new_type_val_to_struct = flex_array_alloc(sizeof(struct type_datum *),
db->p_types.nprim, GFP_ATOMIC | __GFP_ZERO);
struct flex_array *new_val_to_name_types = flex_array_alloc(sizeof(char *),
db->symtab[SYM_TYPES].nprim, GFP_ATOMIC | __GFP_ZERO);
struct flex_array *new_type_val_to_struct =
flex_array_alloc(sizeof(struct type_datum *), db->p_types.nprim,
GFP_ATOMIC | __GFP_ZERO);
struct flex_array *new_val_to_name_types =
flex_array_alloc(sizeof(char *), db->symtab[SYM_TYPES].nprim,
GFP_ATOMIC | __GFP_ZERO);
if (!new_type_attr_map_array) {
pr_err("add_type: alloc type_attr_map_array failed\n");
@@ -707,20 +777,21 @@ static bool add_type(struct policydb *db, const char *type_name, bool attr)
}
// preallocate so we don't have to worry about the put ever failing
if (flex_array_prealloc(new_type_attr_map_array, 0,
db->p_types.nprim, GFP_ATOMIC | __GFP_ZERO)) {
if (flex_array_prealloc(new_type_attr_map_array, 0, db->p_types.nprim,
GFP_ATOMIC | __GFP_ZERO)) {
pr_err("add_type: prealloc type_attr_map_array failed\n");
return false;
}
if (flex_array_prealloc(new_type_val_to_struct, 0,
db->p_types.nprim, GFP_ATOMIC | __GFP_ZERO)) {
if (flex_array_prealloc(new_type_val_to_struct, 0, db->p_types.nprim,
GFP_ATOMIC | __GFP_ZERO)) {
pr_err("add_type: prealloc type_val_to_struct_array failed\n");
return false;
}
if (flex_array_prealloc(new_val_to_name_types, 0,
db->symtab[SYM_TYPES].nprim, GFP_ATOMIC | __GFP_ZERO)) {
db->symtab[SYM_TYPES].nprim,
GFP_ATOMIC | __GFP_ZERO)) {
pr_err("add_type: prealloc val_to_name_types failed\n");
return false;
}
@@ -731,25 +802,27 @@ static bool add_type(struct policydb *db, const char *type_name, bool attr)
for (j = 0; j < db->type_attr_map_array->total_nr_elements; j++) {
old_elem = flex_array_get(db->type_attr_map_array, j);
if (old_elem)
flex_array_put(new_type_attr_map_array, j,
old_elem, GFP_ATOMIC | __GFP_ZERO);
flex_array_put(new_type_attr_map_array, j, old_elem,
GFP_ATOMIC | __GFP_ZERO);
}
for (j = 0; j < db->type_val_to_struct_array->total_nr_elements; j++) {
old_elem = flex_array_get_ptr(db->type_val_to_struct_array, j);
if (old_elem)
flex_array_put_ptr(new_type_val_to_struct, j,
old_elem, GFP_ATOMIC | __GFP_ZERO);
flex_array_put_ptr(new_type_val_to_struct, j, old_elem,
GFP_ATOMIC | __GFP_ZERO);
}
for (j = 0; j < db->symtab[SYM_TYPES].nprim; j++) {
old_elem = flex_array_get_ptr(db->sym_val_to_name[SYM_TYPES], j);
old_elem =
flex_array_get_ptr(db->sym_val_to_name[SYM_TYPES], j);
if (old_elem)
flex_array_put_ptr(new_val_to_name_types, j,
old_elem, GFP_ATOMIC | __GFP_ZERO);
flex_array_put_ptr(new_val_to_name_types, j, old_elem,
GFP_ATOMIC | __GFP_ZERO);
}
// store the pointer of old flex arrays first, when assigning new ones we should free it
// store the pointer of old flex arrays first, when assigning new ones we
// should free it
struct flex_array *old_fa;
old_fa = db->type_attr_map_array;
@@ -767,16 +840,16 @@ static bool add_type(struct policydb *db, const char *type_name, bool attr)
if (old_fa) {
flex_array_free(old_fa);
}
flex_array_put_ptr(db->type_val_to_struct_array, value - 1,
type, GFP_ATOMIC | __GFP_ZERO);
flex_array_put_ptr(db->type_val_to_struct_array, value - 1, type,
GFP_ATOMIC | __GFP_ZERO);
old_fa = db->sym_val_to_name[SYM_TYPES];
db->sym_val_to_name[SYM_TYPES] = new_val_to_name_types;
if (old_fa) {
flex_array_free(old_fa);
}
flex_array_put_ptr(db->sym_val_to_name[SYM_TYPES], value - 1,
key, GFP_ATOMIC | __GFP_ZERO);
flex_array_put_ptr(db->sym_val_to_name[SYM_TYPES], value - 1, key,
GFP_ATOMIC | __GFP_ZERO);
int i;
for (i = 0; i < db->p_roles.nprim; ++i) {
@@ -825,6 +898,12 @@ static void add_typeattribute_raw(struct policydb *db, struct type_datum *type,
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0)
struct ebitmap *sattr = &db->type_attr_map_array[type->value - 1];
#elif defined(CONFIG_IS_HW_HISI)
/*
* HISI_SELINUX_EBITMAP_RO is Huawei's unique features.
*/
struct ebitmap *sattr = &db->type_attr_map[type->value - 1],
HISI_SELINUX_EBITMAP_RO;
#else
struct ebitmap *sattr =
flex_array_get(db->type_attr_map_array, type->value - 1);

View File

@@ -17,7 +17,16 @@ fi
test -d "$GKI_ROOT/KernelSU" || git clone https://github.com/tiann/KernelSU
cd "$GKI_ROOT/KernelSU"
git stash && git pull
git stash
if [ "$(git status | grep -Po 'v\d+(\.\d+)*' | head -n1)" ]; then
git checkout main
fi
git pull
if [ -z "${1-}" ]; then
git checkout "$(git describe --abbrev=0 --tags)"
else
git checkout "$1"
fi
cd "$GKI_ROOT"
echo "[+] GKI_ROOT: $GKI_ROOT"

View File

@@ -97,7 +97,10 @@ static void do_update_uid(struct work_struct *work)
// 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()) {
// if manager is installed in work profile, the uid in packages.list is still equals main profile
// don't delete it in this case!
int manager_uid = ksu_get_manager_uid() % 100000;
if (np->uid == manager_uid) {
manager_exist = true;
break;
}

View File

@@ -61,27 +61,33 @@ android {
dependencies {
val accompanistVersion = "0.28.0"
val composeDestinationsVersion = "1.7.27-beta"
implementation(platform("androidx.compose:compose-bom:2022.12.00"))
implementation(platform("androidx.compose:compose-bom:2023.04.00"))
debugImplementation("androidx.compose.ui:ui-test-manifest")
debugImplementation("androidx.compose.ui:ui-tooling")
implementation("androidx.activity:activity-compose:1.6.1")
implementation("androidx.compose.material:material:1.4.0-beta02")
implementation("androidx.activity:activity-compose:1.7.0")
implementation("androidx.compose.material:material:1.5.0-alpha01")
implementation("androidx.compose.material:material-icons-extended")
implementation("androidx.compose.material3:material3")
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1")
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1")
implementation("androidx.navigation:navigation-compose:2.5.3")
implementation("com.google.accompanist:accompanist-drawablepainter:$accompanistVersion")
implementation("com.google.accompanist:accompanist-navigation-animation:$accompanistVersion")
implementation("com.google.accompanist:accompanist-systemuicontroller:$accompanistVersion")
implementation("io.github.raamcosta.compose-destinations:animations-core:$composeDestinationsVersion")
implementation("io.coil-kt:coil-compose:2.2.2")
implementation("io.coil-kt:coil-compose:2.3.0")
implementation("me.zhanghai.android.appiconloader:appiconloader-coil:1.5.0")
implementation("com.github.topjohnwu.libsu:core:5.0.3")
val libsuVersion = "5.0.5"
// change to official build(com.github.topjohnwu.libsu) when this pr is merged:
// https://github.com/topjohnwu/libsu/pull/151
implementation("com.github.tiann.libsu:core:$libsuVersion")
implementation("com.github.tiann.libsu:service:$libsuVersion")
implementation("dev.rikka.rikkax.parcelablelist:parcelablelist:2.0.0")
implementation("com.github.alorma:compose-settings-ui-m3:0.22.0")
ksp("io.github.raamcosta.compose-destinations:ksp:$composeDestinationsVersion")

View File

@@ -2,10 +2,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission
android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />
<application
android:name=".KernelSUApplication"
android:allowBackup="true"

View File

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

View File

@@ -6,6 +6,7 @@
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include "ksu.h"
@@ -29,7 +30,14 @@ static bool ksuctl(int cmd, void* arg1, void* arg2) {
bool become_manager(const char* pkg) {
char param[128];
sprintf(param, "/data/data/%s", pkg);
uid_t uid = getuid();
uint32_t userId = uid / 100000;
if (userId == 0) {
sprintf(param, "/data/data/%s", pkg);
} else {
snprintf(param, sizeof(param), "/data/user/%d/%s", userId, pkg);
}
return ksuctl(CMD_BECOME_MANAGER, param, nullptr);
}

View File

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

View File

@@ -0,0 +1,118 @@
package me.weishu.kernelsu.ui.component
import android.text.method.LinkMovementMethod
import android.widget.TextView
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.MutableState
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.compose.ui.window.Dialog
import androidx.core.content.res.ResourcesCompat
import androidx.core.text.HtmlCompat
import com.google.accompanist.drawablepainter.rememberDrawablePainter
import me.weishu.kernelsu.BuildConfig
import me.weishu.kernelsu.R
@Preview
@Composable
fun AboutCard() {
ElevatedCard(
modifier = Modifier
.fillMaxWidth(),
shape = RoundedCornerShape(8.dp),
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(24.dp)
) {
AboutCardContent()
}
}
}
@Composable
fun AboutDialog(showAboutDialog: MutableState<Boolean>) {
if (showAboutDialog.value) {
Dialog(onDismissRequest = { showAboutDialog.value = false }) {
AboutCard()
}
}
}
@Composable
private fun AboutCardContent() {
Column(
modifier = Modifier
.fillMaxWidth()
) {
CompositionLocalProvider(LocalTextStyle provides MaterialTheme.typography.bodyMedium) {
val drawable = ResourcesCompat.getDrawable(
LocalContext.current.resources,
R.mipmap.ic_launcher,
LocalContext.current.theme
)
Row {
Image(
painter = rememberDrawablePainter(drawable),
contentDescription = "icon",
modifier = Modifier.size(40.dp)
)
Spacer(modifier = Modifier.width(12.dp))
Column {
Text(
stringResource(id = R.string.app_name),
style = MaterialTheme.typography.titleSmall,
fontSize = 18.sp
)
Text(
BuildConfig.VERSION_NAME,
style = MaterialTheme.typography.bodySmall,
fontSize = 14.sp
)
Spacer(modifier = Modifier.height(8.dp))
HtmlText(
html = stringResource(
id = R.string.about_source_code,
"<b><a href=\"https://github.com/tiann/KernelSU\">GitHub</a></b>",
"<b><a href=\"https://t.me/KernelSU\">Telegram</a></b>"
)
)
}
}
}
}
}
@Composable
fun HtmlText(html: String, modifier: Modifier = Modifier) {
AndroidView(
modifier = modifier,
factory = { context ->
TextView(context).also {
it.movementMethod = LinkMovementMethod.getInstance()
}
},
update = { it.text = HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_COMPACT) }
)
}

View File

@@ -1,7 +1,5 @@
package me.weishu.kernelsu.ui.screen
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.os.Build
import android.os.PowerManager
@@ -30,14 +28,10 @@ import androidx.compose.ui.unit.dp
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootNavGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
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.LocalSnackbarHost
import me.weishu.kernelsu.ui.util.reboot
import me.weishu.kernelsu.ui.util.getSELinuxStatus
import me.weishu.kernelsu.ui.util.install
import me.weishu.kernelsu.ui.util.*
@OptIn(ExperimentalMaterial3Api::class)
@RootNavGraph(start = true)
@@ -67,6 +61,8 @@ fun HomeScreen(navigator: DestinationsNavigator) {
StatusCard(kernelVersion, ksuVersion)
InfoCard()
DonateCard()
LearnMoreCard()
Spacer(Modifier)
}
}
@@ -102,7 +98,8 @@ private fun TopBar(onSettingsClick: () -> Unit) {
RebootDropdownItem(id = R.string.reboot)
val pm = LocalContext.current.getSystemService(Context.POWER_SERVICE) as PowerManager?
val pm =
LocalContext.current.getSystemService(Context.POWER_SERVICE) as PowerManager?
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && pm?.isRebootingUserspaceSupported == true) {
RebootDropdownItem(id = R.string.reboot_userspace, reason = "userspace")
}
@@ -161,6 +158,16 @@ private fun StatusCard(kernelVersion: KernelVersion, ksuVersion: Int?) {
text = stringResource(R.string.home_working_version, ksuVersion),
style = MaterialTheme.typography.bodyMedium
)
Spacer(Modifier.height(4.dp))
Text(
text = stringResource(R.string.home_superuser_count, getSuperuserCount()),
style = MaterialTheme.typography.bodyMedium
)
Spacer(Modifier.height(4.dp))
Text(
text = stringResource(R.string.home_module_count, getModuleCount()),
style = MaterialTheme.typography.bodyMedium
)
}
}
kernelVersion.isGKI() -> {
@@ -197,11 +204,69 @@ private fun StatusCard(kernelVersion: KernelVersion, ksuVersion: Int?) {
}
}
@Composable
fun LearnMoreCard() {
val uriHandler = LocalUriHandler.current
ElevatedCard {
Row(
modifier = Modifier
.fillMaxWidth()
.clickable {
uriHandler.openUri("https://kernelsu.org/guide/what-is-kernelsu.html")
}
.padding(24.dp),
verticalAlignment = Alignment.CenterVertically
) {
Column() {
Text(
text = stringResource(R.string.home_learn_kernelsu),
style = MaterialTheme.typography.titleSmall
)
Spacer(Modifier.height(4.dp))
Text(
text = stringResource(R.string.home_click_to_learn_kernelsu),
style = MaterialTheme.typography.bodyMedium
)
}
}
}
}
@Composable
fun DonateCard() {
val uriHandler = LocalUriHandler.current
ElevatedCard {
Row(
modifier = Modifier
.fillMaxWidth()
.clickable {
uriHandler.openUri("https://patreon.com/weishu")
}
.padding(24.dp),
verticalAlignment = Alignment.CenterVertically
) {
Column() {
Text(
text = stringResource(R.string.home_support_title),
style = MaterialTheme.typography.titleSmall
)
Spacer(Modifier.height(4.dp))
Text(
text = stringResource(R.string.home_support_content),
style = MaterialTheme.typography.bodyMedium
)
}
}
}
}
@Composable
private fun InfoCard() {
val context = LocalContext.current
val snackbarHost = LocalSnackbarHost.current
val scope = rememberCoroutineScope()
ElevatedCard {
Column(
@@ -221,39 +286,19 @@ private fun InfoCard() {
InfoCardItem(stringResource(R.string.home_kernel), uname.release)
Spacer(Modifier.height(24.dp))
Spacer(Modifier.height(16.dp))
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())
Spacer(Modifier.height(24.dp))
InfoCardItem(stringResource(R.string.home_abi), Build.SUPPORTED_ABIS.joinToString(", "))
Spacer(Modifier.height(24.dp))
Spacer(Modifier.height(16.dp))
InfoCardItem(stringResource(R.string.home_fingerprint), Build.FINGERPRINT)
Spacer(Modifier.height(24.dp))
InfoCardItem(stringResource(R.string.home_securitypatch), Build.VERSION.SECURITY_PATCH)
Spacer(Modifier.height(24.dp))
Spacer(Modifier.height(16.dp))
InfoCardItem(stringResource(R.string.home_selinux_status), getSELinuxStatus())
val copiedMessage = stringResource(R.string.home_copied_to_clipboard)
TextButton(
modifier = Modifier.align(Alignment.End),
onClick = {
val cm = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
cm.setPrimaryClip(ClipData.newPlainText("KernelSU", contents.toString()))
scope.launch { snackbarHost.showSnackbar(copiedMessage) }
},
content = { Text(stringResource(android.R.string.copy)) }
)
}
}
}
fun getManagerVersion(context: Context) : String {
fun getManagerVersion(context: Context): String {
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
return "${packageInfo.versionName} (${packageInfo.versionCode})"
}

View File

@@ -2,28 +2,34 @@ package me.weishu.kernelsu.ui.screen
import android.content.Intent
import android.net.Uri
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color.Companion.White
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import androidx.core.content.FileProvider
import com.alorma.compose.settings.ui.*
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import me.weishu.kernelsu.BuildConfig
import me.weishu.kernelsu.R
import me.weishu.kernelsu.ui.component.SimpleDialog
import me.weishu.kernelsu.ui.util.LinkifyText
import me.weishu.kernelsu.ui.component.AboutDialog
import me.weishu.kernelsu.ui.util.LocalDialogHost
import me.weishu.kernelsu.ui.util.getBugreportFile
/**
* @author weishu
* @date 2023/1/1.
@@ -41,45 +47,60 @@ fun SettingScreen(navigator: DestinationsNavigator) {
}
) { paddingValues ->
SimpleDialog {
SupportCard()
}
val showAboutDialog = remember { mutableStateOf(false) }
AboutDialog(showAboutDialog)
var showLoadingDialog by remember { mutableStateOf(false) }
LoadingDialog(showLoadingDialog)
Column(modifier = Modifier.padding(paddingValues)) {
val context = LocalContext.current
SettingsMenuLink(title = {
Text(stringResource(id = R.string.send_log))
},
val scope = rememberCoroutineScope()
val dialogHost = LocalDialogHost.current
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)
scope.launch {
showLoadingDialog = true
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)
val bugreport = withContext(Dispatchers.IO) {
getBugreportFile(context)
}
context.startActivity(
Intent.createChooser(
shareIntent,
context.getString(R.string.send_log)
showLoadingDialog = false
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)
)
)
)
}
}
)
val about = stringResource(id = R.string.about)
val ok = stringResource(id = android.R.string.ok)
val scope = rememberCoroutineScope()
val dialogHost = LocalDialogHost.current
SettingsMenuLink(title = {
Text(about)
},
SettingsMenuLink(
title = {
Text(about)
},
onClick = {
scope.launch {
dialogHost.showDialog(about, content = "unused", confirm = ok)
}
showAboutDialog.value = true
}
)
}
@@ -99,18 +120,23 @@ private fun TopBar(onBack: () -> Unit = {}) {
)
}
@Preview
@Composable
private fun SupportCard() {
Column(
modifier = Modifier
.fillMaxWidth()
fun LoadingDialog(showLoadingDialog: Boolean) {
if (!showLoadingDialog) {
return
}
Dialog(
onDismissRequest = { },
DialogProperties(dismissOnBackPress = false, dismissOnClickOutside = false)
) {
CompositionLocalProvider(LocalTextStyle provides MaterialTheme.typography.bodyMedium) {
LinkifyText("Author: weishu")
LinkifyText("Github: https://github.com/tiann/KernelSU")
LinkifyText("Telegram: https://t.me/KernelSU")
LinkifyText("QQ: https://pd.qq.com/s/8lipl1brp")
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.size(100.dp)
.background(White, shape = RoundedCornerShape(8.dp))
) {
CircularProgressIndicator()
}
}
}

View File

@@ -24,7 +24,10 @@ import com.ramcosta.composedestinations.annotation.Destination
import kotlinx.coroutines.launch
import me.weishu.kernelsu.Natives
import me.weishu.kernelsu.R
import me.weishu.kernelsu.ui.component.ConfirmDialog
import me.weishu.kernelsu.ui.component.DialogResult
import me.weishu.kernelsu.ui.component.SearchAppBar
import me.weishu.kernelsu.ui.util.LocalDialogHost
import me.weishu.kernelsu.ui.util.LocalSnackbarHost
import me.weishu.kernelsu.ui.viewmodel.SuperUserViewModel
import java.util.*
@@ -91,6 +94,8 @@ fun SuperUserScreen() {
}
) { innerPadding ->
ConfirmDialog()
val refreshState = rememberPullRefreshState(
refreshing = viewModel.isRefreshing,
onRefresh = { scope.launch { viewModel.fetchAppList() } },
@@ -103,14 +108,34 @@ fun SuperUserScreen() {
val failMessage = stringResource(R.string.superuser_failed_to_grant_root)
LazyColumn(Modifier.fillMaxSize()) {
items(viewModel.appList, key = { it.packageName }) { app ->
items(viewModel.appList, key = { it.packageName + it.uid }) { app ->
var isChecked by rememberSaveable(app) { mutableStateOf(app.onAllowList) }
val dialogHost = LocalDialogHost.current
val content =
stringResource(id = R.string.superuser_allow_root_confirm, app.label)
val confirm = stringResource(id = android.R.string.ok)
val cancel = stringResource(id = android.R.string.cancel)
AppItem(app, isChecked) { checked ->
val success = Natives.allowRoot(app.uid, checked)
if (success) {
isChecked = checked
} else scope.launch {
snackbarHost.showSnackbar(failMessage.format(app.uid))
scope.launch {
if (checked) {
val dialogResult = dialogHost.showDialog(
app.label,
content = content,
confirm = confirm,
dismiss = cancel
)
if (dialogResult != DialogResult.Confirmed) {
return@launch
}
}
val success = Natives.allowRoot(app.uid, checked)
if (success) {
isChecked = checked
} else {
snackbarHost.showSnackbar(failMessage.format(app.uid))
}
}
}
}

View File

@@ -7,7 +7,10 @@ import com.topjohnwu.superuser.CallbackList
import com.topjohnwu.superuser.Shell
import com.topjohnwu.superuser.ShellUtils
import me.weishu.kernelsu.BuildConfig
import me.weishu.kernelsu.Natives
import me.weishu.kernelsu.ksuApp
import me.weishu.kernelsu.ui.viewmodel.ModuleViewModel
import org.json.JSONArray
import java.io.File
@@ -21,6 +24,14 @@ private fun getKsuDaemonPath(): String {
return ksuApp.applicationInfo.nativeLibraryDir + File.separator + "libksud.so"
}
object KsuCli {
val SHELL: Shell = createRootShell()
}
fun getRootShell(): Shell {
return KsuCli.SHELL
}
fun createRootShell(): Shell {
Shell.enableVerboseLogging = BuildConfig.DEBUG
val builder = Shell.Builder.create()
@@ -33,7 +44,7 @@ fun createRootShell(): Shell {
}
fun execKsud(args: String): Boolean {
val shell = createRootShell()
val shell = getRootShell()
return ShellUtils.fastCmdResult(shell, "${getKsuDaemonPath()} $args")
}
@@ -44,12 +55,25 @@ fun install() {
}
fun listModules(): String {
val shell = createRootShell()
val shell = getRootShell()
val out = shell.newJob().add("${getKsuDaemonPath()} module list").to(ArrayList(), null).exec().out
val out =
shell.newJob().add("${getKsuDaemonPath()} module list").to(ArrayList(), null).exec().out
return out.joinToString("\n").ifBlank { "[]" }
}
fun getModuleCount(): Int {
val result = listModules()
runCatching {
val array = JSONArray(result)
return array.length()
}.getOrElse { return 0 }
}
fun getSuperuserCount(): Int {
return Natives.getAllowList().size
}
fun toggleModule(id: String, enable: Boolean): Boolean {
val cmd = if (enable) {
"module enable $id"
@@ -61,14 +85,14 @@ fun toggleModule(id: String, enable: Boolean): Boolean {
return result
}
fun uninstallModule(id: String) : Boolean {
fun uninstallModule(id: String): Boolean {
val cmd = "module uninstall $id"
val result = execKsud(cmd)
Log.i(TAG, "uninstall module $id result: $result")
return result
}
fun installModule(uri: Uri, onFinish: (Boolean)->Unit, onOutput: (String) -> Unit) : Boolean {
fun installModule(uri: Uri, onFinish: (Boolean) -> Unit, onOutput: (String) -> Unit): Boolean {
val resolver = ksuApp.contentResolver
with(resolver.openInputStream(uri)) {
val file = File(ksuApp.cacheDir, "module.zip")
@@ -77,7 +101,7 @@ fun installModule(uri: Uri, onFinish: (Boolean)->Unit, onOutput: (String) -> Uni
}
val cmd = "module install ${file.absolutePath}"
val shell = createRootShell()
val shell = getRootShell()
val callbackList: CallbackList<String?> = object : CallbackList<String?>() {
override fun onAddElement(s: String?) {
@@ -85,7 +109,8 @@ fun installModule(uri: Uri, onFinish: (Boolean)->Unit, onOutput: (String) -> Uni
}
}
val result = shell.newJob().add("${getKsuDaemonPath()} $cmd").to(callbackList, callbackList).exec()
val result =
shell.newJob().add("${getKsuDaemonPath()} $cmd").to(callbackList, callbackList).exec()
Log.i("KernelSU", "install module $uri result: $result")
file.delete()
@@ -96,7 +121,7 @@ fun installModule(uri: Uri, onFinish: (Boolean)->Unit, onOutput: (String) -> Uni
}
fun reboot(reason: String = "") {
val shell = createRootShell()
val shell = getRootShell()
if (reason == "recovery") {
// KEYCODE_POWER = 26, hide incorrect "Factory data reset" message
ShellUtils.fastCmd(shell, "/system/bin/input keyevent 26")
@@ -105,13 +130,13 @@ fun reboot(reason: String = "") {
}
fun overlayFsAvailable(): Boolean {
val shell = createRootShell()
val shell = getRootShell()
// check /proc/filesystems
return ShellUtils.fastCmdResult(shell, "cat /proc/filesystems | grep overlay")
}
fun hasMagisk(): Boolean {
val shell = createRootShell()
val shell = getRootShell()
val result = shell.newJob().add("nsenter --mount=/proc/1/ns/mnt which magisk").exec()
Log.i(TAG, "has magisk: ${result.isSuccess}")
return result.isSuccess

View File

@@ -3,6 +3,7 @@ package me.weishu.kernelsu.ui.util
import android.content.Context
import android.os.Build
import android.system.Os
import com.topjohnwu.superuser.ShellUtils
import me.weishu.kernelsu.Natives
import me.weishu.kernelsu.ui.screen.getManagerVersion
import java.io.File
@@ -22,26 +23,32 @@ fun getBugreportFile(context: Context): File {
val dropboxFile = File(bugreportDir, "dropbox.tar.gz")
val pstoreFile = File(bugreportDir, "pstore.tar.gz")
val diagFile = File(bugreportDir, "diag.tar.gz")
val bootlogFile = File(bugreportDir, "bootlog.tar.gz")
val mountsFile = File(bugreportDir, "mounts.txt")
val fileSystemsFile = File(bugreportDir, "filesystems.txt")
val ksuFileTree = File(bugreportDir, "ksu_tree.txt")
val appListFile = File(bugreportDir, "app_list.txt")
val appListFile = File(bugreportDir, "packages.txt")
val propFile = File(bugreportDir, "props.txt")
val allowListFile = File(bugreportDir, "allowlist.bin")
val shell = createRootShell()
val shell = getRootShell()
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("tar -czf ${pstoreFile.absolutePath} /sys/fs/pstore").exec()
shell.newJob().add("tar -czf ${diagFile.absolutePath} /data/vendor/diag").exec()
shell.newJob().add("tar -czf ${tombstonesFile.absolutePath} -C /data/tombstones .").exec()
shell.newJob().add("tar -czf ${dropboxFile.absolutePath} -C /data/system/dropbox .").exec()
shell.newJob().add("tar -czf ${pstoreFile.absolutePath} -C /sys/fs/pstore .").exec()
shell.newJob().add("tar -czf ${diagFile.absolutePath} -C /data/vendor/diag .").exec()
shell.newJob().add("tar -czf ${bootlogFile.absolutePath} -C /data/adb/ksu/log .").exec()
shell.newJob().add("cat /proc/mounts > ${mountsFile.absolutePath}").exec()
shell.newJob().add("cat /proc/1/mountinfo > ${mountsFile.absolutePath}").exec()
shell.newJob().add("cat /proc/filesystems > ${fileSystemsFile.absolutePath}").exec()
shell.newJob().add("ls -alRZ /data/adb > ${ksuFileTree.absolutePath}").exec()
shell.newJob().add("cat /data/system/packages.list > ${appListFile.absolutePath}").exec()
shell.newJob().add("cp /data/system/packages.list ${appListFile.absolutePath}").exec()
shell.newJob().add("getprop > ${propFile.absolutePath}").exec()
shell.newJob().add("cp /data/adb/ksu/.allowlist ${allowListFile.absolutePath}").exec()
val selinux = ShellUtils.fastCmd(shell, "getenforce");
// basic information
val buildInfo = File(bugreportDir, "basic.txt")
@@ -56,6 +63,7 @@ fun getBugreportFile(context: Context): File {
pw.println("FINGERPRINT: " + Build.FINGERPRINT)
pw.println("DEVICE: " + Build.DEVICE)
pw.println("Manager: " + getManagerVersion(context))
pw.println("SELinux: $selinux")
val uname = Os.uname()
pw.println("KernelRelease: ${uname.release}")
@@ -84,4 +92,4 @@ fun getBugreportFile(context: Context): File {
shell.newJob().add("chmod 0644 ${targetFile.absolutePath}").exec()
return targetFile
}
}

View File

@@ -1,8 +1,11 @@
package me.weishu.kernelsu.ui.viewmodel
import android.content.ComponentName
import android.content.Intent
import android.content.ServiceConnection
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.graphics.drawable.Drawable
import android.os.IBinder
import android.os.SystemClock
import android.util.Log
import androidx.compose.runtime.derivedStateOf
@@ -10,13 +13,19 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import me.weishu.kernelsu.IKsuInterface
import me.weishu.kernelsu.Natives
import me.weishu.kernelsu.ksuApp
import me.weishu.kernelsu.ui.KsuService
import me.weishu.kernelsu.ui.util.HanziToPinyin
import me.weishu.kernelsu.ui.util.KsuCli
import java.text.Collator
import java.util.*
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
class SuperUserViewModel : ViewModel() {
@@ -62,16 +71,61 @@ class SuperUserViewModel : ViewModel() {
}
}
private suspend inline fun connectKsuService(
crossinline onDisconnect: () -> Unit = {}
): Pair<IBinder, ServiceConnection> = suspendCoroutine {
val connection = object : ServiceConnection {
override fun onServiceDisconnected(name: ComponentName?) {
onDisconnect()
}
override fun onServiceConnected(name: ComponentName?, binder: IBinder?) {
it.resume(binder as IBinder to this)
}
}
val intent = Intent(ksuApp, KsuService::class.java);
val task = KsuService.bindOrTask(
intent,
Shell.EXECUTOR,
connection,
)
val shell = KsuCli.SHELL
task?.let { it1 -> shell.execTask(it1) }
}
private fun stopKsuService() {
val intent = Intent(ksuApp, KsuService::class.java);
KsuService.stop(intent)
}
suspend fun fetchAppList() {
isRefreshing = true
val result = connectKsuService {
Log.w(TAG, "KsuService disconnected")
}
withContext(Dispatchers.IO) {
isRefreshing = true
val pm = ksuApp.packageManager
val allowList = Natives.getAllowList().toSet()
val denyList = Natives.getDenyList().toSet()
Log.i(TAG, "allowList: $allowList")
Log.i(TAG, "denyList: $denyList")
val start = SystemClock.elapsedRealtime()
apps = pm.getInstalledPackages(0).map {
val binder = result.first
val allPackages = IKsuInterface.Stub.asInterface(binder).getPackages(0)
withContext(Dispatchers.Main) {
stopKsuService()
}
val packages = allPackages.list
apps = packages.map {
val appInfo = it.applicationInfo
val uid = appInfo.uid
AppInfo(

View File

@@ -5,6 +5,8 @@
<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_superuser_count">Superuser: %d</string>
<string name="home_module_count">Module: %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>
@@ -23,13 +25,14 @@
<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="superuser_allow_root_confirm">Ijinkan akses root untuk aplikasi %s?</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">Memasang module</string>
<string name="install">Pasang</string>
<string name="module_install">Pasang module</string>
<string name="install">Memasang module...</string>
<string name="reboot">Reboot perangkat</string>
<string name="settings">Pengaturan</string>
<string name="reboot_userspace">Soft Reboot</string>
@@ -52,4 +55,9 @@
<string name="safe_mode">Mode aman</string>
<string name="reboot_to_apply">Restart untuk menerapkan</string>
<string name="module_magisk_conflict">Module akan di nonaktifkan karna konflik dengan magisk\'s!</string>
<string name="home_learn_kernelsu">Belajar KernelSU</string>
<string name="home_click_to_learn_kernelsu">Cara menginstall KernelSu dan menggunakan Module</string>
<string name="home_support_title">Dukung kami</string>
<string name="home_support_content">KernelSU akan selalu gratis dan open source. Namun Anda dapat menunjukkan kepada kami bahwa Anda peduli dengan memberikan sedikit donasi.</string>
<string name="about_source_code"><![CDATA[Lihat sumber kode di %1$s<br/>Gabung sekarang %2$s channel]]></string>
</resources>

View File

@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" translatable="false">KernelSU</string>
<string name="home">ホーム</string>
<string name="home">ホーム</string>
<string name="home_not_installed">未インストール</string>
<string name="home_click_to_install">タップでインストール</string>
<string name="home_working">動作中</string>
@@ -40,6 +39,7 @@
<string name="reboot_edl">EDLで再起動</string>
<string name="about">アプリについて</string>
<string name="require_kernel_version_8">KernelSU バージョン8以降が必要です</string>
<string name="module_uninstall_confirm">モジュール %s をアンインストールしますか?</string>
<string name="module_uninstall_success">%sをアンインストールしました</string>
<string name="module_uninstall_failed">アンインストールに失敗: %s</string>
<string name="module_version">バージョン</string>

View File

@@ -25,6 +25,7 @@
<string name="selinux_status_unknown">Necunoscut</string>
<string name="superuser">Superutilizator</string>
<string name="superuser_failed_to_grant_root">Nu s-a putut acorda acces root pentru %d</string>
<string name="superuser_allow_root_confirm">Sigur oferi acces root pentru %s?</string>
<string name="module_failed_to_enable">Activarea modulului %s a eșuat</string>
<string name="module_failed_to_disable">Dezactivarea modulului %s a eșuat</string>
<string name="module_empty">Niciun modul instalat</string>

View File

@@ -4,6 +4,8 @@
<string name="home_click_to_install">Нажмите чтобы установить</string>
<string name="home_working">Работает</string>
<string name="home_working_version">Версия: %d</string>
<string name="home_superuser_count">Superusers: %d</string>
<string name="home_module_count">Модули: %d</string>
<string name="home_unsupported">Не поддерживается</string>
<string name="home_unsupported_reason">KernelSU поддерживает только GKI ядра</string>
<string name="home_copied_to_clipboard">Скопировано в буфер обмена</string>
@@ -23,7 +25,8 @@
<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="superuser_failed_to_grant_root">Не удалось предоставить root права для %d</string>
<string name="superuser_allow_root_confirm">Вы уверены, что хотите предоставить root права для %s?</string>
<string name="module_failed_to_enable">Не удалось включить модуль: %s</string>
<string name="module_failed_to_disable">Не удалось отключить модуль: %s</string>
<string name="module_empty">Нет установленных модулей</string>
@@ -41,6 +44,7 @@
<string name="reboot_edl">Reboot to EDL</string>
<string name="about">О KernelSU</string>
<string name="require_kernel_version_8">Требуется KernelSU версии 8 и выше</string>
<string name="module_uninstall_confirm">Вы уверены, что хотите удалить модуль %s?</string>
<string name="module_uninstall_success">%s удален</string>
<string name="module_uninstall_failed">Не удалось удалить: %s</string>
<string name="module_version">Версия</string>
@@ -52,5 +56,10 @@
<string name="send_log">Отправить лог</string>
<string name="safe_mode">Безопасный режим</string>
<string name="reboot_to_apply">Перезагрузите, чтобы вступить в силу</string>
<string name="module_magisk_conflict">Модули отключены, потому что они конфликтуют с модулями Magisk!</string>
<string name="home_learn_kernelsu">Узнайте о KernelSU</string>
<string name="home_click_to_learn_kernelsu">Узнайте, как установить KernelSU и использовать модули</string>
<string name="home_support_title">Поддержите нас</string>
<string name="home_support_content">KernelSU был и всегда будет бесплатным и открытым проектом. Однако Вы всегда можете поддержать нас, отправив небольшое пожертвование.</string>
<string name="about_source_code"><![CDATA[View source code at %1$s<br/>Join our %2$s channel]]></string>
</resources>

View File

@@ -1,4 +1,13 @@
<resources>
<string name="home_learn_kernelsu">Tìm hiểu về KernelSU</string>
<string name="home_click_to_learn_kernelsu">Cách cài đặt KernelSU và sử dụng mô-đun</string>
<string name="home_support_title">Hỗ trợ chúng tôi</string>
<string name="home_support_content">KernelSU sẽ luôn luôn miễn phi và mã nguồn mở. Tuy nhiên, bạn có thể cho chúng tôi thấy rằng bạn quan tâm bằng cách gửi một khoản đóng góp nhỏ.</string>
<string name="about_source_code"><![CDATA[Xem mã nguồn tại %1$s<br/>Tham gia kênh %2$s của chúng tôi]]></string>
<string name="superuser_allow_root_confirm">Bạn có chắc chắn muốn cấp quyền truy cập root cho %s?</string>
<string name="module_magisk_conflict">"Các mô-đun bị vô hiệu hóa vì nó xung đột với Magisk!"</string>
<string name="module_uninstall_confirm">Bạn có chắc chắn muốn gỡ cài đặt mô-đun %s?</string>
<string name="send_log">Gửi nhật ký</string>
<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>

View File

@@ -5,6 +5,7 @@
<string name="home_click_to_install">点击安装</string>
<string name="home_working">工作中</string>
<string name="home_working_version">版本: %d</string>
<string name="home_superuser_count">超级用户数:%d</string>
<string name="home_unsupported">不支持</string>
<string name="home_unsupported_reason">KernelSU 现在只支持 GKI 内核</string>
<string name="home_copied_to_clipboard">已复制到剪贴板</string>
@@ -23,6 +24,7 @@
<string name="selinux_status_unknown">未知</string>
<string name="superuser">超级用户</string>
<string name="superuser_failed_to_grant_root">无法为 %d 授予 Root</string>
<string name="superuser_allow_root_confirm">确定要授予 %s ROOT 权限吗?</string>
<string name="module_failed_to_enable">无法启用模块: %s</string>
<string name="module_failed_to_disable">无法禁用模块: %s</string>
<string name="module_empty">没有安装模块</string>
@@ -52,4 +54,10 @@
<string name="safe_mode">安全模式</string>
<string name="reboot_to_apply">重启生效</string>
<string name="module_magisk_conflict">所有模块已被禁用,因为它与 Magisk 的模块系统有冲突!</string>
<string name="home_module_count">模块数:%d</string>
<string name="home_learn_kernelsu">了解 KernelSU</string>
<string name="home_click_to_learn_kernelsu">了解如何安装 KernelSU 以及如何开发模块</string>
<string name="home_support_title">支持开发</string>
<string name="home_support_content">KernelSU 将保持免费和开源,向开发者捐赠以表示支持。</string>
<string name="about_source_code"><![CDATA[在 %1$s 查看源码<br/>加入我们的 %2$s 频道<br/>加入我们的 <b><a href="https://pd.qq.com/s/8lipl1brp">QQ 频道</a></b>]]></string>
</resources>

View File

@@ -25,6 +25,7 @@
<string name="selinux_status_unknown">未知</string>
<string name="superuser">超級使用者</string>
<string name="superuser_failed_to_grant_root">無法為 %d 授予 Root 存取權</string>
<string name="superuser_allow_root_confirm">您確定要授予 %s Root 存取權嗎?</string>
<string name="module_failed_to_enable">無法啟用模組:%s</string>
<string name="module_failed_to_disable">無法停用模組:%s</string>
<string name="module_empty">尚未安裝模組</string>

View File

@@ -5,6 +5,8 @@
<string name="home_click_to_install">按一下以安裝</string>
<string name="home_working">正在處理</string>
<string name="home_working_version">版本:%d</string>
<string name="home_superuser_count">已 Root 授權:%d 個</string>
<string name="home_module_count">已安裝模組: %d 個</string>
<string name="home_unsupported">不支援</string>
<string name="home_unsupported_reason">KernelSU 現在僅支援 GKI 核心</string>
<string name="home_copied_to_clipboard">已複製到剪貼簿</string>
@@ -24,7 +26,8 @@
<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="superuser_failed_to_grant_root">無法為%d授予 Root 權</string>
<string name="superuser_allow_root_confirm">您確定要授予「%s」Root 權限嗎?</string>
<string name="module_failed_to_enable">無法啟用模組:%s</string>
<string name="module_failed_to_disable">無法停用模組:%s</string>
<string name="module_empty">尚未安裝模組</string>
@@ -42,8 +45,8 @@
<string name="reboot_edl">重新啟動至 EDL</string>
<string name="about">關於</string>
<string name="require_kernel_version_8">需要 KernelSU 8+ 版本</string>
<string name="module_uninstall_confirm">您確定要解除安裝模組 %s 嗎?</string>
<string name="module_uninstall_success">%s 已解除安裝</string>
<string name="module_uninstall_confirm">您確定要解除安裝模組%s嗎?</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>
@@ -51,8 +54,13 @@
<string name="refresh">重新整理</string>
<string name="show_system_apps">顯示系統應用程式</string>
<string name="hide_system_apps">隱藏系統應用程式</string>
<string name="send_log">傳送記錄</string>
<string name="send_log">傳送日誌</string>
<string name="safe_mode">安全模式</string>
<string name="reboot_to_apply">重新啟動以生效</string>
<string name="module_magisk_conflict">模組已停用,因其與 Magisk 的模組存在衝突!</string>
<string name="home_learn_kernelsu">瞭解 KernelSU</string>
<string name="home_click_to_learn_kernelsu">瞭解如何安裝 KernelSU 以及如何開發模組</string>
<string name="home_support_title">支援開發</string>
<string name="home_support_content">KernelSU 將保持免費和開源,您可以可慮向開發者捐贈以表示支援。</string>
<string name="about_source_code"><![CDATA[在 %1$s 檢視原始碼<br/>加入我們的 %2$s 頻道<br/>]]></string>
</resources>

View File

@@ -6,6 +6,8 @@
<string name="home_click_to_install">Click to install</string>
<string name="home_working">Working</string>
<string name="home_working_version">Version: %d</string>
<string name="home_superuser_count">Superusers: %d</string>
<string name="home_module_count">Modules: %d</string>
<string name="home_unsupported">Unsupported</string>
<string name="home_unsupported_reason">KernelSU only supports GKI kernels now</string>
<string name="home_copied_to_clipboard">Copied to clipboard</string>
@@ -26,6 +28,7 @@
<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="superuser_allow_root_confirm">Are you sure to grant root access to %s?</string>
<string name="module_failed_to_enable">Failed to enable module: %s</string>
<string name="module_failed_to_disable">Failed to disable module: %s</string>
<string name="module_empty">No module installed</string>
@@ -56,5 +59,9 @@
<string name="safe_mode">Safe mode</string>
<string name="reboot_to_apply">Reboot to take effect</string>
<string name="module_magisk_conflict">Modules are disabled because it is conflict with Magisk\'s!</string>
<string name="home_learn_kernelsu">Learn KernelSU</string>
<string name="home_click_to_learn_kernelsu">Learn how to install KernelSU and use modules</string>
<string name="home_support_title">Support Us</string>
<string name="home_support_content">KernelSU is, and always will be, free, and open source. You can however show us that you care by making a donation.</string>
<string name="about_source_code"><![CDATA[View source code at %1$s<br/>Join our %2$s channel]]></string>
</resources>

View File

@@ -7,7 +7,7 @@ pluginManagement {
mavenCentral()
}
plugins {
val agp = "7.3.1"
val agp = "7.4.2"
val kotlin = "1.7.20"
id("com.android.application") version agp
id("com.android.library") version agp

View File

@@ -82,9 +82,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "base64ct"
version = "1.5.3"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf"
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]]
name = "bindgen"
@@ -763,9 +763,9 @@ dependencies = [
[[package]]
name = "jobserver"
version = "0.1.25"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b"
checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"
dependencies = [
"libc",
]
@@ -810,7 +810,6 @@ dependencies = [
"libc",
"log",
"nom",
"proc-mounts",
"procfs",
"regex",
"retry",
@@ -998,15 +997,6 @@ version = "6.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
[[package]]
name = "partition-identity"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fa925f9becb532d758b0014b472c576869910929cf4c3f8054b386f19ab9e21"
dependencies = [
"thiserror",
]
[[package]]
name = "password-hash"
version = "0.4.2"
@@ -1093,15 +1083,6 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "proc-mounts"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d652f8435d0ab70bf4f3590a6a851d59604831a458086541b95238cc51ffcf2"
dependencies = [
"partition-identity",
]
[[package]]
name = "procfs"
version = "0.15.1"
@@ -1374,7 +1355,7 @@ dependencies = [
[[package]]
name = "sys-mount"
version = "2.0.2"
source = "git+https://github.com/tiann/sys-mount#328928573feb9dbe6318d7ebcb8c8c9b681c47cd"
source = "git+https://github.com/tiann/sys-mount?branch=loopfix#c7c4048e4a4ffdf8b108a85956363a75f2c554f0"
dependencies = [
"bitflags",
"libc",
@@ -1426,9 +1407,9 @@ dependencies = [
[[package]]
name = "time"
version = "0.3.17"
version = "0.3.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376"
checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890"
dependencies = [
"serde",
"time-core",
@@ -1732,7 +1713,7 @@ dependencies = [
"hmac",
"pbkdf2",
"sha1",
"time 0.3.17",
"time 0.3.20",
"zstd",
]
@@ -1766,9 +1747,9 @@ dependencies = [
[[package]]
name = "zstd-sys"
version = "2.0.6+zstd.1.5.2"
version = "2.0.7+zstd.1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68a3f9792c0c3dc6c165840a75f47ae1f4da402c2d006881129579f6597e801b"
checksum = "94509c3ba2fe55294d752b79842c530ccfab760192521df74a081a78d2b3c7f5"
dependencies = [
"cc",
"libc",

View File

@@ -35,11 +35,10 @@ which = "4.2.2"
getopts = "0.2.21"
[target.'cfg(any(target_os = "android", target_os = "linux"))'.dependencies]
sys-mount = { git = "https://github.com/tiann/sys-mount" }
sys-mount = { git = "https://github.com/tiann/sys-mount", branch = "loopfix" }
# some android specific dependencies which compiles under unix are also listed here for convenience of coding
android-properties = { version = "0.2.2", features = ["bionic-deprecated"] }
procfs = "0.15"
proc-mounts = "0.3"
[target.'cfg(target_os = "android")'.dependencies]
android_logger = "0.13"

View File

@@ -72,6 +72,8 @@ enum Debug {
/// Get kernel version
Version,
Mount,
/// For testing
Test,
}
@@ -187,12 +189,13 @@ pub fn run() -> Result<()> {
Ok(())
}
Debug::Su => crate::ksu::grant_root(),
Debug::Mount => event::mount_systemlessly(defs::MODULE_DIR),
Debug::Test => todo!(),
},
};
if let Err(e) = &result {
log::error!("Error: {}", e);
log::error!("Error: {:?}", e);
}
result
}

View File

@@ -3,8 +3,10 @@ use const_format::concatcp;
pub const ADB_DIR: &str = "/data/adb/";
pub const WORKING_DIR: &str = concatcp!(ADB_DIR, "ksu/");
pub const BINARY_DIR: &str = concatcp!(WORKING_DIR, "bin/");
pub const LOG_DIR: &str = concatcp!(WORKING_DIR, "log/");
pub const KSURC_PATH: &str = concatcp!(WORKING_DIR, ".ksurc");
pub const KSU_OVERLAY_SOURCE: &str = "KSU";
pub const DAEMON_PATH: &str = concatcp!(ADB_DIR, "ksud");
#[cfg(target_os = "android")]

View File

@@ -1,50 +1,28 @@
use anyhow::{bail, Context, Result};
use log::{info, warn};
use std::path::PathBuf;
use std::{collections::HashMap, path::Path};
use crate::{
assets, defs, mount,
assets, defs, mount, restorecon,
utils::{self, ensure_clean_dir, ensure_dir_exists},
};
fn mount_partition(partition: &str, lowerdir: &mut Vec<String>) -> Result<()> {
fn mount_partition(partition: &str, lowerdir: &Vec<String>) -> Result<()> {
if lowerdir.is_empty() {
warn!("partition: {partition} lowerdir is empty");
return Ok(());
}
let partition = format!("/{partition}");
// if /partition is a symlink and linked to /system/partition, then we don't need to overlay it separately
if Path::new(&format!("/{partition}")).read_link().is_ok() {
if Path::new(&partition).read_link().is_ok() {
warn!("partition: {partition} is a symlink");
return Ok(());
}
// handle stock mounts under /partition, we should restore the mount point after overlay
// because the overlayfs mount will "overlay" the bind mount such as /vendor/bt_firmware, /vendor/dsp
// which will cause the system bootloop or bluetooth/dsp not working
let stock_mount = mount::StockMount::new(&format!("/{partition}/"))
.with_context(|| format!("get stock mount of partition: {partition} failed"))?;
// add /partition as the lowerest dir
let lowest_dir = format!("/{partition}");
lowerdir.push(lowest_dir.clone());
let lowerdir = lowerdir.join(":");
info!("partition: {partition} lowerdir: {lowerdir}");
let result = mount::mount_overlay(&lowerdir, &lowest_dir);
if let Err(e) = stock_mount.remount() {
if result.is_ok() {
// if mount overlay ok but stock remount failed, we should umount overlay
warn!("remount stock failed: {:?}, umount overlay {lowest_dir}", e);
if mount::umount_dir(&lowest_dir).is_err() {
warn!("umount overlay {lowest_dir} failed");
}
}
}
result
mount::mount_overlay(&partition, lowerdir)
}
pub fn mount_systemlessly(module_dir: &str) -> Result<()> {
@@ -74,7 +52,7 @@ pub fn mount_systemlessly(module_dir: &str) -> Result<()> {
}
let module_system = Path::new(&module).join("system");
if module_system.exists() {
if module_system.is_dir() {
system_lowerdir.push(format!("{}", module_system.display()));
}
@@ -82,24 +60,23 @@ pub fn mount_systemlessly(module_dir: &str) -> Result<()> {
// if /partition is a mountpoint, we would move it to $MODPATH/$partition when install
// otherwise it must be a symlink and we don't need to overlay!
let part_path = Path::new(&module).join(part);
if !part_path.exists() {
continue;
}
if let Some(v) = partition_lowerdir.get_mut(*part) {
v.push(format!("{}", part_path.display()));
if part_path.is_dir() {
if let Some(v) = partition_lowerdir.get_mut(*part) {
v.push(format!("{}", part_path.display()));
}
}
}
}
// mount /system first
if let Err(e) = mount_partition("system", &mut system_lowerdir) {
warn!("mount system failed: {e}");
if let Err(e) = mount_partition("system", &system_lowerdir) {
warn!("mount system failed: {:#}", e);
}
// mount other partitions
for (k, mut v) in partition_lowerdir {
if let Err(e) = mount_partition(&k, &mut v) {
warn!("mount {k} failed: {e}");
for (k, v) in partition_lowerdir {
if let Err(e) = mount_partition(&k, &v) {
warn!("mount {k} failed: {:#}", e);
}
}
@@ -109,6 +86,9 @@ pub fn mount_systemlessly(module_dir: &str) -> Result<()> {
pub fn on_post_data_fs() -> Result<()> {
crate::ksu::report_post_fs_data();
#[cfg(unix)]
let _ = catch_bootlog();
if utils::has_magisk() {
warn!("Magisk detected, skip post-fs-data!");
return Ok(());
@@ -184,17 +164,12 @@ pub fn on_post_data_fs() -> Result<()> {
warn!("load system.prop failed: {}", e);
}
// Finally, we should do systemless mount
// But we should umount all stock overlayfs and remount them after module mounted
let stock_overlay = mount::StockOverlay::new();
stock_overlay.umount_all();
// mount moduke systemlessly by overlay
// mount module systemlessly by overlay
if let Err(e) = mount_systemlessly(module_dir) {
warn!("do systemless mount failed: {}", e);
}
stock_overlay.mount_all();
std::env::set_current_dir("/").with_context(|| "failed to chdir to /")?;
Ok(())
}
@@ -246,7 +221,7 @@ pub fn daemon() -> Result<()> {
pub fn install() -> Result<()> {
ensure_dir_exists(defs::ADB_DIR)?;
std::fs::copy("/proc/self/exe", defs::DAEMON_PATH)?;
restorecon::setcon(defs::DAEMON_PATH, restorecon::ADB_CON)?;
// install binary assets
assets::ensure_binaries().with_context(|| "Failed to extract assets")?;
@@ -258,7 +233,6 @@ pub fn install() -> Result<()> {
#[cfg(target_os = "android")]
fn link_ksud_to_bin() -> Result<()> {
use std::path::PathBuf;
let ksu_bin = PathBuf::from(defs::DAEMON_PATH);
let ksu_bin_link = PathBuf::from(defs::DAEMON_LINK_PATH);
if ksu_bin.exists() && !ksu_bin_link.exists() {
@@ -266,3 +240,42 @@ fn link_ksud_to_bin() -> Result<()> {
}
Ok(())
}
#[cfg(unix)]
fn catch_bootlog() -> Result<()> {
use std::os::unix::process::CommandExt;
use std::process::Stdio;
let logdir = Path::new(defs::LOG_DIR);
utils::ensure_dir_exists(logdir)?;
let bootlog = logdir.join("boot.log");
let oldbootlog = logdir.join("boot.old.log");
if bootlog.exists() {
std::fs::rename(&bootlog, oldbootlog)?;
}
let bootlog = std::fs::File::create(bootlog)?;
// timeout -s 9 30s logcat > boot.log
let result = unsafe {
std::process::Command::new("timeout")
.process_group(0)
.pre_exec(|| {
utils::switch_cgroups();
Ok(())
})
.arg("-s")
.arg("9")
.arg("30s")
.arg("logcat")
.stdout(Stdio::from(bootlog))
.spawn()
};
if let Err(e) = result {
warn!("Failed to start logcat: {:#}", e);
}
Ok(())
}

View File

@@ -389,10 +389,6 @@ install_module() {
[ -f $MODPATH/customize.sh ] && . $MODPATH/customize.sh
fi
handle_partition vendor
handle_partition system_ext
handle_partition product
# Handle replace folders
for TARGET in $REPLACE; do
ui_print "- Replace target: $TARGET"
@@ -405,6 +401,10 @@ install_module() {
mark_remove $MODPATH$TARGET
done
handle_partition vendor
handle_partition system_ext
handle_partition product
if $BOOTMODE; then
mktouch $NVBASE/modules/$MODID/update
rm -rf $NVBASE/modules/$MODID/remove 2>/dev/null

View File

@@ -1,4 +1,4 @@
use anyhow::{Ok, Result};
use anyhow::{bail, Ok, Result};
#[cfg(any(target_os = "linux", target_os = "android"))]
use anyhow::Context;
@@ -7,10 +7,11 @@ use retry::delay::NoDelay;
#[cfg(any(target_os = "linux", target_os = "android"))]
use sys_mount::{unmount, FilesystemType, Mount, MountFlags, Unmount, UnmountFlags};
use crate::defs::KSU_OVERLAY_SOURCE;
use log::{info, warn};
#[cfg(any(target_os = "linux", target_os = "android"))]
use procfs::process::{MountInfo, Process};
#[cfg(any(target_os = "linux", target_os = "android"))]
use std::collections::HashSet;
use procfs::process::Process;
use std::path::Path;
pub struct AutoMountExt4 {
mnt: String,
@@ -25,6 +26,7 @@ impl AutoMountExt4 {
let result = Mount::builder()
.fstype(FilesystemType::from("ext4"))
.flags(MountFlags::empty())
.create_loop(true)
.mount(src, mnt)
.map(|mount| {
Ok(Self {
@@ -99,6 +101,7 @@ fn mount_image(src: &str, target: &str, autodrop: bool) -> Result<()> {
if autodrop {
Mount::builder()
.fstype(FilesystemType::from("ext4"))
.create_loop(true)
.mount_autodrop(src, target, UnmountFlags::empty())
.with_context(|| format!("Failed to do mount: {src} -> {target}"))?;
} else {
@@ -128,14 +131,133 @@ pub fn umount_dir(src: &str) -> Result<()> {
}
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn mount_overlay(lowerdir: &str, mnt: &str) -> Result<()> {
fn mount_overlayfs(
lower_dirs: &[String],
lowest: impl AsRef<Path>,
dest: impl AsRef<Path>,
) -> Result<()> {
let options = format!(
"lowerdir={}:{}",
lower_dirs.join(":"),
lowest.as_ref().display()
);
info!(
"mount overlayfs on {}, options={}",
dest.as_ref().display(),
options
);
Mount::builder()
.fstype(FilesystemType::from("overlay"))
.flags(MountFlags::RDONLY)
.data(&format!("lowerdir={lowerdir}"))
.mount("overlay", mnt)
.map(|_| ())
.map_err(|e| anyhow::anyhow!("mount partition: {mnt} overlay failed: {e}"))
.data(&options)
.mount(KSU_OVERLAY_SOURCE, dest.as_ref())
.with_context(|| {
format!(
"mount overlayfs on {} options {} failed",
dest.as_ref().display(),
options
)
})?;
Ok(())
}
#[cfg(any(target_os = "linux", target_os = "android"))]
fn bind_mount(from: impl AsRef<Path>, to: impl AsRef<Path>) -> Result<()> {
info!(
"bind mount {} -> {}",
from.as_ref().display(),
to.as_ref().display()
);
Mount::builder()
.flags(MountFlags::BIND)
.mount(from.as_ref(), to.as_ref())
.with_context(|| {
format!(
"bind mount failed: {} -> {}",
from.as_ref().display(),
to.as_ref().display()
)
})?;
Ok(())
}
#[cfg(any(target_os = "linux", target_os = "android"))]
fn mount_overlay_child(
mount_point: &str,
relative: &String,
module_roots: &Vec<String>,
stock_root: &String,
) -> Result<()> {
if !module_roots
.iter()
.any(|lower| Path::new(&format!("{lower}{relative}")).exists())
{
return bind_mount(stock_root, mount_point);
}
if !Path::new(&stock_root).is_dir() {
return Ok(());
}
let mut lower_dirs: Vec<String> = vec![];
for lower in module_roots {
let lower_dir = format!("{lower}{relative}");
let path = Path::new(&lower_dir);
if path.is_dir() {
lower_dirs.push(lower_dir);
} else if path.exists() {
// stock root has been blocked by this file
return Ok(());
}
}
if lower_dirs.is_empty() {
return Ok(());
}
// merge modules and stock
if let Err(e) = mount_overlayfs(&lower_dirs, stock_root, mount_point) {
warn!("failed: {:#}, fallback to bind mount", e);
bind_mount(stock_root, mount_point)?;
}
Ok(())
}
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn mount_overlay(root: &String, module_roots: &Vec<String>) -> Result<()> {
info!("mount overlay for {}", root);
std::env::set_current_dir(root).with_context(|| format!("failed to chdir to {root}"))?;
let stock_root = ".";
// collect child mounts before mounting the root
let mounts = Process::myself()?
.mountinfo()
.with_context(|| "get mountinfo")?;
let mut mount_seq = mounts
.iter()
.filter(|m| {
m.mount_point.starts_with(root) && !Path::new(&root).starts_with(&m.mount_point)
})
.map(|m| m.mount_point.to_str())
.collect::<Vec<_>>();
mount_seq.sort();
mount_seq.dedup();
mount_overlayfs(module_roots, root, root).with_context(|| "mount overlayfs for root failed")?;
for mount_point in mount_seq.iter() {
let Some(mount_point) = mount_point else {
continue;
};
let relative = mount_point.replacen(root, "", 1);
let stock_root: String = format!("{stock_root}{relative}");
if !Path::new(&stock_root).exists() {
continue;
}
if let Err(e) = mount_overlay_child(mount_point, &relative, module_roots, &stock_root) {
warn!(
"failed to mount overlay for child {}: {:#}, revert",
mount_point, e
);
umount_dir(root).with_context(|| format!("failed to revert {root}"))?;
bail!(e);
}
}
Ok(())
}
#[cfg(not(any(target_os = "linux", target_os = "android")))]
@@ -149,185 +271,6 @@ pub fn umount_dir(_src: &str) -> Result<()> {
}
#[cfg(not(any(target_os = "linux", target_os = "android")))]
pub fn mount_overlay(_lowerdir: &str, _mnt: &str) -> Result<()> {
pub fn mount_overlay(_dest: &String, _lower_dirs: &Vec<String>) -> Result<()> {
unimplemented!()
}
pub struct StockOverlay {
#[cfg(any(target_os = "linux", target_os = "android"))]
mountinfos: Vec<MountInfo>,
}
#[cfg(not(any(target_os = "linux", target_os = "android")))]
impl StockOverlay {
pub fn new() -> Self {
unimplemented!()
}
pub fn mount_all(&self) {
unimplemented!()
}
pub fn umount_all(&self) {
unimplemented!()
}
}
#[cfg(any(target_os = "linux", target_os = "android"))]
impl StockOverlay {
pub fn new() -> Self {
if let std::result::Result::Ok(process) = Process::myself() {
if let std::result::Result::Ok(mountinfos) = process.mountinfo() {
let overlay_mounts = mountinfos
.into_iter()
.filter(|m| m.fs_type == "overlay")
.collect::<Vec<_>>();
return Self {
mountinfos: overlay_mounts,
};
}
}
Self { mountinfos: vec![] }
}
pub fn mount_all(&self) {
log::info!("stock overlay: mount all: {:?}", self.mountinfos);
for mount in self.mountinfos.clone() {
let Some(mnt) = mount.mount_point.to_str() else {
log::warn!("Failed to get mount point");
continue;
};
if mnt == "/system" {
log::warn!("stock overlay found /system, skip!");
continue;
}
let (_flags, b): (HashSet<_>, HashSet<_>) = mount
.mount_options
.into_iter()
.chain(mount.super_options)
.partition(|(_, m)| m.is_none());
let mut overlay_opts = vec![];
for (opt, val) in b {
if let Some(val) = val {
overlay_opts.push(format!("{opt}={val}"));
} else {
log::warn!("opt empty: {}", opt);
}
}
let overlay_data = overlay_opts.join(",");
let result = Mount::builder()
.fstype(FilesystemType::from("overlay"))
.flags(MountFlags::RDONLY)
.data(&overlay_data)
.mount("overlay", mnt);
if let Err(e) = result {
log::error!(
"stock mount overlay: {} failed: {}",
mount.mount_point.display(),
e
);
} else {
log::info!(
"stock mount :{} overlay_opts: {}",
mount.mount_point.display(),
overlay_opts.join(",")
);
}
}
}
pub fn umount_all(&self) {
log::info!("stock overlay: umount all: {:?}", self.mountinfos);
for mnt in &self.mountinfos {
let Some(p) = mnt.mount_point.to_str() else {
log::warn!("Failed to umount: {}", mnt.mount_point.display());
continue;
};
let result = umount_dir(p);
log::info!("stock umount {}: {:?}", p, result);
}
}
}
// some ROMs mount device(ext4,exfat) to /vendor, when we do overlay mount, it will overlay
// the stock mounts, these mounts include bt_firmware, wifi_firmware, etc.
// so we to remount these mounts when we do overlay mount.
// this is a workaround, we should find a better way to do this.
#[derive(Debug)]
pub struct StockMount {
mnt: String,
#[cfg(any(target_os = "linux", target_os = "android"))]
mountlist: proc_mounts::MountList,
}
#[cfg(any(target_os = "linux", target_os = "android"))]
impl StockMount {
pub fn new(mnt: &str) -> Result<Self> {
let mountlist = proc_mounts::MountList::new()?;
Ok(Self {
mnt: mnt.to_string(),
mountlist,
})
}
fn get_target_mounts(&self) -> Vec<&proc_mounts::MountInfo> {
let mut mounts = self
.mountlist
.destination_starts_with(std::path::Path::new(&self.mnt))
.filter(|m| m.fstype != "overlay" && m.fstype != "rootfs")
.collect::<Vec<_>>();
mounts.sort_by(|a, b| b.dest.cmp(&a.dest)); // inverse order
mounts
}
pub fn remount(&self) -> Result<()> {
let mut mounts = self.get_target_mounts();
mounts.reverse(); // remount it in order
log::info!("remount stock for {} : {:?}", self.mnt, mounts);
for m in mounts {
let src = std::fs::canonicalize(&m.source)?;
let src = src.to_str().ok_or(anyhow::anyhow!("Failed to get src"))?;
let dst = m
.dest
.to_str()
.ok_or(anyhow::anyhow!("Failed to get dst"))?;
let fstype = m.fstype.as_str();
let options = m.options.join(",");
log::info!("begin remount: {src} -> {dst}");
let result = std::process::Command::new("mount")
.arg("-t")
.arg(fstype)
.arg("-o")
.arg(options)
.arg(src)
.arg(dst)
.status();
if let Err(e) = result {
log::error!("remount failed: {}", e);
} else {
log::info!("remount {src} -> {dst} succeed!");
}
}
Ok(())
}
}
#[cfg(not(any(target_os = "linux", target_os = "android")))]
impl StockMount {
pub fn new(mnt: &str) -> Result<Self> {
Ok(Self {
mnt: mnt.to_string(),
})
}
pub fn remount(&self) -> Result<()> {
unimplemented!()
}
}

View File

@@ -7,8 +7,8 @@ use anyhow::{Context, Ok};
#[cfg(any(target_os = "linux", target_os = "android"))]
use extattr::{setxattr, Flags as XattrFlags};
const SYSTEM_CON: &str = "u:object_r:system_file:s0";
const _ADB_CON: &str = "u:object_r:adb_data_file:s0";
pub const SYSTEM_CON: &str = "u:object_r:system_file:s0";
pub const ADB_CON: &str = "u:object_r:adb_data_file:s0";
const SELINUX_XATTR: &str = "security.selinux";
pub fn setcon<P: AsRef<Path>>(path: P, con: &str) -> Result<()> {

View File

@@ -16,7 +16,7 @@ Yes, But it is in early version, it may be buggy. Please wait for it to be stabl
## Does KernelSU support Xposed?
Yes, [Dreamland](https://github.com/canyie/Dreamland) and [TaiChi](https::/taichi.cool) work now. For LSPosed, you can make it work by [Zygisk on KernelSU](https://github.com/Dr-TSNG/ZygiskOnKernelSU)
Yes, [Dreamland](https://github.com/canyie/Dreamland) and [TaiChi](https://taichi.cool) work now. For LSPosed, you can make it work by [Zygisk on KernelSU](https://github.com/Dr-TSNG/ZygiskOnKernelSU)
## Does KernelSU support Zygisk?

View File

@@ -42,10 +42,24 @@ tools/bazel build --config=fast //common:kernel_aarch64_dist
## Build Kernel with KernelSU
If you can build the kernel successfully, then build KernelSU is so easy, run this command in Kernel source root dir:
If you can build the kernel successfully, then build KernelSU is so easy, Select any one run in Kernel source root dir:
- Latest tag(stable)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -
```
- main branch(dev)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s main
```
- Select tag(Such as v0.5.2)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.5.2
```
And then rebuild the kernel and you will get a kernel image with KernelSU!

View File

@@ -46,10 +46,24 @@ If kprobe can not work in your kernel (maybe a upstream bug or kernel below 4.8)
First, add KernelSU to your kernel source tree:
- Latest tag(stable)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -
```
- main branch(dev)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s main
```
- Select tag(Such as v0.5.2)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.5.2
```
Then, add KernelSU calls to the kernel source, here is a patch to refer:
```diff

View File

@@ -16,7 +16,7 @@ Ya, Tetapi masih dalam versi awal, bisa jadi ngebug. Mohon tunggu sampai semuany
## Apakah KernelSU mendukung Xposed?
Ya, [Dreamland](https://github.com/canyie/Dreamland) dan [TaiChi](https::/taichi.cool) sekarang bekerja sebagian, Dan kita sedang mencoba untuk membuat Xposed Framework lainnya bekerja.
Ya, [Dreamland](https://github.com/canyie/Dreamland) dan [TaiChi](https://taichi.cool) sekarang bekerja sebagian, Dan kita sedang mencoba untuk membuat Xposed Framework lainnya bekerja.
## Apakah KernelSU kompatibel dengan Magisk?

View File

@@ -42,8 +42,22 @@ tools/bazel build --config=fast //common:kernel_aarch64_dist
Jika Anda dapat build kernel dengan sukses, maka build KernelSU sangatlah mudah, jalankan perintah ini di root dir kernel source:
- Latest tag(stable)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -
```
- main branch(dev)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s main
```
- Select tag(Such as v0.5.2)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.5.2
```
Dan kemudian build ulang kernel dan Anda akan mendapatkan image kernel dengan KernelSU!

View File

@@ -17,10 +17,24 @@ KernelSU menggunakan kprobe untuk melakukan hook kernel, jika *kprobe* berjalan
Pertama, tambahkan KernelSU ke dalam berkas kernel source tree:
- Latest tag(stable)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -
```
- main branch(dev)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s main
```
- Select tag(Such as v0.5.2)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.5.2
```
Kemudian, Anda harus memeriksa apakah *kprobe* diaktifkan dalam konfigurasi kernel Anda, jika tidak, tambahkan konfigurasi ini ke dalamnya:
```

View File

@@ -194,5 +194,26 @@
"kernel_name": "kernel_oneplus_msm8998",
"kernel_link": "https://github.com/TheNoFace/kernel_oneplus_msm8998",
"devices": "OnePlus 5/5T"
},
{
"maintainer": "Evans Mike",
"maintainer_link": "https://github.com/etnperlong",
"kernel_name": "kernel_xiaomi_raphael_bool-x",
"kernel_link": "https://github.com/etnperlong/kernel_xiaomi_raphael_bool-x",
"devices": "Xiaomi Redmi K20 Pro / Mi 9T Pro (raphael)"
},
{
"maintainer": "easterNday",
"maintainer_link": "https://github.com/DogDayAndroid",
"kernel_name": "KSU_Thyme_BuildBot",
"kernel_link": "https://github.com/DogDayAndroid/KSU_Thyme_BuildBot",
"devices": "Xiaomi 10S"
},
{
"maintainer": "tedomi2705",
"maintainer_link": "https://github.com/tedomi2705",
"kernel_name": "kernel_xiaomi_sdm660",
"kernel_link": "https://github.com/tedomi2705/kernel_xiaomi_sdm660",
"devices": "Xiaomi Redmi Note 6 Pro (tulip)"
}
]
]

View File

@@ -16,7 +16,7 @@ Có, nhưng ở những phiên bản thử nghiệm này có thể có rất nhi
## KernelSU có hỗ trợ Xposed không?
Có, [Dreamland](https://github.com/canyie/Dreamland) và [TaiChi](https::/taichi.cool) hiện đã hoạt động được một phần nào đó. Với Lsposed, bạn có thể thử [Zygisk trên KernelSU](https://github.com/Dr-TSNG/ZygiskOnKernelSU)
Có, [Dreamland](https://github.com/canyie/Dreamland) và [TaiChi](https://taichi.cool) hiện đã hoạt động được một phần nào đó. Với Lsposed, bạn có thể thử [Zygisk trên KernelSU](https://github.com/Dr-TSNG/ZygiskOnKernelSU)
## KernelSU có tương thích với Magisk không?

View File

@@ -44,8 +44,22 @@ tools/bazel build --config=fast //common:kernel_aarch64_dist
Nếu bạn có thể build được kernel hoàn chỉnh, thì việc tích hợp KernelSU rất dễ dàng, chạy lệnh sau tại thư mục chứa mã nguồn kernel:
- Latest tag(stable)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -
```
- main branch(dev)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s main
```
- Select tag(Such as v0.5.2)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.5.2
```
Và rồi build lại, bạn sẽ có được một image chứa KernelSU

View File

@@ -18,10 +18,24 @@ KernelSU sử dụng kprobe để thực hiện hook kernel, nếu *kprobe* ch
Đầu tiên, thêm KernelSU vào mã nguồn kernel của bạn:
- Latest tag(stable)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -
```
- main branch(dev)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s main
```
- Select tag(Such as v0.5.2)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.5.2
```
Sau đó, bạn nên kiểm tra xem *kprobe* có được bật trong config của bạn hay không, nếu không, vui lòng thêm các cấu hình sau vào:
```

View File

@@ -16,7 +16,7 @@
## KernelSU 是否支持 Xposed
支持。[Dreamland](https://github.com/canyie/Dreamland) 和 [TaiChi](https::/taichi.cool) 可以正常运行。LSPosed 可以在 [Zygisk on KernelSU](https://github.com/Dr-TSNG/ZygiskOnKernelSU) 的支持下正常运行。
支持。[Dreamland](https://github.com/canyie/Dreamland) 和 [TaiChi](https://taichi.cool) 可以正常运行。LSPosed 可以在 [Zygisk on KernelSU](https://github.com/Dr-TSNG/ZygiskOnKernelSU) 的支持下正常运行。
## KernelSU 支持 Zygisk 吗?

View File

@@ -42,10 +42,24 @@ tools/bazel build --config=fast //common:kernel_aarch64_dist
## 使用 KernelSU 构建内核
如果您可以成功构建内核,那么构建 KernelSU 就很容易,在内核源代码根目录中运行命令:
如果您可以成功构建内核,那么构建 KernelSU 就很容易,根据自己的需求在内核源代码根目录中运行以下任一命令:
- 最新tag(稳定版本)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -
```
- main分支(开发版本)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s main
```
- 指定tag(比如v0.5.2)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.5.2
```
然后重建内核,您将获得带有 KernelSU 的内核映像!

View File

@@ -17,10 +17,24 @@ KernelSU 使用 kprobe 机制来做内核的相关 hook如果 *kprobe* 可以
首先,把 KernelSU 添加到你的内核源码树,在内核的根目录执行以下命令:
- 最新tag(稳定版本)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -
```
- main分支(开发版本)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s main
```
- 指定tag(比如v0.5.2)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.5.2
```
然后,你需要检查你的内核是否开启了 *kprobe* 相关的配置,如果没有开启,需要添加以下配置:
```

View File

@@ -89,7 +89,7 @@ PS. 这种方法在升级 KernelSU 的时候较为方便,无需电脑即可完
## 使用 KernelSU 提供的 boot.img 安装 {#install-by-kernelsu-boot-image}
方法无需你有 TWRP也不需要你的手机有 root 权限;适用于你初次安装 KernelSU。
方法无需你有 TWRP也不需要你的手机有 root 权限;适用于你初次安装 KernelSU。
### 找到合适的 boot.img {#found-propery-image}