Compare commits

...

49 Commits

Author SHA1 Message Date
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
49 changed files with 1286 additions and 427 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 "${1//Image-/}"-"$image".gz
mv "$image".gz "${1//Image-/}"-"$image"-"$VERSION".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 "${1//Image-/}"-"$image".gz
mv "$image".gz "${1//Image-/}"-"$image"-"$VERSION".gz
done
echo '[+] Images to upload'

View File

@@ -108,7 +108,7 @@ jobs:
uses: actions/upload-artifact@v3
with:
name: boot-images-android12
path: Image-android12*/*.img.gz
path: Image-android12*/*.img*.gz
check-build-kernel:
if: github.event_name == 'pull_request'

View File

@@ -111,7 +111,7 @@ jobs:
uses: actions/upload-artifact@v3
with:
name: boot-images-android13
path: Image-android13*/*.img.gz
path: Image-android13*/*.img*.gz
check-build-kernel:
if: github.event_name == 'pull_request'

View File

@@ -143,7 +143,8 @@ jobs:
echo "[+] Compress images"
gzip -n -f -9 "${{ env.file_path }}"
echo "[+] Image to upload"
find . -type f -name "*.gz"
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/*

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

@@ -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"

View File

@@ -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,11 @@ 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()
{
#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))
avc_ss_reset(0);
selnl_notify_policyload(0);
selinux_status_update_policyload(0);
@@ -190,8 +192,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

@@ -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

@@ -61,27 +61,31 @@ 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.4"
implementation("com.github.topjohnwu.libsu:core:$libsuVersion")
implementation("com.github.topjohnwu.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

@@ -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

@@ -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 = 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

@@ -28,8 +28,8 @@
<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>

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

@@ -23,6 +23,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

@@ -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

@@ -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

@@ -26,6 +26,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>

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

@@ -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",

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,6 +189,7 @@ pub fn run() -> Result<()> {
Ok(())
}
Debug::Su => crate::ksu::grant_root(),
Debug::Mount => event::mount_systemlessly(defs::MODULE_DIR),
Debug::Test => todo!(),
},
};

View File

@@ -3,9 +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 STOCK_MNT_ROOT: &str = concatcp!(WORKING_DIR, ".mnt");
pub const KSU_OVERLAY_SOURCE: &str = "KSU";
pub const DAEMON_PATH: &str = concatcp!(ADB_DIR, "ksud");
#[cfg(target_os = "android")]

View File

@@ -1,5 +1,6 @@
use anyhow::{bail, Context, Result};
use log::{info, warn};
use std::path::PathBuf;
use std::{collections::HashMap, path::Path};
use crate::{
@@ -7,44 +8,21 @@ use crate::{
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,23 +60,22 @@ 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) {
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) {
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,16 +164,12 @@ pub fn on_post_data_fs() -> Result<()> {
warn!("load system.prop failed: {}", e);
}
// Finally, we should do systemless mount
// But we should backup all stock overlayfs and remount them after module mounted
let stock_overlay = mount::StockOverlay::new();
// 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(())
}
@@ -257,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() {
@@ -265,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

@@ -7,12 +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 crate::utils;
use procfs::process::Process;
use std::path::Path;
pub struct AutoMountExt4 {
mnt: String,
@@ -27,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 {
@@ -101,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 {
@@ -130,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")))]
@@ -151,213 +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!()
}
}
#[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(",")
);
}
}
}
}
// 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: Vec<(proc_mounts::MountInfo, std::path::PathBuf)>,
#[cfg(any(target_os = "linux", target_os = "android"))]
rootmount: sys_mount::Mount,
}
#[cfg(any(target_os = "linux", target_os = "android"))]
impl StockMount {
pub fn new(mnt: &str) -> Result<Self> {
let mountlist = proc_mounts::MountList::new()?;
let mut mounts = mountlist
.destination_starts_with(std::path::Path::new(mnt))
.filter(|m| m.fstype != "overlay" && m.fstype != "rootfs")
.collect::<Vec<_>>();
mounts.sort_by(|a, b| b.dest.cmp(&a.dest)); // inverse order
let mntroot = std::path::Path::new(crate::defs::STOCK_MNT_ROOT);
utils::ensure_dir_exists(mntroot)?;
log::info!("stock mount root: {}", mntroot.display());
let rootdir = mntroot.join(
mnt.strip_prefix('/')
.ok_or(anyhow::anyhow!("invalid mnt: {}!", mnt))?,
);
utils::ensure_dir_exists(&rootdir)?;
let rootmount = Mount::builder().fstype("tmpfs").mount("tmpfs", &rootdir)?;
let mut ms = vec![];
for m in mounts {
let dest = &m.dest;
if dest == std::path::Path::new(mnt) {
continue;
}
let path = rootdir.join(dest.strip_prefix("/")?);
log::info!("rootdir: {}, path: {}", rootdir.display(), path.display());
if dest.is_dir() {
utils::ensure_dir_exists(&path)
.with_context(|| format!("Failed to create dir: {}", path.display(),))?;
} else if dest.is_file() {
if !path.exists() {
let parent = path
.parent()
.with_context(|| format!("Failed to get parent: {}", path.display()))?;
utils::ensure_dir_exists(parent).with_context(|| {
format!("Failed to create parent: {}", parent.display())
})?;
std::fs::File::create(&path)
.with_context(|| format!("Failed to create file: {}", path.display(),))?;
}
} else {
bail!("unknown file type: {:?}", dest)
}
log::info!("bind stock mount: {} -> {}", dest.display(), path.display());
Mount::builder()
.flags(MountFlags::BIND)
.mount(dest, &path)
.with_context(|| {
format!("Failed to mount: {} -> {}", dest.display(), path.display())
})?;
ms.push((m.clone(), path));
}
Ok(Self {
mnt: mnt.to_string(),
mountlist: ms,
rootmount,
})
}
// Yes, we move self here!
pub fn remount(self) -> Result<()> {
log::info!("remount stock for {} : {:?}", self.mnt, self.mountlist);
let mut result = Ok(());
for (m, src) in self.mountlist {
let dst = m.dest;
log::info!("begin remount: {} -> {}", src.display(), dst.display());
let mount_result = Mount::builder()
.flags(MountFlags::BIND | MountFlags::MOVE)
.mount(&src, &dst);
if let Err(e) = mount_result {
log::error!("remount failed: {}", e);
result = Err(e.into());
} else {
log::info!(
"remount {}({}) -> {} succeed!",
m.source.display(),
src.display(),
dst.display()
);
}
}
// umount the root tmpfs mount
if let Err(e) = self.rootmount.unmount(UnmountFlags::DETACH) {
log::warn!("umount root mount failed: {}", e);
}
result
}
}
#[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

@@ -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,12 @@
"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)"
}
]

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* 相关的配置,如果没有开启,需要添加以下配置:
```