Compare commits

...

22 Commits

Author SHA1 Message Date
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
51 changed files with 1087 additions and 380 deletions

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,11 +62,11 @@ 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 += -DEXPECTED_MANAGER_SIZE=$(KSU_NEXT_MANAGER_SIZE)
ccflags-y += -DEXPECTED_MANAGER_HASH=\"$(KSU_NEXT_MANAGER_HASH)\"
ccflags-y += -DKSU_UMOUNT

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

@@ -255,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)
{
@@ -277,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);
@@ -446,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;
@@ -499,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) {
@@ -523,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

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

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

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

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

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

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

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

@@ -231,4 +231,6 @@
<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,7 +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">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="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

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

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

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

@@ -231,4 +231,6 @@
<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>
@@ -32,7 +32,7 @@
<string name="home_android">Versi android</string>
<string name="home_manager_version">Versi manajer</string>
<string name="home_abi">ABI</string>
<string name="home_selinux_status">Status SELinu</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>
@@ -232,4 +232,6 @@
<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,7 +17,7 @@
<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>
@@ -37,7 +37,7 @@
<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>
@@ -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,12 +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

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

@@ -231,4 +231,6 @@
<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,19 +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">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="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

@@ -53,7 +53,7 @@
<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>
@@ -228,7 +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">Fazer backup dos módulos instalados.</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="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">Global Namespace Mode</string>
<string name="settings_global_namespace_mode_summary">All root sessions use the global mount namespace</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>
@@ -100,7 +100,7 @@
<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>
@@ -117,7 +117,7 @@
<string name="profile">Профиль Приложения</string>
<string name="profile_default">По умолчанию</string>
<string name="profile_template">Шаблон</string>
<string name="profile_custom">Настроить</string>
<string name="profile_custom">Пользовательский</string>
<string name="profile_name">Имя профиля</string>
<string name="profile_namespace">Пространство монтирования</string>
<string name="profile_namespace_inherited">Унаследованный</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">По умолчанию включает статус \"Umount\" для приложений. Если эта настройка включена, то все модификации, внесённые модулями, будут удалены для приложений без включённого 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">Шаблоны доступа</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>
@@ -231,4 +231,6 @@
<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

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

@@ -231,4 +231,6 @@
<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,12 +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_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

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

@@ -231,4 +231,6 @@
<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,7 +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="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

@@ -229,6 +229,8 @@
<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="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

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

@@ -31,4 +31,9 @@ if [ -f "./build.gradle.kts" ]; then
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

@@ -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,6 +323,7 @@ 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")
@@ -370,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)?;
}
@@ -536,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();
@@ -584,7 +622,8 @@ fn do_patch(
.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 =
@@ -605,43 +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)
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")?;
}
@@ -800,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(""));
@@ -822,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

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

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

@@ -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,6 +323,7 @@ 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")
@@ -370,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)?;
}
@@ -536,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();
@@ -584,7 +622,8 @@ fn do_patch(
.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 =
@@ -605,43 +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)
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")?;
}
@@ -800,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(""));
@@ -822,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

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

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

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