Compare commits

...

39 Commits

Author SHA1 Message Date
Rifat Azad
dc8130161b New translations manager/app/src/main/res/values-ru-rRU/strings.xml (bundle: 8) 2025-08-14 16:46:21 +06:00
Rifat Azad
79e9edcb77 New translations manager/app/src/main/res/values-pt-rBR/strings.xml (bundle: 8) 2025-08-14 16:46:21 +06:00
Rifat Azad
f0934e6b90 New translations manager/app/src/main/res/values-ru-rRU/strings.xml (bundle: 8) 2025-08-11 13:20:54 +06:00
Rifat Azad
0744aebee0 New translations manager/app/src/main/res/values-ru-rRU/strings.xml (bundle: 8) 2025-08-05 16:53:17 +06:00
Rifat Azad
f5b771f6af New translations manager/app/src/main/res/values-ru-rRU/strings.xml (bundle: 8) 2025-08-04 16:40:36 +06:00
Rifat Azad
e497c5396c New translations manager/app/src/main/res/values-it-rIT/strings.xml (bundle: 8) 2025-08-04 16:40:35 +06:00
Rifat Azad
43a6fcce28 New translations manager/app/src/main/res/values-bg-rBG/strings.xml (bundle: 8) 2025-08-04 16:40:33 +06:00
Rifat Azad
aa37bcc368 New Crowdin updates (#660)
* New translations manager/app/src/main/res/values-zh-rCN/strings.xml (bundle: 8)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

* New translations manager/app/src/main/res/values-it-rIT/strings.xml (bundle: 8)
2025-08-01 16:44:29 +06:00
Rifat Azad
107cd4add0 Update README.md 2025-07-28 19:37:12 +06:00
Rifat Azad
94c4b41ea3 README: updated 2025-07-28 19:36:30 +06:00
Rifat Azad
0bde9047b9 manager: add -spoof string to apk output 2025-07-27 22:42:36 +06:00
Fahrez256Bit
bc9927b9b6 POC: load icon app via ksu://icon/[packageName] (#674)
* manager: load app icons from package name using AppIconUti

Trying basic icon rendering from package via WebView ksu:// scheme.
Includes cache and bitmap scaling.
Still subject to refinement.

* Update WebUIActivity.kt

This proof-of-concept intercepts custom URLs of the form:
  ksu://icon/com.example.app

It fetches the app icon using PackageManager via AppIconUtil,
converts it to PNG, and returns it as a WebResourceResponse.

Used inside shouldInterceptRequest() for early experimentation
with dynamic WebView asset routing.

Fallbacks to WebViewAssetLoader for all other requests.

Notes:
- Icon size currently fixed at 512px
- No error icon or fallback image yet
- No caching headers or mime sniffing implemented

* POC: Handle ksu://icon/[packageName] to serve app icon via WebView

This proof-of-concept intercepts custom URLs of the form:
  ksu://icon/com.example.app

It fetches the app icon using PackageManager via AppIconUtil,
converts it to PNG, and returns it as a WebResourceResponse.

Used inside shouldInterceptRequest() for early experimentation
with dynamic WebView asset routing.

Fallbacks to WebViewAssetLoader for all other requests.

Notes:
- Icon size currently fixed at 512px
- No error icon or fallback image yet
- No caching headers or mime sniffing implemented
2025-07-25 21:23:29 +06:00
James McConnell
d4f4c0a0cc Syscall Hooks (#686)
* Update gki-kernel.yml: Add Syscall Hooks

* Update gki-kernel.yml: Fuzz is needed?

* workflows: apply syscall hook patches and configs only for NON-LKM build

---------

Co-authored-by: Rifat Azad <33044977+rifsxd@users.noreply.github.com>
2025-07-25 19:35:29 +06:00
Rifat Azad
0aaae919c0 userspace/su: add ndk compatible su from kernelnosu
Co-authored-by: nampud <nampud@users.noreply.github.com>
2025-07-25 06:40:48 +06:00
Rifat Azad
3f4c23a34f kernel: allow only perms for /{system | vendor | product | system_ext}/bin/su path
kernel: guard kernelnosu perms if not using KSU_KPROBES_HOOK
2025-07-24 06:44:10 +06:00
Rifat Azad
d69a72c658 src: build script for a full featured manager 2025-07-23 23:02:37 +06:00
Rifat Azad
adbff41a22 ksud: decide best partition to direct flash LKM 2025-07-23 23:02:28 +06:00
Rifat Azad
512f84504e ksud: create our own new ramdisk when no compatible ramdisk found 2025-07-22 07:23:07 +06:00
Rifat Azad
c44f48c8a4 Update README.md 2025-07-21 15:36:05 +06:00
Rifat Azad
5c6c3870a0 ksud_magic: fix rust fmt 2025-07-21 06:59:34 +06:00
Alessandro Paluzzi
c6b5440682 manager | ksud: Add toggle for global mount namespace (#99)
* This is untested, if you facing any issues, open a new issue or comments at our group
* and also, this changes maybe reverted if didn't meet the target.

Taken from Apatch's implementations:
8de6b9d676
57d527a846
f093d6a633

Critics are welcome!

Signed-off-by: rsuntk <90097027+rsuntk@users.noreply.github.com>
2025-07-21 06:34:11 +06:00
Rifat Azad
a917314e84 manager: fixed sus_su features
susfsd: added `sus_su support` command
2025-07-21 06:19:50 +06:00
nampud
948975ba35 kernel: core_hook: add support for KernelNoSU
reorder ksu_handle_prctl checks a bit to allow non-manager to use CMD 15
this allows us to piggyback a small su to KernelSU's permission system after
disabling kernel sucompat

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

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-07-21 06:19:34 +06:00
Rifat Azad
45ad73e9dd kernel: guard syscall hook types
- for kernel syscall hooks we need to pass additional guards for ksun (#ifdef CONFIG_KSU -> #if defined(CONFIG_KSU) && !defined(CONFIG_KSU_KPROBES_HOOK)) or else it will fail to build because of undefined symbol

- reference https://github.com/KernelSU-Next/kernel_patches/blob/main/syscall_hook/min_scope_syscall_hooks_v1.4.patch
2025-07-21 02:10:36 +06:00
Rifat Azad
892a62afdf manager: bump MINIMAL_SUPPORTED_KERNEL to 12797 2025-07-19 23:36:00 +06:00
Rifat Azad
d61de07c21 kernel: implement v2_signature size/hash override from userspace through kernel module parameter
- /sys/module/kernelsu/parameters/expected_manager_*
2025-07-19 23:10:48 +06:00
Rifat Azad
4382dca515 ksud: do backup for vendor_boot partition 2025-07-17 23:24:32 +06:00
Rifat Azad
2c9078e038 kernel: use ksu_strncpy_from_user_retry when kprobes hook sucompat pagefaults 2025-07-16 21:06:59 +06:00
Edrick Sinsuan
81f4f09d0c ksud: Address pagefault in ksu_handle_execveat_ksud (#662)
* ksud: Address pagefault in ksu_handle_execveat_ksud

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

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

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

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

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

This reverts commit c6b60a24e8.

---------

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

* New translations manager/app/src/main/res/values-vi-rVN/strings.xml (bundle: 8)
2025-07-15 01:10:58 +06:00
Rifat Azad
8fc85993f1 ksud: fix clippy errors 2025-07-14 22:55:22 +06:00
Rifat Azad
df07860e44 ksud: fix rust fmt errors 2025-07-14 20:22:31 +06:00
Rifat Azad
bd03c296a1 kernel/Makefile: remove redundant get_cred_rcu backports 2025-07-14 20:11:13 +06:00
Rifat Azad
14b7861f44 template: add feature request template 2025-07-14 19:59:38 +06:00
Rifat Azad
3c421b1362 manager: added more module list sort options ( enabled, action and webui) 2025-07-13 20:59:33 +06:00
76 changed files with 1573 additions and 689 deletions

View File

@@ -60,8 +60,9 @@ body:
value: |
- Device:
- OS Version:
- KernelSU Version:
- Kernel Version:
- KSUN Driver Version:
- KSUN Manager Version:
validations:
required: true

View File

@@ -1,5 +1 @@
blank_issues_enabled: false
contact_links:
- name: Feature Request
url: https://t.me/ksunext/578
about: "We do not accept external Feature Requests anymore, check the link for more details."
blank_issues_enabled: false

41
.github/ISSUE_TEMPLATE/request.yml vendored Normal file
View File

@@ -0,0 +1,41 @@
name: Feature Request
description: Suggest a new feature or improvement for KernelSU Next.
title: "[Feature] <short description>"
labels: ["enhancement"]
body:
- type: markdown
attributes:
value: |
Thank you for taking the time to suggest a feature! Please fill out the following details.
- type: textarea
id: problem
attributes:
label: "Is your feature request related to a problem?"
description: "A clear and concise description of what the problem is. Ex: I'm always frustrated when..."
placeholder: "Describe the problem or need."
validations:
required: false
- type: textarea
id: solution
attributes:
label: "Describe the solution you'd like"
description: "A clear and concise description of what you want to happen."
placeholder: "Describe your proposed solution."
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: "Describe alternatives you've considered"
description: "A clear and concise description of any alternative solutions or features you've considered."
placeholder: "List any alternatives."
validations:
required: false
- type: textarea
id: additional
attributes:
label: "Additional context"
description: "Add any other context or screenshots about the feature request here."
placeholder: "Additional context or screenshots."
validations:
required: false

View File

@@ -195,6 +195,18 @@ jobs:
sed -i 's/needs unknown symbol/Dont abort when unknown symbol/g' build/kernel/*.sh || echo "No unknown symbol scripts found"
fi
- name: Setup Syscall Hooks
if: ${{ inputs.build_lkm == false }}
run: |
cd $GITHUB_WORKSPACE/android-kernel/common
echo "[+] Patch Kernel"
curl -L https://github.com/KernelSU-Next/kernel_patches/raw/main/syscall_hook/min_scope_syscall_hooks_v1.4.patch | patch -p1 --fuzz=3
echo "[+] Set Config"
echo "CONFIG_KSU=y" >> ./arch/arm64/configs/gki_defconfig
echo "CONFIG_KSU_KPROBES_HOOK=n" >> ./arch/arm64/configs/gki_defconfig
echo "[+] Disable Config Check"
sed -i 's/check_defconfig//' ./build.config.gki
- name: Make working directory clean to avoid dirty
working-directory: android-kernel
run: |

31
build.sh Executable file
View File

@@ -0,0 +1,31 @@
#!/bin/bash
# This script builds the KernelSU Next manager APK.
# Ensure you have the setup Android SDK & NDK installed and necessary environment variables set and sourced.
# For LKM make sure you have imported the androidX-X.X_kernelsu.ko drivers to userspace/ksud_*/bin/aarch64 directory.
cross build --target aarch64-linux-android --release --manifest-path ./userspace/ksud_magic/Cargo.toml
cp userspace/ksud_magic/target/aarch64-linux-android/release/ksud manager/app/src/main/jniLibs/arm64-v8a/libksud_magic.so
cross build --target aarch64-linux-android --release --manifest-path ./userspace/ksud_overlayfs/Cargo.toml
cp userspace/ksud_overlayfs/target/aarch64-linux-android/release/ksud manager/app/src/main/jniLibs/arm64-v8a/libksud_overlayfs.so
cd userspace/susfsd/jni
ndk-build
cp ../libs/arm64-v8a/susfsd ../../../manager/app/src/main/jniLibs/arm64-v8a/libsusfsd.so
cd ../../..
cd manager
./setup.sh
cd ..
adb install manager/app/build/outputs/apk/release/KernelSU_Next_v*.apk

View File

@@ -74,6 +74,7 @@ If youd like to support the project:
- **USDT (BEP20, ERC20)**: `0x12b5224b7aca0121c2f003240a901e1d064371c1`
- **USDT (TRC20)**: `TYUVMWGTcnR5svnDoX85DWHyqUAeyQcdjh`
- **USDT (SOL)**: `A4wqBXYd6Ey4nK4SJ2bmjeMgGyaLKT9TwDLh8BEo8Zu6`
- **ETH (ERC20)**: `0x12b5224b7aca0121c2f003240a901e1d064371c1`
- **LTC**: `Ld238uYBuRQdZB5YwdbkuU6ektBAAUByoL`
- **BTC**: `19QgifcjMjSr1wB2DJcea5cxitvWVcXMT6`
@@ -87,5 +88,4 @@ If youd like to support the project:
- [Genuine](https://github.com/brevent/genuine/) APK v2 signature validation
- [Diamorphine](https://github.com/m0nad/Diamorphine) Rootkit techniques
- [KernelSU](https://github.com/tiann/KernelSU) The original base that made KernelSU Next possible
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs) 💜 to 5ec1cff for keeping KernelSU alive
- [Crowdin Translators](https://crowdin.com/project/kernelsu-next/members) 💬 Thanks to everyone for helping make KernelSU Next multi-lingual!
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs) For magic mount support

View File

@@ -49,12 +49,12 @@ ifeq ($(shell grep "ssize_t kernel_write" $(srctree)/fs/read_write.c | grep -q "
ccflags-y += -DKSU_KERNEL_WRITE
endif
ifndef KSU_NEXT_EXPECTED_SIZE
KSU_NEXT_EXPECTED_SIZE := 0x3e6
ifndef KSU_NEXT_MANAGER_SIZE
KSU_NEXT_MANAGER_SIZE := 0x3e6
endif
ifndef KSU_NEXT_EXPECTED_HASH
KSU_NEXT_EXPECTED_HASH := 79e590113c4c4c0c222978e413a5faa801666957b1212a328e46c00c69821bf7
ifndef KSU_NEXT_MANAGER_HASH
KSU_NEXT_MANAGER_HASH := 79e590113c4c4c0c222978e413a5faa801666957b1212a328e46c00c69821bf7
endif
ifdef KSU_MANAGER_PACKAGE
@@ -62,48 +62,14 @@ ccflags-y += -DKSU_MANAGER_PACKAGE=\"$(KSU_MANAGER_PACKAGE)\"
$(info -- KernelSU-Next Manager package name: $(KSU_MANAGER_PACKAGE))
endif
$(info -- KernelSU-Next Manager signature size: $(KSU_NEXT_EXPECTED_SIZE))
$(info -- KernelSU-Next Manager signature hash: $(KSU_NEXT_EXPECTED_HASH))
$(info -- KernelSU-Next Manager signature size: $(KSU_NEXT_MANAGER_SIZE))
$(info -- KernelSU-Next Manager signature hash: $(KSU_NEXT_MANAGER_HASH))
ccflags-y += -DEXPECTED_NEXT_SIZE=$(KSU_NEXT_EXPECTED_SIZE)
ccflags-y += -DEXPECTED_NEXT_HASH=\"$(KSU_NEXT_EXPECTED_HASH)\"
ccflags-y += -DKSU_COMPAT_GET_CRED_RCU
ccflags-y += -DEXPECTED_MANAGER_SIZE=$(KSU_NEXT_MANAGER_SIZE)
ccflags-y += -DEXPECTED_MANAGER_HASH=\"$(KSU_NEXT_MANAGER_HASH)\"
ccflags-y += -DKSU_UMOUNT
# Determine the appropriate atomic function and apply patch accordingly
ifeq ($(shell grep -q "atomic_inc_not_zero" $(srctree)/kernel/cred.c; echo $$?),0)
ATOMIC_INC_FUNC = atomic_inc_not_zero
else ifeq ($(shell grep -q "atomic_long_inc_not_zero" $(srctree)/kernel/cred.c; echo $$?),0)
ATOMIC_INC_FUNC = atomic_long_inc_not_zero
else
$(info -- KSU_NEXT: Neither atomic_inc_not_zero nor atomic_long_inc_not_zero found in kernel/cred.c)
endif
# Inform which function is being patched
$(info -- KSU_NEXT: Using $(ATOMIC_INC_FUNC) in get_cred_rcu patch.)
# Add the get_cred_rcu function to cred.h if not already present
ifneq ($(shell grep -Eq "^static inline const struct cred \*get_cred_rcu" $(srctree)/include/linux/cred.h; echo $$?),0)
$(info -- KSU_NEXT: adding function 'static inline const struct cred *get_cred_rcu(const struct cred *cred);' to $(srctree)/include/linux/cred.h)
GET_CRED_RCU = static inline const struct cred *get_cred_rcu(const struct cred *cred)\n\
{\n\t\
struct cred *nonconst_cred = (struct cred *) cred;\n\t\
if (!cred)\n\t\t\
return NULL;\n\t\
if (!$(ATOMIC_INC_FUNC)(&nonconst_cred->usage))\n\t\t\
return NULL;\n\t\
validate_creds(cred);\n\t\
return cred;\n\
}\n
$(shell grep -qF "$(GET_CRED_RCU)" $(srctree)/include/linux/cred.h || sed -i '/^static inline void put_cred/i $(GET_CRED_RCU)' $(srctree)/include/linux/cred.h)
# Modify get_task_cred in cred.c
$(info -- KSU_NEXT: modifying 'get_task_cred' function in $(srctree)/kernel/cred.c)
$(shell sed -i "s/!$(ATOMIC_INC_FUNC)(&((struct cred \*)cred)->usage)/!get_cred_rcu(cred)/g" $(srctree)/kernel/cred.c)
endif
ifneq ($(shell grep -Eq "^static int can_umount" $(srctree)/fs/namespace.c; echo $$?),0)
$(info -- KSU_NEXT: adding function 'static int can_umount(const struct path *path, int flags);' to $(srctree)/fs/namespace.c)
CAN_UMOUNT = static int can_umount(const struct path *path, int flags)\n\

View File

@@ -3,10 +3,9 @@
#include <linux/gfp.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/version.h>
#ifdef CONFIG_KSU_DEBUG
#include <linux/moduleparam.h>
#endif
#include <crypto/hash.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
#include <crypto/sha2.h>
@@ -19,6 +18,8 @@
#include "kernel_compat.h"
#include "throne_tracker.h"
static unsigned int expected_manager_size = EXPECTED_MANAGER_SIZE;
static char expected_manager_hash[SHA256_DIGEST_SIZE * 2 + 1] = EXPECTED_MANAGER_HASH;
struct sdesc {
struct shash_desc shash;
@@ -313,6 +314,53 @@ static struct kernel_param_ops expected_size_ops = {
module_param_cb(ksu_debug_manager_uid, &expected_size_ops,
&ksu_debug_manager_uid, S_IRUSR | S_IWUSR);
#else
static int set_expected_size(const char *val, const struct kernel_param *kp)
{
int rv = param_set_uint(val, kp);
pr_info("expected_manager_size set to %u\n", expected_manager_size);
return rv;
}
static int get_expected_size(char *buf, const struct kernel_param *kp)
{
return snprintf(buf, PAGE_SIZE, "%u\n", expected_manager_size);
}
static int set_expected_hash(const char *val, const struct kernel_param *kp)
{
if (strlen(val) != SHA256_DIGEST_SIZE * 2) {
pr_err("Invalid hash length: %s\n", val);
return -EINVAL;
}
strncpy(expected_manager_hash, val, SHA256_DIGEST_SIZE * 2);
expected_manager_hash[SHA256_DIGEST_SIZE * 2] = '\0';
pr_info("expected_manager_hash set to %s\n", expected_manager_hash);
return 0;
}
static int get_expected_hash(char *buf, const struct kernel_param *kp)
{
return snprintf(buf, PAGE_SIZE, "%s\n", expected_manager_hash);
}
static struct kernel_param_ops expected_size_ops = {
.set = set_expected_size,
.get = get_expected_size,
};
static struct kernel_param_ops expected_hash_ops = {
.set = set_expected_hash,
.get = get_expected_hash,
};
module_param_cb(expected_manager_size, &expected_size_ops, &expected_manager_size, 0644);
module_param_cb(expected_manager_hash, &expected_hash_ops, &expected_manager_hash, 0644);
#endif
bool is_manager_apk(char *path)
@@ -333,5 +381,13 @@ bool is_manager_apk(char *path)
return false;
}
return check_v2_signature(path, EXPECTED_NEXT_SIZE, EXPECTED_NEXT_HASH);
// set debug info to print size and hash to kernel log
pr_info("%s: expected size: %u, expected hash: %s\n",
path, expected_manager_size, expected_manager_hash);
#ifdef CONFIG_KSU_DEBUG
return check_v2_signature(path, EXPECTED_MANAGER_SIZE, EXPECTED_MANAGER_HASH);
#else
return check_v2_signature(path, expected_manager_size, expected_manager_hash);
#endif
}

View File

@@ -47,10 +47,6 @@
#include "throne_tracker.h"
#include "kernel_compat.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) || defined(KSU_COMPAT_GET_CRED_RCU)
#define KSU_GET_CRED_RCU
#endif
static bool ksu_module_mounted = false;
extern int handle_sepolicy(unsigned long arg3, void __user *arg4);
@@ -259,6 +255,34 @@ static void nuke_ext4_sysfs() {
path_put(&path);
}
static bool is_system_bin_su(void)
{
static const char *su_paths[] = {
"/system/bin/su",
"/vendor/bin/su",
"/product/bin/su",
"/system_ext/bin/su",
"/odm/bin/su",
"/system/xbin/su",
"/system_ext/xbin/su"
};
char path_buf[256];
char *pathname;
int i;
struct mm_struct *mm = current->mm;
if (mm && mm->exe_file) {
pathname = d_path(&mm->exe_file->f_path, path_buf, sizeof(path_buf));
if (!IS_ERR(pathname)) {
for (i = 0; i < ARRAY_SIZE(su_paths); i++) {
if (strcmp(pathname, su_paths[i]) == 0)
return true;
}
}
}
return false;
}
int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5)
{
@@ -281,10 +305,18 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
bool from_root = 0 == current_uid().val;
bool from_manager = is_manager();
#ifdef CONFIG_KSU_KPROBES_HOOK
if (!from_root && !from_manager
&& !(is_allow_su() && is_system_bin_su())) {
// only root or manager can access this interface
return 0;
}
#else
if (!from_root && !from_manager) {
// only root or manager can access this interface
return 0;
}
#endif
#ifdef CONFIG_KSU_DEBUG
pr_info("option: 0x%x, cmd: %ld\n", option, arg2);
@@ -450,6 +482,32 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
return 0;
}
#ifdef CONFIG_KSU_KPROBES_HOOK
if (arg2 == CMD_ENABLE_SU) {
bool enabled = (arg3 != 0);
if (enabled == ksu_su_compat_enabled) {
pr_info("cmd enable su but no need to change.\n");
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {// return the reply_ok directly
pr_err("prctl reply error, cmd: %lu\n", arg2);
}
return 0;
}
if (enabled) {
ksu_sucompat_init();
} else {
ksu_sucompat_exit();
}
ksu_su_compat_enabled = enabled;
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
pr_err("prctl reply error, cmd: %lu\n", arg2);
}
return 0;
}
#endif
// all other cmds are for 'root manager'
if (!from_manager) {
return 0;
@@ -503,7 +561,7 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
}
return 0;
}
#ifndef CONFIG_KSU_KPROBES_HOOK
if (arg2 == CMD_ENABLE_SU) {
bool enabled = (arg3 != 0);
if (enabled == ksu_su_compat_enabled) {
@@ -527,6 +585,8 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
return 0;
}
#endif
return 0;
}

View File

@@ -173,3 +173,26 @@ long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
return ret;
}
#endif
static inline int ksu_access_ok(const void *addr, unsigned long size)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)
return access_ok(addr, size);
#else
return access_ok(VERIFY_READ, addr, size);
#endif
}
long ksu_strncpy_from_user_retry(char *dst, const void __user *unsafe_addr,
long count)
{
long ret = ksu_strncpy_from_user_nofault(dst, unsafe_addr, count);
if (likely(ret >= 0))
return ret;
// we faulted! fallback to slow path
if (unlikely(!ksu_access_ok(unsafe_addr, count)))
return -EFAULT;
return strncpy_from_user(dst, unsafe_addr, count);
}

View File

@@ -23,6 +23,9 @@
extern long ksu_strncpy_from_user_nofault(char *dst,
const void __user *unsafe_addr,
long count);
extern long ksu_strncpy_from_user_retry(char *dst,
const void __user *unsafe_addr,
long count);
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
extern struct key *init_session_keyring;

View File

@@ -58,12 +58,11 @@ static void stop_input_hook();
static struct work_struct stop_vfs_read_work;
static struct work_struct stop_execve_hook_work;
static struct work_struct stop_input_hook_work;
#endif
#else
bool ksu_vfs_read_hook __read_mostly = true;
bool ksu_execveat_hook __read_mostly = true;
bool ksu_input_hook __read_mostly = true;
#endif
u32 ksu_devpts_sid;
@@ -197,12 +196,11 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
const char __user *p = get_user_arg_ptr(*argv, 1);
if (p && !IS_ERR(p)) {
char first_arg[16];
ksu_strncpy_from_user_nofault(
ksu_strncpy_from_user_retry(
first_arg, p, sizeof(first_arg));
pr_info("/system/bin/init first arg: %s\n",
first_arg);
if (!strcmp(first_arg, "second_stage") ||
(argc == 2 && !strcmp(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;
@@ -223,7 +221,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
const char __user *p = get_user_arg_ptr(*argv, 1);
if (p && !IS_ERR(p)) {
char first_arg[16];
ksu_strncpy_from_user_nofault(
ksu_strncpy_from_user_retry(
first_arg, p, sizeof(first_arg));
pr_info("/init first arg: %s\n", first_arg);
if (!strcmp(first_arg, "--second-stage")) {
@@ -248,7 +246,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
}
char env[256];
// Reading environment variable strings from user space
if (ksu_strncpy_from_user_nofault(
if (ksu_strncpy_from_user_retry(
env, p, sizeof(env)) < 0)
continue;
// Parsing environment variable names and values
@@ -489,10 +487,12 @@ __maybe_unused int ksu_handle_execve_ksud(const char __user *filename_user,
struct filename filename_in, *filename_p;
char path[32];
#ifndef CONFIG_KSU_KPROBES_HOOK
// return early if disabled.
if (!ksu_execveat_hook) {
return 0;
}
#endif
if (!filename_user)
return 0;

View File

@@ -179,23 +179,8 @@ int ksu_handle_execve_sucompat(int *fd, const char __user **filename_user,
if (unlikely(!filename_user))
return 0;
// nofault variant fails probably due to pagefault_disable
// some cpus dont really have that good speculative execution
// substitute set_fs, check if pointer is valid
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0)
if (!access_ok(VERIFY_READ, *filename_user, sizeof(path)))
return 0;
#else
if (!access_ok(*filename_user, sizeof(path)))
return 0;
#endif
// success = returns number of bytes and should be less than path
long len = strncpy_from_user(path, *filename_user, sizeof(path));
if (len <= 0 || len > sizeof(path))
return 0;
// strncpy_from_user_nofault does this too
path[sizeof(path) - 1] = '\0';
memset(path, 0, sizeof(path));
ksu_strncpy_from_user_retry(path, *filename_user, sizeof(path));
if (likely(memcmp(path, su, sizeof(su))))
return 0;

3
manager/.gitignore vendored
View File

@@ -7,5 +7,4 @@ build
captures
.cxx
local.properties
key.jks
setup.sh
key.jks

View File

@@ -16,11 +16,12 @@ object Natives {
// 10946: add capabilities
// 10977: change groups_count and groups to avoid overflow write
// 11071: Fix the issue of failing to set a custom SELinux type.
const val MINIMAL_SUPPORTED_KERNEL = 11071
// 12797: zygisk query and get manager uid.
const val MINIMAL_SUPPORTED_KERNEL = 12797
// 11640: Support query working mode, LKM or GKI
// when MINIMAL_SUPPORTED_KERNEL > 11640, we can remove this constant.
const val MINIMAL_SUPPORTED_KERNEL_LKM = 11648
const val MINIMAL_SUPPORTED_KERNEL_LKM = 12797
// 12404: Support disable sucompat mode
const val MINIMAL_SUPPORTED_SU_COMPAT = 12404
@@ -119,6 +120,9 @@ object Natives {
return version < MINIMAL_SUPPORTED_KERNEL
}
val KSU_WORK_DIR = "/data/adb/ksu/"
val GLOBAL_NAMESPACE_FILE = KSU_WORK_DIR + ".global_mnt"
@Immutable
@Parcelize
@Keep

View File

@@ -1,5 +1,6 @@
package com.rifsxd.ksunext.ui.screen
import android.app.Activity
import android.content.Context
import android.net.Uri
import android.os.Environment
@@ -67,6 +68,9 @@ import com.rifsxd.ksunext.R
import com.rifsxd.ksunext.ui.component.rememberConfirmDialog
import com.rifsxd.ksunext.ui.component.ConfirmResult
import com.rifsxd.ksunext.ui.component.KeyEventBlocker
import com.rifsxd.ksunext.ui.theme.ORANGE
import com.rifsxd.ksunext.ui.theme.GREEN
import com.rifsxd.ksunext.ui.theme.RED
import com.rifsxd.ksunext.ui.util.FlashResult
import com.rifsxd.ksunext.ui.util.LkmSelection
import com.rifsxd.ksunext.ui.util.LocalSnackbarHost
@@ -80,9 +84,6 @@ import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import androidx.compose.ui.platform.LocalContext
import android.app.Activity
enum class FlashingStatus {
FLASHING,
SUCCESS,
@@ -408,6 +409,11 @@ private fun TopBar(
),
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Black,
color = when (status) {
FlashingStatus.FLASHING -> ORANGE
FlashingStatus.SUCCESS -> GREEN
FlashingStatus.FAILED -> RED
}
)
},
navigationIcon = {

View File

@@ -650,7 +650,7 @@ private fun InfoCard(autoExpand: Boolean = false) {
val suSFS = getSuSFS()
if (suSFS == "Supported") {
val isSUS_SU = getSuSFSFeatures() == "CONFIG_KSU_SUSFS_SUS_SU"
val isSUS_SU = hasSuSFs_SUS_SU() == "Supported"
val susSUMode = if (isSUS_SU) {
val mode = susfsSUS_SU_Mode()
val modeString =

View File

@@ -150,6 +150,10 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
viewModel.sortZToA = prefs.getBoolean("module_sort_z_to_a", false)
viewModel.sortSizeLowToHigh = prefs.getBoolean("module_sort_size_low_to_high", false)
viewModel.sortSizeHighToLow = prefs.getBoolean("module_sort_size_high_to_low", false)
viewModel.sortEnabledFirst = prefs.getBoolean("module_sort_enabled_first", false)
viewModel.sortActionFirst = prefs.getBoolean("module_sort_action_first", false)
viewModel.sortWebUiFirst = prefs.getBoolean("module_sort_webui_first", false)
if (viewModel.moduleList.isEmpty() || viewModel.isNeedRefresh) {
viewModel.fetchModuleList()
}
@@ -233,11 +237,17 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
viewModel.sortZToA = false
viewModel.sortSizeLowToHigh = false
viewModel.sortSizeHighToLow = false
viewModel.sortEnabledFirst = false
viewModel.sortActionFirst = false
viewModel.sortWebUiFirst = false
prefs.edit()
.putBoolean("module_sort_a_to_z", viewModel.sortAToZ)
.putBoolean("module_sort_z_to_a", false)
.putBoolean("module_sort_size_low_to_high", false)
.putBoolean("module_sort_size_high_to_low", false)
.putBoolean("module_sort_enabled_first", false)
.putBoolean("module_sort_action_first", false)
.putBoolean("module_sort_webui_first", false)
.apply()
scope.launch {
viewModel.fetchModuleList()
@@ -257,11 +267,17 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
viewModel.sortAToZ = false
viewModel.sortSizeLowToHigh = false
viewModel.sortSizeHighToLow = false
viewModel.sortEnabledFirst = false
viewModel.sortActionFirst = false
viewModel.sortWebUiFirst = false
prefs.edit()
.putBoolean("module_sort_z_to_a", viewModel.sortZToA)
.putBoolean("module_sort_a_to_z", false)
.putBoolean("module_sort_size_low_to_high", false)
.putBoolean("module_sort_size_high_to_low", false)
.putBoolean("module_sort_enabled_first", false)
.putBoolean("module_sort_action_first", false)
.putBoolean("module_sort_webui_first", false)
.apply()
scope.launch {
viewModel.fetchModuleList()
@@ -281,11 +297,17 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
viewModel.sortAToZ = false
viewModel.sortZToA = false
viewModel.sortSizeHighToLow = false
viewModel.sortEnabledFirst = false
viewModel.sortActionFirst = false
viewModel.sortWebUiFirst = false
prefs.edit()
.putBoolean("module_sort_size_low_to_high", viewModel.sortSizeLowToHigh)
.putBoolean("module_sort_a_to_z", false)
.putBoolean("module_sort_z_to_a", false)
.putBoolean("module_sort_size_high_to_low", false)
.putBoolean("module_sort_enabled_first", false)
.putBoolean("module_sort_action_first", false)
.putBoolean("module_sort_webui_first", false)
.apply()
scope.launch {
viewModel.fetchModuleList()
@@ -305,11 +327,104 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
viewModel.sortAToZ = false
viewModel.sortZToA = false
viewModel.sortSizeLowToHigh = false
viewModel.sortEnabledFirst = false
viewModel.sortActionFirst = false
viewModel.sortWebUiFirst = false
prefs.edit()
.putBoolean("module_sort_size_high_to_low", viewModel.sortSizeHighToLow)
.putBoolean("module_sort_a_to_z", false)
.putBoolean("module_sort_z_to_a", false)
.putBoolean("module_sort_size_low_to_high", false)
.putBoolean("module_sort_enabled_first", false)
.putBoolean("module_sort_action_first", false)
.putBoolean("module_sort_webui_first", false)
.apply()
scope.launch {
viewModel.fetchModuleList()
}
}
)
DropdownMenuItem(
text = {
Text(stringResource(R.string.module_sort_enabled_first))
},
trailingIcon = {
Checkbox(checked = viewModel.sortEnabledFirst, onCheckedChange = null)
},
onClick = {
viewModel.sortEnabledFirst = !viewModel.sortEnabledFirst
viewModel.sortAToZ = false
viewModel.sortZToA = false
viewModel.sortSizeLowToHigh = false
viewModel.sortSizeHighToLow = false
viewModel.sortActionFirst = false
viewModel.sortWebUiFirst = false
prefs.edit()
.putBoolean("module_sort_enabled_first", viewModel.sortEnabledFirst)
.putBoolean("module_sort_a_to_z", false)
.putBoolean("module_sort_z_to_a", false)
.putBoolean("module_sort_size_low_to_high", false)
.putBoolean("module_sort_size_high_to_low", false)
.putBoolean("module_sort_action_first", false)
.putBoolean("module_sort_webui_first", false)
.apply()
scope.launch {
viewModel.fetchModuleList()
}
}
)
DropdownMenuItem(
text = {
Text(stringResource(R.string.module_sort_action_first))
},
trailingIcon = {
Checkbox(checked = viewModel.sortActionFirst, onCheckedChange = null)
},
onClick = {
viewModel.sortActionFirst = !viewModel.sortActionFirst
viewModel.sortAToZ = false
viewModel.sortZToA = false
viewModel.sortSizeLowToHigh = false
viewModel.sortSizeHighToLow = false
viewModel.sortEnabledFirst = false
viewModel.sortWebUiFirst = false
prefs.edit()
.putBoolean("module_sort_action_first", viewModel.sortActionFirst)
.putBoolean("module_sort_a_to_z", false)
.putBoolean("module_sort_z_to_a", false)
.putBoolean("module_sort_size_low_to_high", false)
.putBoolean("module_sort_size_high_to_low", false)
.putBoolean("module_sort_enabled_first", false)
.putBoolean("module_sort_webui_first", false)
.apply()
scope.launch {
viewModel.fetchModuleList()
}
}
)
DropdownMenuItem(
text = {
Text(stringResource(R.string.module_sort_webui_first))
},
trailingIcon = {
Checkbox(checked = viewModel.sortWebUiFirst, onCheckedChange = null)
},
onClick = {
viewModel.sortWebUiFirst = !viewModel.sortWebUiFirst
viewModel.sortAToZ = false
viewModel.sortZToA = false
viewModel.sortSizeLowToHigh = false
viewModel.sortSizeHighToLow = false
viewModel.sortEnabledFirst = false
viewModel.sortActionFirst = false
prefs.edit()
.putBoolean("module_sort_webui_first", viewModel.sortWebUiFirst)
.putBoolean("module_sort_a_to_z", false)
.putBoolean("module_sort_z_to_a", false)
.putBoolean("module_sort_size_low_to_high", false)
.putBoolean("module_sort_size_high_to_low", false)
.putBoolean("module_sort_enabled_first", false)
.putBoolean("module_sort_action_first", false)
.apply()
scope.launch {
viewModel.fetchModuleList()

View File

@@ -88,6 +88,8 @@ import com.rifsxd.ksunext.ui.component.rememberLoadingDialog
import com.rifsxd.ksunext.ui.util.LocalSnackbarHost
import com.rifsxd.ksunext.ui.util.getBugreportFile
import com.rifsxd.ksunext.ui.util.*
import com.rifsxd.ksunext.ui.util.isGlobalNamespaceEnabled
import com.rifsxd.ksunext.ui.util.setGlobalNamespaceEnabled
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
@@ -101,6 +103,8 @@ import java.time.format.DateTimeFormatter
fun SettingScreen(navigator: DestinationsNavigator) {
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
val snackBarHost = LocalSnackbarHost.current
var isGlobalNamespaceEnabled by rememberSaveable { mutableStateOf(false) }
isGlobalNamespaceEnabled = isGlobalNamespaceEnabled()
val isManager = Natives.becomeManager(ksuApp.packageName)
val ksuVersion = if (isManager) Natives.version else null
@@ -196,14 +200,31 @@ fun SettingScreen(navigator: DestinationsNavigator) {
}
}
}
SwitchItem(
icon = Icons.Filled.Engineering,
title = stringResource(id = R.string.settings_global_namespace_mode),
summary = stringResource(id = R.string.settings_global_namespace_mode_summary),
checked = isGlobalNamespaceEnabled,
onCheckedChange = {
setGlobalNamespaceEnabled(
if (isGlobalNamespaceEnabled) {
"0"
} else {
"1"
}
)
isGlobalNamespaceEnabled = it
}
)
}
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
val suSFS = getSuSFS()
val isSUS_SU = getSuSFSFeatures()
val isSUS_SU = hasSuSFs_SUS_SU() == "Supported"
if (suSFS == "Supported") {
if (isSUS_SU == "CONFIG_KSU_SUSFS_SUS_SU") {
if (isSUS_SU) {
var isEnabled by rememberSaveable {
mutableStateOf(susfsSUS_SU_Mode() == "2")
}

View File

@@ -12,4 +12,9 @@ val SECONDARY_DARK = Color(0xFFF5BDE6) // Catppuccin Pink
val AMOLED_BLACK = Color(0xFF000000) // Pure black for AMOLED
val DARK_PURPLE = Color(0xFF6E6CB6) // Catppuccin Mauve (dark purple)
val DARK_GREY = Color(0xFF363A4F) // Catppuccin Surface (dark grey)
val DARK_GREY = Color(0xFF363A4F) // Catppuccin Surface (dark grey)
val GREEN = Color(0xFF4CAF50) // Green
val RED = Color(0xFFF44336) // Red
val YELLOW = Color(0xFFFFEB3B) // Yellow
val ORANGE = Color(0xFFFF9800) // Orange

View File

@@ -103,7 +103,10 @@ fun Uri.getFileName(context: Context): String? {
fun createRootShell(globalMnt: Boolean = false): Shell {
Shell.enableVerboseLogging = BuildConfig.DEBUG
val builder = Shell.Builder.create()
val builder = Shell.Builder.create().apply {
setFlags(Shell.FLAG_MOUNT_MASTER)
}
return try {
if (globalMnt) {
builder.build(ksuDaemonMagicPath(), "debug", "su", "-g")
@@ -403,6 +406,22 @@ fun hasMagisk(): Boolean {
return result.isSuccess
}
fun isGlobalNamespaceEnabled(): Boolean {
val shell = getRootShell()
val result =
ShellUtils.fastCmd(shell, "nsenter --mount=/proc/1/ns/mnt cat ${Natives.GLOBAL_NAMESPACE_FILE}")
Log.i(TAG, "is global namespace enabled: $result")
return result == "1"
}
fun setGlobalNamespaceEnabled(value: String) {
getRootShell().newJob()
.add("nsenter --mount=/proc/1/ns/mnt echo $value > ${Natives.GLOBAL_NAMESPACE_FILE}")
.submit { result ->
Log.i(TAG, "setGlobalNamespaceEnabled result: ${result.isSuccess} [${result.out}]")
}
}
fun isSepolicyValid(rules: String?): Boolean {
if (rules == null) {
return true
@@ -591,12 +610,19 @@ fun getSuSFSVariant(): String {
val result = ShellUtils.fastCmd(shell, "${getSuSFSDaemonPath()} variant")
return result
}
fun getSuSFSFeatures(): String {
val shell = getRootShell()
val result = ShellUtils.fastCmd(shell, "${getSuSFSDaemonPath()} features")
return result
}
fun hasSuSFs_SUS_SU(): String {
val shell = getRootShell()
val result = ShellUtils.fastCmd(shell, "${getSuSFSDaemonPath()} sus_su support")
return result
}
fun susfsSUS_SU_0(): String {
val shell = getRootShell()
val result = ShellUtils.fastCmd(shell, "${getSuSFSDaemonPath()} sus_su 0")

View File

@@ -67,9 +67,15 @@ class ModuleViewModel : ViewModel() {
var sortZToA by mutableStateOf(false)
var sortSizeLowToHigh by mutableStateOf(false)
var sortSizeHighToLow by mutableStateOf(false)
var sortEnabledFirst by mutableStateOf(false)
var sortActionFirst by mutableStateOf(false)
var sortWebUiFirst by mutableStateOf(false)
val moduleList by derivedStateOf {
val comparator = when {
sortWebUiFirst -> compareByDescending<ModuleInfo> { it.hasWebUi }
sortEnabledFirst -> compareByDescending<ModuleInfo> { it.enabled }
sortActionFirst -> compareByDescending<ModuleInfo> { it.hasActionScript }
sortAToZ -> compareBy<ModuleInfo> { it.name.lowercase() }
sortZToA -> compareByDescending<ModuleInfo> { it.name.lowercase() }
sortSizeLowToHigh -> compareBy<ModuleInfo> { it.size }

View File

@@ -0,0 +1,46 @@
package com.rifsxd.ksunext.ui.webui;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import java.util.HashMap;
import java.util.Map;
public class AppIconUtil {
private static final Map<String, Bitmap> iconCache = new HashMap<>();
public static Bitmap loadAppIconSync(Context context, String packageName, int sizePx) {
Bitmap cached = iconCache.get(packageName);
if (cached != null) return cached;
try {
PackageManager pm = context.getPackageManager();
ApplicationInfo appInfo = pm.getApplicationInfo(packageName, 0);
Drawable drawable = pm.getApplicationIcon(appInfo);
Bitmap raw = drawableToBitmap(drawable, sizePx);
Bitmap icon = Bitmap.createScaledBitmap(raw, sizePx, sizePx, true);
iconCache.put(packageName, icon);
return icon;
} catch (Exception e) {
return null;
}
}
private static Bitmap drawableToBitmap(Drawable drawable, int size) {
if (drawable instanceof BitmapDrawable) return ((BitmapDrawable) drawable).getBitmap();
int width = drawable.getIntrinsicWidth() > 0 ? drawable.getIntrinsicWidth() : size;
int height = drawable.getIntrinsicHeight() > 0 ? drawable.getIntrinsicHeight() : size;
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmp);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bmp;
}
}

View File

@@ -96,7 +96,23 @@ class WebUIActivity : ComponentActivity() {
view: WebView,
request: WebResourceRequest
): WebResourceResponse? {
return webViewAssetLoader.shouldInterceptRequest(request.url)
val url = request.url
//POC: Handle ksu://icon/[packageName] to serve app icon via WebView
if (url.scheme.equals("ksu", ignoreCase = true) && url.host.equals("icon", ignoreCase = true)) {
val packageName = url.path?.substring(1)
if (!packageName.isNullOrEmpty()) {
val icon = AppIconUtil.loadAppIconSync(this@WebUIActivity, packageName, 512)
if (icon != null) {
val stream = java.io.ByteArrayOutputStream()
icon.compress(android.graphics.Bitmap.CompressFormat.PNG, 100, stream)
val inputStream = java.io.ByteArrayInputStream(stream.toByteArray())
return WebResourceResponse("image/png", null, inputStream)
}
}
}
return webViewAssetLoader.shouldInterceptRequest(url)
}
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
@@ -119,4 +135,4 @@ class WebUIActivity : ComponentActivity() {
super.onDestroy()
runCatching { rootShell?.close() }
}
}
}

View File

@@ -230,4 +230,9 @@
<string name="home_module_count_singular">وحدة</string>
<string name="home_module_count_plural">وحدات</string>
<string name="module_backup_message">نسخ احتياطي للوحدات المثبتة حالياً.</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_webui_first">Sort (WebUI first)</string>
<string name="settings_global_namespace_mode">Global Namespace Mode</string>
<string name="settings_global_namespace_mode_summary">All root sessions use the global mount namespace</string>
</resources>

View File

@@ -228,4 +228,9 @@
<string name="home_module_count_singular">Модул</string>
<string name="home_module_count_plural">Модули</string>
<string name="module_backup_message">Архивиране на текущо инсталираните модули.</string>
<string name="module_sort_enabled_first">Сортиране (първо активирани)</string>
<string name="module_sort_action_first">Сортиране (първо действие)</string>
<string name="module_sort_webui_first">Сортиране (първо WebUI)</string>
<string name="settings_global_namespace_mode">Режим на глобално пространство от имена</string>
<string name="settings_global_namespace_mode_summary">Всички сесии на root използват глобалното пространство от имена за монтиране</string>
</resources>

View File

@@ -228,4 +228,9 @@
<string name="home_module_count_singular">Module</string>
<string name="home_module_count_plural">Modules</string>
<string name="module_backup_message">Backup currently installed modules.</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_webui_first">Sort (WebUI first)</string>
<string name="settings_global_namespace_mode">Global Namespace Mode</string>
<string name="settings_global_namespace_mode_summary">All root sessions use the global mount namespace</string>
</resources>

View File

@@ -3,7 +3,7 @@
<string name="issue_report_title">Haben Sie Schwierigkeiten?</string>
<string name="issue_report_body">Sind Sie auf einen Fehler gestoßen, oder wollen Sie eine Rückmeldung geben?</string>
<string name="issue_report_body_2">Melden Sie es so schnell wie möglich!</string>
<string name="issue_report_github">Bericht über GitHub</string>
<string name="issue_report_github">Meldung über GitHub</string>
<string name="issue_report_telegram">Kontakt über Telegram</string>
<string name="issue_report_github_link">https://github.com/KernelSU-Next/KernelSU-Next/issues</string>
<string name="issue_report_telegram_link">https://t.me/ksunext</string>
@@ -12,8 +12,8 @@
<string name="home">Hauptseite</string>
<string name="home_not_installed">Nicht installiert</string>
<string name="home_click_to_install">Klicke zum Installieren</string>
<string name="lkm_mode_deprecated">Der LKM -Modus ist jetzt veraltet!</string>
<string name="lkm_alternative_suggestion">Installieren Sie den GKI Kernel oder integrieren Sie KernelSU Next in Ihrem Gerät.</string>
<string name="lkm_mode_deprecated">Der LKM-Modus ist jetzt veraltet!</string>
<string name="lkm_alternative_suggestion">Installieren Sie den GKI-Kernel oder integrieren Sie KernelSU Next in Ihrem Gerät.</string>
<string name="home_working">Funktioniert</string>
<string name="home_working_version">Version: %d</string>
<string name="home_module_update_count">Aktualisierungen: %d</string>
@@ -178,7 +178,7 @@
<string name="settings_check_update">Nach Aktualisierungen suchen</string>
<string name="settings_check_update_summary">Automatische Suche nach Updates beim Öffnen der App</string>
<string name="grant_root_failed">Root-Zugriff konnte nicht gewährt werden!</string>
<string name="action">Aktivität</string>
<string name="action">Aktion</string>
<string name="webui">WebUI</string>
<string name="open">Öffnen</string>
<string name="enable_web_debugging">WebView-Debugging einschalten</string>
@@ -222,10 +222,15 @@
<string name="developer">Entwickler</string>
<string name="sucompat_disabled">SUCOMPAT DEAKTIVIERT</string>
<string name="zygisk_required">Zygisk erforderlich</string>
<string name="zygisk_status">Zygisk Einbindung</string>
<string name="zygisk_status">Zygisk-Einbindung</string>
<string name="home_superuser_count_singular">Superuser</string>
<string name="home_superuser_count_plural">Superusers</string>
<string name="home_module_count_singular">Modul</string>
<string name="home_module_count_plural">Module</string>
<string name="module_backup_message">Sicherung der aktuell installierten Module.</string>
<string name="module_sort_enabled_first">Sortierung (aktivierte zuerst)</string>
<string name="module_sort_action_first">Sortierung (Aktion zuerst)</string>
<string name="module_sort_webui_first">Sortierung (WebUI zuerst)</string>
<string name="settings_global_namespace_mode">Globaler Namensraum-Modus</string>
<string name="settings_global_namespace_mode_summary">Alle Root-Sitzungen verwenden den globalen Mount-Namespace</string>
</resources>

View File

@@ -17,7 +17,7 @@
<string name="home_working">Funcionando</string>
<string name="home_working_version">Versión: %d</string>
<string name="home_module_update_count">Actualizaciones: %d</string>
<string name="home_failure">¡No se encontró la firma de KernelSU Next v2 en el kernel! [ !KSU_NEXT || != size/hash ]</string>
<string name="home_failure">¡Firma v2 de KernelSU Next no encontrada en el kernel! [ !KSU_NEXT || != size/hash ]</string>
<string name="home_failure_tip">¡Pídele a tu desarrollador de kernel que integre KernelSU Next!</string>
<string name="home_kernel">Versión del kernel</string>
<string name="hook_mode">Método de intercepción</string>
@@ -119,7 +119,7 @@
<string name="profile_template">Plantilla</string>
<string name="profile_custom">Personalizado</string>
<string name="profile_name">Nombre de perfil</string>
<string name="profile_namespace">Espacio de nombres de montaje</string>
<string name="profile_namespace">Espacio de montaje aislado</string>
<string name="profile_namespace_inherited">Heredado</string>
<string name="profile_namespace_global">Global</string>
<string name="profile_namespace_individual">Individual</string>
@@ -228,4 +228,9 @@
<string name="home_module_count_singular">Módulo</string>
<string name="home_module_count_plural">Módulos</string>
<string name="module_backup_message">Respaldar los módulos actualmente instalados.</string>
<string name="module_sort_enabled_first">Ordenar (Activados Primero)</string>
<string name="module_sort_action_first">Ordenar (Accionables primero)</string>
<string name="module_sort_webui_first">Ordenar (WrbUI primero)</string>
<string name="settings_global_namespace_mode">Usar el Espacio de Montaje Aislado Global</string>
<string name="settings_global_namespace_mode_summary">Todas las sesiones root usan el espacio de montaje aislado global</string>
</resources>

View File

@@ -229,4 +229,9 @@
<string name="home_module_count_singular">ماژول</string>
<string name="home_module_count_plural">ماژول ها</string>
<string name="module_backup_message">از ماژول‌های نصب‌شده‌ی فعلی پشتیبان تهیه کنید.</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_webui_first">Sort (WebUI first)</string>
<string name="settings_global_namespace_mode">Global Namespace Mode</string>
<string name="settings_global_namespace_mode_summary">All root sessions use the global mount namespace</string>
</resources>

View File

@@ -17,7 +17,7 @@
<string name="home_working">En fonctionnement</string>
<string name="home_working_version">Version : %d</string>
<string name="home_module_update_count">Mises à jour : %d</string>
<string name="home_failure">KernelSU La signature v2 suivante est introuvable dans le noyau! [ !KSU_NEXT || != size/hash ]</string>
<string name="home_failure">La signature suivante de la v2 KernelSU Next est introuvable dans le noyau! [ !KSU_NEXT || != size/hash ]</string>
<string name="home_failure_tip">Demandez à votre développeur de noyau d\'intégrer KernelSU Next !</string>
<string name="home_kernel">Version du noyau</string>
<string name="hook_mode">Méthode d\'interception</string>
@@ -230,4 +230,9 @@
<string name="home_module_count_singular">Module</string>
<string name="home_module_count_plural">Modules</string>
<string name="module_backup_message">Sauvegarder les modules actuellement installés.</string>
<string name="module_sort_enabled_first">Trier (Activé en premier)</string>
<string name="module_sort_action_first">Trier (Action en premier)</string>
<string name="module_sort_webui_first">Trier (WebUI en premier)</string>
<string name="settings_global_namespace_mode">Global Namespace Mode</string>
<string name="settings_global_namespace_mode_summary">All root sessions use the global mount namespace</string>
</resources>

View File

@@ -14,7 +14,7 @@
<string name="home_click_to_install">इंस्टॉल करने के लिए क्लिक करें</string>
<string name="lkm_mode_deprecated">LKM मोड अब अप्रचलित हो गया है!</string>
<string name="lkm_alternative_suggestion">GKI कर्नल अधिष्ठापित करें या KernelSU Next को अपने डिवाइस पर इन्स्टॉल करें।</string>
<string name="home_working">कार्य जारी</string>
<string name="home_working">काम कर रहा है</string>
<string name="home_working_version">वर्जन: %d</string>
<string name="home_module_update_count">अपडेट्स: %d</string>
<string name="home_failure">KernelSU Next v2 सिग्नेचर कर्नेल में नहीं मिला!
@@ -44,10 +44,10 @@
<string name="module_empty">कोई मॉड्यूल इंस्टाल नहीं हुआ |</string>
<string name="module">मॉड्यूल</string>
<string name="module_install_prompt_with_name">निम्नलिखित मॉड्यूल इंस्टाल किए जाएंगे: %1$s</string>
<string name="module_sort_a_to_z">सॉर्ट (A → Z)</string>
<string name="module_sort_z_to_a">सॉर्ट (Z → A)</string>
<string name="module_size_low_to_high">सॉर्ट (Low → High)</string>
<string name="module_size_high_to_low">सॉर्ट (High → Low)</string>
<string name="module_sort_a_to_z">क्रमबद्ध करें (A → Z)</string>
<string name="module_sort_z_to_a">क्रमबद्ध करें (Z → A)</string>
<string name="module_size_low_to_high">क्रमबद्ध करें (न्यूनतम → उच्चतम)</string>
<string name="module_size_high_to_low">क्रमबद्ध करें (उच्चतम → न्यूनतम)</string>
<string name="uninstall">अनइंस्टॉल करें</string>
<string name="restore">पहले जैसा करें</string>
<string name="module_install">इंस्टॉल करें</string>
@@ -90,7 +90,7 @@
<string name="use_overlay_fs">OverlayFS का उपयोग करें</string>
<string name="use_overlay_fs_summary">Toggle between using OverlayFS over Magic Mount for KernelSU Next\'s mount system.</string>
<string name="reboot_required">रिबूट करना जरूरी है!</string>
<string name="reboot_message">The changes will take effect after the system restart. Do you want to reboot now?</string>
<string name="reboot_message">सिस्टम रीस्टार्ट के बाद यह परिवर्तन प्रभावी होगा। क्या आप अभी रीबूट करना चाहते हैं?</string>
<string name="module_restore">Restore module</string>
<string name="module_restore_message">Restore modules from recent backup.</string>
<string name="backup_restore">बैकअप &amp; रिस्टोर</string>
@@ -108,7 +108,7 @@
<string name="home_next_kernelsu">🔥 Next build</string>
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
<string name="home_next_kernelsu_body">Next experimental branch. Check it out on GitHub!</string>
<string name="home_experimental_kernelsu">⚠️ Experimental development warning!</string>
<string name="home_experimental_kernelsu">⚠️ प्रायोगिक विकास की चेतावनी!</string>
<string name="home_experimental_kernelsu_repo">127.0.0.1</string>
<string name="home_experimental_kernelsu_body">KernelSU Next एक गैर-आधिकारिक संस्करण है जो हमेशा सक्रिय प्रयोगात्मक विकास के अंतर्गत रहता है। इसे वैसे ही उपलब्ध कराया जाता है, जिसमें स्थिरता, प्रदर्शन या विश्वसनीयता की कोई गारंटी नहीं होती।</string>
<string name="home_experimental_kernelsu_body_point_1"> • अपने जोखिम पर उपयोग करें: क्रैश, अप्रत्याशित व्यवहार या सिस्टम समस्याएं हो सकती हैं।</string>
@@ -126,13 +126,14 @@
<string name="profile_namespace_individual">विशिष्ट</string>
<string name="profile_groups">ग्रुप्स</string>
<string name="profile_capabilities">क्षमताएं</string>
<string name="profile_selinux_context">SELinux context</string>
<string name="profile_selinux_context">SELinux कॉन्टेक्स्ट</string>
<string name="profile_umount_modules">मॉड्यूल्स यूमाउंट करें</string>
<string name="failed_to_update_app_profile">%s के लिए ऐप प्रोफ़ाइल अपडेट करने में विफल</string>
<string name="require_kernel_version">मैनेजर के ठीक से काम करने के लिए वर्तमान KernelSU Next वर्जन %1$d बहुत कम है। कृपया वर्जन %2$d या उच्चतर में अपग्रेड करें!</string>
<string name="settings_umount_modules_default">मॉड्यूल्स यूमाउंट करें</string>
<string name="settings_umount_modules_default_summary">ऐप प्रोफाइल में \"अनमाउंट मॉड्यूल\" के लिए ग्लोबल डिफ़ॉल्ट वैल्यू। यदि चालू किया गया है, तो यह एप्लीकेशंस के लिऐ सिस्टम के सभी मॉड्यूल मोडिफिकेशन को हटा देगा जिनकी प्रोफ़ाइल सेट नहीं है।</string>
<string name="settings_susfs_toggle">Hide kprobes hook</string>
<string name="settings_susfs_toggle">Kprobes हुक को छिपाएं
</string>
<string name="settings_susfs_toggle_summary">यह विकल्प KSU द्वारा निर्मित kprobes हुक को निष्क्रिय कर देता है, तथा इसके स्थान पर एम्बेडेड non-kprobes हुक को सक्रिय कर देता है, तथा उसी कार्यक्षमता को क्रियान्वित करता है जो non-GKI कर्नल पर लागू होती है, जो kprobe का समर्थन नहीं करता है।</string>
<string name="profile_umount_modules_summary">इस विकल्प को चालू करने से KernelSU Next इस एप्लिकेशन के लिए मॉड्यूल द्वारा किसी भी मोडिफाइड फ़ाइल को रिस्टोर कर सकता है।</string>
<string name="profile_selinux_domain">डोमेन</string>
@@ -147,67 +148,67 @@
<string name="close">बंद</string>
<string name="force_stop_app">ज़बरदस्ती रोकें</string>
<string name="restart_app">रिस्टार्ट करें</string>
<string name="settings_amoled_mode">AMOLED mode</string>
<string name="settings_amoled_mode">AMOLED मोड</string>
<string name="settings_amoled_mode_summary">आंखों पर पड़ने वाले तनाव को कम करने और बैटरी बचाने के लिए AMOLED स्क्रीन के लिए उपयोगी काले रंग की थीम को सक्षम करें।</string>
<string name="restart_required">पुनः आरंभ की आवश्यकता है</string>
<string name="restart_app_message">The app needs to restart for this change to take effect.</string>
<string name="restart_app_message">इस बदलाव के लिए ऐप को दोबारा शुरू करना होगा।</string>
<string name="failed_to_update_sepolicy">%s के लिए SELinux नियमों को अपटेड करने में विफल</string>
<string name="su_not_allowed">%s को सुपरयूज़र एक्सेस नहीं दिया जा सका</string>
<string name="module_changelog">चेंजलॉग</string>
<string name="settings_profile_template">App Profile template</string>
<string name="settings_profile_template_summary">Manage local and online template of App Profile</string>
<string name="settings_profile_template">ऐप प्रोफ़ाइल नमूना</string>
<string name="settings_profile_template_summary">ऐप प्रोफ़ाइल के स्थानीय और ऑनलाइन नमूनों का प्रबंधन करें</string>
<string name="app_profile_template_create">नया टेम्प्लेट बनाएं</string>
<string name="app_profile_template_edit">टेम्पलेट एडिट करें</string>
<string name="app_profile_template_id">आइडी</string>
<string name="app_profile_template_id_invalid">Invalid template ID</string>
<string name="app_profile_template_id_invalid">अमान्य नमूना ID</string>
<string name="app_profile_template_name">नाम</string>
<string name="app_profile_template_description">विवरण</string>
<string name="app_profile_template_save">सेव</string>
<string name="app_profile_template_delete">डिलीट</string>
<string name="app_profile_template_view">View template</string>
<string name="app_profile_template_view">नमूना देखें</string>
<string name="app_profile_template_readonly">केवल पढ़ने के लिए</string>
<string name="app_profile_template_id_exist">Template ID already exists!</string>
<string name="app_profile_template_id_exist">नमूना ID पहले से मौजूद है!</string>
<string name="app_profile_import_export">आयात/निर्यात</string>
<string name="app_profile_import_from_clipboard">क्लिपबोर्ड से इम्पोर्ट करें</string>
<string name="app_profile_export_to_clipboard">क्लिपबोर्ड को निर्यात करें</string>
<string name="app_profile_template_export_empty">Cannot find local template to export!</string>
<string name="app_profile_template_export_empty">एक्सपोर्ट करने के लिए कोई स्थानीय नमूना नहीं मिला!</string>
<string name="app_profile_template_import_success">सफलतापूर्वक आयात किया गया</string>
<string name="app_profile_template_sync">Sync online templates</string>
<string name="app_profile_template_save_failed">Failed to save template</string>
<string name="app_profile_template_sync">ऑनलाइन नमूने सिंक करें</string>
<string name="app_profile_template_save_failed">नमूना सहेजने में विफल रहा</string>
<string name="app_profile_template_import_empty">क्लिपबोर्ड खाली है!</string>
<string name="module_changelog_failed">Fetch changelog failed: %s</string>
<string name="settings_check_update">अपडेट के लिए चेक करें</string>
<string name="settings_check_update_summary">Automatically check for updates when opening the app</string>
<string name="grant_root_failed">Failed to grant root!</string>
<string name="settings_check_update_summary">ऐप खोलने पर अपने आप अपडेट जांचें</string>
<string name="grant_root_failed">रूट एक्सेस देने में विफल!</string>
<string name="action">एक्शन</string>
<string name="webui">WebUI</string>
<string name="open">खोलें</string>
<string name="enable_web_debugging">Enable WebView debugging</string>
<string name="enable_web_debugging"></string>
<string name="enable_web_debugging_summary">Can be used to debug WebUI. Please enable only when needed.</string>
<string name="direct_install">Direct install (Recommended)</string>
<string name="direct_install">सीधा इंस्टॉल करें (सिफारिश की जाती है)</string>
<string name="select_file">फाइल चुनें</string>
<string name="install_inactive_slot">Install to inactive slot (After OTA)</string>
<string name="install_inactive_slot">निष्क्रिय स्लॉट में इंस्टॉल करें (OTA के बाद)</string>
<string name="install_inactive_slot_warning">Your device will be **FORCED** to boot to the current inactive slot after a reboot!\nOnly use this option after OTA is done.\nContinue?</string>
<string name="install_next">अगला</string>
<string name="select_file_tip">%1$s partition image is recommended</string>
<string name="select_kmi">Select KMI</string>
<string name="select_file_tip">%1$s partition image की सिफारिश की जाती है</string>
<string name="select_kmi">KMI चुनें</string>
<string name="shrink_sparse_image">Minimize sparse image</string>
<string name="shrink_sparse_image_message">Resize the sparse image where the module is located to its actual size. Note that this may cause the module to work abnormally, so please only use when necessary (Such as for backup).</string>
<string name="settings_uninstall">अनइंस्टॉल करें</string>
<string name="settings_uninstall_temporary">Uninstall temporarily</string>
<string name="settings_uninstall_permanent">Uninstall permanently</string>
<string name="settings_uninstall_temporary">कुछ समय के लिए हटाएं</string>
<string name="settings_uninstall_permanent">हमेशा के लिए हटाएं</string>
<string name="settings_restore_stock_image">Restore stock image</string>
<string name="settings_uninstall_temporary_message">Temporarily uninstall KernelSU Next, restore to original state after next reboot.</string>
<string name="settings_uninstall_permanent_message">Uninstalling KernelSU Next (Root and all modules) completely and permanently.</string>
<string name="settings_uninstall_temporary_message">KernelSU Next को अभी के लिए हटाया जाएगा, अगली बार डिवाइस चालू होने पर यह वापस आ जाएगा।</string>
<string name="settings_uninstall_permanent_message">KernelSU Next को रूट और सभी मॉड्यूल के साथ पूरी तरह से हमेशा के लिए हटाया जा रहा है।</string>
<string name="settings_restore_stock_image_message">Restore the stock factory image (If a backup exists), usually used before OTA; if you need to uninstall KernelSU Next, please use \"Uninstall permanently\".</string>
<string name="flashing">फ़्लैश हो रहा है</string>
<string name="flash_success">Flash success</string>
<string name="flash_failed">Flash failed</string>
<string name="selected_lkm">Selected LKM: %s</string>
<string name="flash_success">फ्लैश सफल रहा</string>
<string name="flash_failed">फ्लैश असफल रहा</string>
<string name="selected_lkm">चुना गया LKM: %s</string>
<string name="save_log">लॉग सहेजें</string>
<string name="log_saved">Logs saved</string>
<string name="send_log">लॉग शेयर करें</string>
<string name="settings_disable_su">Disable su compatibility</string>
<string name="settings_disable_su">SU compatibility अस्थायी रूप से बंद करें</string>
<string name="settings_disable_su_summary">Temporarily disable the ability of any app to gain root privileges via the su command (Existing root processes won\'t be affected).</string>
<string name="settings_language">भाषा</string>
<string name="system_default">सिस्टम डिफ़ॉल्ट</string>
@@ -215,7 +216,7 @@
<string name="settings_legacyui_summary">Switch to the previous user interface style.</string>
<string name="settings_banner">Enable banners</string>
<string name="settings_banner_summary">Show background banners for modules.</string>
<string name="use_webuix">Use WebUI X</string>
<string name="use_webuix">WebUI X का उपयोग करें</string>
<string name="use_webuix_summary">WebUI के बजाय WebUI X का उपयोग करें, जो अधिक API का समर्थन करता है।</string>
<string name="use_webuix_eruda">Eruda को WebUI X में इंजेक्ट करें</string>
<string name="use_webuix_eruda_summary">डीबगिंग को आसान बनाने के लिए WebUI X में डीबग कंसोल इंजेक्ट करें। वेब डीबगिंग चालू होना आवश्यक है।</string>
@@ -223,10 +224,15 @@
<string name="developer">डेवलपर</string>
<string name="sucompat_disabled">SUCOMPAT DISABLED</string>
<string name="zygisk_required">Zygisk आवश्यक है!</string>
<string name="zygisk_status">Zygisk injection</string>
<string name="zygisk_status">Zygisk इंजेक्शन</string>
<string name="home_superuser_count_singular">सुपरयूजर</string>
<string name="home_superuser_count_plural">सुपरयूजरस</string>
<string name="home_module_count_singular">मॉड्यूल</string>
<string name="home_module_count_plural">मॉड्यूलस</string>
<string name="module_backup_message">Backup currently installed modules.</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_webui_first">Sort (WebUI first)</string>
<string name="settings_global_namespace_mode">Global Namespace Mode</string>
<string name="settings_global_namespace_mode_summary">All root sessions use the global mount namespace</string>
</resources>

View File

@@ -228,4 +228,9 @@
<string name="home_module_count_singular">Module</string>
<string name="home_module_count_plural">Modules</string>
<string name="module_backup_message">Backup currently installed modules.</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_webui_first">Sort (WebUI first)</string>
<string name="settings_global_namespace_mode">Global Namespace Mode</string>
<string name="settings_global_namespace_mode_summary">All root sessions use the global mount namespace</string>
</resources>

View File

@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="issue_report_title">Ada kendala?</string>
<string name="issue_report_body">Menemukan bug atau memiliki umpan balik?</string>
<string name="issue_report_body_2">Laporkan sesegera mungkin!</string>
<string name="issue_report_title">Memiliki kendala?</string>
<string name="issue_report_body">Mengalami kesalahan atau memiliki umpan balik?</string>
<string name="issue_report_body_2">Laporkan secepatnya!</string>
<string name="issue_report_github">Laporkan di GitHub</string>
<string name="issue_report_telegram">Hubungi melalui Telegram</string>
<string name="issue_report_github_link">https://github.com/KernelSU-Next/KernelSU-Next/issues</string>
<string name="issue_report_telegram_link">https://t.me/ksunext</string>
<string name="confirm">Konfirmasi</string>
<string name="confirm">Ya</string>
<string name="app_name">KernelSU Next</string>
<string name="home">Beranda</string>
<string name="home_not_installed">Tidak terpasang</string>
<string name="home_click_to_install">Klik untuk memasang</string>
<string name="home_not_installed">Tidak terinstal</string>
<string name="home_click_to_install">Klik untuk menginstal</string>
<string name="lkm_mode_deprecated">Mode LKM sekarang sudah tidak digunakan lagi!</string>
<string name="lkm_alternative_suggestion">Pasang kernel GKI atau integrasikan KernelSU Next ke perangkat anda.</string>
<string name="home_working">Berfungsi</string>
@@ -30,9 +30,9 @@
<string name="home_susfs_version">Versi SuSFS</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_android">Versi android</string>
<string name="home_manager_version">Versi manager</string>
<string name="home_manager_version">Versi manajer</string>
<string name="home_abi">ABI</string>
<string name="home_selinux_status">Status SElinux</string>
<string name="home_selinux_status">SELinux status</string>
<string name="selinux_status_disabled">Nonaktif</string>
<string name="selinux_status_enforcing">Enforcing</string>
<string name="selinux_status_permissive">Permissive</string>
@@ -42,7 +42,7 @@
<string name="module_failed_to_disable">Gagal menonaktifkan modul: %s</string>
<string name="module_empty">Tidak ada modul yang terpasang</string>
<string name="module">Modul</string>
<string name="module_install_prompt_with_name">Modul berikut akan dipasang: %1$s</string>
<string name="module_install_prompt_with_name">Modul yang akan diinstal: %1$s</string>
<string name="module_sort_a_to_z">Urutkan (A → Z)</string>
<string name="module_sort_z_to_a">Urutkan (Z → A)</string>
<string name="module_size_low_to_high">Urutkan (Kecil → Besar)</string>
@@ -229,4 +229,9 @@
<string name="home_module_count_singular">Modul</string>
<string name="home_module_count_plural">Modul</string>
<string name="module_backup_message">Cadangkan modul yang terinstal saat ini.</string>
<string name="module_sort_enabled_first">Urutkan (Diaktifkan lebih dulu)</string>
<string name="module_sort_action_first">Urutkan (Aksi lebih dulu)</string>
<string name="module_sort_webui_first">Urutkan (WebUI lebih dulu)</string>
<string name="settings_global_namespace_mode">Mode Namespace Universal</string>
<string name="settings_global_namespace_mode_summary">Semua sesi root menggunakan mount namespace universal</string>
</resources>

View File

@@ -9,7 +9,7 @@
<string name="issue_report_telegram_link">https://t.me/ksunext</string>
<string name="confirm">Conferma</string>
<string name="app_name">KernelSU Next</string>
<string name="home">Casa</string>
<string name="home">Home</string>
<string name="home_not_installed">Non installato</string>
<string name="home_click_to_install">Clicca per installare</string>
<string name="lkm_mode_deprecated">La modalità LKM è ora obsoleta!</string>
@@ -17,10 +17,10 @@
<string name="home_working">In esecuzione</string>
<string name="home_working_version">Versione: %d</string>
<string name="home_module_update_count">Aggiornamenti: %d</string>
<string name="home_failure">KernelSU Next firma v2 non trovata nel kernel! [ !KSU_NEXT || != size/hash ]</string>
<string name="home_failure">Firma v2 di KernelSU Next non trovata nel kernel! [ !KSU_NEXT || != size/hash ]</string>
<string name="home_failure_tip">Chiedi allo sviluppatore del kernel d\'integrare KernelSU Next!</string>
<string name="home_kernel">Versione kernel</string>
<string name="hook_mode">Modalità Hook</string>
<string name="hook_mode">Modalità hook</string>
<string name="enable">Abilita</string>
<string name="disable">Disabilita</string>
<string name="enabled">Abilitato</string>
@@ -30,14 +30,14 @@
<string name="home_susfs_version">Versione SuSFS</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_android">Versione Android</string>
<string name="home_manager_version">Versione Manager</string>
<string name="home_manager_version">Versione manager</string>
<string name="home_abi">ABI</string>
<string name="home_selinux_status">Stato SELinux</string>
<string name="selinux_status_disabled">Disabilitato</string>
<string name="selinux_status_enforcing">Enforcing</string>
<string name="selinux_status_permissive">Permissive</string>
<string name="selinux_status_unknown">Sconosciuto</string>
<string name="superuser">Superutente</string>
<string name="superuser">Accesso root</string>
<string name="module_failed_to_enable">Impossibile abilitare il modulo: %s</string>
<string name="module_failed_to_disable">Impossibile disabilitare il modulo: %s</string>
<string name="module_empty">Nessun modulo installato</string>
@@ -103,7 +103,7 @@
<string name="proceed">Procedi</string>
<string name="cancel">Annulla</string>
<string name="later">Più tardi</string>
<string name="lkm_warning_message">La patch LKM si basa su codici vuoi continuare?</string>
<string name="lkm_warning_message">La patch LKM si basa su componenti closed source. Vuoi continuare?</string>
<string name="home_next_kernelsu">🔥 Prossima build</string>
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
<string name="home_next_kernelsu_body">Prossimo branch sperimentale. Provalo su GitHub!</string>
@@ -176,8 +176,8 @@
<string name="app_profile_template_import_empty">Gli appunti sono vuoti!</string>
<string name="module_changelog_failed">Recupero del changelog non riuscito: %s</string>
<string name="settings_check_update">Controlla aggiornamenti</string>
<string name="settings_check_update_summary">Cerca automaticamente gli aggiornamenti all\'apertura dell\'applicazione.</string>
<string name="grant_root_failed">Impossibile concedere i permessi root! </string>
<string name="settings_check_update_summary">Cerca automaticamente gli aggiornamenti all\'apertura dell\'applicazione</string>
<string name="grant_root_failed">Impossibile concedere i permessi root!</string>
<string name="action">Azione</string>
<string name="webui">WebUI</string>
<string name="open">Apri</string>
@@ -187,7 +187,7 @@
<string name="select_file">Seleziona un file</string>
<string name="install_inactive_slot">Installa nello slot inattivo (dopo un aggiornamento OTA)</string>
<string name="install_inactive_slot_warning">Dopo il riavvio, il dispositivo sarà FORZATO ad avviarsi nello slot attualmente inattivo!\nUtilizza questa opzione solo dopo aver completato l\'aggiornamento OTA.\nVuoi continuare?</string>
<string name="install_next"></string>
<string name="install_next">Next</string>
<string name="select_file_tip">Immagine partizione %1$s consigliata</string>
<string name="select_kmi">Seleziona KMI</string>
<string name="shrink_sparse_image">Minimizza l\'immagine sparsa</string>
@@ -207,7 +207,7 @@
<string name="log_saved">Log salvati</string>
<string name="send_log">Condividi i log</string>
<string name="settings_disable_su">Disattiva la compatibilità su</string>
<string name="settings_disable_su_summary">Disattiva temporaneamente la capacità di ogni applicazione di ottenere i permessi di root tramite il comando su (le sessioni di root esistenti non subiranno modifiche).</string>
<string name="settings_disable_su_summary">Disattiva temporaneamente la capacità di ogni applicazione di ottenere i permessi root tramite il comando su (le sessioni di root esistenti non subiranno modifiche).</string>
<string name="settings_language">Lingua</string>
<string name="system_default">Default di sistema</string>
<string name="settings_legacyui">Usa lo stile d\'interfaccia precedente</string>
@@ -223,9 +223,14 @@
<string name="sucompat_disabled">SUCOMPAT DISABILITATO</string>
<string name="zygisk_required">Zygisk richiesto</string>
<string name="zygisk_status">Iniezione Zygisk</string>
<string name="home_superuser_count_singular">Superutente</string>
<string name="home_superuser_count_plural">Superutenti</string>
<string name="home_superuser_count_singular">Accesso root</string>
<string name="home_superuser_count_plural">Accessi root</string>
<string name="home_module_count_singular">Modulo</string>
<string name="home_module_count_plural">Moduli</string>
<string name="module_backup_message">Esegue il backup dei moduli attualmente esistenti.</string>
<string name="module_sort_enabled_first">Ordina (prima Abilitato)</string>
<string name="module_sort_action_first">Ordina (prima Azione)</string>
<string name="module_sort_webui_first">Ordina (prima WebUI)</string>
<string name="settings_global_namespace_mode">Modalità Namespace globale</string>
<string name="settings_global_namespace_mode_summary">Tutte le sessioni root usano lo spazio di montaggio globale</string>
</resources>

View File

@@ -228,4 +228,9 @@
<string name="home_module_count_singular">モジュール</string>
<string name="home_module_count_plural">モジュール</string>
<string name="module_backup_message">現在インストールされているモジュールをバックアップします。</string>
<string name="module_sort_enabled_first">並べ替え (有効を優先)</string>
<string name="module_sort_action_first">並べ替え (実行可能を優先)</string>
<string name="module_sort_webui_first">並べ替え (WebUIを優先)</string>
<string name="settings_global_namespace_mode">グローバル名前空間モード</string>
<string name="settings_global_namespace_mode_summary">すべての root セッションがグローバルマウント名前空間を使用します</string>
</resources>

View File

@@ -228,4 +228,9 @@
<string name="home_module_count_singular">모듈</string>
<string name="home_module_count_plural">모듈</string>
<string name="module_backup_message">현재 설치된 모듈을 백업</string>
<string name="module_sort_enabled_first">정렬 (활성화됨 우선)</string>
<string name="module_sort_action_first">정렬 (동작 우선)</string>
<string name="module_sort_webui_first">정렬 (WebUI 우선)</string>
<string name="settings_global_namespace_mode">Global Namespace Mode</string>
<string name="settings_global_namespace_mode_summary">All root sessions use the global mount namespace</string>
</resources>

View File

@@ -45,8 +45,8 @@
<string name="module_install_prompt_with_name">Następujące moduły zostaną zainstalowane: %1$s</string>
<string name="module_sort_a_to_z">Sortuj (A → Z)</string>
<string name="module_sort_z_to_a">Sortuj (Z → A)</string>
<string name="module_size_low_to_high">Sortuj (Najmniejszy → Największy)</string>
<string name="module_size_high_to_low">Sortuj (Największy → Najmniejszy)</string>
<string name="module_size_low_to_high">Sortuj (Małe → Duże)</string>
<string name="module_size_high_to_low">Sortuj (Duże → Małe)</string>
<string name="uninstall">Odinstaluj</string>
<string name="restore">Przywróć</string>
<string name="module_install">Zainstaluj</string>
@@ -216,16 +216,21 @@
<string name="settings_banner_summary">Wyświetlaj banery modułów w tle.</string>
<string name="use_webuix">Używaj WebUI X</string>
<string name="use_webuix_summary">Używaj WebUI X zamiast WebUI, który obsługuje więcej interfejsów API.</string>
<string name="use_webuix_eruda">Wstrzyknij Eruda do WebUI X</string>
<string name="use_webuix_eruda">Wstrzykiwanie Eruda do WebUI X</string>
<string name="use_webuix_eruda_summary">Wstrzyknij konsolę debugowania do WebUI X, aby ułatwić debugowanie. Wymagane jest aktywne debugowanie WebView.</string>
<string name="customization">Personalizacja</string>
<string name="developer">Programista</string>
<string name="sucompat_disabled">SUCOMPAT NIEAKTYWNY</string>
<string name="zygisk_required">Wymagany Zygisk</string>
<string name="zygisk_status">Wstrzyknięcie Zygisk</string>
<string name="zygisk_status">Wstrzykiwanie Zygisk</string>
<string name="home_superuser_count_singular">Superuser</string>
<string name="home_superuser_count_plural">Superuserzy</string>
<string name="home_module_count_singular">Moduł</string>
<string name="home_module_count_plural">Moduły</string>
<string name="module_backup_message">Utwórz kopię zapasową obecnie zainstalowanych modułów.</string>
<string name="module_sort_enabled_first">Sortuj (najpierw włączone)</string>
<string name="module_sort_action_first">Sortuj (najpierw z Akcją)</string>
<string name="module_sort_webui_first">Sortuj (najpierw z WebUI)</string>
<string name="settings_global_namespace_mode">Tryb globalnej przestrzeni nazw</string>
<string name="settings_global_namespace_mode_summary">Wszystkie sesje roota używają globalnej przestrzeni nazw montowania</string>
</resources>

View File

@@ -1,157 +1,156 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="issue_report_title">Está com problema?</string>
<string name="issue_report_body">Encontrou algum bug ou tem algum feedback?</string>
<string name="issue_report_body_2">Relate o mais rápido possível</string>
<string name="issue_report_github">Enviei um relatório no Github</string>
<string name="issue_report_telegram">Contato via telegram</string>
<string name="issue_report_title">Precisa de ajuda?</string>
<string name="issue_report_body">Encontrou uma falha ou tem alguma sugestão?</string>
<string name="issue_report_body_2">Reporte o mais rápido possível!</string>
<string name="issue_report_github">Reportar no GitHub</string>
<string name="issue_report_telegram">Contato via Telegram</string>
<string name="issue_report_github_link">https://github.com/KernelSU-Next/KernelSU-Next/issues</string>
<string name="issue_report_telegram_link">https://t.me/ksunext</string>
<string name="confirm">Confirmar</string>
<string name="app_name">KernelSU Next</string>
<string name="home">Início</string>
<string name="home">KSU</string>
<string name="home_not_installed">Não instalado</string>
<string name="home_click_to_install">Clique para instalar</string>
<string name="lkm_mode_deprecated">O modo LKM está agora obsoleto!</string>
<string name="lkm_mode_deprecated">O modo LKM agora está obsoleto!</string>
<string name="lkm_alternative_suggestion">Instale o kernel GKI ou integre o KernelSU Next ao seu dispositivo.</string>
<string name="home_working">Rodando</string>
<string name="home_working_version">Versão</string>
<string name="home_module_update_count">Atualizações</string>
<string name="home_failure">Assinatura do KernelSU Next v2 não encontrada no kernel! [ !KSU_NEXT || tamanho/hash diferente ]</string>
<string name="home_failure_tip">Peça ao seu desenvolvedor de kernel para integrar o KernelSU Next! </string>
<string name="home_working">Em execução</string>
<string name="home_working_version">Versão: %d</string>
<string name="home_module_update_count">Atualizações: %d</string>
<string name="home_failure">Assinatura KernelSU Next v2 não encontrada no kernel! [!KSU_NEXT || != size/hash]</string>
<string name="home_failure_tip">Peça ao seu desenvolvedor de kernel para integrar o KernelSU Next!</string>
<string name="home_kernel">Versão do kernel</string>
<string name="hook_mode">Modo hook</string>
<string name="enable">Habilitar</string>
<string name="disable">Desabilitado</string>
<string name="enabled">Habilitado </string>
<string name="disabled">Desabilitando</string>
<string name="hook_mode">Modo do hook</string>
<string name="enable">Ativar</string>
<string name="disable">Desativar</string>
<string name="enabled">Ativado</string>
<string name="disabled">Desativado</string>
<string name="susfs_supported">Suportado</string>
<string name="home_susfs">SuSFS</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">Versão do SuSFS</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_android">Versão do Android</string>
<string name="home_manager_version">Versão do gerenciador</string>
<string name="home_abi">ABI</string>
<string name="home_selinux_status">SELinux status</string>
<string name="selinux_status_disabled">Desabilitado</string>
<string name="home_selinux_status">Status do SELinux</string>
<string name="selinux_status_disabled">Desativado</string>
<string name="selinux_status_enforcing">Impondo</string>
<string name="selinux_status_permissive">Permissivo</string>
<string name="selinux_status_unknown">Desconhecido</string>
<string name="superuser">Superusuário</string>
<string name="module_failed_to_enable">Falha a o habilitar modulo</string>
<string name="module_failed_to_disable">Falha a o desabilitar modulo</string>
<string name="module_empty">Nenhum modulo instalado</string>
<string name="module">Mudulo</string>
<string name="module_install_prompt_with_name">Os seguintes módulos serão instalado</string>
<string name="superuser">SuperUsuário</string>
<string name="module_failed_to_enable">Não foi possível ativar o módulo %s</string>
<string name="module_failed_to_disable">Não foi possível desativar o módulo %s</string>
<string name="module_empty">Nenhum módulo instalado</string>
<string name="module">Módulos</string>
<string name="module_install_prompt_with_name">Os seguintes módulos serão instalados: %1$s</string>
<string name="module_sort_a_to_z">Ordenar (A → Z)</string>
<string name="module_sort_z_to_a">Ordenar (Z → A)</string>
<string name="module_size_low_to_high">Ordenar (baixo → cima)</string>
<string name="module_size_high_to_low">Ordenar (Cima → baixo)</string>
<string name="module_sort_z_to_a">Organizar (Z → A)</string>
<string name="module_size_low_to_high">Organizar (Menor → Maior)</string>
<string name="module_size_high_to_low">Ordenar (Maior → Menor)</string>
<string name="uninstall">Desinstalar</string>
<string name="restore">Restaurar</string>
<string name="module_install">Desinstalar</string>
<string name="module_install">Instalar</string>
<string name="install">Instalar</string>
<string name="reboot">Reiniciar</string>
<string name="uninstalled">Desinstalado</string>
<string name="settings">Configurações</string>
<string name="settings">Ajustes</string>
<string name="reboot_userspace">Reiniciar</string>
<string name="reboot_recovery">Reiniciar em modo recovery</string>
<string name="reboot_bootloader">Reiniciar em modo bootloader</string>
<string name="reboot_download">Reiniciar em modo download</string>
<string name="reboot_recovery">Reiniciar em modo Recovery</string>
<string name="reboot_bootloader">Reiniciar em modo Bootloader</string>
<string name="reboot_download">Reiniciar em modo Download</string>
<string name="reboot_edl">Reiniciar em modo EDL</string>
<string name="about">Sobre</string>
<string name="module_uninstall_confirm">Tem certeza que deseja desinstalar o módulo?</string>
<string name="module_uninstall_success">Desinstalado</string>
<string name="module_uninstall_failed">Falha a o desinstalar</string>
<string name="module_restore_confirm">Tem certeza que deseja restaurar o módulo?</string>
<string name="module_restore_success">Restaurado</string>
<string name="module_restore_failed">Falha ao restaurar</string>
<string name="module_uninstall_confirm">Tem certeza que deseja desinstalar o módulo %s?</string>
<string name="module_uninstall_success">%s desinstalado</string>
<string name="module_uninstall_failed">Falha ao desinstalar %s</string>
<string name="module_restore_confirm">Tem certeza que deseja restaurar o módulo %s?</string>
<string name="module_restore_success">%s restaurado</string>
<string name="module_restore_failed">Falha ao restaurar %s</string>
<string name="module_version">Versão</string>
<string name="module_author">Autor</string>
<string name="module_id">ID</string>
<string name="module_version_code">Código</string>
<string name="module_update_json">AtualizarJson</string>
<string name="module_update_json">UpdateJson</string>
<string name="module_update_json_empty">Vazio</string>
<string name="enable_developer_options">Habilitar opções do desenvolvedor</string>
<string name="enable_developer_options_summary">Mostrar configurações ocultas e informações de debug relevantes apena para desenvolvedores.</string>
<string name="module_overlay_fs_not_available">Os módulos não estão disponíveis porque o OverlayFS está desabilitado pelo kernel!</string>
<string name="enable_developer_options">Ativar opções do desenvolvedor</string>
<string name="enable_developer_options_summary">Exibe ajustes ocultos e informações de depuração relevantes apenas para desenvolvedores.</string>
<string name="module_overlay_fs_not_available">Os módulos estão indisponíveis porque OverlayFS está desabilitado pelo kernel!</string>
<string name="refresh">Atualizar</string>
<string name="show_system_apps">Mostrar aplicativos do sistema</string>
<string name="hide_system_apps">Ocultar aplicativos do sistema</string>
<string name="export_log">Exportar logs</string>
<string name="safe_mode">Modo seguro</string>
<string name="reboot_to_apply">Reinicie para aplicar as alterações</string>
<string name="module_magisk_conflict">Os módulos não estão disponíveis devido a um conflito com o Magisk!</string>
<string name="home_mount_system">Montagem sistema</string>
<string name="home_magic_mount">Montagem magisk</string>
<string name="show_system_apps">Mostrar apps do sistema</string>
<string name="hide_system_apps">Ocultar apps do sistema</string>
<string name="export_log">Exportar registros</string>
<string name="safe_mode">Modo de segurança</string>
<string name="reboot_to_apply">Reinicie para entrar em vigor</string>
<string name="module_magisk_conflict">Os módulos estão indisponíveis devido a um conflito com Magisk!</string>
<string name="home_mount_system">Sistema de montagem</string>
<string name="home_magic_mount">Magic Mount</string>
<string name="home_overlayfs_mount">OverlayFS</string>
<string name="unavailable">Indisponível</string>
<string name="use_overlay_fs">Usar OverlayFS</string>
<string name="use_overlay_fs_summary">Alternar entre usar OverlayFS ou montar magisk no sistema de montagem do KernelSU Next.</string>
<string name="reboot_required">Requer reinicialização</string>
<string name="reboot_message">As mudanças serão aplicadas após reinicialização. Quer reiniciar agora?</string>
<string name="use_overlay_fs_summary">Alterne entre usar OverlayFS sobre Magic Mount para o sistema de montagem do KernelSU Next.</string>
<string name="reboot_required">Reinicialização necessária</string>
<string name="reboot_message">As alterações entrarão em vigor após a reinicialização do sistema. Deseja reiniciar agora?</string>
<string name="module_restore">Restaurar módulo</string>
<string name="module_restore_message">Restaurar módulos do backup recente.</string>
<string name="backup_restore">Backup e restaure</string>
<string name="module_backup">Backup módulo</string>
<string name="allowlist_restore">Restaurar lista de permissão</string>
<string name="allowlist_restore_message">Restaurar permissões do backup recente.</string>
<string name="allowlist_backup">Backup de permissões</string>
<string name="allowlist_backup_message">Fazer backup da lista de permissões atual.</string>
<string name="warning">Perigo</string>
<string name="warning_message">Este recurso ainda está em beta e em desenvolvimento. Certifique-se de fazer backup dos seus módulos antes de prosseguir. Use este recurso somente se você compreender os riscos potenciais.
Prossiga com cautela.</string>
<string name="module_restore_message">Restaure os módulos de um backup recente.</string>
<string name="backup_restore">Backup e restauração</string>
<string name="module_backup">Backup do módulo</string>
<string name="allowlist_restore">Restaurar lista de permissões</string>
<string name="allowlist_restore_message">Restaure a lista de permissões de um backup recente.</string>
<string name="allowlist_backup">Backup da lista de permissões</string>
<string name="allowlist_backup_message">Faça backup da lista de permissões atual.</string>
<string name="warning">Aviso</string>
<string name="warning_message">Este recurso ainda está em beta e em desenvolvimento. Certifique-se de fazer backup de seus módulos antes de continuar. Use esse recurso somente se você compreender os riscos potenciais. Proceda com cautela.</string>
<string name="proceed">Prosseguir</string>
<string name="cancel">Cancelar</string>
<string name="later">Depois</string>
<string name="later">Mais tarde</string>
<string name="lkm_warning_message">O patch LKM depende de componentes de código fechado. Deseja continuar?</string>
<string name="home_next_kernelsu">Nova atualização</string>
<string name="home_next_kernelsu">🔥 Compilação next</string>
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
<string name="home_next_kernelsu_body">Novo branch. Experimental confira no Github!</string>
<string name="home_experimental_kernelsu">⚠️ Aviso: recurso em desenvolvimento experimental!</string>
<string name="home_next_kernelsu_body">Branch next experimental. Confira no GitHub!</string>
<string name="home_experimental_kernelsu">⚠️ Aviso de desenvolvimento experimental!</string>
<string name="home_experimental_kernelsu_repo">127.0.0.1</string>
<string name="home_experimental_kernelsu_body">KernelSU Next é uma versão não oficial que está sempre em desenvolvimento experimental ativo. É fornecida como está, sem garantias de estabilidade, desempenho ou confiabilidade.</string>
<string name="home_experimental_kernelsu_body_point_1"> Use por sua conta e risco: podem ocorrer travamentos, comportamentos inesperados ou problemas no sistema.</string>
<string name="home_experimental_kernelsu_body_point_2"> Sem garantia: os desenvolvedores não se responsabilizam por qualquer perda de dados, danos ao sistema ou outras consequências decorrentes do uso.</string>
<string name="home_experimental_kernelsu_body_point_3"> Somente para fins de teste: destinado a usuários que entendem os riscos e se sentem confortáveis em solucionar problemas.</string>
<string name="about_source_code">Ver código-fonte em %1$s</string>
<string name="profile">Perfil do aplicativo</string>
<string name="home_experimental_kernelsu_body">KernelSU Next é uma versão não oficial que está sempre em desenvolvimento experimental ativo. É fornecido no estado em que se encontra, sem garantias de estabilidade, desempenho ou confiabilidade.</string>
<string name="home_experimental_kernelsu_body_point_1"> Use por sua conta e risco: podem ocorrer travamentos, comportamento inesperado ou problemas no sistema.</string>
<string name="home_experimental_kernelsu_body_point_2"> Sem garantia: os desenvolvedores não são responsáveis por qualquer perda de dados, danos ao sistema ou outras consequências resultantes de seu uso.</string>
<string name="home_experimental_kernelsu_body_point_3"> • Apenas para fins de teste: destinado a usuários que entendem os riscos e se sentem confortáveis em solucionar problemas.</string>
<string name="about_source_code">Veja o código-fonte no %1$s</string>
<string name="profile">Perfil do Aplicativo</string>
<string name="profile_default">Padrão</string>
<string name="profile_template">Templete</string>
<string name="profile_custom">Customizado</string>
<string name="profile_template">Modelo</string>
<string name="profile_custom">Personalizado</string>
<string name="profile_name">Nome do perfil</string>
<string name="profile_namespace">Montar nomespaço</string>
<string name="profile_namespace">Montar namespace</string>
<string name="profile_namespace_inherited">Herdado</string>
<string name="profile_namespace_global">Global</string>
<string name="profile_namespace_individual">Individual</string>
<string name="profile_groups">Grupos </string>
<string name="profile_capabilities">Recursos</string>
<string name="profile_selinux_context">SELinux contexto</string>
<string name="profile_groups">Grupos</string>
<string name="profile_capabilities">Capacidades</string>
<string name="profile_selinux_context">Contexto do SELinux</string>
<string name="profile_umount_modules">Desmontar módulos</string>
<string name="failed_to_update_app_profile">Falha ao atualizar o perfil do aplicativo para %s</string>
<string name="require_kernel_version">A versão atual do KernelSU Next %1$d é muito antiga para que o gerenciador funcione corretamente. Atualize para a versão %2$d ou superior!</string>
<string name="settings_umount_modules_default">Desmontar módulos </string>
<string name="settings_umount_modules_default_summary">O valor padrão global para \"Desmontar módulos\" no Perfil do Aplicativo. Se ativado, removerá todas as modificações de módulos no sistema para os aplicativos que não possuem um perfil definido.</string>
<string name="failed_to_update_app_profile">Failed to update App Profile for %s</string>
<string name="require_kernel_version">A versão atual do KernelSU Next %1$d é muito baixa para o gerenciador funcionar corretamente. Por favor, atualize para a versão %2$d ou superior!</string>
<string name="settings_umount_modules_default">Desmontar módulos</string>
<string name="settings_umount_modules_default_summary">O valor padrão global para \"Desmontar módulos\" em Perfil do Aplicativo. Se ativado, ele removerá todas as modificações do módulo no sistema para apps que não possuem um perfil definido.</string>
<string name="settings_susfs_toggle">Ocultar hook kprobes</string>
<string name="settings_susfs_toggle_summary">Essa opção desativa o hook do kprobes criado pelo ksu e, em vez disso, ativa o hook embutido sem kprobes, implementando a mesma funcionalidade aplicada a um kernel não-GKI, que não oferece suporte a kprobes.</string>
<string name="profile_umount_modules_summary">Ativar essa opção permitirá que o KernelSU Next restaure quaisquer arquivos modificados pelos módulos para este aplicativo.</string>
<string name="settings_susfs_toggle_summary">Esta opção desativa os hook kprobes criados pelo ksu e, em vez disso, ativa os hooks embutidos não-kprobes, implementando a mesma funcionalidade que seria aplicada a um kernel não-GKI, que não oferece suporte para kprobe.</string>
<string name="profile_umount_modules_summary">Ativar esta opção permitirá que o KernelSU Next restaure quaisquer arquivos modificados pelos módulos para este app.</string>
<string name="profile_selinux_domain">Domínio</string>
<string name="profile_selinux_rules">Regras</string>
<string name="module_update">atualizar</string>
<string name="module_update">Atualizar</string>
<string name="module_update_available">Atualizar</string>
<string name="module_updated">Atualizado</string>
<string name="module_downloading">Baixando modulo</string>
<string name="module_start_downloading">Download iniciado</string>
<string name="new_version_available">Nova versão disponível, clique para atualizar</string>
<string name="launch_app">Lançar</string>
<string name="module_downloading">Baixando módulo %s</string>
<string name="module_start_downloading">Começando a baixar %s</string>
<string name="new_version_available">Nova versão %s está disponível, clique para atualizar.</string>
<string name="launch_app">Iniciar</string>
<string name="close">Fechar</string>
<string name="force_stop_app">Forçar parada</string>
<string name="restart_app">Reiniciar</string>
<string name="settings_amoled_mode">Modo AMOLED</string>
<string name="settings_amoled_mode_summary">Ativar tema pure black útil para telas AMOLED para reduzir o cansaço visual e economizar bateria.</string>
<string name="restart_required">Requer reinicialização</string>
<string name="restart_app_message">O aplicativo precisa ser reiniciado para que as mudanças sejam aplicadas</string>
<string name="failed_to_update_sepolicy">Falha a o atualizar SELinux para</string>
<string name="settings_amoled_mode_summary">Ative um tema preto puro útil para telas AMOLED para reduzir o cansaço visual e economizar bateria.</string>
<string name="restart_required">Reinicialização necessária</string>
<string name="restart_app_message">O app precisa ser reiniciado para que essa alteração entre em vigor.</string>
<string name="failed_to_update_sepolicy">Falha ao atualizar as regras do SELinux para %s</string>
<string name="su_not_allowed">Não foi possível conceder acesso de Superusuário a %s</string>
<string name="module_changelog">Lista de alterações</string>
<string name="settings_profile_template">Modelo de perfil de aplicativo</string>
@@ -229,4 +228,9 @@ Prossiga com cautela.</string>
<string name="home_module_count_singular">Módulo</string>
<string name="home_module_count_plural">Módulos</string>
<string name="module_backup_message">Fazer backup dos módulos instalados.</string>
<string name="module_sort_enabled_first">Ordenar (Habilitado primeiro)</string>
<string name="module_sort_action_first">Ordenar (exceto primeiro)</string>
<string name="module_sort_webui_first">Ordenar (WebUI primeiro)</string>
<string name="settings_global_namespace_mode">Modo de namespace global</string>
<string name="settings_global_namespace_mode_summary">Todas as sessões raiz usam o namespace de montagem global</string>
</resources>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="issue_report_title">Возникли проблемы?</string>
<string name="issue_report_body">Обнаружена ошибка или есть обратная связь?</string>
<string name="issue_report_body">Заметили ошибку или есть предложения?</string>
<string name="issue_report_body_2">Сообщите об этом как можно скорее!</string>
<string name="issue_report_github">Сообщить на GitHub</string>
<string name="issue_report_telegram">Связаться через Telegram</string>
@@ -17,7 +17,7 @@
<string name="home_working">Работает</string>
<string name="home_working_version">Версия драйвера: %d</string>
<string name="home_module_update_count">Обновлений: %d</string>
<string name="home_failure">Подпись KernelSU Next v2 не найдена в ядре!</string>
<string name="home_failure">Подпись KernelSU Next v2 не найдена в ядре! [ !KSU_NEXT || != size/hash ]</string>
<string name="home_failure_tip">Напишите разработчику своего ядра, для интеграции KernelSU Next!</string>
<string name="home_kernel">Версия ядра</string>
<string name="hook_mode">Режим хуков</string>
@@ -45,8 +45,8 @@
<string name="module_install_prompt_with_name">Следующие модули будут установлены: %1$s</string>
<string name="module_sort_a_to_z">По имени (А → Я)</string>
<string name="module_sort_z_to_a">По имени (Я → А)</string>
<string name="module_size_low_to_high">Сортировать (Меньше → Больше)</string>
<string name="module_size_high_to_low">Сортировать (Больше → Меньше)</string>
<string name="module_size_low_to_high">По размеру (Меньше → Больше)</string>
<string name="module_size_high_to_low">По размеру (Больше → Меньше)</string>
<string name="uninstall">Удалить</string>
<string name="restore">Восстановить</string>
<string name="module_install">Установить</string>
@@ -96,11 +96,11 @@
<string name="module_backup">Бэкап модулей</string>
<string name="allowlist_restore">Восстановить список прав</string>
<string name="allowlist_restore_message">Восстановить список прав из последней резервной копии.</string>
<string name="allowlist_backup">Бэкап списка разрешений</string>
<string name="allowlist_backup">Бэкап списка прав</string>
<string name="allowlist_backup_message">Резервное копирование текущего списка разрешений.</string>
<string name="warning">Предупреждение</string>
<string name="warning_message">Эта функция всё ещё находится в стадии бета-тестирования. Пожалуйста, убедитесь, что вы создали резервные копии модулей перед использованием. Используйте это только если понимаете возможные риски. Будьте осторожны.</string>
<string name="proceed">В процессе</string>
<string name="proceed">Продолжить</string>
<string name="cancel">Отмена</string>
<string name="later">Позже</string>
<string name="lkm_warning_message">Патч LKM использует компоненты с закрытым исходным кодом. Хотите продолжить?</string>
@@ -126,14 +126,14 @@
<string name="profile_groups">Группы</string>
<string name="profile_capabilities">Возможности</string>
<string name="profile_selinux_context">Контекст SELinux</string>
<string name="profile_umount_modules">Отключить модули</string>
<string name="profile_umount_modules">Размонтировать модули</string>
<string name="failed_to_update_app_profile">Не удалось обновить Профиль Приложения для %s</string>
<string name="require_kernel_version">Текущая версия KernelSU Next %1$d слишком низкая для корректной работы менеджера. Пожалуйста, обновитесь до версии %2$d или выше!</string>
<string name="settings_umount_modules_default">Отключить модули</string>
<string name="settings_umount_modules_default_summary">Глобальное значение по умолчанию для \"Отключить модули\" в Профиле Приложения. Если включено, это удалит все модификации системы модулями для приложений без установленного профиля.</string>
<string name="settings_umount_modules_default">Размонтировать модули</string>
<string name="settings_umount_modules_default_summary">Глобальное значение по умолчанию для параметра \"Размонтировать модули\" в Профиле Приложения. Если этот параметр включён, то все изменения, внесённые модулями, будут скрыты для приложений без установленного профиля или root-доступа.</string>
<string name="settings_susfs_toggle">Скрыть хук kprobes</string>
<string name="settings_susfs_toggle_summary">Эта опция отключает хук kprobes, созданный ksu, и вместо него активирует встроенный хук без использования kprobes, реализующий ту же функциональность, которая применяется к ядрам без GKI, не поддерживающим kprobe.</string>
<string name="profile_umount_modules_summary">Включение этой опции позволит KernelSU Next восстанавливать любые изменённые модулями файлы для этого приложения.</string>
<string name="profile_umount_modules_summary">Если этот параметр включен, то все модификации, внесённые модулями, будут скрыты для данного приложения.</string>
<string name="profile_selinux_domain">Домен</string>
<string name="profile_selinux_rules">Правила</string>
<string name="module_update">Обновить</string>
@@ -153,8 +153,8 @@
<string name="failed_to_update_sepolicy">Не удалось обновить правила SELinux для %s</string>
<string name="su_not_allowed">Предоставление прав суперпользователя запрещено для: %s</string>
<string name="module_changelog">Журнал изменений</string>
<string name="settings_profile_template">Шаблон Профиля Приложений</string>
<string name="settings_profile_template_summary">Управление локальными и онлайн шаблонами Профилей Приложений</string>
<string name="settings_profile_template">Шаблоны root-доступа</string>
<string name="settings_profile_template_summary">Управление локальными и онлайн шаблонами root-доступа.</string>
<string name="app_profile_template_create">Создать шаблон</string>
<string name="app_profile_template_edit">Изменить шаблон</string>
<string name="app_profile_template_id">ID</string>
@@ -176,7 +176,7 @@
<string name="app_profile_template_import_empty">Буфер обмена пуст!</string>
<string name="module_changelog_failed">Не удалось получить журнал изменений: %s</string>
<string name="settings_check_update">Проверять обновления</string>
<string name="settings_check_update_summary">Автоматически проверять обновления при открытии приложения</string>
<string name="settings_check_update_summary">Автоматически проверять обновления при открытии приложения.</string>
<string name="grant_root_failed">Не удалось выдать root!</string>
<string name="action">Скрипт</string>
<string name="webui">WebUI</string>
@@ -228,4 +228,9 @@
<string name="home_module_count_singular">Модуль</string>
<string name="home_module_count_plural">Модулей</string>
<string name="module_backup_message">Резервное копирование текущих установленных модулей.</string>
<string name="module_sort_enabled_first">По статусу (Сначала включённые)</string>
<string name="module_sort_action_first">По статусу (Сначала со скриптом)</string>
<string name="module_sort_webui_first">По статусу (Сначала с WebUI)</string>
<string name="settings_global_namespace_mode">Общее пространство монтирования</string>
<string name="settings_global_namespace_mode_summary">Все сессии root используют одну файловую систему.</string>
</resources>

View File

@@ -228,4 +228,9 @@
<string name="home_module_count_singular">Module</string>
<string name="home_module_count_plural">Modules</string>
<string name="module_backup_message">Backup currently installed modules.</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_webui_first">Sort (WebUI first)</string>
<string name="settings_global_namespace_mode">Global Namespace Mode</string>
<string name="settings_global_namespace_mode_summary">All root sessions use the global mount namespace</string>
</resources>

View File

@@ -228,4 +228,9 @@
<string name="home_module_count_singular">Module</string>
<string name="home_module_count_plural">Modules</string>
<string name="module_backup_message">Backup currently installed modules.</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_webui_first">Sort (WebUI first)</string>
<string name="settings_global_namespace_mode">Global Namespace Mode</string>
<string name="settings_global_namespace_mode_summary">All root sessions use the global mount namespace</string>
</resources>

View File

@@ -1,52 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="issue_report_title">Sorun mu yaşıyorsunuz?</string>
<string name="issue_report_body">Hata veya öneri mi bildirmek istiyorsunuz?</string>
<string name="issue_report_body_2">Hemen bildirin!</string>
<string name="issue_report_github">GitHub\'de bildirin</string>
<string name="issue_report_telegram">Telegram ile iletişim kurun</string>
<string name="issue_report_body">Bir hatayla mı karşılaştınız veya geri bildiriminiz mi var?</string>
<string name="issue_report_body_2">Mümkün olan en kısa sürede bildirin!</string>
<string name="issue_report_github">GitHubda bildirin</string>
<string name="issue_report_telegram">Telegram üzerinden iletişim kurun</string>
<string name="issue_report_github_link">https://github.com/KernelSU-Next/KernelSU-Next/issues</string>
<string name="issue_report_telegram_link">https://t.me/ksunext</string>
<string name="confirm">Onayla</string>
<string name="app_name">KernelSU Next</string>
<string name="home">Ana Ekran</string>
<string name="home_not_installed">Yüklenmedi</string>
<string name="home_click_to_install">Yüklemek için dokunun</string>
<string name="lkm_mode_deprecated">LKM modu kullanımdan kaldırıldı!</string>
<string name="lkm_alternative_suggestion">GKI kernel yükleyin veya KernelSU Next\'i cihazınıza entegre edin.</string>
<string name="home_not_installed">Yüklü değil</string>
<string name="home_click_to_install">Yüklemek için tıklayın</string>
<string name="lkm_mode_deprecated">LKM modu artık kullanımdan kaldırıldı!</string>
<string name="lkm_alternative_suggestion">GKI çekirdeğini yükleyin veya KernelSU Next\'i cihazınıza entegre edin.</string>
<string name="home_working">Çalışıyor</string>
<string name="home_working_version">Sürüm: %d</string>
<string name="home_module_update_count">Güncellemeler: %d</string>
<string name="home_failure">KernelSU Next v2 imzası kernelde bulunamadı! [ !KSU_NEXT || != size/hash ]</string>
<string name="home_failure">KernelSU Next v2 imzası çekirdekte bulunamadı! [ !KSU_NEXT || != size/hash ]</string>
<string name="home_failure_tip">Kernel geliştiricinizden KernelSU Next\'i entegre etmelerini isteyin!</string>
<string name="home_kernel">Kernel sürümü</string>
<string name="hook_mode">Hook modu</string>
<string name="home_kernel">Çekirdek sürümü</string>
<string name="hook_mode">Kanca modu</string>
<string name="enable">Etkinleştir</string>
<string name="disable">Devre dışı bırak</string>
<string name="enabled">Etkinleştir</string>
<string name="disabled">Devre dışı bırak</string>
<string name="enabled">Etkin</string>
<string name="disabled">Devre dışı</string>
<string name="susfs_supported">Destekleniyor</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">SuSFS sürümü</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_android">Android sürümü</string>
<string name="home_manager_version">Uygulama sürümü</string>
<string name="home_manager_version">Yönetici sürümü</string>
<string name="home_abi">ABI</string>
<string name="home_selinux_status">SELinux durumu</string>
<string name="selinux_status_disabled">Devre dışı</string>
<string name="selinux_status_enforcing">Zorlanıyor</string>
<string name="selinux_status_permissive">Etkin değil</string>
<string name="selinux_status_permissive">Permissive (Serbest)</string>
<string name="selinux_status_unknown">Bilinmiyor</string>
<string name="superuser">Superuser</string>
<string name="superuser">Süper Kullanıcı</string>
<string name="module_failed_to_enable">Modül etkinleştirilemedi: %s</string>
<string name="module_failed_to_disable">Modül devre dışı bırakılamadı: %s</string>
<string name="module_empty">Yüklenmiş modül yok</string>
<string name="module_empty">Yüklü modül yok</string>
<string name="module">Modül</string>
<string name="module_install_prompt_with_name">Bu modüller yüklenecektir: %1$s</string>
<string name="module_sort_a_to_z">Sırala (A → Z)</string>
<string name="module_sort_z_to_a">Sırala (Z → A)</string>
<string name="module_size_low_to_high">Sırala (Low → High)</string>
<string name="module_size_high_to_low">Sırala (High → Low)</string>
<string name="module_size_low_to_high">Sırala (Düşük → Yüksek)</string>
<string name="module_size_high_to_low">Sırala (Yüksek → Düşük)</string>
<string name="uninstall">Kaldır</string>
<string name="restore">Geri yükle</string>
<string name="module_install">Yükle</string>
@@ -63,9 +63,9 @@
<string name="module_uninstall_confirm">%s modülünü kaldırmak istediğinize emin misiniz?</string>
<string name="module_uninstall_success">%s kaldırıldı</string>
<string name="module_uninstall_failed">Kaldırma başarısız oldu: %s</string>
<string name="module_restore_confirm">%s modülünü geri getirmek istediğinize emin misiniz?</string>
<string name="module_restore_success">%s geri getirildi</string>
<string name="module_restore_failed">Geri getirme başarısız oldu: %s</string>
<string name="module_restore_confirm">%s modülünü geri yüklemek istediğinize emin misiniz?</string>
<string name="module_restore_success">%s geri yüklendi</string>
<string name="module_restore_failed">Geri yükleme başarısız oldu: %s</string>
<string name="module_version">Sürüm</string>
<string name="module_author">Geliştirici</string>
<string name="module_id">Kimlik</string>
@@ -74,7 +74,7 @@
<string name="module_update_json_empty">Boş</string>
<string name="enable_developer_options">Geliştirici seçeneklerini etkinleştir</string>
<string name="enable_developer_options_summary">Yalnızca geliştiricilere yönelik gizli ayarları ve hata ayıklama bilgilerini göster.</string>
<string name="module_overlay_fs_not_available">OverlayFS çekirdek tarafından devre dışı bırakıldığından modüller kullanılamaz!</string>
<string name="module_overlay_fs_not_available">OverlayFS çekirdek tarafından devre dışı bırakıldığı için modüller kullanılamıyor!</string>
<string name="refresh">Yenile</string>
<string name="show_system_apps">Sistem uygulamalarını göster</string>
<string name="hide_system_apps">Sistem uygulamalarını gizle</string>
@@ -90,28 +90,28 @@
<string name="use_overlay_fs_summary">KernelSU Next\'in bağlama sistemi için Magic Mount üzerinden OverlayFS kullanımı arasında geçiş yapın.</string>
<string name="reboot_required">Yeniden başlatma gerekli</string>
<string name="reboot_message">Değişiklikler sistem yeniden başlatıldıktan sonra geçerli olacaktır. Şimdi yeniden başlatmak istiyor musunuz?</string>
<string name="module_restore">Modülü geri getir</string>
<string name="module_restore_message">En yeni yedeklemeden modülleri geri getir.</string>
<string name="module_restore">Modülü geri yükle</string>
<string name="module_restore_message">Modülleri son yedeklemeden geri yükleyin.</string>
<string name="backup_restore">Yedekle &amp; Geri Getir</string>
<string name="module_backup">Modülü yedekle</string>
<string name="allowlist_restore">İzin verilen listesini geri yükle</string>
<string name="allowlist_restore_message">En yeni yedeklemeden modülleri geri getir.</string>
<string name="allowlist_backup">İzin verilen listesini yedekle</string>
<string name="allowlist_restore">İzin listesini geri yükle</string>
<string name="allowlist_restore_message">İzin listesini son yedeklemeden geri yükleyin.</string>
<string name="allowlist_backup">İzin listesini yedekle</string>
<string name="allowlist_backup_message">Şu anda yapılandırılmış izin listesini yedekleyin.</string>
<string name="warning">Uyarı!</string>
<string name="warning">Uyarı</string>
<string name="warning_message">Bu özellik hala beta aşamasındadır ve geliştirilme aşamasındadır. Lütfen devam etmeden önce modüllerinizi yedeklediğinizden emin olun. Bu özelliği yalnızca potansiyel riskleri anlıyorsanız kullanın. Dikkatli bir şekilde ilerleyin.</string>
<string name="proceed">Devam et</string>
<string name="cancel">İptal et</string>
<string name="later">Sonra</string>
<string name="lkm_warning_message">LKM yamaları kapalı kaynak kodludur. Devam etmek istiyor musunuz?</string>
<string name="home_next_kernelsu">🔥 Sıradaki yapı</string>
<string name="lkm_warning_message">LKM yaması kapalı kaynak bileşenlerine dayanır. Devam etmek istiyor musunuz?</string>
<string name="home_next_kernelsu">🔥 Next Yapımı</string>
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
<string name="home_next_kernelsu_body">Next deneysel sürümü. GitHub\'da göz atın!</string>
<string name="home_next_kernelsu_body">Next deneysel dalı. GitHub\'da göz atın!</string>
<string name="home_experimental_kernelsu">⚠️ Deneysel geliştirme uyarısı!</string>
<string name="home_experimental_kernelsu_repo">127.0.0.1</string>
<string name="home_experimental_kernelsu_body">KernelSU Next, sürekli geliştirme aşamasında olan resmi olmayan bir sürümdür. Kararlılık, performans veya güvenilirlik garantisi olmadan olduğu gibi sunulur.</string>
<string name="home_experimental_kernelsu_body_point_1"> • Risk size aittir: çökmeler, beklenmedik davranışlar veya sistem sorunları meydana gelebilir.</string>
<string name="home_experimental_kernelsu_body_point_2"> • Garantili değil: geliştiriciler; kullanımından kaynaklı veri kaybı, sistem hasarı gibi sonuçlardan sorumlu değildir.</string>
<string name="home_experimental_kernelsu_body_point_2"> • Garanti yok: geliştiriciler herhangi bir veri kaybından, sistem hasarından veya kullanımından kaynaklanan diğer sonuçlardan sorumlu değildir.</string>
<string name="home_experimental_kernelsu_body_point_3"> • Sadece test amaçlı: riskleri anlayan ve sorun giderme konusunda uzman olan kullanıcılar içindir.</string>
<string name="about_source_code">Kaynak kodunu görüntüleyin: %1$s</string>
<string name="profile">Uygulama Profili</string>
@@ -121,42 +121,42 @@
<string name="profile_name">Profil ismi</string>
<string name="profile_namespace">Bağlama alanadı</string>
<string name="profile_namespace_inherited">Inherited</string>
<string name="profile_namespace_global">Global</string>
<string name="profile_namespace_individual">Bireysel</string>
<string name="profile_namespace_global">Genel</string>
<string name="profile_namespace_individual">Özel</string>
<string name="profile_groups">Gruplar</string>
<string name="profile_capabilities">Yetenekler</string>
<string name="profile_capabilities">Kabiliyetler</string>
<string name="profile_selinux_context">SELinux bağlamı</string>
<string name="profile_umount_modules">Modüllerin bağlantısını kes</string>
<string name="failed_to_update_app_profile">Uygulama profil güncellemesi %s için başarısız oldu</string>
<string name="require_kernel_version">Mecvut KernelSU Next sürümü %1$d, uygulamanın doğru çalışması için çok düşük. Lütfen %2$d ya da daha yüksek bir sürüme yükseltin!</string>
<string name="failed_to_update_app_profile">%s için Uygulama Profili güncellenemedi</string>
<string name="require_kernel_version">Geçerli KernelSU Next sürümü %1$d, yöneticinin düzgün çalışması için çok düşük. Lütfen %2$d veya daha yüksek bir sürüme yükseltin!</string>
<string name="settings_umount_modules_default">Modüllerin bağlantısını kes</string>
<string name="settings_umount_modules_default_summary">Uygulama profilinde \"Modüllerin bağlantısını kes\" ayarı için genel varsayılan değer. Etkinleştirilirse, profili ayarlanmamış tüm uygulamalar için sistemdeki tüm modül değişikliklerini kaldırır.</string>
<string name="settings_susfs_toggle">kprobes kancasını gizle</string>
<string name="settings_susfs_toggle_summary">Bu seçenek, ksu tarafından oluşturulan kprobes kancasını devre dışı bırakır ve bunun yerine gömülü kprobes olmayan kancayı etkinleştirir ve kprobe desteklemeyip GKI olmayan bir çekirdeğe uygulanacak aynı işlevi uygular.</string>
<string name="profile_umount_modules_summary">Bu seçeneği etkinleştirmek, KernelSU Next\'in bu uygulama için modüller tarafından değiştirilen dosyaları geri yüklemesine izin verecektir.</string>
<string name="settings_susfs_toggle_summary">Bu seçenek, ksu tarafından oluşturulan kprobes kancasını devre dışı bırakır ve bunun yerine, kprobe\'u desteklemeyen GKI olmayan bir çekirdeğe uygulanacak aynı işlevselliği uygulayan gömülü kprobes olmayan kancayı etkinleştirir.</string>
<string name="profile_umount_modules_summary">Bu seçeneğin etkinleştirilmesi, KernelSU Next\'in bu uygulama için modüller tarafından değiştirilen tüm dosyaları geri yüklemesine izin verecektir.</string>
<string name="profile_selinux_domain">Alan adı</string>
<string name="profile_selinux_rules">Kurallar</string>
<string name="module_update">Güncelleme</string>
<string name="module_update">Güncelle</string>
<string name="module_update_available">Güncelleme mevcut</string>
<string name="module_updated">Güncellendi</string>
<string name="module_downloading">Modül indiriliyor: %s</string>
<string name="module_start_downloading">İndirme başlıyor: %s</string>
<string name="new_version_available">Yeni sürüm %s mevcut, güncellemek için dokunun.</string>
<string name="launch_app"></string>
<string name="new_version_available">Yeni sürüm %s mevcut, güncellemek için tıklayın.</string>
<string name="launch_app">Başlat</string>
<string name="close">Kapat</string>
<string name="force_stop_app">Durmaya zorla</string>
<string name="restart_app">Yeniden başlat</string>
<string name="settings_amoled_mode">AMOLED modu</string>
<string name="settings_amoled_mode_summary">AMOLED ekranlar için göz yorgunluğunu azaltmak ve pil tasarrufu sağlamak için kullanışlı saf siyah temayı etkinleştirin.</string>
<string name="settings_amoled_mode_summary">Göz yorgunluğunu azaltmak ve pil tasarrufu sağlamak için AMOLED ekranlar için kullanışlı olan saf siyah temayı etkinleştirin.</string>
<string name="restart_required">Yeniden başlatma gerekli</string>
<string name="restart_app_message">Uygulamanın bu değişikliği uygulaması için yeniden başlatılması gerekiyor.</string>
<string name="restart_app_message">Bu değişikliğin etkili olması için uygulamanın yeniden başlatılması gerekiyor.</string>
<string name="failed_to_update_sepolicy">%s için SELinux kuralları güncellenemedi</string>
<string name="su_not_allowed">%s\'ye Superuser izni verilemedi</string>
<string name="su_not_allowed">%s\'ye per kullanıcı izni verilemedi</string>
<string name="module_changelog">Değişiklik Notları</string>
<string name="settings_profile_template">Uygulama Profili şablonu</string>
<string name="settings_profile_template_summary">Uygulama Profil Şablonunu yerel ve çevrimiçi olarak yönetin</string>
<string name="settings_profile_template_summary">Uygulama Profilinin yerel ve çevrimiçi şablonunu yönetme</string>
<string name="app_profile_template_create">Şablon oluştur</string>
<string name="app_profile_template_edit">Şablonu Düzenle</string>
<string name="app_profile_template_edit">Şablonu düzenle</string>
<string name="app_profile_template_id">Kimlik</string>
<string name="app_profile_template_id_invalid">Geçersiz şablon kimliği</string>
<string name="app_profile_template_name">Ad</string>
@@ -164,12 +164,12 @@
<string name="app_profile_template_save">Kaydet</string>
<string name="app_profile_template_delete">Sil</string>
<string name="app_profile_template_view">Şablonu görüntüle</string>
<string name="app_profile_template_readonly">Sadece okunabilir</string>
<string name="app_profile_template_readonly">Salt okunur</string>
<string name="app_profile_template_id_exist">Şablon kimliği zaten mevcut!</string>
<string name="app_profile_import_export">İçe Aktar / Dışa Aktar</string>
<string name="app_profile_import_from_clipboard">Pano\'dan içe aktar</string>
<string name="app_profile_export_to_clipboard">Panoya çıkar</string>
<string name="app_profile_template_export_empty">Dışa aktarmak için yerel şablon bulunamadı!</string>
<string name="app_profile_import_from_clipboard">Panodan içe aktar</string>
<string name="app_profile_export_to_clipboard">Panoya aktar</string>
<string name="app_profile_template_export_empty">Dışa aktarılacak yerel şablon bulunamıyor!</string>
<string name="app_profile_template_import_success">Başarıyla içe aktarıldı</string>
<string name="app_profile_template_sync">Çevrimiçi şablonları senkronize et</string>
<string name="app_profile_template_save_failed">Şablon kaydedilemedi</string>
@@ -177,35 +177,35 @@
<string name="module_changelog_failed">Değişiklik günlüğü alınamadı: %s</string>
<string name="settings_check_update">Güncellemeleri kontrol et</string>
<string name="settings_check_update_summary">Uygulamayı açarken güncellemeleri otomatik denetle</string>
<string name="grant_root_failed">Kök yetkisi verilemedi!</string>
<string name="action">İşlem</string>
<string name="grant_root_failed">Kök izni verilemedi!</string>
<string name="action">Eylem</string>
<string name="webui">WebUI</string>
<string name="open"></string>
<string name="enable_web_debugging">WebView hata ayıklama etkinleştir</string>
<string name="enable_web_debugging_summary">WebUI\'yi hata ayıklamak için kullanılabilir. Sadece ihtiyaç duyulduğunda etkinleştirin.</string>
<string name="enable_web_debugging">WebView hata ayıklamayı etkinleştir</string>
<string name="enable_web_debugging_summary">WebUI\'de hata ayıklamak için kullanılabilir. Lütfen yalnızca gerektiğinde etkinleştirin.</string>
<string name="direct_install">Doğrudan kurulum (Önerilen)</string>
<string name="select_file">Bir dosya seçin</string>
<string name="install_inactive_slot">Aktif olmayan yuvaya kur (OTA sonrası)</string>
<string name="install_inactive_slot_warning">Cihazınız **ZORUNLU** olarak aktif olmayan yuvadan yeniden başlatılacaktır!\nBunu sadece OTA tamamlandıktan sonra kullanın\nDevam etmek istiyor musunuz?</string>
<string name="install_next">Sıradaki</string>
<string name="install_inactive_slot_warning">Cihazınız yeniden başlatıldıktan sonra mevcut etkin olmayan yuvaya önyükleme yapmak için **ZORUNLU** olacaktır.\nBu seçeneği yalnızca OTA tamamlandıktan sonra kullanın.\nDevam?</string>
<string name="install_next">Sonraki</string>
<string name="select_file_tip">%1$s bölüm imajı önerilir</string>
<string name="select_kmi">KMI seçin</string>
<string name="shrink_sparse_image">Sparse imajını küçültün</string>
<string name="shrink_sparse_image_message">Modülün bulunduğu sparse imajını gerçek boyutuna yeniden boyutlandırın. Bunun modülün anormal çalışmasına neden olabileceğini unutmayın, bu nedenle lütfen yalnızca gerekli olduğunda kullanın (yedekleme gibi).</string>
<string name="shrink_sparse_image_message">Modülün bulunduğu sparse imajını gerçek boyutuna yeniden boyutlandırın. Bunun modülün anormal çalışmasına neden olabileceğini unutmayın, bu nedenle lütfen yalnızca gerekli olduğunda kullanın (Yedekleme gibi).</string>
<string name="settings_uninstall">Kaldır</string>
<string name="settings_uninstall_temporary">Geçici olarak kaldır</string>
<string name="settings_uninstall_permanent">Kalıcı olarak kaldır</string>
<string name="settings_restore_stock_image">Stok imajı geri yükle</string>
<string name="settings_uninstall_temporary_message">KernelSU\'yu geçici olarak kaldırın, bir sonraki yeniden başlatmadan sonra orijinal duruma geri dönün.</string>
<string name="settings_uninstall_permanent_message">KernelSU Next\'i (Root ve tüm modüller) tamamen ve kalıcı olarak kaldırın.</string>
<string name="settings_uninstall_permanent_message">KernelSU Next\'i (Kök ve tüm modüller) tamamen ve kalıcı olarak kaldırın.</string>
<string name="settings_restore_stock_image_message">Stok fabrika imajını geri yükler (eğer yedek varsa), genellikle OTA\'dan önce kullanılır; KernelSU\'yu kaldırmanız gerekiyorsa, lütfen \"Kalıcı olarak kaldır\" seçeneğini kullanın.</string>
<string name="flashing">Kuruluyor</string>
<string name="flash_success">Kurulum başarılı</string>
<string name="flash_failed">Kurulum başarısız</string>
<string name="selected_lkm">Seçili LKM: %s</string>
<string name="save_log">Logları kaydet</string>
<string name="log_saved">Loglar kaydedildi</string>
<string name="send_log">Logları paylaş</string>
<string name="save_log">Günlükleri kaydet</string>
<string name="log_saved">Günlükler kaydedildi</string>
<string name="send_log">Günlükleri paylaş</string>
<string name="settings_disable_su">Su uyumluluğunu devre dışı bırak</string>
<string name="settings_disable_su_summary">Geçici olarak uygulamaların su komutu ile kök erişimi kazanmasını devre dışı bırakın (Zaten kök erişimi bulunan işlemler etkilenmez).</string>
<string name="settings_language">Dil</string>
@@ -223,9 +223,14 @@
<string name="sucompat_disabled">SUCOMPAT DEVRE DIŞI</string>
<string name="zygisk_required">Zygisk gerekli</string>
<string name="zygisk_status">Zygisk enjeksiyonu</string>
<string name="home_superuser_count_singular">Superuser</string>
<string name="home_superuser_count_plural">Superusers</string>
<string name="home_superuser_count_singular">Süper Kullanıcı</string>
<string name="home_superuser_count_plural">Süper Kullanıcılar</string>
<string name="home_module_count_singular">Modül</string>
<string name="home_module_count_plural">Modüller</string>
<string name="module_backup_message">Şu anda kurulu olan modülleri yedekleyin.</string>
<string name="module_sort_enabled_first">Sırala (Önce etkin)</string>
<string name="module_sort_action_first">Sırala (Önce eylem)</string>
<string name="module_sort_webui_first">Sırala (Önce WebUI)</string>
<string name="settings_global_namespace_mode">Küresel Ad Alanı Modu</string>
<string name="settings_global_namespace_mode_summary">Tüm kök oturumları genel bağlama ad alanını kullanır</string>
</resources>

View File

@@ -222,10 +222,15 @@
<string name="developer">Для Розробників</string>
<string name="sucompat_disabled">SUCOMPAT ВИМКНЕНО</string>
<string name="zygisk_required">Потрібно Zygisk</string>
<string name="zygisk_status">Zygisk-інджект</string>
<string name="home_superuser_count_singular">Суперкористувач</string>
<string name="home_superuser_count_plural">Суперкористувачі</string>
<string name="zygisk_status">Інжект Zygisk</string>
<string name="home_superuser_count_singular">Видано право</string>
<string name="home_superuser_count_plural">Видано прав</string>
<string name="home_module_count_singular">Модуль</string>
<string name="home_module_count_plural">Модулі</string>
<string name="module_backup_message">Бекап поточних встановлених модулів.</string>
<string name="module_sort_enabled_first">За статусом (Спочатку включені)</string>
<string name="module_sort_action_first">За статусом (Спочатку зі скриптом)</string>
<string name="module_sort_webui_first">За статусом (Спочатку з WebUI)</string>
<string name="settings_global_namespace_mode">Загальний простір імен</string>
<string name="settings_global_namespace_mode_summary">Усі сесії користувача root будуть використовувати спільний простір імен</string>
</resources>

View File

@@ -33,7 +33,7 @@
<string name="home_manager_version">Phiên bản trình quản lý</string>
<string name="home_abi">ABI</string>
<string name="home_selinux_status">Trạng thái SELinux</string>
<string name="selinux_status_disabled">Đã vô hiệu hoá</string>
<string name="selinux_status_disabled">Vô hiệu hoá</string>
<string name="selinux_status_enforcing">Enforcing</string>
<string name="selinux_status_permissive">Permissive</string>
<string name="selinux_status_unknown">Không xác định</string>
@@ -222,10 +222,15 @@
<string name="developer">Nhà phát triển</string>
<string name="sucompat_disabled">Vô hiệu hoá lệnh SU</string>
<string name="zygisk_required">Yêu cầu Zygisk</string>
<string name="zygisk_status">Zygisk Inject</string>
<string name="zygisk_status">Triển khai Zygisk</string>
<string name="home_superuser_count_singular">Superuser</string>
<string name="home_superuser_count_plural">Superusers</string>
<string name="home_module_count_singular">Module</string>
<string name="home_module_count_plural">Modules</string>
<string name="module_backup_message">Sao lưu các module hiện đang được cài đặt</string>
<string name="module_sort_enabled_first">Sắp xếp (Bật trước)</string>
<string name="module_sort_action_first">Sắp xếp (Khởi chạy trước)</string>
<string name="module_sort_webui_first">Sắp xếp (WebUI trước)</string>
<string name="settings_global_namespace_mode">Chế độ Namespace chung</string>
<string name="settings_global_namespace_mode_summary">Tất cả các phiên root đều sử dụng mount namespace chung</string>
</resources>

View File

@@ -15,7 +15,7 @@
<string name="lkm_mode_deprecated">LKM 模式已弃用!</string>
<string name="lkm_alternative_suggestion">安装 GKI 内核或集成 KernelSU 到你的设备。</string>
<string name="home_working">工作中</string>
<string name="home_working_version">版本%d</string>
<string name="home_working_version">版本: %d</string>
<string name="home_module_update_count">%d 个模块可更新!</string>
<string name="home_failure">无法在内核中找到 KernelSU Next v2 签名![ !KSU_NEXT || != size/hash ]</string>
<string name="home_failure_tip">请让你的内核开发人员集成 KernelSU Next</string>
@@ -26,27 +26,27 @@
<string name="enabled">已启用</string>
<string name="disabled">已禁用</string>
<string name="susfs_supported">支持</string>
<string name="home_susfs">SuSFS%s</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">SuSFS 版本</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_android">Android 版本</string>
<string name="home_manager_version">管理器版本</string>
<string name="home_abi">接口</string>
<string name="home_abi">ABI 类型</string>
<string name="home_selinux_status">SELinux 状态</string>
<string name="selinux_status_disabled">禁用</string>
<string name="selinux_status_enforcing">严格模式</string>
<string name="selinux_status_permissive">宽容模式</string>
<string name="selinux_status_unknown">未知</string>
<string name="superuser">超级用户</string>
<string name="module_failed_to_enable">启用模块失败:%s</string>
<string name="module_failed_to_disable">禁用模块失败:%s</string>
<string name="module_failed_to_enable">无法启用模块: %s</string>
<string name="module_failed_to_disable">无法禁用模块: %s</string>
<string name="module_empty">未安装任何模块</string>
<string name="module">模块</string>
<string name="module_install_prompt_with_name">将安装以下模块%1$s</string>
<string name="module_sort_a_to_z">按 A - Z 排序</string>
<string name="module_sort_z_to_a">按 Z - A 排序</string>
<string name="module_size_low_to_high">按模块大小正序排序</string>
<string name="module_size_high_to_low">按模块大小倒序排序</string>
<string name="module_install_prompt_with_name">将安装以下模块: %1$s</string>
<string name="module_sort_a_to_z">排序 (A -&gt; Z)</string>
<string name="module_sort_z_to_a">排序 (Z -&gt; A)</string>
<string name="module_size_low_to_high">排序 (按模块从小到大)</string>
<string name="module_size_high_to_low">排序 (按模块从大到小)</string>
<string name="uninstall">卸载</string>
<string name="restore">还原</string>
<string name="module_install">安装</string>
@@ -62,10 +62,10 @@
<string name="about">关于</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_uninstall_failed">卸载失败: %s</string>
<string name="module_restore_confirm">确定要还原模块 %s 吗?</string>
<string name="module_restore_success">已还原 %s</string>
<string name="module_restore_failed">恢复失败%s</string>
<string name="module_restore_failed">恢复失败: %s</string>
<string name="module_version">版本</string>
<string name="module_author">作者</string>
<string name="module_id">模块标识</string>
@@ -82,7 +82,7 @@
<string name="safe_mode">安全模式</string>
<string name="reboot_to_apply">重启生效</string>
<string name="module_magisk_conflict">由于与 Magisk 冲突,模块系统不可用!</string>
<string name="home_mount_system">模块系统</string>
<string name="home_mount_system">挂载系统</string>
<string name="home_magic_mount">Magic Mount</string>
<string name="home_overlayfs_mount">OverlayFS</string>
<string name="unavailable">不可用</string>
@@ -103,10 +103,10 @@
<string name="proceed">继续</string>
<string name="cancel">取消</string>
<string name="later">稍后</string>
<string name="lkm_warning_message">LKM 补丁依赖于闭源组件,确认操作代表你知晓因继续使用该功能所导致的一切后果与开发团队无关</string>
<string name="home_next_kernelsu">🔥 Next 构建</string>
<string name="lkm_warning_message">LKM 补丁依赖于闭源组件。是否继续?</string>
<string name="home_next_kernelsu">🔥 下一个版本</string>
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
<string name="home_next_kernelsu_body">Next 实验性分支。在 GitHub 上查看!</string>
<string name="home_next_kernelsu_body">下一个实验性分支。在 GitHub 上查看!</string>
<string name="home_experimental_kernelsu">⚠️ 实验性开发警告!</string>
<string name="home_experimental_kernelsu_repo">127.0.0.1</string>
<string name="home_experimental_kernelsu_body">KernelSU Next 是一个非官方版本,一直处于积极的实验开发阶段。它按原样提供,不保证稳定性、性能或可靠性。</string>
@@ -139,9 +139,9 @@
<string name="module_update">更新</string>
<string name="module_update_available">更新可用</string>
<string name="module_updated">重启以应用更新</string>
<string name="module_downloading">正在下载模块%s</string>
<string name="module_start_downloading">开始下载%s</string>
<string name="new_version_available">发现新版本%s点击升级。</string>
<string name="module_downloading">正在下载模块: %s</string>
<string name="module_start_downloading">开始下载: %s</string>
<string name="new_version_available">发现新版本 %s点击升级。</string>
<string name="launch_app">启动</string>
<string name="close">关闭</string>
<string name="force_stop_app">强行停止</string>
@@ -174,7 +174,7 @@
<string name="app_profile_template_sync">同步在线模板</string>
<string name="app_profile_template_save_failed">模版保存失败</string>
<string name="app_profile_template_import_empty">剪贴板为空!</string>
<string name="module_changelog_failed">获取更新日志失败%s</string>
<string name="module_changelog_failed">获取更新日志失败: %s</string>
<string name="settings_check_update">检查更新</string>
<string name="settings_check_update_summary">在应用启动后自动检查是否有新版本。</string>
<string name="grant_root_failed">获取 root 失败!</string>
@@ -202,7 +202,7 @@
<string name="flashing">刷写中</string>
<string name="flash_success">刷写成功</string>
<string name="flash_failed">刷写失败</string>
<string name="selected_lkm">选择的 LKM%s</string>
<string name="selected_lkm">选择的 LKM: %s</string>
<string name="save_log">保存日志</string>
<string name="log_saved">日志已保存</string>
<string name="send_log">分享日志</string>
@@ -220,7 +220,7 @@
<string name="use_webuix_eruda_summary">将调试控制台注入 WebUI X 以使调试更容易。需要启用 Web 调试。</string>
<string name="customization">界面设置</string>
<string name="developer">开发者选项</string>
<string name="sucompat_disabled">SU 兼容禁用</string>
<string name="sucompat_disabled">SU 兼容禁用</string>
<string name="zygisk_required">需要 Zygisk</string>
<string name="zygisk_status">Zygisk 注入</string>
<string name="home_superuser_count_singular">超级用户</string>
@@ -228,4 +228,9 @@
<string name="home_module_count_singular">模块</string>
<string name="home_module_count_plural">模块</string>
<string name="module_backup_message">备份当前已安装的模块。</string>
<string name="module_sort_enabled_first">排序 (已启用优先)</string>
<string name="module_sort_action_first">排序 (可执行优先)</string>
<string name="module_sort_webui_first">排序 (支持 WebUI 优先)</string>
<string name="settings_global_namespace_mode">全局命名空间模式</string>
<string name="settings_global_namespace_mode_summary">所有Root会话均使用全局挂载命名空间。</string>
</resources>

View File

@@ -45,8 +45,8 @@
<string name="module_install_prompt_with_name">即將安裝以下模組:%1$s</string>
<string name="module_sort_a_to_z">按 A - Z 排序</string>
<string name="module_sort_z_to_a">按 Z - A 排序</string>
<string name="module_size_low_to_high">模組大小正排序</string>
<string name="module_size_high_to_low">模組大小倒序排序</string>
<string name="module_size_low_to_high">模組大小正排序</string>
<string name="module_size_high_to_low">模組大小反向排序</string>
<string name="uninstall">卸載</string>
<string name="restore">還原</string>
<string name="module_install">安裝</string>
@@ -228,4 +228,9 @@
<string name="home_module_count_singular">模組</string>
<string name="home_module_count_plural">模組</string>
<string name="module_backup_message">備份當前已安裝的模組。</string>
<string name="module_sort_enabled_first">依啟用狀態優先排序</string>
<string name="module_sort_action_first">依支援執行優先排序</string>
<string name="module_sort_webui_first">依具備 WebUI 優先排序</string>
<string name="settings_global_namespace_mode">全域命名空間模式</string>
<string name="settings_global_namespace_mode_summary">所有 Root 工作階段皆使用全域掛載命名空間</string>
</resources>

View File

@@ -228,4 +228,9 @@
<string name="home_superuser_count_plural">Superusers</string>
<string name="home_module_count_singular">Module</string>
<string name="home_module_count_plural">Modules</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_webui_first">Sort (WebUI first)</string>
<string name="settings_global_namespace_mode">Global Namespace Mode</string>
<string name="settings_global_namespace_mode_summary">All root sessions use the global mount namespace</string>
</resources>

26
manager/setup.sh Executable file
View File

@@ -0,0 +1,26 @@
> gradle.properties
{
echo 'android.experimental.enableNewResourceShrinker.preciseShrinking=true'
echo 'android.enableAppCompileTimeRClass=true'
echo 'android.useAndroidX=true'
echo KEYSTORE_PASSWORD=$MY_KEYSTORE_PASSWORD
echo KEY_ALIAS=$MY_KEY_ALIAS
echo KEY_PASSWORD=$MY_KEY_PASSWORD
echo KEYSTORE_FILE='key.jks'
echo 'org.gradle.parallel=true'
echo 'org.gradle.vfs.watch=true'
echo 'org.gradle.jvmargs=-Xmx2048m'
echo 'android.native.buildOutput=verbose'
} >> gradle.properties
./gradlew clean assembleRelease
> gradle.properties
{
echo 'android.experimental.enableNewResourceShrinker.preciseShrinking=true'
echo 'android.enableAppCompileTimeRClass=true'
echo 'android.useAndroidX=true'
} >> gradle.properties

View File

@@ -25,4 +25,15 @@ find . -type f -exec sed -i \
-e "s/com\/rifsxd\/ksunext/$word1\/$word2\/$word3/g" \
-e "s/com_rifsxd_ksunext/${word1}_${word2}_${word3}/g" {} +
echo "Done."
# Append '-spoofed' to managerVersionName in build.gradle.kts
if [ -f "./build.gradle.kts" ]; then
sed -i 's/\(val managerVersionName by extra(getVersionName())\)/\1\nval managerVersionNameSpoofed = "${managerVersionName}-spoofed"/' ./build.gradle.kts
sed -i 's/\(versionName = managerVersionName\)/versionName = managerVersionNameSpoofed/' ./build.gradle.kts
fi
if [ -f "./app/build.gradle.kts" ]; then
sed -i '/val managerVersionName:/a val managerVersionNameSpoofed = "${managerVersionName}-spoofed"' ./app/build.gradle.kts
sed -i 's/outputFileName = "KernelSU_Next_${managerVersionName}_${managerVersionCode}-\$name.apk"/outputFileName = "KernelSU_Next_${managerVersionNameSpoofed}_${managerVersionCode}-\$name.apk"/' ./app/build.gradle.kts
fi
echo "Done."

View File

@@ -1,9 +0,0 @@
_ __ _ ____ _ _
| |/ /___ _ __ _ __ ___| / ___|| | | |
| ' // _ \ '__| '_ \ / _ \ \___ \| | | |
| . \ __/ | | | | | __/ |___) | |_| |
|_|\_\___|_| |_| |_|\___|_|____/ \___/
| \ | | _____ _| |_
| \| |/ _ \ \/ / __|
| |\ | __/> <| |_
|_| \_|\___/_/\_\\__|

View File

@@ -310,7 +310,7 @@ pub fn restore(
let skip_init = kmi.starts_with("android12-");
let (bootimage, bootdevice) = find_boot_image(&image, skip_init, false, false, workdir)?;
let (bootimage, bootdevice) = find_boot_image(&image, skip_init, false, false, workdir, &magiskboot)?;
println!("- Unpacking boot image");
let status = Command::new(&magiskboot)
@@ -323,21 +323,21 @@ pub fn restore(
ensure!(status.success(), "magiskboot unpack failed");
let no_ramdisk = !workdir.join("ramdisk.cpio").exists();
// let no_ramdisk = !workdir.join("ramdisk.cpio").exists();
let no_vendor_init_boot = !workdir
.join("vendor_ramdisk")
.join("init_boot.cpio")
.exists();
let no_vendor_ramdisk = !workdir
.join("vendor_ramdisk")
.join("ramdisk.cpio")
.exists();
let no_vendor_ramdisk = !workdir.join("vendor_ramdisk").join("ramdisk.cpio").exists();
let is_kernelsu_patched = is_kernelsu_patched(&magiskboot, workdir)?;
let is_kernelsu_patched_vendor_init_boot =
is_kernelsu_patched_vendor_init_boot(&magiskboot, workdir)?;
let is_kernelsu_patched_vendor_ramdisk =
is_kernelsu_patched_vendor_ramdisk(&magiskboot, workdir)?;
ensure!(
is_kernelsu_patched || is_kernelsu_patched_vendor_init_boot || is_kernelsu_patched_vendor_ramdisk,
is_kernelsu_patched
|| is_kernelsu_patched_vendor_init_boot
|| is_kernelsu_patched_vendor_ramdisk,
"boot image is not patched by KernelSU Next"
);
@@ -349,7 +349,7 @@ pub fn restore(
do_cpio_cmd(
&magiskboot,
workdir,
&format!("extract {0} {0}", BACKUP_FILENAME),
&format!("extract {BACKUP_FILENAME} {BACKUP_FILENAME}"),
)?;
let sha = std::fs::read(workdir.join(BACKUP_FILENAME))?;
let sha = String::from_utf8(sha)?;
@@ -371,41 +371,78 @@ pub fn restore(
}
if new_boot.is_none() {
if no_ramdisk {
if !no_vendor_init_boot {
// vendor init_boot restore
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
let status =
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
if status {
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
} else {
let vendor_init_boot = workdir.join("vendor_ramdisk").join("init_boot.cpio");
std::fs::remove_file(vendor_init_boot)?;
}
} else if !no_vendor_ramdisk {
// vendor ramdisk restore
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
let status =
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
if status {
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
} else {
let vendor_ramdisk = workdir.join("vendor_ramdisk").join("ramdisk.cpio");
std::fs::remove_file(vendor_ramdisk)?;
}
}
} else {
if !no_ramdisk {
println!("- Restoring /ramdisk");
println!("- Removing /ramdisk/kernelsu.ko");
// remove kernelsu.ko
do_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
// if init.real exists, restore it
println!("- Checking if init.real exists");
let status = do_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
if status {
println!("- /ramdisk/init.real exists");
println!("- Restoring /ramdisk/init.real to init");
do_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
} else {
println!("- /ramdisk/init.real not found");
println!("- Removing ramdisk.cpio");
let ramdisk = workdir.join("ramdisk.cpio");
std::fs::remove_file(ramdisk)?;
}
} else if !no_vendor_init_boot {
println!("- Restoring /vendor_ramdisk/init_boot");
println!("- Removing /vendor_ramdisk/init_boot/kernelsu.ko");
// vendor init_boot restore
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
println!("- Checking if init.real exists");
let status =
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
if status {
println!("- /vendor_ramdisk/init_boot/init.real exists");
println!("- Restoring /vendor_ramdisk/init_boot/init.real to init");
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
} else {
println!("- /vendor_ramdisk/init_boot/init.real not found");
println!("- Removing vendor_ramdisk/init_boot.cpio");
let vendor_init_boot = workdir.join("vendor_ramdisk").join("init_boot.cpio");
std::fs::remove_file(vendor_init_boot)?;
}
} else if !no_vendor_ramdisk {
println!("- Restoring /vendor_ramdisk/ramdisk");
println!("- Removing /vendor_ramdisk/ramdisk/kernelsu.ko");
// vendor ramdisk restore
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
let status =
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
if status {
println!("- /vendor_ramdisk/ramdisk/init.real exists");
println!("- Restoring /vendor_ramdisk/ramdisk/init.real to init");
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
} else {
println!("- /vendor_ramdisk/ramdisk/init.real not found");
println!("- Removing vendor_ramdisk/ramdisk.cpio");
let vendor_ramdisk = workdir.join("vendor_ramdisk").join("ramdisk.cpio");
std::fs::remove_file(vendor_ramdisk)?;
}
} else {
println!("- Restoring /ramdisk");
println!("- Removing /ramdisk/kernelsu.ko");
// remove kernelsu.ko
do_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
// if init.real exists, restore it
println!("- Checking if init.real exists");
let status = do_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
if status {
println!("- /ramdisk/init.real exists");
println!("- Restoring /ramdisk/init.real to init");
do_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
} else {
println!("- /ramdisk/init.real not found");
println!("- Removing ramdisk.cpio");
let ramdisk = workdir.join("ramdisk.cpio");
std::fs::remove_file(ramdisk)?;
}
@@ -483,8 +520,6 @@ fn do_patch(
magiskboot_path: Option<PathBuf>,
kmi: Option<String>,
) -> Result<()> {
println!(include_str!("banner"));
let patch_file = image.is_some();
#[cfg(target_os = "android")]
@@ -516,7 +551,7 @@ fn do_patch(
match get_current_kmi() {
Ok(value) => value,
Err(e) => {
println!("- {}", e);
println!("- {e}");
if let Some(image_path) = &image {
println!(
"- Trying to auto detect KMI version for {}",
@@ -539,7 +574,7 @@ fn do_patch(
let skip_init = kmi.starts_with("android12-");
let (bootimage, bootdevice) =
find_boot_image(&image, skip_init, ota, is_replace_kernel, workdir)?;
find_boot_image(&image, skip_init, ota, is_replace_kernel, workdir, &magiskboot)?;
let bootimage = bootimage.display().to_string();
@@ -585,20 +620,19 @@ fn do_patch(
.join("vendor_ramdisk")
.join("init_boot.cpio")
.exists();
let no_vendor_ramdisk = !workdir
.join("vendor_ramdisk")
.join("ramdisk.cpio")
.exists();
let no_vendor_ramdisk = !workdir.join("vendor_ramdisk").join("ramdisk.cpio").exists();
if no_ramdisk && no_vendor_init_boot && no_vendor_ramdisk {
bail!("No compatible ramdisk found.");
println!("- No compatible ramdisk found.");
println!("- Will create our own ramdisk!");
}
let is_magisk_patched = is_magisk_patched(&magiskboot, workdir)?;
let is_magisk_patched_vendor_init_boot =
is_magisk_patched_vendor_init_boot(&magiskboot, workdir)?;
let is_magisk_patched_vendor_ramdisk =
is_magisk_patched_vendor_ramdisk(&magiskboot, workdir)?;
let is_magisk_patched_vendor_ramdisk = is_magisk_patched_vendor_ramdisk(&magiskboot, workdir)?;
ensure!(
!is_magisk_patched || !is_magisk_patched_vendor_init_boot || !is_magisk_patched_vendor_ramdisk,
!is_magisk_patched
|| !is_magisk_patched_vendor_init_boot
|| !is_magisk_patched_vendor_ramdisk,
"Cannot work with Magisk patched image"
);
@@ -610,41 +644,59 @@ fn do_patch(
is_kernelsu_patched_vendor_ramdisk(&magiskboot, workdir)?;
let mut need_backup = false;
if !is_kernelsu_patched || (no_ramdisk && !is_kernelsu_patched_vendor_init_boot) || (no_ramdisk && no_vendor_init_boot && !is_kernelsu_patched_vendor_ramdisk)
if (no_ramdisk && !is_kernelsu_patched_vendor_init_boot)
|| (no_ramdisk && no_vendor_init_boot && !is_kernelsu_patched_vendor_ramdisk)
|| !is_kernelsu_patched
{
if no_ramdisk {
if !no_vendor_init_boot {
// vendor init_boot patching
let status = do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "exists init");
if status.is_ok() {
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
}
} else if !no_vendor_ramdisk {
// vendor ramdisk patching
let status = do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "exists init");
if status.is_ok() {
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
}
}
} else {
// kernelsu.ko is not exist, backup init if necessary
if !no_ramdisk {
println!("- Checking if /ramdisk/init exists");
let status = do_cpio_cmd(&magiskboot, workdir, "exists init");
if status.is_ok() {
println!("- Backing up ramdisk/init");
do_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
}
need_backup = flash;
} else if !no_vendor_init_boot {
println!("- Checking if /vendor_ramdisk/init_boot/init exists");
let status = do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "exists init");
if status.is_ok() {
println!("- Backing up vendor_ramdisk/init_boot/init");
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
}
need_backup = flash;
} else if !no_vendor_ramdisk {
println!("- Checking if /vendor_ramdisk/ramdisk/init exists");
let status = do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "exists init");
if status.is_ok() {
println!("- Backing up vendor_ramdisk/ramdisk/init");
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
}
need_backup = flash;
} else {
println!("- Checking if /ramdisk/init exists");
let status = do_cpio_cmd(&magiskboot, workdir, "exists init");
if status.is_ok() {
println!("- Backing up ramdisk/init");
do_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
}
need_backup = flash;
}
}
if no_ramdisk {
if !no_vendor_init_boot {
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
} else if !no_vendor_ramdisk {
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "add 0750 init init")?;
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "add 0750 kernelsu.ko kernelsu.ko")?;
}
if !no_ramdisk {
println!("- Patching /ramdisk");
do_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
do_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
} else if !no_vendor_init_boot {
println!("- Patching /vendor_ramdisk/init_boot");
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
} else if !no_vendor_ramdisk {
println!("- Patching /vendor_ramdisk/ramdisk");
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "add 0750 init init")?;
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "add 0750 kernelsu.ko kernelsu.ko")?;
} else {
println!("- Creating and Patching /ramdisk");
do_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
do_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
}
@@ -714,7 +766,7 @@ fn calculate_sha1(file_path: impl AsRef<Path>) -> Result<String> {
}
let result = hasher.finalize();
Ok(format!("{:x}", result))
Ok(format!("{result:x}"))
}
#[cfg(target_os = "android")]
@@ -730,7 +782,7 @@ fn do_backup(magiskboot: &Path, workdir: &Path, image: &str) -> Result<()> {
do_cpio_cmd(
magiskboot,
workdir,
&format!("add 0755 {0} {0}", BACKUP_FILENAME),
&format!("add 0755 {BACKUP_FILENAME} {BACKUP_FILENAME}"),
)?;
println!("- Stock image has been backup to");
println!("- {target}");
@@ -740,7 +792,7 @@ fn do_backup(magiskboot: &Path, workdir: &Path, image: &str) -> Result<()> {
#[cfg(target_os = "android")]
fn clean_backup(sha1: &str) -> Result<()> {
println!("- Clean up backup");
let backup_name = format!("{}{}", KSU_BACKUP_FILE_PREFIX, sha1);
let backup_name = format!("{KSU_BACKUP_FILE_PREFIX}{sha1}");
let dir = std::fs::read_dir(defs::KSU_BACKUP_DIR)?;
for entry in dir.flatten() {
let path = entry.path();
@@ -803,16 +855,17 @@ fn find_boot_image(
ota: bool,
is_replace_kernel: bool,
workdir: &Path,
magiskboot: &Path,
) -> Result<(PathBuf, Option<String>)> {
let bootimage;
let mut bootdevice = None;
if let Some(ref image) = *image {
ensure!(image.exists(), "boot image not found");
ensure!(image.exists(), "- Boot image not found");
bootimage = std::fs::canonicalize(image)?;
} else {
if cfg!(not(target_os = "android")) {
println!("- Current OS is not android, refusing auto bootimage/bootdevice detection");
bail!("Please specify a boot image");
bail!("- Please specify a boot image");
}
let mut slot_suffix =
utils::getprop("ro.boot.slot_suffix").unwrap_or_else(|| String::from(""));
@@ -825,27 +878,104 @@ fn find_boot_image(
}
};
let init_boot_exist =
Path::new(&format!("/dev/block/by-name/init_boot{slot_suffix}")).exists();
let vendor_boot_exist =
Path::new(&format!("/dev/block/by-name/vendor_boot{slot_suffix}")).exists();
let boot_partition = if !is_replace_kernel && init_boot_exist && !skip_init {
format!("/dev/block/by-name/init_boot{slot_suffix}")
} else if !is_replace_kernel && vendor_boot_exist && !skip_init {
format!("/dev/block/by-name/vendor_boot{slot_suffix}")
} else {
format!("/dev/block/by-name/boot{slot_suffix}")
};
let init_boot_partition = format!("/dev/block/by-name/init_boot{slot_suffix}");
let vendor_boot_partition = format!("/dev/block/by-name/vendor_boot{slot_suffix}");
let boot_partition = format!("/dev/block/by-name/boot{slot_suffix}");
println!("- Bootdevice: {boot_partition}");
let init_boot_exist = Path::new(&init_boot_partition).exists();
let vendor_boot_exist = Path::new(&vendor_boot_partition).exists();
// helper: unpack a partition and check for a ramdisk and init
fn unpack_and_check_init(
magiskboot: &Path,
workdir: &Path,
partition: &str,
ramdisk_cpio: &str,
) -> Result<bool> {
let tmp_img = workdir.join("probe.img");
dd(partition, &tmp_img)?;
let status = Command::new(magiskboot)
.current_dir(workdir)
.stdout(Stdio::null())
.stderr(Stdio::null())
.arg("unpack")
.arg(&tmp_img)
.status()?;
if !status.success() {
let _ = std::fs::remove_file(&tmp_img);
return Ok(false);
}
let ramdisk_path = workdir.join(ramdisk_cpio);
let has_init = if ramdisk_path.exists() {
Command::new(magiskboot)
.current_dir(workdir)
.stdout(Stdio::null())
.stderr(Stdio::null())
.arg("cpio")
.arg(ramdisk_cpio)
.arg("exists init")
.status()
.map(|s| s.success())
.unwrap_or(false)
} else {
false
};
// Clean up
let _ = std::fs::remove_file(&tmp_img);
let _ = std::fs::remove_file(workdir.join("ramdisk.cpio"));
let _ = std::fs::remove_dir_all(workdir.join("vendor_ramdisk"));
Ok(has_init)
}
let mut selected_partition = &boot_partition;
if !is_replace_kernel && init_boot_exist && !skip_init {
// try init_boot/ramdisk.cpio
if unpack_and_check_init(magiskboot, workdir, &init_boot_partition, "ramdisk.cpio")? {
println!("- Using init_boot partition (ramdisk.cpio).");
selected_partition = &init_boot_partition;
}
}
// try vendor_boot/vendor_ramdisk/init_boot.cpio
if selected_partition == &boot_partition && !is_replace_kernel && vendor_boot_exist && !skip_init {
if unpack_and_check_init(
magiskboot,
workdir,
&vendor_boot_partition,
"vendor_ramdisk/init_boot.cpio",
)? {
println!("- Using vendor_boot partition (vendor_ramdisk/init_boot.cpio).");
selected_partition = &vendor_boot_partition;
}
}
// try vendor_boot/vendor_ramdisk/ramdisk.cpio
if selected_partition == &boot_partition && !is_replace_kernel && vendor_boot_exist && !skip_init {
if unpack_and_check_init(
magiskboot,
workdir,
&vendor_boot_partition,
"vendor_ramdisk/ramdisk.cpio",
)? {
println!("- Using vendor_boot partition (vendor_ramdisk/ramdisk.cpio).");
selected_partition = &vendor_boot_partition;
}
}
if selected_partition == &boot_partition {
println!("- Using boot partition (ramdisk.cpio).");
}
println!("- Bootdevice: {selected_partition}");
let tmp_boot_path = workdir.join("boot.img");
dd(&boot_partition, &tmp_boot_path)?;
dd(selected_partition, &tmp_boot_path)?;
ensure!(tmp_boot_path.exists(), "boot image not found");
ensure!(tmp_boot_path.exists(), "- Tmp boot image not found");
bootimage = tmp_boot_path;
bootdevice = Some(boot_partition);
bootdevice = Some(selected_partition.to_string());
};
Ok((bootimage, bootdevice))
}

View File

@@ -370,13 +370,13 @@ pub fn run() -> Result<()> {
Commands::BootInfo { command } => match command {
BootInfo::CurrentKmi => {
let kmi = crate::boot_patch::get_current_kmi()?;
println!("{}", kmi);
println!("{kmi}");
// return here to avoid printing the error message
return Ok(());
}
BootInfo::SupportedKmi => {
let kmi = crate::assets::list_supported_kmi()?;
kmi.iter().for_each(|kmi| println!("{}", kmi));
kmi.iter().for_each(|kmi| println!("{kmi}"));
return Ok(());
}
},
@@ -388,7 +388,7 @@ pub fn run() -> Result<()> {
};
if let Err(e) = &result {
log::error!("Error: {:?}", e);
log::error!("Error: {e:?}");
}
result
}

View File

@@ -30,7 +30,7 @@ fn set_kernel_param(uid: u32) -> Result<()> {
fn get_pkg_uid(pkg: &str) -> Result<u32> {
// stat /data/data/<pkg>
let uid = rustix::fs::stat(format!("/data/data/{pkg}"))
.with_context(|| format!("stat /data/data/{}", pkg))?
.with_context(|| format!("stat /data/data/{pkg}"))?
.st_uid;
Ok(uid)
}

View File

@@ -44,3 +44,5 @@ pub const NO_TMPFS_PATH: &str = concatcp!(WORKING_DIR, ".notmpfs");
pub const NO_MOUNT_PATH: &str = concatcp!(WORKING_DIR, ".nomount");
pub const MOUNT_SYSTEM: &str = "Magic_Mount";
pub const GLOBAL_NAMESPACE_FILE: &str = concatcp!(WORKING_DIR, ".global_mnt");

View File

@@ -28,7 +28,7 @@ pub fn on_post_data_fs() -> Result<()> {
} else {
// Then exec common post-fs-data scripts
if let Err(e) = crate::module::exec_common_scripts("post-fs-data.d", true) {
warn!("exec common post-fs-data scripts failed: {}", e);
warn!("exec common post-fs-data scripts failed: {e}");
}
}
@@ -41,21 +41,21 @@ pub fn on_post_data_fs() -> Result<()> {
if safe_mode {
warn!("safe mode, skip post-fs-data scripts and disable all modules!");
if let Err(e) = crate::module::disable_all_modules() {
warn!("disable all modules failed: {}", e);
warn!("disable all modules failed: {e}");
}
return Ok(());
}
if let Err(e) = prune_modules() {
warn!("prune modules failed: {}", e);
warn!("prune modules failed: {e}");
}
if let Err(e) = handle_updated_modules() {
warn!("handle updated modules failed: {}", e);
warn!("handle updated modules failed: {e}");
}
if let Err(e) = restorecon::restorecon() {
warn!("restorecon failed: {}", e);
warn!("restorecon failed: {e}");
}
// load sepolicy.rule
@@ -64,13 +64,13 @@ pub fn on_post_data_fs() -> Result<()> {
}
if let Err(e) = crate::profile::apply_sepolies() {
warn!("apply root profile sepolicy failed: {}", e);
warn!("apply root profile sepolicy failed: {e}");
}
// mount temp dir
if !Path::new(NO_TMPFS_PATH).exists() {
if let Err(e) = mount(KSU_MOUNT_SOURCE, TEMP_DIR, "tmpfs", MountFlags::empty(), "") {
warn!("do temp dir mount failed: {}", e);
warn!("do temp dir mount failed: {e}");
}
} else {
info!("no tmpfs requested");
@@ -79,18 +79,18 @@ pub fn on_post_data_fs() -> Result<()> {
// exec modules post-fs-data scripts
// TODO: Add timeout
if let Err(e) = crate::module::exec_stage_script("post-fs-data", true) {
warn!("exec post-fs-data scripts failed: {}", e);
warn!("exec post-fs-data scripts failed: {e}");
}
// load system.prop
if let Err(e) = crate::module::load_system_prop() {
warn!("load system.prop failed: {}", e);
warn!("load system.prop failed: {e}");
}
// mount module systemlessly by magic mount
if !Path::new(NO_MOUNT_PATH).exists() {
if let Err(e) = mount_modules_systemlessly() {
warn!("do systemless mount failed: {}", e);
warn!("do systemless mount failed: {e}");
}
} else {
info!("no mount requested");
@@ -180,7 +180,7 @@ fn catch_bootlog(logname: &str, command: Vec<&str>) -> Result<()> {
};
if let Err(e) = result {
warn!("Failed to start logcat: {:#}", e);
warn!("Failed to start logcat: {e:#}");
}
Ok(())

View File

@@ -416,14 +416,14 @@ fn do_magic_mount<P: AsRef<Path>, WP: AsRef<Path>>(
pub fn magic_mount() -> Result<()> {
if let Some(root) = collect_module_files()? {
log::debug!("collected: {:#?}", root);
log::debug!("collected: {root:#?}");
let tmp_dir = PathBuf::from(MAGIC_MOUNT_WORK_DIR);
ensure_dir_exists(&tmp_dir)?;
mount(KSU_MOUNT_SOURCE, &tmp_dir, "tmpfs", MountFlags::empty(), "").context("mount tmp")?;
mount_change(&tmp_dir, MountPropagationFlags::PRIVATE).context("make tmp private")?;
let result = do_magic_mount("/", &tmp_dir, root, false);
if let Err(e) = unmount(&tmp_dir, UnmountFlags::DETACH) {
log::error!("failed to unmount tmp {}", e);
log::error!("failed to unmount tmp {e}");
}
fs::remove_dir(tmp_dir).ok();
result

View File

@@ -258,7 +258,7 @@ pub fn prune_modules() -> Result<()> {
let uninstaller = module.join("uninstall.sh");
if uninstaller.exists() {
if let Err(e) = exec_script(uninstaller, true) {
warn!("Failed to exec uninstaller: {}", e);
warn!("Failed to exec uninstaller: {e}");
}
}
@@ -301,9 +301,6 @@ pub fn install_module(zip: &str) -> Result<()> {
fn inner(zip: &str) -> Result<()> {
ensure_boot_completed()?;
// print banner
println!(include_str!("banner"));
assets::ensure_binaries(false).with_context(|| "Failed to extract assets")?;
// first check if working dir is usable
@@ -323,7 +320,7 @@ pub fn install_module(zip: &str) -> Result<()> {
module_prop.insert(k, v);
},
)?;
info!("module prop: {:?}", module_prop);
info!("module prop: {module_prop:?}");
let Some(module_id) = module_prop.get("id") else {
bail!("module id not found in module.prop!");
@@ -401,7 +398,7 @@ pub fn restore_module(id: &str) -> Result<()> {
}
pub fn run_action(id: &str) -> Result<()> {
let action_script_path = format!("/data/adb/modules/{}/action.sh", id);
let action_script_path = format!("/data/adb/modules/{id}/action.sh");
exec_script(&action_script_path, true)
}

View File

@@ -70,9 +70,9 @@ pub fn apply_sepolies() -> Result<()> {
};
let sepolicy = sepolicy.path();
if sepolicy::apply_file(&sepolicy).is_ok() {
log::info!("profile sepolicy applied: {:?}", sepolicy);
log::info!("profile sepolicy applied: {sepolicy:?}");
} else {
log::info!("profile sepolicy apply failed: {:?}", sepolicy);
log::info!("profile sepolicy apply failed: {sepolicy:?}");
}
}
Ok(())

View File

@@ -697,7 +697,7 @@ fn apply_one_rule<'a>(statement: &'a PolicyStatement<'a>, strict: bool) -> Resul
for policy in policies {
if !rustix::process::ksu_set_policy(&FfiPolicy::from(policy)) {
log::warn!("apply rule: {:?} failed.", statement);
log::warn!("apply rule: {statement:?} failed.");
if strict {
return Err(anyhow::anyhow!("apply rule {:?} failed.", statement));
}

View File

@@ -261,7 +261,9 @@ pub fn root_shell() -> Result<()> {
// switch to global mount namespace
#[cfg(any(target_os = "linux", target_os = "android"))]
if mount_master {
let global_namespace_enable =
std::fs::read_to_string(defs::GLOBAL_NAMESPACE_FILE).unwrap_or("0".to_string());
if global_namespace_enable.trim() == "1" || mount_master {
let _ = utils::switch_mnt_ns(1);
}

View File

@@ -104,12 +104,12 @@ pub fn is_safe_mode() -> bool {
|| getprop("ro.sys.safemode")
.filter(|prop| prop == "1")
.is_some();
log::info!("safemode: {}", safemode);
log::info!("safemode: {safemode}");
if safemode {
return true;
}
let safemode = ksucalls::check_kernel_safemode();
log::info!("kernel_safemode: {}", safemode);
log::info!("kernel_safemode: {safemode}");
safemode
}

View File

@@ -1,9 +0,0 @@
_ __ _ ____ _ _
| |/ /___ _ __ _ __ ___| / ___|| | | |
| ' // _ \ '__| '_ \ / _ \ \___ \| | | |
| . \ __/ | | | | | __/ |___) | |_| |
|_|\_\___|_| |_| |_|\___|_|____/ \___/
| \ | | _____ _| |_
| \| |/ _ \ \/ / __|
| |\ | __/> <| |_
|_| \_|\___/_/\_\\__|

View File

@@ -310,7 +310,7 @@ pub fn restore(
let skip_init = kmi.starts_with("android12-");
let (bootimage, bootdevice) = find_boot_image(&image, skip_init, false, false, workdir)?;
let (bootimage, bootdevice) = find_boot_image(&image, skip_init, false, false, workdir, &magiskboot)?;
println!("- Unpacking boot image");
let status = Command::new(&magiskboot)
@@ -323,21 +323,21 @@ pub fn restore(
ensure!(status.success(), "magiskboot unpack failed");
let no_ramdisk = !workdir.join("ramdisk.cpio").exists();
// let no_ramdisk = !workdir.join("ramdisk.cpio").exists();
let no_vendor_init_boot = !workdir
.join("vendor_ramdisk")
.join("init_boot.cpio")
.exists();
let no_vendor_ramdisk = !workdir
.join("vendor_ramdisk")
.join("ramdisk.cpio")
.exists();
let no_vendor_ramdisk = !workdir.join("vendor_ramdisk").join("ramdisk.cpio").exists();
let is_kernelsu_patched = is_kernelsu_patched(&magiskboot, workdir)?;
let is_kernelsu_patched_vendor_init_boot =
is_kernelsu_patched_vendor_init_boot(&magiskboot, workdir)?;
let is_kernelsu_patched_vendor_ramdisk =
is_kernelsu_patched_vendor_ramdisk(&magiskboot, workdir)?;
ensure!(
is_kernelsu_patched || is_kernelsu_patched_vendor_init_boot || is_kernelsu_patched_vendor_ramdisk,
is_kernelsu_patched
|| is_kernelsu_patched_vendor_init_boot
|| is_kernelsu_patched_vendor_ramdisk,
"boot image is not patched by KernelSU Next"
);
@@ -349,7 +349,7 @@ pub fn restore(
do_cpio_cmd(
&magiskboot,
workdir,
&format!("extract {0} {0}", BACKUP_FILENAME),
&format!("extract {BACKUP_FILENAME} {BACKUP_FILENAME}"),
)?;
let sha = std::fs::read(workdir.join(BACKUP_FILENAME))?;
let sha = String::from_utf8(sha)?;
@@ -371,41 +371,78 @@ pub fn restore(
}
if new_boot.is_none() {
if no_ramdisk {
if !no_vendor_init_boot {
// vendor init_boot restore
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
let status =
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
if status {
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
} else {
let vendor_init_boot = workdir.join("vendor_ramdisk").join("init_boot.cpio");
std::fs::remove_file(vendor_init_boot)?;
}
} else if !no_vendor_ramdisk {
// vendor ramdisk restore
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
let status =
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
if status {
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
} else {
let vendor_ramdisk = workdir.join("vendor_ramdisk").join("ramdisk.cpio");
std::fs::remove_file(vendor_ramdisk)?;
}
}
} else {
if !no_ramdisk {
println!("- Restoring /ramdisk");
println!("- Removing /ramdisk/kernelsu.ko");
// remove kernelsu.ko
do_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
// if init.real exists, restore it
println!("- Checking if init.real exists");
let status = do_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
if status {
println!("- /ramdisk/init.real exists");
println!("- Restoring /ramdisk/init.real to init");
do_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
} else {
println!("- /ramdisk/init.real not found");
println!("- Removing ramdisk.cpio");
let ramdisk = workdir.join("ramdisk.cpio");
std::fs::remove_file(ramdisk)?;
}
} else if !no_vendor_init_boot {
println!("- Restoring /vendor_ramdisk/init_boot");
println!("- Removing /vendor_ramdisk/init_boot/kernelsu.ko");
// vendor init_boot restore
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
println!("- Checking if init.real exists");
let status =
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
if status {
println!("- /vendor_ramdisk/init_boot/init.real exists");
println!("- Restoring /vendor_ramdisk/init_boot/init.real to init");
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
} else {
println!("- /vendor_ramdisk/init_boot/init.real not found");
println!("- Removing vendor_ramdisk/init_boot.cpio");
let vendor_init_boot = workdir.join("vendor_ramdisk").join("init_boot.cpio");
std::fs::remove_file(vendor_init_boot)?;
}
} else if !no_vendor_ramdisk {
println!("- Restoring /vendor_ramdisk/ramdisk");
println!("- Removing /vendor_ramdisk/ramdisk/kernelsu.ko");
// vendor ramdisk restore
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
let status =
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
if status {
println!("- /vendor_ramdisk/ramdisk/init.real exists");
println!("- Restoring /vendor_ramdisk/ramdisk/init.real to init");
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
} else {
println!("- /vendor_ramdisk/ramdisk/init.real not found");
println!("- Removing vendor_ramdisk/ramdisk.cpio");
let vendor_ramdisk = workdir.join("vendor_ramdisk").join("ramdisk.cpio");
std::fs::remove_file(vendor_ramdisk)?;
}
} else {
println!("- Restoring /ramdisk");
println!("- Removing /ramdisk/kernelsu.ko");
// remove kernelsu.ko
do_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
// if init.real exists, restore it
println!("- Checking if init.real exists");
let status = do_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
if status {
println!("- /ramdisk/init.real exists");
println!("- Restoring /ramdisk/init.real to init");
do_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
} else {
println!("- /ramdisk/init.real not found");
println!("- Removing ramdisk.cpio");
let ramdisk = workdir.join("ramdisk.cpio");
std::fs::remove_file(ramdisk)?;
}
@@ -483,8 +520,6 @@ fn do_patch(
magiskboot_path: Option<PathBuf>,
kmi: Option<String>,
) -> Result<()> {
println!(include_str!("banner"));
let patch_file = image.is_some();
#[cfg(target_os = "android")]
@@ -516,7 +551,7 @@ fn do_patch(
match get_current_kmi() {
Ok(value) => value,
Err(e) => {
println!("- {}", e);
println!("- {e}");
if let Some(image_path) = &image {
println!(
"- Trying to auto detect KMI version for {}",
@@ -539,7 +574,7 @@ fn do_patch(
let skip_init = kmi.starts_with("android12-");
let (bootimage, bootdevice) =
find_boot_image(&image, skip_init, ota, is_replace_kernel, workdir)?;
find_boot_image(&image, skip_init, ota, is_replace_kernel, workdir, &magiskboot)?;
let bootimage = bootimage.display().to_string();
@@ -585,20 +620,19 @@ fn do_patch(
.join("vendor_ramdisk")
.join("init_boot.cpio")
.exists();
let no_vendor_ramdisk = !workdir
.join("vendor_ramdisk")
.join("ramdisk.cpio")
.exists();
let no_vendor_ramdisk = !workdir.join("vendor_ramdisk").join("ramdisk.cpio").exists();
if no_ramdisk && no_vendor_init_boot && no_vendor_ramdisk {
bail!("No compatible ramdisk found.");
println!("- No compatible ramdisk found.");
println!("- Will create our own ramdisk!");
}
let is_magisk_patched = is_magisk_patched(&magiskboot, workdir)?;
let is_magisk_patched_vendor_init_boot =
is_magisk_patched_vendor_init_boot(&magiskboot, workdir)?;
let is_magisk_patched_vendor_ramdisk =
is_magisk_patched_vendor_ramdisk(&magiskboot, workdir)?;
let is_magisk_patched_vendor_ramdisk = is_magisk_patched_vendor_ramdisk(&magiskboot, workdir)?;
ensure!(
!is_magisk_patched || !is_magisk_patched_vendor_init_boot || !is_magisk_patched_vendor_ramdisk,
!is_magisk_patched
|| !is_magisk_patched_vendor_init_boot
|| !is_magisk_patched_vendor_ramdisk,
"Cannot work with Magisk patched image"
);
@@ -610,41 +644,59 @@ fn do_patch(
is_kernelsu_patched_vendor_ramdisk(&magiskboot, workdir)?;
let mut need_backup = false;
if !is_kernelsu_patched || (no_ramdisk && !is_kernelsu_patched_vendor_init_boot) || (no_ramdisk && no_vendor_init_boot && !is_kernelsu_patched_vendor_ramdisk)
if (no_ramdisk && !is_kernelsu_patched_vendor_init_boot)
|| (no_ramdisk && no_vendor_init_boot && !is_kernelsu_patched_vendor_ramdisk)
|| !is_kernelsu_patched
{
if no_ramdisk {
if !no_vendor_init_boot {
// vendor init_boot patching
let status = do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "exists init");
if status.is_ok() {
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
}
} else if !no_vendor_ramdisk {
// vendor ramdisk patching
let status = do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "exists init");
if status.is_ok() {
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
}
}
} else {
// kernelsu.ko is not exist, backup init if necessary
if !no_ramdisk {
println!("- Checking if /ramdisk/init exists");
let status = do_cpio_cmd(&magiskboot, workdir, "exists init");
if status.is_ok() {
println!("- Backing up ramdisk/init");
do_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
}
need_backup = flash;
} else if !no_vendor_init_boot {
println!("- Checking if /vendor_ramdisk/init_boot/init exists");
let status = do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "exists init");
if status.is_ok() {
println!("- Backing up vendor_ramdisk/init_boot/init");
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
}
need_backup = flash;
} else if !no_vendor_ramdisk {
println!("- Checking if /vendor_ramdisk/ramdisk/init exists");
let status = do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "exists init");
if status.is_ok() {
println!("- Backing up vendor_ramdisk/ramdisk/init");
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
}
need_backup = flash;
} else {
println!("- Checking if /ramdisk/init exists");
let status = do_cpio_cmd(&magiskboot, workdir, "exists init");
if status.is_ok() {
println!("- Backing up ramdisk/init");
do_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
}
need_backup = flash;
}
}
if no_ramdisk {
if !no_vendor_init_boot {
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
} else if !no_vendor_ramdisk {
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "add 0750 init init")?;
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "add 0750 kernelsu.ko kernelsu.ko")?;
}
if !no_ramdisk {
println!("- Patching /ramdisk");
do_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
do_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
} else if !no_vendor_init_boot {
println!("- Patching /vendor_ramdisk/init_boot");
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
} else if !no_vendor_ramdisk {
println!("- Patching /vendor_ramdisk/ramdisk");
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "add 0750 init init")?;
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "add 0750 kernelsu.ko kernelsu.ko")?;
} else {
println!("- Creating and Patching /ramdisk");
do_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
do_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
}
@@ -714,7 +766,7 @@ fn calculate_sha1(file_path: impl AsRef<Path>) -> Result<String> {
}
let result = hasher.finalize();
Ok(format!("{:x}", result))
Ok(format!("{result:x}"))
}
#[cfg(target_os = "android")]
@@ -730,7 +782,7 @@ fn do_backup(magiskboot: &Path, workdir: &Path, image: &str) -> Result<()> {
do_cpio_cmd(
magiskboot,
workdir,
&format!("add 0755 {0} {0}", BACKUP_FILENAME),
&format!("add 0755 {BACKUP_FILENAME} {BACKUP_FILENAME}"),
)?;
println!("- Stock image has been backup to");
println!("- {target}");
@@ -740,7 +792,7 @@ fn do_backup(magiskboot: &Path, workdir: &Path, image: &str) -> Result<()> {
#[cfg(target_os = "android")]
fn clean_backup(sha1: &str) -> Result<()> {
println!("- Clean up backup");
let backup_name = format!("{}{}", KSU_BACKUP_FILE_PREFIX, sha1);
let backup_name = format!("{KSU_BACKUP_FILE_PREFIX}{sha1}");
let dir = std::fs::read_dir(defs::KSU_BACKUP_DIR)?;
for entry in dir.flatten() {
let path = entry.path();
@@ -803,16 +855,17 @@ fn find_boot_image(
ota: bool,
is_replace_kernel: bool,
workdir: &Path,
magiskboot: &Path,
) -> Result<(PathBuf, Option<String>)> {
let bootimage;
let mut bootdevice = None;
if let Some(ref image) = *image {
ensure!(image.exists(), "boot image not found");
ensure!(image.exists(), "- Boot image not found");
bootimage = std::fs::canonicalize(image)?;
} else {
if cfg!(not(target_os = "android")) {
println!("- Current OS is not android, refusing auto bootimage/bootdevice detection");
bail!("Please specify a boot image");
bail!("- Please specify a boot image");
}
let mut slot_suffix =
utils::getprop("ro.boot.slot_suffix").unwrap_or_else(|| String::from(""));
@@ -825,27 +878,104 @@ fn find_boot_image(
}
};
let init_boot_exist =
Path::new(&format!("/dev/block/by-name/init_boot{slot_suffix}")).exists();
let vendor_boot_exist =
Path::new(&format!("/dev/block/by-name/vendor_boot{slot_suffix}")).exists();
let boot_partition = if !is_replace_kernel && init_boot_exist && !skip_init {
format!("/dev/block/by-name/init_boot{slot_suffix}")
} else if !is_replace_kernel && vendor_boot_exist && !skip_init {
format!("/dev/block/by-name/vendor_boot{slot_suffix}")
} else {
format!("/dev/block/by-name/boot{slot_suffix}")
};
let init_boot_partition = format!("/dev/block/by-name/init_boot{slot_suffix}");
let vendor_boot_partition = format!("/dev/block/by-name/vendor_boot{slot_suffix}");
let boot_partition = format!("/dev/block/by-name/boot{slot_suffix}");
println!("- Bootdevice: {boot_partition}");
let init_boot_exist = Path::new(&init_boot_partition).exists();
let vendor_boot_exist = Path::new(&vendor_boot_partition).exists();
// helper: unpack a partition and check for a ramdisk and init
fn unpack_and_check_init(
magiskboot: &Path,
workdir: &Path,
partition: &str,
ramdisk_cpio: &str,
) -> Result<bool> {
let tmp_img = workdir.join("probe.img");
dd(partition, &tmp_img)?;
let status = Command::new(magiskboot)
.current_dir(workdir)
.stdout(Stdio::null())
.stderr(Stdio::null())
.arg("unpack")
.arg(&tmp_img)
.status()?;
if !status.success() {
let _ = std::fs::remove_file(&tmp_img);
return Ok(false);
}
let ramdisk_path = workdir.join(ramdisk_cpio);
let has_init = if ramdisk_path.exists() {
Command::new(magiskboot)
.current_dir(workdir)
.stdout(Stdio::null())
.stderr(Stdio::null())
.arg("cpio")
.arg(ramdisk_cpio)
.arg("exists init")
.status()
.map(|s| s.success())
.unwrap_or(false)
} else {
false
};
// Clean up
let _ = std::fs::remove_file(&tmp_img);
let _ = std::fs::remove_file(workdir.join("ramdisk.cpio"));
let _ = std::fs::remove_dir_all(workdir.join("vendor_ramdisk"));
Ok(has_init)
}
let mut selected_partition = &boot_partition;
if !is_replace_kernel && init_boot_exist && !skip_init {
// try init_boot/ramdisk.cpio
if unpack_and_check_init(magiskboot, workdir, &init_boot_partition, "ramdisk.cpio")? {
println!("- Using init_boot partition (ramdisk.cpio).");
selected_partition = &init_boot_partition;
}
}
// try vendor_boot/vendor_ramdisk/init_boot.cpio
if selected_partition == &boot_partition && !is_replace_kernel && vendor_boot_exist && !skip_init {
if unpack_and_check_init(
magiskboot,
workdir,
&vendor_boot_partition,
"vendor_ramdisk/init_boot.cpio",
)? {
println!("- Using vendor_boot partition (vendor_ramdisk/init_boot.cpio).");
selected_partition = &vendor_boot_partition;
}
}
// try vendor_boot/vendor_ramdisk/ramdisk.cpio
if selected_partition == &boot_partition && !is_replace_kernel && vendor_boot_exist && !skip_init {
if unpack_and_check_init(
magiskboot,
workdir,
&vendor_boot_partition,
"vendor_ramdisk/ramdisk.cpio",
)? {
println!("- Using vendor_boot partition (vendor_ramdisk/ramdisk.cpio).");
selected_partition = &vendor_boot_partition;
}
}
if selected_partition == &boot_partition {
println!("- Using boot partition (ramdisk.cpio).");
}
println!("- Bootdevice: {selected_partition}");
let tmp_boot_path = workdir.join("boot.img");
dd(&boot_partition, &tmp_boot_path)?;
dd(selected_partition, &tmp_boot_path)?;
ensure!(tmp_boot_path.exists(), "boot image not found");
ensure!(tmp_boot_path.exists(), "- Tmp boot image not found");
bootimage = tmp_boot_path;
bootdevice = Some(boot_partition);
bootdevice = Some(selected_partition.to_string());
};
Ok((bootimage, bootdevice))
}

View File

@@ -385,13 +385,13 @@ pub fn run() -> Result<()> {
Commands::BootInfo { command } => match command {
BootInfo::CurrentKmi => {
let kmi = crate::boot_patch::get_current_kmi()?;
println!("{}", kmi);
println!("{kmi}");
// return here to avoid printing the error message
return Ok(());
}
BootInfo::SupportedKmi => {
let kmi = crate::assets::list_supported_kmi()?;
kmi.iter().for_each(|kmi| println!("{}", kmi));
kmi.iter().for_each(|kmi| println!("{kmi}"));
return Ok(());
}
},
@@ -403,7 +403,7 @@ pub fn run() -> Result<()> {
};
if let Err(e) = &result {
log::error!("Error: {:?}", e);
log::error!("Error: {e:?}");
}
result
}

View File

@@ -30,7 +30,7 @@ fn set_kernel_param(uid: u32) -> Result<()> {
fn get_pkg_uid(pkg: &str) -> Result<u32> {
// stat /data/data/<pkg>
let uid = rustix::fs::stat(format!("/data/data/{pkg}"))
.with_context(|| format!("stat /data/data/{}", pkg))?
.with_context(|| format!("stat /data/data/{pkg}"))?
.st_uid;
Ok(uid)
}

View File

@@ -47,3 +47,5 @@ pub const KSU_BACKUP_FILE_PREFIX: &str = "ksu_backup_";
pub const BACKUP_FILENAME: &str = "stock_image.sha1";
pub const MOUNT_SYSTEM: &str = "OverlayFS";
pub const GLOBAL_NAMESPACE_FILE: &str = concatcp!(WORKING_DIR, ".global_mnt");

View File

@@ -83,13 +83,13 @@ pub fn mount_modules_systemlessly(module_dir: &str) -> Result<()> {
// mount /system first
if let Err(e) = mount_partition("system", &system_lowerdir) {
warn!("mount system failed: {:#}", e);
warn!("mount system failed: {e:#}");
}
// mount other partitions
for (k, v) in partition_lowerdir {
if let Err(e) = mount_partition(&k, &v) {
warn!("mount {k} failed: {:#}", e);
warn!("mount {k} failed: {e:#}");
}
}
@@ -120,7 +120,7 @@ pub fn on_post_data_fs() -> Result<()> {
} else {
// Then exec common post-fs-data scripts
if let Err(e) = crate::module::exec_common_scripts("post-fs-data.d", true) {
warn!("exec common post-fs-data scripts failed: {}", e);
warn!("exec common post-fs-data scripts failed: {e}");
}
}
@@ -168,17 +168,17 @@ pub fn on_post_data_fs() -> Result<()> {
if safe_mode {
warn!("safe mode, skip post-fs-data scripts and disable all modules!");
if let Err(e) = crate::module::disable_all_modules() {
warn!("disable all modules failed: {}", e);
warn!("disable all modules failed: {e}");
}
return Ok(());
}
if let Err(e) = prune_modules() {
warn!("prune modules failed: {}", e);
warn!("prune modules failed: {e}");
}
if let Err(e) = restorecon::restorecon() {
warn!("restorecon failed: {}", e);
warn!("restorecon failed: {e}");
}
// load sepolicy.rule
@@ -187,28 +187,28 @@ pub fn on_post_data_fs() -> Result<()> {
}
if let Err(e) = crate::profile::apply_sepolies() {
warn!("apply root profile sepolicy failed: {}", e);
warn!("apply root profile sepolicy failed: {e}");
}
// mount temp dir
if let Err(e) = mount::mount_tmpfs(utils::get_tmp_path()) {
warn!("do temp dir mount failed: {}", e);
warn!("do temp dir mount failed: {e}");
}
// exec modules post-fs-data scripts
// TODO: Add timeout
if let Err(e) = crate::module::exec_stage_script("post-fs-data", true) {
warn!("exec post-fs-data scripts failed: {}", e);
warn!("exec post-fs-data scripts failed: {e}");
}
// load system.prop
if let Err(e) = crate::module::load_system_prop() {
warn!("load system.prop failed: {}", e);
warn!("load system.prop failed: {e}");
}
// mount module systemlessly by overlay
if let Err(e) = mount_modules_systemlessly(module_dir) {
warn!("do systemless mount failed: {}", e);
warn!("do systemless mount failed: {e}");
}
run_stage("post-mount", true);
@@ -298,7 +298,7 @@ fn catch_bootlog(logname: &str, command: Vec<&str>) -> Result<()> {
};
if let Err(e) = result {
warn!("Failed to start logcat: {:#}", e);
warn!("Failed to start logcat: {e:#}");
}
Ok(())

View File

@@ -274,7 +274,7 @@ pub fn prune_modules() -> Result<()> {
let uninstaller = module.join("uninstall.sh");
if uninstaller.exists() {
if let Err(e) = exec_script(uninstaller, true) {
warn!("Failed to exec uninstaller: {}", e);
warn!("Failed to exec uninstaller: {e}");
}
}
@@ -324,9 +324,6 @@ fn create_module_image(image: &str, image_size: u64) -> Result<()> {
fn _install_module(zip: &str) -> Result<()> {
ensure_boot_completed()?;
// print banner
println!(include_str!("banner"));
assets::ensure_binaries(false).with_context(|| "Failed to extract assets")?;
// first check if workding dir is usable
@@ -346,7 +343,7 @@ fn _install_module(zip: &str) -> Result<()> {
module_prop.insert(k, v);
},
)?;
info!("module prop: {:?}", module_prop);
info!("module prop: {module_prop:?}");
let Some(module_id) = module_prop.get("id") else {
bail!("module id not found in module.prop!");
@@ -475,13 +472,13 @@ fn _install_module(zip: &str) -> Result<()> {
let _dontdrop = mount::AutoMountExt4::try_new(tmp_module_img, module_update_tmp_dir, true)?;
info!("mounted {} to {}", tmp_module_img, module_update_tmp_dir);
info!("mounted {tmp_module_img} to {module_update_tmp_dir}");
setsyscon(module_update_tmp_dir)?;
let module_dir = format!("{module_update_tmp_dir}/{module_id}");
ensure_clean_dir(&module_dir)?;
info!("module dir: {}", module_dir);
info!("module dir: {module_dir}");
// unzip the image and move it to modules_update/<id> dir
let file = File::open(zip)?;
@@ -673,7 +670,7 @@ pub fn restore_module(id: &str) -> Result<()> {
}
pub fn run_action(id: &str) -> Result<()> {
let action_script_path = format!("/data/adb/modules/{}/action.sh", id);
let action_script_path = format!("/data/adb/modules/{id}/action.sh");
exec_script(&action_script_path, true)
}

View File

@@ -138,7 +138,7 @@ pub fn mount_overlayfs(
})();
if let Err(e) = result {
warn!("fsopen mount failed: {:#}, fallback to mount", e);
warn!("fsopen mount failed: {e:#}, fallback to mount");
let mut data = format!("lowerdir={lowerdir_config}");
if let (Some(upperdir), Some(workdir)) = (upperdir, workdir) {
data = format!("{data},upperdir={upperdir},workdir={workdir}");
@@ -246,7 +246,7 @@ fn mount_overlay_child(
}
// merge modules and stock
if let Err(e) = mount_overlayfs(&lower_dirs, stock_root, None, None, mount_point) {
warn!("failed: {:#}, fallback to bind mount", e);
warn!("failed: {e:#}, fallback to bind mount");
bind_mount(stock_root, mount_point)?;
}
Ok(())
@@ -259,7 +259,7 @@ pub fn mount_overlay(
workdir: Option<PathBuf>,
upperdir: Option<PathBuf>,
) -> Result<()> {
info!("mount overlay for {}", root);
info!("mount overlay for {root}");
std::env::set_current_dir(root).with_context(|| format!("failed to chdir to {root}"))?;
let stock_root = ".";
@@ -290,10 +290,7 @@ pub fn mount_overlay(
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
);
warn!("failed to mount overlay for child {mount_point}: {e:#}, revert");
umount_dir(root).with_context(|| format!("failed to revert {root}"))?;
bail!(e);
}

View File

@@ -70,9 +70,9 @@ pub fn apply_sepolies() -> Result<()> {
};
let sepolicy = sepolicy.path();
if sepolicy::apply_file(&sepolicy).is_ok() {
log::info!("profile sepolicy applied: {:?}", sepolicy);
log::info!("profile sepolicy applied: {sepolicy:?}");
} else {
log::info!("profile sepolicy apply failed: {:?}", sepolicy);
log::info!("profile sepolicy apply failed: {sepolicy:?}");
}
}
Ok(())

View File

@@ -697,7 +697,7 @@ fn apply_one_rule<'a>(statement: &'a PolicyStatement<'a>, strict: bool) -> Resul
for policy in policies {
if !rustix::process::ksu_set_policy(&FfiPolicy::from(policy)) {
log::warn!("apply rule: {:?} failed.", statement);
log::warn!("apply rule: {statement:?} failed.");
if strict {
return Err(anyhow::anyhow!("apply rule {:?} failed.", statement));
}

View File

@@ -261,7 +261,9 @@ pub fn root_shell() -> Result<()> {
// switch to global mount namespace
#[cfg(any(target_os = "linux", target_os = "android"))]
if mount_master {
let global_namespace_enable =
std::fs::read_to_string(defs::GLOBAL_NAMESPACE_FILE).unwrap_or("0".to_string());
if global_namespace_enable.trim() == "1" || mount_master {
let _ = utils::switch_mnt_ns(1);
}

View File

@@ -110,12 +110,12 @@ pub fn is_safe_mode() -> bool {
|| getprop("ro.sys.safemode")
.filter(|prop| prop == "1")
.is_some();
log::info!("safemode: {}", safemode);
log::info!("safemode: {safemode}");
if safemode {
return true;
}
let safemode = ksucalls::check_kernel_safemode();
log::info!("kernel_safemode: {}", safemode);
log::info!("kernel_safemode: {safemode}");
safemode
}
@@ -240,7 +240,7 @@ pub fn get_tmp_path() -> &'static str {
CHOSEN_TMP_PATH.get_or_init(|| {
let r = find_temp_path();
log::info!("Chosen temp_path: {}", r);
log::info!("Chosen temp_path: {r}");
r
})
}
@@ -367,7 +367,7 @@ fn copy_xattrs(src_path: impl AsRef<Path>, dest_path: impl AsRef<Path>) -> Resul
if let Err(e) =
extattr::lsetxattr(dest_path.as_ref(), &xattr, &value, extattr::Flags::empty())
{
log::warn!("Failed to set xattr: {}", e);
log::warn!("Failed to set xattr: {e}");
}
}
Ok(())
@@ -400,7 +400,7 @@ pub fn copy_module_files(source: impl AsRef<Path>, destination: impl AsRef<Path>
std::fs::remove_file(&dest_path).context("Failed to remove file")?;
}
let target = std::fs::read_link(entry.path()).context("Failed to read symlink")?;
log::info!("Symlink: {:?} -> {:?}", dest_path, target);
log::info!("Symlink: {dest_path:?} -> {target:?}");
std::os::unix::fs::symlink(target, &dest_path).context("Failed to create symlink")?;
copy_xattrs(&source_path, &dest_path)?;
} else if entry.file_type().is_dir() {

View File

@@ -1,11 +1,54 @@
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/prctl.h>
#include <sys/ioctl.h>
#include <sys/xattr.h>
#include <limits.h>
#include <errno.h>
#include <stdlib.h>
#include <termios.h>
// This is a simple example. If you want a full-featured "su", please use "/data/adb/ksud debug su".
int main(){
int32_t result = 0;
prctl(0xdeadbeef, 0, 0, 0, &result);
system("/system/bin/sh");
return 0;
#define KERNEL_SU_OPTION 0xDEADBEEF
#define CMD_GRANT_ROOT 0
#define CMD_ENABLE_SU 15
int main(int argc, char **argv, char **envp) {
unsigned long result = 0;
if (argc >= 2 && strcmp(argv[1], "--disable-sucompat") == 0) {
prctl(KERNEL_SU_OPTION, CMD_ENABLE_SU, 0L, 0L, (unsigned long)&result);
return 0;
}
prctl(KERNEL_SU_OPTION, CMD_GRANT_ROOT, 0L, 0L, (unsigned long)&result);
if (result != KERNEL_SU_OPTION) {
const char *error = "Access Denied: sucompat not permitted\n";
write(STDERR_FILENO, error, strlen(error));
return 1;
}
struct termios term;
if (ioctl(STDIN_FILENO, TCGETS, &term) == 0) {
char tty_path[PATH_MAX];
ssize_t len = readlink("/proc/self/fd/0", tty_path, sizeof(tty_path) - 1);
if (len > 0) {
tty_path[len] = '\0';
const char *selinux_ctx = "u:object_r:devpts:s0";
setxattr(tty_path, "security.selinux", selinux_ctx, strlen(selinux_ctx) + 1, 0);
}
}
const char *default_args[] = { "/system/bin/su", NULL };
if (argc < 1 || !argv) {
argv = (char **)default_args;
} else {
argv[0] = "/system/bin/su";
}
execve("/data/adb/ksud", argv, envp);
const char *error = "Error: Failed to execve /data/adb/ksud\n";
write(STDERR_FILENO, error, strlen(error));
return 1;
}

View File

@@ -104,52 +104,77 @@ int main(int argc, char *argv[]) {
prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_ENABLED_FEATURES, enabled_features, bufsize, &error);
printf("%s\n", error || !strlen(enabled_features) ? "Unsupported" : "Supported");
free(enabled_features);
} else if (argc == 3 && !strcmp(argv[1], "sus_su")) {
int last_working_mode = 0;
int target_working_mode;
char* endptr;
} else if (argc >= 2 && !strcmp(argv[1], "sus_su")) {
if (argc == 3 && strcmp(argv[2], "support") == 0) {
char *enabled_features;
size_t bufsize = getpagesize() * 2;
enabled_features = (char *)malloc(bufsize);
if (!enabled_features) {
perror("malloc");
return -ENOMEM;
}
prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_ENABLED_FEATURES, enabled_features, bufsize, &error);
if (!error && strstr(enabled_features, "CONFIG_KSU_SUSFS_SUS_SU")) {
printf("Supported\n");
} else {
printf("Unsupported\n");
}
free(enabled_features);
return 0;
} else if (argc == 3) {
int last_working_mode = 0;
int target_working_mode;
char *endptr;
prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_SUS_SU_WORKING_MODE, &last_working_mode, NULL, &error);
if (error)
return error;
if (!strcmp(argv[2], "mode")) {
printf("%d\n", last_working_mode);
return 0;
}
target_working_mode = strtol(argv[2], &endptr, 10);
if (*endptr != '\0') {
return 1;
}
if (target_working_mode == SUS_SU_WITH_HOOKS) {
bool is_sus_su_ready;
prctl(KERNEL_SU_OPTION, CMD_SUSFS_IS_SUS_SU_READY, &is_sus_su_ready, NULL, &error);
if (error)
return error;
if (!is_sus_su_ready) {
printf("[-] sus_su mode %d has to be run during or after service stage\n", SUS_SU_WITH_HOOKS);
return 1;
}
if (last_working_mode == SUS_SU_DISABLED) {
error = enable_sus_su(last_working_mode, SUS_SU_WITH_HOOKS);
} else if (last_working_mode == SUS_SU_WITH_HOOKS) {
printf("[-] sus_su is already in mode %d\n", last_working_mode);
return 1;
} else {
error = enable_sus_su(last_working_mode, SUS_SU_DISABLED);
if (!error)
error = enable_sus_su(last_working_mode, SUS_SU_WITH_HOOKS);
}
} else if (target_working_mode == SUS_SU_DISABLED) {
if (last_working_mode == SUS_SU_DISABLED) {
printf("[-] sus_su is already in mode %d\n", last_working_mode);
return 1;
}
error = enable_sus_su(last_working_mode, SUS_SU_DISABLED);
}
prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_SUS_SU_WORKING_MODE, &last_working_mode, NULL, &error);
if (error)
return error;
if (!strcmp(argv[2], "mode")) {
printf("%d\n", last_working_mode);
return 0;
}
target_working_mode = strtol(argv[2], &endptr, 10);
if (*endptr != '\0') {
return 1;
}
if (target_working_mode == SUS_SU_WITH_HOOKS) {
bool is_sus_su_ready;
prctl(KERNEL_SU_OPTION, CMD_SUSFS_IS_SUS_SU_READY, &is_sus_su_ready, NULL, &error);
if (error)
return error;
if (!is_sus_su_ready) {
printf("[-] sus_su mode %d has to be run during or after service stage\n", SUS_SU_WITH_HOOKS);
return 1;
}
if (last_working_mode == SUS_SU_DISABLED) {
error = enable_sus_su(last_working_mode, SUS_SU_WITH_HOOKS);
} else if (last_working_mode == SUS_SU_WITH_HOOKS) {
printf("[-] sus_su is already in mode %d\n", last_working_mode);
return 1;
} else {
error = enable_sus_su(last_working_mode, SUS_SU_DISABLED);
if (!error)
error = enable_sus_su(last_working_mode, SUS_SU_WITH_HOOKS);
}
} else if (target_working_mode == SUS_SU_DISABLED) {
if (last_working_mode == SUS_SU_DISABLED) {
printf("[-] sus_su is already in mode %d\n", last_working_mode);
return 1;
}
error = enable_sus_su(last_working_mode, SUS_SU_DISABLED);
}
} else {
fprintf(stderr, "Usage: %s sus_su <0|2|mode|support>\n", argv[0]);
return 1;
}
} else {
fprintf(stderr, "Invalid argument: %s\n", argv[1]);
return 1;
}
return 0;
}
}