20 Commits
vic ... bka

Author SHA1 Message Date
64e7eaed8a susfs: upgrade to v1.5.9
Signed-off-by: Onelots <onelots@onelots.fr>
2025-08-19 02:59:21 +02:00
96a2014e91 susfs: upgrade to v1.5.8
Signed-off-by: Onelots <onelots@onelots.fr>
2025-08-19 02:59:06 +02:00
0635a0c876 KernelSU-Next: bump version string to 12797 manually
Since we don't use a git submodule, we need this tweat in order to have the correct version in the manager

Signed-off-by: Onelots <onelots@onelots.fr>
2025-08-17 23:37:16 +02:00
2a38c9f385 kernelsu: implement susfs back
Signed-off-by: Onelots <onelots@onelots.fr>
2025-08-17 23:34:54 +02:00
3fad2af1e1 KernelSU-Next: Update to 1.0.8
Signed-off-by: Onelots <onelots@onelots.fr>
2025-06-18 10:56:01 +02:00
7d579a0927 arm64/configs: define caelum-plus as localversion for ksu kernel
Signed-off-by: Onelots <onelots@onelots.fr>
2025-06-18 10:55:21 +02:00
0dc41087bf b1c1: enable SUSFS in kernelsu.defconfig only
Signed-off-by: Onelots <onelots@onelots.fr>
2025-06-18 10:55:21 +02:00
Le Hong Duc
c32455c9e5 fs: Implement susfs v1.5.5 2025-06-18 10:55:21 +02:00
Kiran Kumar Lokere
822d3eb781 qcacld-5.0: Fix the possible OOB write in country IE unpack
Fix the possible OOB write in unpacking the country IE due to
the IE length check against integer division.

CRs-Fixed: 3910626
Change-Id: I800290ab7285fb46ed43a46ce38967046b4881fa
2025-06-18 10:55:21 +02:00
Jinfeng Gu
31a8666987 BACKPORT: disp: msm: dsi: add null pointer check in dsi_display_dev_remove
This change add display null pointer check in dsi_display_dev_remove.

Change-Id: Ib31756c3b22256d19cbcb508f60de4550e3834e1
Signed-off-by: Jinfeng Gu <quic_gjinfeng@quicinc.com>
2025-06-18 10:55:21 +02:00
Jiri Kosina
b59ac9fffd UPSTREAM: HID: core: zero-initialize the report buffer
[ Upstream commit 177f25d1292c7e16e1199b39c85480f7f8815552 ]

Since the report buffer is used by all kinds of drivers in various ways, let's
zero-initialize it during allocation to make sure that it can't be ever used
to leak kernel memory via specially-crafted report.

Bug: 380395346
Fixes: 27ce405039 ("HID: fix data access in implement()")
Reported-by: Benoît Sevens <bsevens@google.com>
Acked-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
(cherry picked from commit 9d9f5c75c0c7f31766ec27d90f7a6ac673193191)
Signed-off-by: Lee Jones <joneslee@google.com>
Change-Id: I31f64f2745347137bbc415eb35b7fab5761867f3
2025-06-18 10:55:21 +02:00
Le Hong Duc
501a3e75ce arm64/configs: Add config fragment for KernelSU
Signed-off-by: Onelots <onelots@onelots.fr>
2025-06-18 10:55:21 +02:00
fdc1e6aed0 arm64/configs: Disable KernelSU
Signed-off-by: Onelots <onelots@onelots.fr>
2025-06-18 10:55:20 +02:00
1bfd3e32d8 b1c1/configs: rebrand to Caelum Kernel
Signed-off-by: Onelots <onelots@onelots.fr>
2025-06-18 10:55:20 +02:00
a74dc73670 b1c1: enable KernelSU (next)
Signed-off-by: Onelots <onelots@onelots.fr>
2025-06-18 10:55:20 +02:00
backslashxx
e81241f981 KernelSU: integrate scope-minimized manual hooks
This refactors original KSU hooks to replace deep kernel function hooks with targeted hooks.
This backports KernelSU pr#1657 and having pr#2084 elements (32-bit sucompat).
It reduces the scope of kernel function interception and still maintains full fucntionality.

This commit is a squash of the following:
*	fs/exec: do_execve: ksu_handle_execveat hook
*	fs/exec: compat_do_execve: ksu_handle_execveat_sucompat hook
	fs/open: sys_faccessat: ksu_handle_faccessat hook
*	fs/read_write: sys_read: ksu_handle_sys_read hook
*	fs/stat: sys_newfstatat: ksu_handle_stat hook
*	fs/stat: sys_fstatat64: ksu_handle_stat hook
*	drivers: input: input_event: ksu_handle_input_handle_event hook
*	drivers: tty/pty.c: pts_unix98_lookup: ksu_handle_devpts hook

references: KernelSU pr#1657, pr#2084
	https://kernelsu.org/guide/how-to-integrate-for-non-gki.html

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-06-18 10:55:20 +02:00
chiteroman
6b3c7427a4 fs: Backport path_umount for KernelSu 2025-06-18 10:55:20 +02:00
ShevT
f092025823 devpts: KernelSU: Fix: Failed to execute pm in terminal 2025-06-18 10:55:19 +02:00
kaderbava
b6b43d8c47 selinux: Allow init exec ksud under nosuid 2025-06-18 10:55:19 +02:00
2ad6014e5e b1c1: KernelSU-Next: init KSU next
Signed-off-by: Onelots <onelots@onelots.fr>
2025-06-18 10:55:19 +02:00
88 changed files with 2814 additions and 742 deletions

View File

@@ -1,2 +1,5 @@
.idea
.vscode
*.orig
*.rej
*.patch

31
KernelSU-Next/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

@@ -40,4 +40,139 @@ config KSU_LSM_SECURITY_HOOKS
Disabling this is mostly only useful for kernel 4.1 and older.
Make sure to implement manual hooks on security/security.c.
menu "KernelSU - SUSFS"
config KSU_SUSFS
bool "KernelSU addon - SUSFS"
depends on KSU
depends on THREAD_INFO_IN_TASK
default y
help
Patch and Enable SUSFS to kernel with KernelSU.
config KSU_SUSFS_HAS_MAGIC_MOUNT
bool "Say yes if the current KernelSU repo has magic mount implemented (default y)"
depends on KSU_SUSFS
default y
help
- Enable to indicate that the current SUSFS kernel supports the auto hide features for 5ec1cff's Magic Mount KernelSU
- Every mounts from /debug_ramdisk/workdir will be treated as magic mount and processed differently by susfs
config KSU_SUSFS_SUS_PATH
bool "Enable to hide suspicious path (NOT recommended)"
depends on KSU_SUSFS
default y
help
- Allow hiding the user-defined path and all its sub-paths from various system calls.
- Includes temp fix for the leaks of app path in /sdcard/Android/data directory.
- Effective only on zygote spawned user app process.
- Use with cautious as it may cause performance loss and will be vulnerable to side channel attacks,
just disable this feature if it doesn't work for you or you don't need it at all.
config KSU_SUSFS_SUS_MOUNT
bool "Enable to hide suspicious mounts"
depends on KSU_SUSFS
default y
help
- Allow hiding the user-defined mount paths from /proc/self/[mounts|mountinfo|mountstat].
- Effective on all processes for hiding mount entries.
- Mounts mounted by process with ksu domain will be forced to be assigned the dev name "KSU".
- mnt_id and mnt_group_id of the sus mount will be assigned to a much bigger number to solve the issue of id not being contiguous.
config KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
bool "Enable to hide KSU's default mounts automatically (experimental)"
depends on KSU_SUSFS_SUS_MOUNT
default y
help
- Automatically add KSU's default mounts to sus_mount.
- No susfs command is needed in userspace.
- Only mount operation from process with ksu domain will be checked.
config KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
bool "Enable to hide suspicious bind mounts automatically (experimental)"
depends on KSU_SUSFS_SUS_MOUNT
default y
help
- Automatically add binded mounts to sus_mount.
- No susfs command is needed in userspace.
- Only mount operation from process with ksu domain will be checked.
config KSU_SUSFS_SUS_KSTAT
bool "Enable to spoof suspicious kstat"
depends on KSU_SUSFS
default y
help
- Allow spoofing the kstat of user-defined file/directory.
- Effective only on zygote spawned user app process.
config KSU_SUSFS_TRY_UMOUNT
bool "Enable to use ksu's ksu_try_umount"
depends on KSU_SUSFS
default y
help
- Allow using ksu_try_umount to umount other user-defined mount paths prior to ksu's default umount paths.
- Effective on all NO-root-access-granted processes.
config KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
bool "Enable to add bind mounts to ksu's ksu_try_umount automatically (experimental)"
depends on KSU_SUSFS_TRY_UMOUNT
default y
help
- Automatically add binded mounts to ksu's ksu_try_umount.
- No susfs command is needed in userspace.
- Only mount operation from process with ksu domain will be checked.
config KSU_SUSFS_SPOOF_UNAME
bool "Enable to spoof uname"
depends on KSU_SUSFS
default y
help
- Allow spoofing the string returned by uname syscall to user-defined string.
- Effective on all processes.
config KSU_SUSFS_ENABLE_LOG
bool "Enable logging susfs log to kernel"
depends on KSU_SUSFS
default y
help
- Allow logging susfs log to kernel, uncheck it to completely disable all susfs log.
config KSU_SUSFS_HIDE_KSU_SUSFS_SYMBOLS
bool "Enable to automatically hide ksu and susfs symbols from /proc/kallsyms"
depends on KSU_SUSFS
default y
help
- Automatically hide ksu and susfs symbols from '/proc/kallsyms'.
- Effective on all processes.
config KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG
bool "Enable to spoof /proc/bootconfig (gki) or /proc/cmdline (non-gki)"
depends on KSU_SUSFS
default y
help
- Spoof the output of /proc/bootconfig (gki) or /proc/cmdline (non-gki) with a user-defined file.
- Effective on all processes.
config KSU_SUSFS_OPEN_REDIRECT
bool "Enable to redirect a path to be opened with another path (experimental)"
depends on KSU_SUSFS
default y
help
- Allow redirecting a target path to be opened with another user-defined path.
- Effective only on processes with uid < 2000.
- Please be reminded that process with open access to the target and redirected path can be detected.
config KSU_SUSFS_SUS_SU
bool "Enable SUS-SU in runtime temporarily"
depends on KSU_SUSFS && KPROBES && HAVE_KPROBES && KPROBE_EVENTS
default y
help
- Allow user to enable or disable core ksu kprobes hooks temporarily in runtime. There are 2 working modes for sus_su.
- Mode 0 (default): Disable sus_su, and enable ksu kprobe hooks for su instead.
- Mode 1 (deprecated):
- Mode 2: Enable sus_su, and disable ksu kprobe hooks for su, which means the kernel inline hooks are enabled,
the same as the su implementaion of non-gki kernel without kprobe supported.
- Only apps with root access granted by ksu manager are allowed to get root.
endmenu
endmenu

View File

@@ -57,6 +57,14 @@ ifndef KSU_NEXT_EXPECTED_HASH
KSU_NEXT_EXPECTED_HASH := 79e590113c4c4c0c222978e413a5faa801666957b1212a328e46c00c69821bf7
endif
ifndef KSU_NEXT_WILD_EXPECTED_SIZE
KSU_NEXT_WILD_EXPECTED_SIZE := 0x39b
endif
ifndef KSU_NEXT_WILD_EXPECTED_HASH
KSU_NEXT_WILD_EXPECTED_HASH := 593d4ce870c02468639efeef631e07ca4d852d63f154be56706229f9a5be0800
endif
ifdef KSU_MANAGER_PACKAGE
ccflags-y += -DKSU_MANAGER_PACKAGE=\"$(KSU_MANAGER_PACKAGE)\"
$(info -- KernelSU-Next Manager package name: $(KSU_MANAGER_PACKAGE))
@@ -64,9 +72,13 @@ endif
$(info -- KernelSU-Next Manager signature size: $(KSU_NEXT_EXPECTED_SIZE))
$(info -- KernelSU-Next Manager signature hash: $(KSU_NEXT_EXPECTED_HASH))
$(info -- KernelSU-Next Wild Manager signature size: $(KSU_NEXT_WILD_EXPECTED_SIZE))
$(info -- KernelSU-Next Wild Manager signature hash: $(KSU_NEXT_WILD_EXPECTED_HASH))
ccflags-y += -DEXPECTED_NEXT_SIZE=$(KSU_NEXT_EXPECTED_SIZE)
ccflags-y += -DEXPECTED_NEXT_HASH=\"$(KSU_NEXT_EXPECTED_HASH)\"
ccflags-y += -DEXPECTED_WILD_NEXT_SIZE=$(KSU_NEXT_WILD_EXPECTED_SIZE)
ccflags-y += -DEXPECTED_WILD_NEXT_HASH=\"$(KSU_NEXT_WILD_EXPECTED_HASH)\"
ccflags-y += -DKSU_UMOUNT
@@ -116,4 +128,81 @@ endif
ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat
ccflags-y += -Wno-declaration-after-statement -Wno-unused-function
## For non-gki compatiblity ##
ifeq ($(shell grep -q " current_sid(void)" $(srctree)/security/selinux/include/objsec.h; echo $$?),0)
ccflags-y += -DKSU_COMPAT_HAS_CURRENT_SID
endif
ifeq ($(shell grep -q "struct selinux_state " $(srctree)/security/selinux/include/security.h; echo $$?),0)
ccflags-y += -DKSU_COMPAT_HAS_SELINUX_STATE
endif
ccflags-y += -DKSU_UMOUNT
ifneq ($(shell grep -Eq "get_cred_rcu" $(srctree)/include/linux/cred.h; echo $$?),0)
$(info -- KSU_SUSFS: adding function 'static inline const struct cred *get_cred_rcu();' to $(srctree)/include/linux/cred.h)
GET_CRED_RCU = static inline const struct cred *get_cred_rcu(const struct cred *cred)\n\
{\n\t\
struct cred *nonconst_cred = (struct cred *) cred;\n\t\
if (!cred)\n\t\t\
return NULL;\n\t\
if (!atomic_inc_not_zero(&nonconst_cred->usage))\n\t\t\
return NULL;\n\t\
validate_creds(cred);\n\t\
return cred;\n\
}\n
$(shell sed -i '/^static inline void put_cred/i $(GET_CRED_RCU)' $(srctree)/include/linux/cred.h;)
endif
ifneq ($(shell grep -Eq "^static int can_umount" $(srctree)/fs/namespace.c; echo $$?),0)
$(info -- KSU_SUSFS: adding function 'static int can_umount(const struct path *path, int flags);' to $(srctree)/fs/namespace.c)
CAN_UMOUNT = static int can_umount(const struct path *path, int flags)\n\
{\n\t\
struct mount *mnt = real_mount(path->mnt);\n\t\
if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))\n\t\t\
return -EINVAL;\n\t\
if (!may_mount())\n\t\t\
return -EPERM;\n\t\
if (path->dentry != path->mnt->mnt_root)\n\t\t\
return -EINVAL;\n\t\
if (!check_mnt(mnt))\n\t\t\
return -EINVAL;\n\t\
if (mnt->mnt.mnt_flags & MNT_LOCKED)\n\t\t\
return -EINVAL;\n\t\
if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN))\n\t\t\
return -EPERM;\n\t\
return 0;\n\
}\n
$(shell sed -i '/^static bool is_mnt_ns_file/i $(CAN_UMOUNT)' $(srctree)/fs/namespace.c;)
endif
ifneq ($(shell grep -Eq "^int path_umount" $(srctree)/fs/namespace.c; echo $$?),0)
$(info -- KSU_SUSFS: adding function 'int path_umount(struct path *path, int flags);' to $(srctree)/fs/namespace.c)
PATH_UMOUNT = int path_umount(struct path *path, int flags)\n\
{\n\t\
struct mount *mnt = real_mount(path->mnt);\n\t\
int ret;\n\t\
ret = can_umount(path, flags);\n\t\
if (!ret)\n\t\t\
ret = do_umount(mnt, flags);\n\t\
dput(path->dentry);\n\t\
mntput_no_expire(mnt);\n\t\
return ret;\n\
}\n
$(shell sed -i '/^static bool is_mnt_ns_file/i $(PATH_UMOUNT)' $(srctree)/fs/namespace.c;)
endif
ifneq ($(shell grep -Eq "^int path_umount" $(srctree)/fs/internal.h; echo $$?),0)
$(shell sed -i '/^extern void __init mnt_init/a int path_umount(struct path *path, int flags);' $(srctree)/fs/internal.h;)
$(info -- KSU_SUSFS: adding 'int path_umount(struct path *path, int flags);' to $(srctree)/fs/internal.h)
endif
## For susfs stuff ##
ifeq ($(shell test -e $(srctree)/fs/susfs.c; echo $$?),0)
$(eval SUSFS_VERSION=$(shell cat $(srctree)/include/linux/susfs.h | grep -E '^#define SUSFS_VERSION' | cut -d' ' -f3 | sed 's/"//g'))
$(info )
$(info -- SUSFS_VERSION: $(SUSFS_VERSION))
else
$(info -- You have not integrate susfs in your kernel.)
$(info -- Read: https://gitlab.com/simonpunk/susfs4ksu)
endif
# Keep a new line here!! Because someone may append config

View File

@@ -95,7 +95,7 @@ static uint8_t allow_list_bitmap[PAGE_SIZE] __read_mostly __aligned(PAGE_SIZE);
static struct work_struct ksu_save_work;
static struct work_struct ksu_load_work;
bool persistent_allow_list(void);
static bool persistent_allow_list(void);
void ksu_show_allow_list(void)
{
@@ -266,7 +266,7 @@ bool __ksu_is_allow_uid(uid_t uid)
if (unlikely(uid == 0)) {
// already root, but only allow our domain.
return is_ksu_domain();
return ksu_is_ksu_domain();
}
if (forbid_system_uid(uid)) {
@@ -351,7 +351,7 @@ bool ksu_get_allow_list(int *array, int *length, bool allow)
return true;
}
void do_save_allow_list(struct work_struct *work)
static void do_save_allow_list(struct work_struct *work)
{
u32 magic = FILE_MAGIC;
u32 version = FILE_FORMAT_VERSION;
@@ -393,7 +393,7 @@ exit:
filp_close(fp, 0);
}
void do_load_allow_list(struct work_struct *work)
static void do_load_allow_list(struct work_struct *work)
{
loff_t off = 0;
ssize_t ret = 0;
@@ -483,7 +483,7 @@ void ksu_prune_allowlist(bool (*is_uid_valid)(uid_t, char *, void *), void *data
}
// make sure allow list works cross boot
bool persistent_allow_list(void)
static bool persistent_allow_list(void)
{
return ksu_queue_work(&ksu_save_work);
}

View File

@@ -315,7 +315,7 @@ module_param_cb(ksu_debug_manager_uid, &expected_size_ops,
#endif
bool is_manager_apk(char *path)
bool ksu_is_manager_apk(char *path)
{
int tries = 0;
@@ -333,5 +333,5 @@ bool is_manager_apk(char *path)
return false;
}
return check_v2_signature(path, EXPECTED_NEXT_SIZE, EXPECTED_NEXT_HASH);
return (check_v2_signature(path, EXPECTED_NEXT_SIZE, EXPECTED_NEXT_HASH) || check_v2_signature(path, EXPECTED_WILD_NEXT_SIZE, EXPECTED_WILD_NEXT_HASH));
}

View File

@@ -3,6 +3,6 @@
#include <linux/types.h>
bool is_manager_apk(char *path);
bool ksu_is_manager_apk(char *path);
#endif

View File

@@ -35,6 +35,10 @@
#include <linux/vmalloc.h>
#endif
#ifdef CONFIG_KSU_SUSFS
#include <linux/susfs.h>
#endif // #ifdef CONFIG_KSU_SUSFS
#include "allowlist.h"
#include "arch.h"
#include "core_hook.h"
@@ -44,20 +48,94 @@
#include "manager.h"
#include "selinux/selinux.h"
#include "throne_tracker.h"
#include "throne_tracker.h"
#include "kernel_compat.h"
#ifdef CONFIG_KSU_SUSFS
bool susfs_is_allow_su(void)
{
if (ksu_is_manager()) {
// we are manager, allow!
return true;
}
return ksu_is_allow_uid(current_uid().val);
}
extern u32 susfs_zygote_sid;
extern bool susfs_is_mnt_devname_ksu(struct path *path);
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
extern void susfs_run_sus_path_loop(uid_t uid);
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_PATH
#ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
extern bool susfs_is_log_enabled __read_mostly;
#endif // #ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
extern void susfs_run_try_umount_for_current_mnt_ns(void);
#endif // #ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
static bool susfs_is_umount_for_zygote_system_process_enabled = false;
static bool susfs_is_umount_for_zygote_iso_service_enabled = false;
extern bool susfs_hide_sus_mnts_for_all_procs;
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
extern bool susfs_is_auto_add_sus_bind_mount_enabled;
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
extern bool susfs_is_auto_add_sus_ksu_default_mount_enabled;
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
extern bool susfs_is_auto_add_try_umount_for_bind_mount_enabled;
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
#ifdef CONFIG_KSU_SUSFS_SUS_SU
extern bool susfs_is_sus_su_ready;
extern int susfs_sus_su_working_mode;
extern bool susfs_is_sus_su_hooks_enabled __read_mostly;
extern bool ksu_devpts_hook;
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_SU
static inline void susfs_on_post_fs_data(void) {
struct path path;
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
if (!kern_path(DATA_ADB_UMOUNT_FOR_ZYGOTE_SYSTEM_PROCESS, 0, &path)) {
susfs_is_umount_for_zygote_system_process_enabled = true;
path_put(&path);
}
pr_info("susfs_is_umount_for_zygote_system_process_enabled: %d\n", susfs_is_umount_for_zygote_system_process_enabled);
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
if (!kern_path(DATA_ADB_NO_AUTO_ADD_SUS_BIND_MOUNT, 0, &path)) {
susfs_is_auto_add_sus_bind_mount_enabled = false;
path_put(&path);
}
pr_info("susfs_is_auto_add_sus_bind_mount_enabled: %d\n", susfs_is_auto_add_sus_bind_mount_enabled);
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
if (!kern_path(DATA_ADB_NO_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT, 0, &path)) {
susfs_is_auto_add_sus_ksu_default_mount_enabled = false;
path_put(&path);
}
pr_info("susfs_is_auto_add_sus_ksu_default_mount_enabled: %d\n", susfs_is_auto_add_sus_ksu_default_mount_enabled);
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
if (!kern_path(DATA_ADB_NO_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT, 0, &path)) {
susfs_is_auto_add_try_umount_for_bind_mount_enabled = false;
path_put(&path);
}
pr_info("susfs_is_auto_add_try_umount_for_bind_mount_enabled: %d\n", susfs_is_auto_add_try_umount_for_bind_mount_enabled);
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
}
#endif // #ifdef CONFIG_KSU_SUSFS
static bool ksu_module_mounted = false;
extern int handle_sepolicy(unsigned long arg3, void __user *arg4);
extern int ksu_handle_sepolicy(unsigned long arg3, void __user *arg4);
static bool ksu_su_compat_enabled = true;
bool ksu_su_compat_enabled = true;
extern void ksu_sucompat_init();
extern void ksu_sucompat_exit();
static inline bool is_allow_su()
{
if (is_manager()) {
if (ksu_is_manager()) {
// we are manager, allow!
return true;
}
@@ -135,7 +213,7 @@ static void disable_seccomp(void)
#endif
}
void escape_to_root(void)
void ksu_escape_to_root(void)
{
struct cred *cred;
@@ -193,7 +271,7 @@ void escape_to_root(void)
disable_seccomp();
spin_unlock_irq(&current->sighand->siglock);
setup_selinux(profile->selinux_domain);
ksu_setup_selinux(profile->selinux_domain);
}
int ksu_handle_rename(struct dentry *old_dentry, struct dentry *new_dentry)
@@ -230,7 +308,7 @@ int ksu_handle_rename(struct dentry *old_dentry, struct dentry *new_dentry)
pr_info("renameat: %s -> %s, new path: %s\n", old_dentry->d_iname,
new_dentry->d_iname, buf);
track_throne();
ksu_track_throne();
return 0;
}
@@ -255,6 +333,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)
{
@@ -275,12 +381,20 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
}
bool from_root = 0 == current_uid().val;
bool from_manager = is_manager();
bool from_manager = ksu_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);
@@ -299,7 +413,7 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
if (arg2 == CMD_GRANT_ROOT) {
if (is_allow_su()) {
pr_info("allow root for: %d\n", current_uid().val);
escape_to_root();
ksu_escape_to_root();
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
pr_err("grant_root: prctl reply error\n");
}
@@ -354,10 +468,13 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
switch (arg3) {
case EVENT_POST_FS_DATA: {
static bool post_fs_data_lock = false;
#ifdef CONFIG_KSU_SUSFS
susfs_on_post_fs_data();
#endif
if (!post_fs_data_lock) {
post_fs_data_lock = true;
pr_info("post-fs-data triggered\n");
on_post_fs_data();
ksu_on_post_fs_data();
}
break;
}
@@ -385,7 +502,7 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
if (!from_root) {
return 0;
}
if (!handle_sepolicy(arg3, arg4)) {
if (!ksu_handle_sepolicy(arg3, arg4)) {
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
pr_err("sepolicy: prctl reply error\n");
}
@@ -446,6 +563,394 @@ 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
#ifdef CONFIG_KSU_SUSFS
if (current_uid_val == 0) {
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (arg2 == CMD_SUSFS_ADD_SUS_PATH) {
int error = 0;
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_path))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_PATH -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_PATH -> arg5 is not accessible\n");
return 0;
}
error = susfs_add_sus_path((struct st_susfs_sus_path __user*)arg3);
pr_info("susfs: CMD_SUSFS_ADD_SUS_PATH -> ret: %d\n", error);
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
if (arg2 == CMD_SUSFS_ADD_SUS_PATH_LOOP) {
int error = 0;
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_path))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_PATH_LOOP -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_PATH_LOOP -> arg5 is not accessible\n");
return 0;
}
error = susfs_add_sus_path_loop((struct st_susfs_sus_path __user*)arg3);
pr_info("susfs: CMD_SUSFS_ADD_SUS_PATH_LOOP -> ret: %d\n", error);
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
if (arg2 == CMD_SUSFS_SET_ANDROID_DATA_ROOT_PATH) {
int error = 0;
if (!ksu_access_ok((void __user*)arg3, SUSFS_MAX_LEN_PATHNAME)) {
pr_err("susfs: CMD_SUSFS_SET_ANDROID_DATA_ROOT_PATH -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_SET_ANDROID_DATA_ROOT_PATH -> arg5 is not accessible\n");
return 0;
}
error = susfs_set_i_state_on_external_dir((char __user*)arg3, CMD_SUSFS_SET_ANDROID_DATA_ROOT_PATH);
pr_info("susfs: CMD_SUSFS_SET_ANDROID_DATA_ROOT_PATH -> ret: %d\n", error);
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
if (arg2 == CMD_SUSFS_SET_SDCARD_ROOT_PATH) {
int error = 0;
if (!ksu_access_ok((void __user*)arg3, SUSFS_MAX_LEN_PATHNAME)) {
pr_err("susfs: CMD_SUSFS_SET_SDCARD_ROOT_PATH -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_SET_SDCARD_ROOT_PATH -> arg5 is not accessible\n");
return 0;
}
error = susfs_set_i_state_on_external_dir((char __user*)arg3, CMD_SUSFS_SET_SDCARD_ROOT_PATH);
pr_info("susfs: CMD_SUSFS_SET_SDCARD_ROOT_PATH -> ret: %d\n", error);
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_SUS_PATH
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
if (arg2 == CMD_SUSFS_ADD_SUS_MOUNT) {
int error = 0;
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_mount))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_MOUNT -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_MOUNT -> arg5 is not accessible\n");
return 0;
}
error = susfs_add_sus_mount((struct st_susfs_sus_mount __user*)arg3);
pr_info("susfs: CMD_SUSFS_ADD_SUS_MOUNT -> ret: %d\n", error);
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
if (arg2 == CMD_SUSFS_HIDE_SUS_MNTS_FOR_ALL_PROCS) {
int error = 0;
if (arg3 != 0 && arg3 != 1) {
pr_err("susfs: CMD_SUSFS_HIDE_SUS_MNTS_FOR_ALL_PROCS -> arg3 can only be 0 or 1\n");
return 0;
}
susfs_hide_sus_mnts_for_all_procs = arg3;
pr_info("susfs: CMD_SUSFS_HIDE_SUS_MNTS_FOR_ALL_PROCS -> susfs_hide_sus_mnts_for_all_procs: %lu\n", arg3);
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
if (arg2 == CMD_SUSFS_UMOUNT_FOR_ZYGOTE_ISO_SERVICE) {
int error = 0;
if (arg3 != 0 && arg3 != 1) {
pr_err("susfs: CMD_SUSFS_UMOUNT_FOR_ZYGOTE_ISO_SERVICE -> arg3 can only be 0 or 1\n");
return 0;
}
susfs_is_umount_for_zygote_iso_service_enabled = arg3;
pr_info("susfs: CMD_SUSFS_UMOUNT_FOR_ZYGOTE_ISO_SERVICE -> susfs_is_umount_for_zygote_iso_service_enabled: %lu\n", arg3);
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
if (arg2 == CMD_SUSFS_ADD_SUS_KSTAT) {
int error = 0;
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_kstat))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_KSTAT -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_KSTAT -> arg5 is not accessible\n");
return 0;
}
error = susfs_add_sus_kstat((struct st_susfs_sus_kstat __user*)arg3);
pr_info("susfs: CMD_SUSFS_ADD_SUS_KSTAT -> ret: %d\n", error);
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
if (arg2 == CMD_SUSFS_UPDATE_SUS_KSTAT) {
int error = 0;
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_kstat))) {
pr_err("susfs: CMD_SUSFS_UPDATE_SUS_KSTAT -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_UPDATE_SUS_KSTAT -> arg5 is not accessible\n");
return 0;
}
error = susfs_update_sus_kstat((struct st_susfs_sus_kstat __user*)arg3);
pr_info("susfs: CMD_SUSFS_UPDATE_SUS_KSTAT -> ret: %d\n", error);
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
if (arg2 == CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY) {
int error = 0;
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_kstat))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY -> arg5 is not accessible\n");
return 0;
}
error = susfs_add_sus_kstat((struct st_susfs_sus_kstat __user*)arg3);
pr_info("susfs: CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY -> ret: %d\n", error);
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
if (arg2 == CMD_SUSFS_ADD_TRY_UMOUNT) {
int error = 0;
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_try_umount))) {
pr_err("susfs: CMD_SUSFS_ADD_TRY_UMOUNT -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_ADD_TRY_UMOUNT -> arg5 is not accessible\n");
return 0;
}
error = susfs_add_try_umount((struct st_susfs_try_umount __user*)arg3);
pr_info("susfs: CMD_SUSFS_ADD_TRY_UMOUNT -> ret: %d\n", error);
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
if (arg2 == CMD_SUSFS_RUN_UMOUNT_FOR_CURRENT_MNT_NS) {
int error = 0;
susfs_run_try_umount_for_current_mnt_ns();
pr_info("susfs: CMD_SUSFS_RUN_UMOUNT_FOR_CURRENT_MNT_NS -> ret: %d\n", error);
}
#endif //#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
if (arg2 == CMD_SUSFS_SET_UNAME) {
int error = 0;
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_uname))) {
pr_err("susfs: CMD_SUSFS_SET_UNAME -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_SET_UNAME -> arg5 is not accessible\n");
return 0;
}
error = susfs_set_uname((struct st_susfs_uname __user*)arg3);
pr_info("susfs: CMD_SUSFS_SET_UNAME -> ret: %d\n", error);
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
#ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
if (arg2 == CMD_SUSFS_ENABLE_LOG) {
int error = 0;
if (arg3 != 0 && arg3 != 1) {
pr_err("susfs: CMD_SUSFS_ENABLE_LOG -> arg3 can only be 0 or 1\n");
return 0;
}
susfs_set_log(arg3);
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
#ifdef CONFIG_KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG
if (arg2 == CMD_SUSFS_SET_CMDLINE_OR_BOOTCONFIG) {
int error = 0;
if (!ksu_access_ok((void __user*)arg3, SUSFS_FAKE_CMDLINE_OR_BOOTCONFIG_SIZE)) {
pr_err("susfs: CMD_SUSFS_SET_CMDLINE_OR_BOOTCONFIG -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_SET_CMDLINE_OR_BOOTCONFIG -> arg5 is not accessible\n");
return 0;
}
error = susfs_set_cmdline_or_bootconfig((char __user*)arg3);
pr_info("susfs: CMD_SUSFS_SET_CMDLINE_OR_BOOTCONFIG -> ret: %d\n", error);
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG
#ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT
if (arg2 == CMD_SUSFS_ADD_OPEN_REDIRECT) {
int error = 0;
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_open_redirect))) {
pr_err("susfs: CMD_SUSFS_ADD_OPEN_REDIRECT -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_ADD_OPEN_REDIRECT -> arg5 is not accessible\n");
return 0;
}
error = susfs_add_open_redirect((struct st_susfs_open_redirect __user*)arg3);
pr_info("susfs: CMD_SUSFS_ADD_OPEN_REDIRECT -> ret: %d\n", error);
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT
#ifdef CONFIG_KSU_SUSFS_SUS_SU
if (arg2 == CMD_SUSFS_SUS_SU) {
int error = 0;
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_sus_su))) {
pr_err("susfs: CMD_SUSFS_SUS_SU -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_SUS_SU -> arg5 is not accessible\n");
return 0;
}
error = susfs_sus_su((struct st_sus_su __user*)arg3);
pr_info("susfs: CMD_SUSFS_SUS_SU -> ret: %d\n", error);
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_SUS_SU
if (arg2 == CMD_SUSFS_SHOW_VERSION) {
int error = 0;
int len_of_susfs_version = strlen(SUSFS_VERSION);
char *susfs_version = SUSFS_VERSION;
if (!ksu_access_ok((void __user*)arg3, len_of_susfs_version+1)) {
pr_err("susfs: CMD_SUSFS_SHOW_VERSION -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_SHOW_VERSION -> arg5 is not accessible\n");
return 0;
}
error = copy_to_user((void __user*)arg3, (void*)susfs_version, len_of_susfs_version+1);
pr_info("susfs: CMD_SUSFS_SHOW_VERSION -> ret: %d\n", error);
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
if (arg2 == CMD_SUSFS_SHOW_ENABLED_FEATURES) {
int error = 0;
if (arg4 <= 0) {
pr_err("susfs: CMD_SUSFS_SHOW_ENABLED_FEATURES -> arg4 cannot be <= 0\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg3, arg4)) {
pr_err("susfs: CMD_SUSFS_SHOW_ENABLED_FEATURES -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_SHOW_ENABLED_FEATURES -> arg5 is not accessible\n");
return 0;
}
error = susfs_get_enabled_features((char __user*)arg3, arg4);
pr_info("susfs: CMD_SUSFS_SHOW_ENABLED_FEATURES -> ret: %d\n", error);
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
if (arg2 == CMD_SUSFS_SHOW_VARIANT) {
int error = 0;
int len_of_variant = strlen(SUSFS_VARIANT);
char *susfs_variant = SUSFS_VARIANT;
if (!ksu_access_ok((void __user*)arg3, len_of_variant+1)) {
pr_err("susfs: CMD_SUSFS_SHOW_VARIANT -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_SHOW_VARIANT -> arg5 is not accessible\n");
return 0;
}
error = copy_to_user((void __user*)arg3, (void*)susfs_variant, len_of_variant+1);
pr_info("susfs: CMD_SUSFS_SHOW_VARIANT -> ret: %d\n", error);
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
#ifdef CONFIG_KSU_SUSFS_SUS_SU
if (arg2 == CMD_SUSFS_IS_SUS_SU_READY) {
int error = 0;
if (!ksu_access_ok((void __user*)arg3, sizeof(susfs_is_sus_su_ready))) {
pr_err("susfs: CMD_SUSFS_IS_SUS_SU_READY -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_IS_SUS_SU_READY -> arg5 is not accessible\n");
return 0;
}
error = copy_to_user((void __user*)arg3, (void*)&susfs_is_sus_su_ready, sizeof(susfs_is_sus_su_ready));
pr_info("susfs: CMD_SUSFS_IS_SUS_SU_READY -> ret: %d\n", error);
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
if (arg2 == CMD_SUSFS_SHOW_SUS_SU_WORKING_MODE) {
int error = 0;
int working_mode = susfs_get_sus_su_working_mode();
if (!ksu_access_ok((void __user*)arg3, sizeof(working_mode))) {
pr_err("susfs: CMD_SUSFS_SHOW_SUS_SU_WORKING_MODE -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_SHOW_SUS_SU_WORKING_MODE -> arg5 is not accessible\n");
return 0;
}
error = copy_to_user((void __user*)arg3, (void*)&working_mode, sizeof(working_mode));
pr_info("susfs: CMD_SUSFS_SHOW_SUS_SU_WORKING_MODE -> ret: %d\n", error);
if (copy_to_user((void __user*)arg5, &error, sizeof(error)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_SU
}
#endif //#ifdef CONFIG_KSU_SUSFS
// all other cmds are for 'root manager'
if (!from_manager) {
return 0;
@@ -499,7 +1004,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) {
@@ -511,6 +1016,12 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
}
if (enabled) {
#ifdef CONFIG_KSU_SUSFS_SUS_SU
// We disable all sus_su hook whenever user toggle on su_kps
susfs_is_sus_su_hooks_enabled = false;
ksu_devpts_hook = false;
susfs_sus_su_working_mode = SUS_SU_DISABLED;
#endif
ksu_sucompat_init();
} else {
ksu_sucompat_exit();
@@ -523,6 +1034,8 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
return 0;
}
#endif
return 0;
}
@@ -549,11 +1062,15 @@ static bool should_umount(struct path *path)
return false;
}
#ifdef CONFIG_KSU_SUSFS
return susfs_is_mnt_devname_ksu(path);
#else
if (path->mnt && path->mnt->mnt_sb && path->mnt->mnt_sb->s_type) {
const char *fstype = path->mnt->mnt_sb->s_type->name;
return strcmp(fstype, "overlay") == 0;
}
return false;
#endif
}
static int ksu_umount_mnt(struct path *path, int flags)
@@ -566,7 +1083,11 @@ static int ksu_umount_mnt(struct path *path, int flags)
#endif
}
static void try_umount(const char *mnt, bool check_mnt, int flags)
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
void ksu_try_umount(const char *mnt, bool check_mnt, int flags, uid_t uid)
#else
static void ksu_try_umount(const char *mnt, bool check_mnt, int flags)
#endif
{
struct path path;
int err = kern_path(mnt, 0, &path);
@@ -586,12 +1107,35 @@ static void try_umount(const char *mnt, bool check_mnt, int flags)
return;
}
#if defined(CONFIG_KSU_SUSFS_TRY_UMOUNT) && defined(CONFIG_KSU_SUSFS_ENABLE_LOG)
if (susfs_is_log_enabled) {
pr_info("susfs: umounting '%s' for uid: %d\n", mnt, uid);
}
#endif
err = ksu_umount_mnt(&path, flags);
if (err) {
pr_warn("umount %s failed: %d\n", mnt, err);
}
}
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
void susfs_try_umount_all(uid_t uid) {
susfs_try_umount(uid);
/* For Legacy KSU only */
ksu_try_umount("/system", true, 0, uid);
ksu_try_umount("/system_ext", true, 0, uid);
ksu_try_umount("/vendor", true, 0, uid);
ksu_try_umount("/product", true, 0, uid);
ksu_try_umount("/odm", true, 0, uid);
// - For '/data/adb/modules' we pass 'false' here because it is a loop device that we can't determine whether
// its dev_name is KSU or not, and it is safe to just umount it if it is really a mountpoint
ksu_try_umount("/data/adb/modules", false, MNT_DETACH, uid);
/* For both Legacy KSU and Magic Mount KSU */
ksu_try_umount("/debug_ramdisk", true, MNT_DETACH, uid);
}
#endif
int ksu_handle_setuid(struct cred *new, const struct cred *old)
{
// this hook is used for umounting overlayfs for some uid, if there isn't any module mounted, just ignore it!
@@ -611,6 +1155,53 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
return 0;
}
#ifdef CONFIG_KSU_SUSFS
// check if current process is zygote
bool is_zygote_child = susfs_is_sid_equal(old->security, susfs_zygote_sid);
if (likely(is_zygote_child)) {
// if spawned process is non user app process
if (unlikely(new_uid.val < 10000 && new_uid.val >= 1000)) {
#ifdef CONFIG_KSU_SUSFS_SUS_SU
// set flag if zygote spawned system process is allowed for root access
if (!ksu_is_allow_uid(new_uid.val)) {
task_lock(current);
susfs_set_current_proc_su_not_allowed();
task_unlock(current);
}
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_SU
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
// umount for the system process if path DATA_ADB_UMOUNT_FOR_ZYGOTE_SYSTEM_PROCESS exists
if (susfs_is_umount_for_zygote_system_process_enabled) {
goto out_ksu_try_umount;
}
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
}
// - here we check if uid is a isolated service spawned by zygote directly
// - Apps that do not use "useAppZyogte" to start a isolated service will be directly
// spawned by zygote which KSU will ignore it by default, the only fix for now is to
// force a umount for those uid
// - Therefore make sure your root app doesn't use isolated service for root access
// - Kudos to ThePedroo, the author and maintainer of Rezygisk for finding and reporting
// the detection, really big helps here!
else if (new_uid.val >= 90000 && new_uid.val < 1000000) {
task_lock(current);
susfs_set_current_non_root_user_app_proc();
#ifdef CONFIG_KSU_SUSFS_SUS_SU
susfs_set_current_proc_su_not_allowed();
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_SU
task_unlock(current);
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
susfs_run_sus_path_loop(new_uid.val);
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_PATH
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
if (susfs_is_umount_for_zygote_iso_service_enabled) {
goto out_susfs_try_umount_all;
}
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
}
}
#endif // #ifdef CONFIG_KSU_SUSFS
if (!is_appuid(new_uid) || is_unsupported_uid(new_uid.val)) {
// pr_info("handle setuid ignore non application or isolated uid: %d\n", new_uid.val);
return 0;
@@ -620,7 +1211,23 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
// pr_info("handle setuid ignore allowed application: %d\n", new_uid.val);
return 0;
}
#ifdef CONFIG_KSU_SUSFS
else {
task_lock(current);
susfs_set_current_non_root_user_app_proc();
#ifdef CONFIG_KSU_SUSFS_SUS_SU
susfs_set_current_proc_su_not_allowed();
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_SU
task_unlock(current);
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
susfs_run_sus_path_loop(new_uid.val);
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_PATH
}
#endif // #ifdef CONFIG_KSU_SUSFS
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
out_ksu_try_umount:
#endif
if (!ksu_uid_should_umount(new_uid.val)) {
return 0;
} else {
@@ -629,10 +1236,12 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
#endif
}
#ifndef CONFIG_KSU_SUSFS
// check old process's selinux context, if it is not zygote, ignore it!
// because some su apps may setuid to untrusted_app but they are in global mount namespace
// when we umount for such process, that is a disaster!
bool is_zygote_child = is_zygote(old->security);
bool is_zygote_child = ksu_is_zygote(old->security);
#endif
if (!is_zygote_child) {
pr_info("handle umount ignore non zygote child: %d\n",
current->pid);
@@ -644,26 +1253,31 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
current->pid);
#endif
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
out_susfs_try_umount_all:
// susfs come first, and lastly umount by ksu, make sure umount in reversed order
susfs_try_umount_all(new_uid.val);
#else
// fixme: use `collect_mounts` and `iterate_mount` to iterate all mountpoint and
// filter the mountpoint whose target is `/data/adb`
try_umount("/odm", true, 0);
try_umount("/system", true, 0);
try_umount("/system_ext", true, 0);
try_umount("/vendor", true, 0);
try_umount("/product", true, 0);
try_umount("/data/adb/modules", false, MNT_DETACH);
ksu_try_umount("/odm", true, 0);
ksu_try_umount("/system", true, 0);
ksu_try_umount("/system_ext", true, 0);
ksu_try_umount("/vendor", true, 0);
ksu_try_umount("/product", true, 0);
ksu_try_umount("/data/adb/modules", false, MNT_DETACH);
// try umount ksu temp path
try_umount("/debug_ramdisk", false, MNT_DETACH);
try_umount("/sbin", false, MNT_DETACH);
ksu_try_umount("/debug_ramdisk", false, MNT_DETACH);
ksu_try_umount("/sbin", false, MNT_DETACH);
// try umount hosts file
try_umount("/system/etc/hosts", false, MNT_DETACH);
ksu_try_umount("/system/etc/hosts", false, MNT_DETACH);
// try umount lsposed dex2oat bins
try_umount("/apex/com.android.art/bin/dex2oat64", false, MNT_DETACH);
try_umount("/apex/com.android.art/bin/dex2oat32", false, MNT_DETACH);
ksu_try_umount("/apex/com.android.art/bin/dex2oat64", false, MNT_DETACH);
ksu_try_umount("/apex/com.android.art/bin/dex2oat32", false, MNT_DETACH);
#endif // #ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
return 0;
}

View File

@@ -76,6 +76,16 @@ void ksu_android_ns_fs_check()
task_unlock(current);
}
int ksu_access_ok(const void *addr, unsigned long size) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0)
/* For kernels before 5.0.0, pass the type argument to access_ok. */
return access_ok(VERIFY_READ, addr, size);
#else
/* For kernels 5.0.0 and later, ignore the type argument. */
return access_ok(addr, size);
#endif
}
struct file *ksu_filp_open_compat(const char *filename, int flags, umode_t mode)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
@@ -173,3 +183,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,12 +23,16 @@
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;
#endif
extern void ksu_android_ns_fs_check();
extern int ksu_access_ok(const void *addr, unsigned long size);
extern struct file *ksu_filp_open_compat(const char *filename, int flags,
umode_t mode);
extern ssize_t ksu_kernel_read_compat(struct file *p, void *buf, size_t count,

View File

@@ -11,6 +11,10 @@
#include "ksu.h"
#include "throne_tracker.h"
#ifdef CONFIG_KSU_SUSFS
#include <linux/susfs.h>
#endif
static struct workqueue_struct *ksu_workqueue;
bool ksu_queue_work(struct work_struct *work)
@@ -37,7 +41,7 @@ extern void ksu_sucompat_exit();
extern void ksu_ksud_init();
extern void ksu_ksud_exit();
int __init kernelsu_init(void)
int __init ksu_kernelsu_init(void)
{
#ifdef CONFIG_KSU_DEBUG
pr_alert("*************************************************************");
@@ -49,6 +53,10 @@ int __init kernelsu_init(void)
pr_alert("*************************************************************");
#endif
#ifdef CONFIG_KSU_SUSFS
susfs_init();
#endif
ksu_core_init();
ksu_workqueue = alloc_ordered_workqueue("kernelsu_work_queue", 0);
@@ -72,7 +80,7 @@ int __init kernelsu_init(void)
return 0;
}
void kernelsu_exit(void)
void ksu_kernelsu_exit(void)
{
ksu_allowlist_exit();
@@ -88,8 +96,8 @@ void kernelsu_exit(void)
ksu_core_exit();
}
module_init(kernelsu_init);
module_exit(kernelsu_exit);
module_init(ksu_kernelsu_init);
module_exit(ksu_kernelsu_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("weishu");

View File

@@ -58,12 +58,15 @@ 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
#ifdef CONFIG_KSU_SUSFS_SUS_SU
bool susfs_is_sus_su_ready = false;
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_SU
u32 ksu_devpts_sid;
@@ -71,15 +74,15 @@ u32 ksu_devpts_sid;
bool ksu_is_compat __read_mostly = false;
#endif
void on_post_fs_data(void)
void ksu_on_post_fs_data(void)
{
static bool done = false;
if (done) {
pr_info("on_post_fs_data already done\n");
pr_info("ksu_on_post_fs_data already done\n");
return;
}
done = true;
pr_info("on_post_fs_data!\n");
pr_info("ksu_on_post_fs_data!\n");
ksu_load_allow_list();
// sanity check, this may influence the performance
stop_input_hook();
@@ -197,14 +200,13 @@ 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();
ksu_apply_kernelsu_rules();
init_second_stage_executed = true;
ksu_android_ns_fs_check();
}
@@ -223,12 +225,12 @@ 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")) {
pr_info("/init second_stage executed\n");
apply_kernelsu_rules();
ksu_apply_kernelsu_rules();
init_second_stage_executed = true;
ksu_android_ns_fs_check();
}
@@ -248,7 +250,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
@@ -265,7 +267,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
(!strcmp(env_value, "1") ||
!strcmp(env_value, "true"))) {
pr_info("/init second_stage executed\n");
apply_kernelsu_rules();
ksu_apply_kernelsu_rules();
init_second_stage_executed =
true;
ksu_android_ns_fs_check();
@@ -280,7 +282,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
first_app_process = false;
pr_info("exec app_process, /data prepared, second_stage: %d\n",
init_second_stage_executed);
on_post_fs_data(); // we keep this for old ksud
ksu_on_post_fs_data(); // we keep this for old ksud
stop_execve_hook();
}
@@ -489,10 +491,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;
@@ -678,6 +682,10 @@ static void stop_execve_hook()
ksu_execveat_hook = false;
pr_info("stop execve_hook\n");
#endif
#ifdef CONFIG_KSU_SUSFS_SUS_SU
susfs_is_sus_su_ready = true;
pr_info("susfs: sus_su is ready\n");
#endif
}
static void stop_input_hook()

View File

@@ -5,7 +5,7 @@
#define KSUD_PATH "/data/adb/ksud"
void on_post_fs_data(void);
void ksu_on_post_fs_data(void);
bool ksu_is_safe_mode(void);

View File

@@ -13,7 +13,7 @@ static inline bool ksu_is_manager_uid_valid()
return ksu_manager_uid != KSU_INVALID_UID;
}
static inline bool is_manager()
static inline bool ksu_is_manager()
{
return unlikely(ksu_manager_uid == current_uid().val);
}

View File

@@ -38,11 +38,11 @@ static struct policydb *get_policydb(void)
static DEFINE_MUTEX(ksu_rules);
void apply_kernelsu_rules()
void ksu_apply_kernelsu_rules()
{
struct policydb *db;
if (!getenforce()) {
if (!ksu_getenforce()) {
pr_info("SELinux permissive or disabled, apply rules!\n");
}
@@ -139,6 +139,14 @@ void apply_kernelsu_rules()
ksu_allow(db, "system_server", KERNEL_SU_DOMAIN, "process", "getpgid");
ksu_allow(db, "system_server", KERNEL_SU_DOMAIN, "process", "sigkill");
#ifdef CONFIG_KSU_SUSFS
// Allow umount in zygote process without installing zygisk
ksu_allow(db, "zygote", "labeledfs", "filesystem", "unmount");
susfs_set_init_sid();
susfs_set_ksu_sid();
susfs_set_zygote_sid();
#endif
mutex_unlock(&ksu_rules);
}
@@ -228,13 +236,13 @@ static void reset_avc_cache()
selinux_xfrm_notify_policyload();
}
int handle_sepolicy(unsigned long arg3, void __user *arg4)
int ksu_handle_sepolicy(unsigned long arg3, void __user *arg4)
{
if (!arg4) {
return -1;
}
if (!getenforce()) {
if (!ksu_getenforce()) {
pr_info("SELinux permissive or disabled when handle policy!\n");
}

View File

@@ -8,6 +8,14 @@
#define KERNEL_SU_DOMAIN "u:r:su:s0"
#ifdef CONFIG_KSU_SUSFS
#define KERNEL_INIT_DOMAIN "u:r:init:s0"
#define KERNEL_ZYGOTE_DOMAIN "u:r:zygote:s0"
u32 susfs_ksu_sid = 0;
u32 susfs_init_sid = 0;
u32 susfs_zygote_sid = 0;
#endif
static int transive_to_domain(const char *domain)
{
struct cred *cred;
@@ -37,7 +45,7 @@ static int transive_to_domain(const char *domain)
return error;
}
void setup_selinux(const char *domain)
void ksu_setup_selinux(const char *domain)
{
if (transive_to_domain(domain)) {
pr_err("transive domain failed.\n");
@@ -52,7 +60,7 @@ if (!is_domain_permissive) {
}*/
}
void setenforce(bool enforce)
void ksu_setenforce(bool enforce)
{
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
#ifdef KSU_COMPAT_USE_SELINUX_STATE
@@ -63,7 +71,7 @@ void setenforce(bool enforce)
#endif
}
bool getenforce()
bool ksu_getenforce()
{
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
#ifdef KSU_COMPAT_USE_SELINUX_STATE
@@ -99,7 +107,7 @@ static inline u32 current_sid(void)
}
#endif
bool is_ksu_domain()
bool ksu_is_ksu_domain()
{
char *domain;
u32 seclen;
@@ -113,7 +121,7 @@ bool is_ksu_domain()
return result;
}
bool is_zygote(void *sec)
bool ksu_is_zygote(void *sec)
{
struct task_security_struct *tsec = (struct task_security_struct *)sec;
if (!tsec) {
@@ -131,6 +139,83 @@ bool is_zygote(void *sec)
return result;
}
#ifdef CONFIG_KSU_SUSFS
static inline void susfs_set_sid(const char *secctx_name, u32 *out_sid)
{
int err;
if (!secctx_name || !out_sid) {
pr_err("secctx_name || out_sid is NULL\n");
return;
}
err = security_secctx_to_secid(secctx_name, strlen(secctx_name),
out_sid);
if (err) {
pr_err("failed setting sid for '%s', err: %d\n", secctx_name, err);
return;
}
pr_info("sid '%u' is set for secctx_name '%s'\n", *out_sid, secctx_name);
}
bool susfs_is_sid_equal(void *sec, u32 sid2) {
struct task_security_struct *tsec = (struct task_security_struct *)sec;
if (!tsec) {
return false;
}
return tsec->sid == sid2;
}
u32 susfs_get_sid_from_name(const char *secctx_name)
{
u32 out_sid = 0;
int err;
if (!secctx_name) {
pr_err("secctx_name is NULL\n");
return 0;
}
err = security_secctx_to_secid(secctx_name, strlen(secctx_name),
&out_sid);
if (err) {
pr_err("failed getting sid from secctx_name: %s, err: %d\n", secctx_name, err);
return 0;
}
return out_sid;
}
u32 susfs_get_current_sid(void) {
return current_sid();
}
void susfs_set_zygote_sid(void)
{
susfs_set_sid(KERNEL_ZYGOTE_DOMAIN, &susfs_zygote_sid);
}
bool susfs_is_current_zygote_domain(void) {
return unlikely(current_sid() == susfs_zygote_sid);
}
void susfs_set_ksu_sid(void)
{
susfs_set_sid(KERNEL_SU_DOMAIN, &susfs_ksu_sid);
}
bool susfs_is_current_ksu_domain(void) {
return unlikely(current_sid() == susfs_ksu_sid);
}
void susfs_set_init_sid(void)
{
susfs_set_sid(KERNEL_INIT_DOMAIN, &susfs_init_sid);
}
bool susfs_is_current_init_domain(void) {
return unlikely(current_sid() == susfs_init_sid);
}
#endif
#define DEVPTS_DOMAIN "u:object_r:ksu_file:s0"
u32 ksu_get_devpts_sid()

View File

@@ -8,17 +8,29 @@
#define KSU_COMPAT_USE_SELINUX_STATE
#endif
void setup_selinux(const char *);
void ksu_setup_selinux(const char *);
void setenforce(bool);
void ksu_setenforce(bool);
bool getenforce();
bool ksu_getenforce();
bool is_ksu_domain();
bool ksu_is_ksu_domain();
bool is_zygote(void *cred);
bool ksu_is_zygote(void *cred);
void apply_kernelsu_rules();
void ksu_apply_kernelsu_rules();
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
bool susfs_is_sid_equal(void *sec, u32 sid2);
u32 susfs_get_sid_from_name(const char *secctx_name);
u32 susfs_get_current_sid(void);
void susfs_set_zygote_sid(void);
bool susfs_is_current_zygote_domain(void);
void susfs_set_ksu_sid(void);
bool susfs_is_current_ksu_domain(void);
void susfs_set_init_sid(void);
bool susfs_is_current_init_domain(void);
#endif
u32 ksu_get_devpts_sid();

View File

@@ -13,6 +13,9 @@
#else
#include <linux/sched.h>
#endif
#ifdef CONFIG_KSU_SUSFS_SUS_SU
#include <linux/susfs_def.h>
#endif
#include "objsec.h"
#include "allowlist.h"
@@ -28,9 +31,13 @@
static bool ksu_sucompat_non_kp __read_mostly = true;
#endif
extern void escape_to_root();
extern void ksu_escape_to_root();
static void __user *userspace_stack_buffer(const void *d, size_t len)
static const char sh_path[] = "/system/bin/sh";
static const char ksud_path[] = KSUD_PATH;
static const char su[] = SU_PATH;
static inline void __user *userspace_stack_buffer(const void *d, size_t len)
{
/* To avoid having to mmap a page in userspace, just write below the stack
* pointer. */
@@ -39,24 +46,19 @@ static void __user *userspace_stack_buffer(const void *d, size_t len)
return copy_to_user(p, d, len) ? NULL : p;
}
static char __user *sh_user_path(void)
static inline char __user *sh_user_path(void)
{
static const char sh_path[] = "/system/bin/sh";
return userspace_stack_buffer(sh_path, sizeof(sh_path));
}
static char __user *ksud_user_path(void)
static inline char __user *ksud_user_path(void)
{
static const char ksud_path[] = KSUD_PATH;
return userspace_stack_buffer(ksud_path, sizeof(ksud_path));
}
int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
int *__unused_flags)
{
const char su[] = SU_PATH;
#ifndef CONFIG_KSU_KPROBES_HOOK
if (!ksu_sucompat_non_kp) {
@@ -64,12 +66,19 @@ int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
}
#endif
#ifndef CONFIG_KSU_SUSFS_SUS_SU
if (!ksu_is_allow_uid(current_uid().val)) {
return 0;
}
#endif
#ifdef CONFIG_KSU_SUSFS_SUS_SU
char path[sizeof(su) + 1] = {0};
#else
char path[sizeof(su) + 1];
memset(path, 0, sizeof(path));
#endif
ksu_strncpy_from_user_nofault(path, *filename_user, sizeof(path));
if (unlikely(!memcmp(path, su, sizeof(su)))) {
@@ -80,10 +89,27 @@ int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
return 0;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) && defined(CONFIG_KSU_SUSFS_SUS_SU)
struct filename* susfs_ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags) {
struct filename *name = getname_flags(*filename_user, getname_statx_lookup_flags(*flags), NULL);
if (unlikely(IS_ERR(name) || name->name == NULL)) {
return name;
}
if (likely(memcmp(name->name, su, sizeof(su)))) {
return name;
}
const char sh[] = SH_PATH;
pr_info("vfs_fstatat su->sh!\n");
memcpy((void *)name->name, sh, sizeof(sh));
return name;
}
#endif
int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags)
{
// const char sh[] = SH_PATH;
const char su[] = SU_PATH;
#ifndef CONFIG_KSU_KPROBES_HOOK
if (!ksu_sucompat_non_kp){
@@ -91,16 +117,22 @@ int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags)
}
#endif
#ifndef CONFIG_KSU_SUSFS_SUS_SU
if (!ksu_is_allow_uid(current_uid().val)) {
return 0;
}
#endif
if (unlikely(!filename_user)) {
return 0;
}
char path[sizeof(su) + 1];
memset(path, 0, sizeof(path));
#ifdef CONFIG_KSU_SUSFS_SUS_SU
char path[sizeof(su) + 1] = {0};
#else
char path[sizeof(su) + 1];
memset(path, 0, sizeof(path));
#endif
// Remove this later!! we use syscall hook, so this will never happen!!!!!
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) && 0
// it becomes a `struct filename *` after 5.18
@@ -132,8 +164,6 @@ int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
int *__never_use_flags)
{
struct filename *filename;
const char sh[] = KSUD_PATH;
const char su[] = SU_PATH;
#ifndef CONFIG_KSU_KPROBES_HOOK
if (!ksu_sucompat_non_kp) {
@@ -152,13 +182,15 @@ int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
if (likely(memcmp(filename->name, su, sizeof(su))))
return 0;
#ifndef CONFIG_KSU_SUSFS_SUS_SU
if (!ksu_is_allow_uid(current_uid().val))
return 0;
#endif
pr_info("do_execveat_common su found\n");
memcpy((void *)filename->name, sh, sizeof(sh));
memcpy((void *)filename->name, ksud_path, sizeof(ksud_path));
escape_to_root();
ksu_escape_to_root();
return 0;
}
@@ -167,8 +199,12 @@ int ksu_handle_execve_sucompat(int *fd, const char __user **filename_user,
void *__never_use_argv, void *__never_use_envp,
int *__never_use_flags)
{
const char su[] = SU_PATH;
char path[sizeof(su) + 1];
//const char su[] = SU_PATH;
#ifdef CONFIG_KSU_SUSFS_SUS_SU
char path[sizeof(su) + 1] = {0};
#else
char path[sizeof(su) + 1];
#endif
#ifndef CONFIG_KSU_KPROBES_HOOK
if (!ksu_sucompat_non_kp) {
@@ -179,23 +215,10 @@ 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;
#ifndef CONFIG_KSU_SUSFS_SUS_SU
memset(path, 0, sizeof(path));
#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';
ksu_strncpy_from_user_retry(path, *filename_user, sizeof(path));
if (likely(memcmp(path, su, sizeof(su))))
return 0;
@@ -206,7 +229,7 @@ int ksu_handle_execve_sucompat(int *fd, const char __user **filename_user,
pr_info("sys_execve su found\n");
*filename_user = ksud_user_path();
escape_to_root();
ksu_escape_to_root();
return 0;
}
@@ -352,3 +375,41 @@ void ksu_sucompat_exit()
pr_info("ksu_sucompat_exit: hooks disabled: execve/execveat_su, faccessat, stat, devpts\n");
#endif
}
#ifdef CONFIG_KSU_SUSFS_SUS_SU
extern bool ksu_su_compat_enabled;
bool ksu_devpts_hook = false;
bool susfs_is_sus_su_hooks_enabled __read_mostly = false;
int susfs_sus_su_working_mode = 0;
static bool ksu_is_su_kps_enabled(void) {
for (int i = 0; i < ARRAY_SIZE(su_kps); i++) {
if (su_kps[i]) {
return true;
}
}
return false;
}
void ksu_susfs_disable_sus_su(void) {
susfs_is_sus_su_hooks_enabled = false;
ksu_devpts_hook = false;
susfs_sus_su_working_mode = SUS_SU_DISABLED;
// Re-enable the su_kps for user, users need to toggle off the kprobe hooks again in ksu manager if they want it disabled.
if (!ksu_is_su_kps_enabled()) {
ksu_sucompat_init();
ksu_su_compat_enabled = true;
}
}
void ksu_susfs_enable_sus_su(void) {
if (ksu_is_su_kps_enabled()) {
ksu_sucompat_exit();
ksu_su_compat_enabled = false;
}
susfs_is_sus_su_hooks_enabled = true;
ksu_devpts_hook = true;
susfs_sus_su_working_mode = SUS_SU_WITH_HOOKS;
}
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_SU

View File

@@ -192,7 +192,7 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
}
}
bool is_manager = is_manager_apk(dirpath);
bool is_manager = ksu_is_manager_apk(dirpath);
pr_info("Found new base.apk at path: %s, is_manager: %d\n",
dirpath, is_manager);
if (is_manager) {
@@ -351,7 +351,7 @@ static bool is_uid_exist(uid_t uid, char *package, void *data)
return exist;
}
void track_throne()
void ksu_track_throne()
{
struct file *fp;
int tries = 0;

View File

@@ -5,7 +5,7 @@ void ksu_throne_tracker_init();
void ksu_throne_tracker_exit();
void track_throne();
void ksu_track_throne();
bool is_lock_held(const char *path);

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

@@ -81,35 +81,6 @@ import com.rifsxd.ksunext.ui.util.rootAvailable
@Destination<RootGraph>
@Composable
fun InstallScreen(navigator: DestinationsNavigator) {
var showLkmWarning by rememberSaveable { mutableStateOf(true) }
if (showLkmWarning) {
AlertDialog(
onDismissRequest = {
showLkmWarning = false
navigator.popBackStack()
},
title = { Text(
text = stringResource(R.string.warning),
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.SemiBold
) },
text = { Text(stringResource(R.string.lkm_warning_message)) },
confirmButton = {
TextButton(onClick = { showLkmWarning = false }) {
Text(stringResource(R.string.proceed))
}
},
dismissButton = {
TextButton(onClick = {
showLkmWarning = false
navigator.popBackStack()
}) {
Text(stringResource(R.string.cancel))
}
}
)
}
var installMethod by remember {
mutableStateOf<InstallMethod?>(null)

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
KernelSU-Next/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);
}

227
KernelSU-Next/userspace/ksuinit/Cargo.lock generated Normal file
View File

@@ -0,0 +1,227 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "anyhow"
version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1"
[[package]]
name = "bitflags"
version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
[[package]]
name = "errno"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "goblin"
version = "0.8.0"
source = "git+https://github.com/tiann/goblin#138d40d4c36471cfbb611eb493f0378ee9fc63f5"
dependencies = [
"log",
"plain",
"scroll",
]
[[package]]
name = "kernlog"
version = "0.3.1"
source = "git+https://github.com/tiann/kernlog.rs#ff0b1bd6d5261eae0fa297cec6951fe8d982151a"
dependencies = [
"libc",
"log",
]
[[package]]
name = "ksuinit"
version = "0.1.0"
dependencies = [
"anyhow",
"goblin",
"kernlog",
"log",
"obfstr",
"rustix",
"scroll",
"syscalls",
]
[[package]]
name = "libc"
version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "linux-raw-sys"
version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
[[package]]
name = "log"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "obfstr"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3ba2979b86cc910a6d13837ef97fef0c6b68fa807c5e014d622449db18351dc"
[[package]]
name = "plain"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
[[package]]
name = "proc-macro2"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rustix"
version = "0.38.34"
source = "git+https://github.com/Kernel-SU/rustix.git?rev=4a53fbc#4a53fbc7cb7a07cabe87125cc21dbc27db316259"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "scroll"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ab8598aa408498679922eff7fa985c25d58a90771bd6be794434c5277eab1a6"
dependencies = [
"scroll_derive",
]
[[package]]
name = "scroll_derive"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f81c2fde025af7e69b1d1420531c8a8811ca898919db177141a85313b1cb932"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "syn"
version = "2.0.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syscalls"
version = "0.6.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56b389b38331a454883a34fd19f25cbd1510b3510ff7aa28cb8d6de85d888439"
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
[[package]]
name = "windows_i686_gnu"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
[[package]]
name = "windows_i686_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"

View File

@@ -0,0 +1,34 @@
[package]
name = "ksuinit"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
# for elf parsing
goblin = { git = "https://github.com/tiann/goblin" }
scroll = "0.12"
anyhow = "1"
# If you want to use the following dependencies, please use aarch64-unknown-linux-musl & x86_64-unknown-linux-musl to compile statically
# rustix = { git = "https://github.com/bytecodealliance/rustix", rev = "7b44528", features = ["mount", "fs", "runtime", "system", "process"] }
rustix = { git = "https://github.com/Kernel-SU/rustix.git", rev = "4a53fbc", features = ["mount", "fs", "runtime", "system", "process"] }
syscalls = { version = "0.6", default-features = false, features = [
"aarch64",
"x86_64",
] }
# for kmsg logging
log = "0.4"
kernlog = { git = "https://github.com/tiann/kernlog.rs" }
obfstr = "0.4"
[profile.release]
strip = true
lto = true
opt-level = "z"
panic = "abort"

View File

@@ -0,0 +1,185 @@
use std::io::{ErrorKind, Write};
use crate::loader::load_module;
use anyhow::Result;
use rustix::fs::{chmodat, symlink, unlink, AtFlags, Mode};
use rustix::{
fd::AsFd,
fs::{access, makedev, mkdir, mknodat, Access, FileType, CWD},
mount::{
fsconfig_create, fsmount, fsopen, move_mount, unmount, FsMountFlags, FsOpenFlags,
MountAttrFlags, MoveMountFlags, UnmountFlags,
},
};
use obfstr::obfstr as s;
struct AutoUmount {
mountpoints: Vec<String>,
}
impl Drop for AutoUmount {
fn drop(&mut self) {
for mountpoint in self.mountpoints.iter().rev() {
if let Err(e) = unmount(mountpoint.as_str(), UnmountFlags::DETACH) {
log::error!("{} {}: {}", s!("Cannot umount"), mountpoint, e)
}
}
}
}
fn prepare_mount() -> AutoUmount {
let mut mountpoints = vec![];
// mount procfs
let result = mkdir("/proc", Mode::from_raw_mode(0o755))
.or_else(|err| match err.kind() {
ErrorKind::AlreadyExists => Ok(()),
_ => Err(err),
})
.and_then(|_| fsopen("proc", FsOpenFlags::FSOPEN_CLOEXEC))
.and_then(|fd| fsconfig_create(fd.as_fd()).map(|_| fd))
.and_then(|fd| {
fsmount(
fd.as_fd(),
FsMountFlags::FSMOUNT_CLOEXEC,
MountAttrFlags::empty(),
)
})
.and_then(|fd| {
move_mount(
fd.as_fd(),
"",
CWD,
"/proc",
MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH,
)
});
match result {
Ok(_) => mountpoints.push("/proc".to_string()),
Err(e) => log::error!("{} {:?}", s!("Cannot mount procfs: "), e),
}
// mount sysfs
let result = mkdir("/sys", Mode::from_raw_mode(0o755))
.or_else(|err| match err.kind() {
ErrorKind::AlreadyExists => Ok(()),
_ => Err(err),
})
.and_then(|_| fsopen("sysfs", FsOpenFlags::FSOPEN_CLOEXEC))
.and_then(|fd| fsconfig_create(fd.as_fd()).map(|_| fd))
.and_then(|fd| {
fsmount(
fd.as_fd(),
FsMountFlags::FSMOUNT_CLOEXEC,
MountAttrFlags::empty(),
)
})
.and_then(|fd| {
move_mount(
fd.as_fd(),
"",
CWD,
"/sys",
MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH,
)
});
match result {
Ok(_) => mountpoints.push("/sys".to_string()),
Err(e) => log::error!("{} {:?}", s!("Cannot mount sysfs:"), e),
}
AutoUmount { mountpoints }
}
fn setup_kmsg() {
const KMSG: &str = "/dev/kmsg";
let device = match access(KMSG, Access::EXISTS) {
Ok(_) => KMSG,
Err(_) => {
// try to create it
mknodat(
CWD,
"/kmsg",
FileType::CharacterDevice,
0o666.into(),
makedev(1, 11),
)
.ok();
"/kmsg"
}
};
let _ = kernlog::init_with_device(device);
}
fn unlimit_kmsg() {
// Disable kmsg rate limiting
if let Ok(mut rate) = std::fs::File::options()
.write(true)
.open(s!("/proc/sys/kernel/printk_devkmsg"))
{
writeln!(rate, "on").ok();
}
}
pub fn init() -> Result<()> {
// Setup kernel log first
setup_kmsg();
log::info!("{}", s!("Hello, KernelSU!"));
// mount /proc and /sys to access kernel interface
let _dontdrop = prepare_mount();
// This relies on the fact that we have /proc mounted
unlimit_kmsg();
if has_kernelsu() {
log::info!("{}", s!("KernelSU may be already loaded in kernel, skip!"));
} else {
log::info!("{}", s!("Loading kernelsu.ko.."));
if let Err(e) = load_module(s!("/kernelsu.ko")) {
log::error!("{}: {}", s!("Cannot load kernelsu.ko"), e);
}
}
// And now we should prepare the real init to transfer control to it
unlink("/init")?;
let real_init = match access("/init.real", Access::EXISTS) {
Ok(_) => "init.real",
Err(_) => "/system/bin/init",
};
log::info!("{} {}", s!("init is"), real_init);
symlink(real_init, "/init")?;
chmodat(
CWD,
"/init",
Mode::from_raw_mode(0o755),
AtFlags::SYMLINK_NOFOLLOW,
)?;
Ok(())
}
fn has_kernelsu() -> bool {
use syscalls::{syscall, Sysno};
let mut version = 0;
const CMD_GET_VERSION: i32 = 2;
unsafe {
let _ = syscall!(
Sysno::prctl,
0xDEADBEEF,
CMD_GET_VERSION,
std::ptr::addr_of_mut!(version)
);
}
log::info!("{}: {}", s!("KernelSU version"), version);
version != 0
}

View File

@@ -0,0 +1,97 @@
use anyhow::{Context, Result};
use goblin::elf::{section_header, sym::Sym, Elf};
use rustix::{cstr, system::init_module};
use scroll::{ctx::SizeWith, Pwrite};
use std::collections::HashMap;
use std::fs;
use obfstr::obfstr as s;
struct Kptr {
value: String,
}
impl Kptr {
pub fn new() -> Result<Self> {
let value = fs::read_to_string(s!("/proc/sys/kernel/kptr_restrict"))?;
fs::write(s!("/proc/sys/kernel/kptr_restrict"), "1")?;
Ok(Kptr { value })
}
}
impl Drop for Kptr {
fn drop(&mut self) {
let _ = fs::write(s!("/proc/sys/kernel/kptr_restrict"), self.value.as_bytes());
}
}
fn parse_kallsyms() -> Result<HashMap<String, u64>> {
let _dontdrop = Kptr::new()?;
let allsyms = fs::read_to_string(s!("/proc/kallsyms"))?
.lines()
.map(|line| line.split_whitespace())
.filter_map(|mut splits| {
splits
.next()
.and_then(|addr| u64::from_str_radix(addr, 16).ok())
.and_then(|addr| splits.nth(1).map(|symbol| (symbol, addr)))
})
.map(|(symbol, addr)| {
(
symbol
.find("$").or_else(|| symbol.find(".llvm."))
.map_or(symbol, |pos| &symbol[0..pos])
.to_owned(),
addr,
)
})
.collect::<HashMap<_, _>>();
Ok(allsyms)
}
pub fn load_module(path: &str) -> Result<()> {
// check if self is init process(pid == 1)
if !rustix::process::getpid().is_init() {
anyhow::bail!("{}", s!("Invalid process"));
}
let mut buffer =
fs::read(path).with_context(|| format!("{} {}", s!("Cannot read file"), path))?;
let elf = Elf::parse(&buffer)?;
let kernel_symbols =
parse_kallsyms().with_context(|| s!("Cannot parse kallsyms").to_string())?;
let mut modifications = Vec::new();
for (index, mut sym) in elf.syms.iter().enumerate() {
if index == 0 {
continue;
}
if sym.st_shndx != section_header::SHN_UNDEF as usize {
continue;
}
let Some(name) = elf.strtab.get_at(sym.st_name) else {
continue;
};
let offset = elf.syms.offset() + index * Sym::size_with(elf.syms.ctx());
let Some(real_addr) = kernel_symbols.get(name) else {
log::warn!("{}: {}", s!("Cannot found symbol"), &name);
continue;
};
sym.st_shndx = section_header::SHN_ABS as usize;
sym.st_value = *real_addr;
modifications.push((sym, offset));
}
let ctx = *elf.syms.ctx();
for ele in modifications {
buffer.pwrite_with(ele.0, ele.1, ctx)?;
}
init_module(&buffer, cstr!("")).with_context(|| s!("init_module failed.").to_string())?;
Ok(())
}

View File

@@ -0,0 +1,19 @@
#![no_main]
mod init;
mod loader;
use rustix::{cstr, runtime::execve};
/// # Safety
/// This is the entry point of the program
/// We cannot use the main because rust will abort if we don't have std{in/out/err}
/// https://github.com/rust-lang/rust/blob/3071aefdb2821439e2e6f592f41a4d28e40c1e79/library/std/src/sys/unix/mod.rs#L80
/// So we use the C main function and call rust code from there
#[no_mangle]
pub unsafe extern "C" fn main(_argc: i32, argv: *const *const u8, envp: *const *const u8) -> i32 {
let _ = init::init();
unsafe {
execve(cstr!("/init"), argv, envp);
}
0
}

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

View File

@@ -1,5 +1,3 @@
CONFIG_LOCALVERSION="-✨Caelum-b4s4"
# Compression
CONFIG_KERNEL_LZ4=y
# CONFIG_FHANDLE is not set
CONFIG_AUDIT=y

View File

@@ -54,15 +54,6 @@
#include <asm/ioctls.h>
#include "internal.h"
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
#include <linux/susfs_def.h>
extern bool susfs_is_inode_sus_path(struct inode *inode);
extern bool susfs_is_sus_android_data_d_name_found(const char *d_name);
extern bool susfs_is_sus_sdcard_d_name_found(const char *d_name);
extern bool susfs_is_base_dentry_android_data_dir(struct dentry* base);
extern bool susfs_is_base_dentry_sdcard_dir(struct dentry* base);
#endif
/*
* Not all architectures have sys_utime, so implement this in terms
* of sys_utimes.
@@ -838,11 +829,6 @@ struct compat_old_linux_dirent {
struct compat_readdir_callback {
struct dir_context ctx;
struct compat_old_linux_dirent __user *dirent;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
struct super_block *sb;
bool is_base_dentry_android_data_root_dir;
bool is_base_dentry_sdcard_root_dir;
#endif
int result;
};
@@ -854,9 +840,6 @@ static int compat_fillonedir(struct dir_context *ctx, const char *name,
container_of(ctx, struct compat_readdir_callback, ctx);
struct compat_old_linux_dirent __user *dirent;
compat_ulong_t d_ino;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
struct inode *inode;
#endif
if (buf->result)
return -EINVAL;
@@ -865,28 +848,6 @@ static int compat_fillonedir(struct dir_context *ctx, const char *name,
buf->result = -EOVERFLOW;
return -EOVERFLOW;
}
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (buf->is_base_dentry_android_data_root_dir) {
if (susfs_is_sus_android_data_d_name_found(name)) {
return 0;
}
} else if (buf->is_base_dentry_sdcard_root_dir) {
if (susfs_is_sus_sdcard_d_name_found(name)) {
return 0;
}
}
inode = ilookup(buf->sb, ino);
if (!inode) {
goto orig_flow;
}
if (susfs_is_inode_sus_path(inode)) {
iput(inode);
return 0;
}
iput(inode);
orig_flow:
#endif
buf->result++;
dirent = buf->dirent;
if (!access_ok(VERIFY_WRITE, dirent,
@@ -914,33 +875,9 @@ COMPAT_SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
.ctx.actor = compat_fillonedir,
.dirent = dirent
};
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
struct inode *inode;
#endif
if (!f.file)
return -EBADF;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
buf.sb = f.file->f_inode->i_sb;
inode = f.file->f_path.dentry->d_inode;
if (f.file->f_path.dentry && inode) {
if (susfs_is_base_dentry_android_data_dir(f.file->f_path.dentry))
{
buf.is_base_dentry_android_data_root_dir = true;
buf.is_base_dentry_sdcard_root_dir = false;
goto orig_flow;
}
if (susfs_is_base_dentry_sdcard_dir(f.file->f_path.dentry))
{
buf.is_base_dentry_sdcard_root_dir = true;
buf.is_base_dentry_android_data_root_dir = false;
goto orig_flow;
}
}
buf.is_base_dentry_android_data_root_dir = false;
buf.is_base_dentry_sdcard_root_dir = false;
orig_flow:
#endif
error = iterate_dir(f.file, &buf.ctx);
if (buf.result)
@@ -961,11 +898,6 @@ struct compat_getdents_callback {
struct dir_context ctx;
struct compat_linux_dirent __user *current_dir;
struct compat_linux_dirent __user *previous;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
struct super_block *sb;
bool is_base_dentry_android_data_root_dir;
bool is_base_dentry_sdcard_root_dir;
#endif
int count;
int error;
};
@@ -979,9 +911,6 @@ static int compat_filldir(struct dir_context *ctx, const char *name, int namlen,
compat_ulong_t d_ino;
int reclen = ALIGN(offsetof(struct compat_linux_dirent, d_name) +
namlen + 2, sizeof(compat_long_t));
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
struct inode *inode;
#endif
buf->error = -EINVAL; /* only used if we fail.. */
if (reclen > buf->count)
@@ -991,26 +920,6 @@ static int compat_filldir(struct dir_context *ctx, const char *name, int namlen,
buf->error = -EOVERFLOW;
return -EOVERFLOW;
}
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (buf->is_base_dentry_android_data_root_dir) {
if (susfs_is_sus_android_data_d_name_found(name)) {
return 0;
}
} else if (buf->is_base_dentry_sdcard_root_dir) {
if (susfs_is_sus_sdcard_d_name_found(name)) {
return 0;
} }
inode = ilookup(buf->sb, ino);
if (!inode) { goto orig_flow;
}
if (susfs_is_inode_sus_path(inode)) {
iput(inode);
return 0;
}
iput(inode);
orig_flow:
#endif
dirent = buf->previous;
if (dirent) {
if (signal_pending(current))
@@ -1050,9 +959,6 @@ COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd,
.count = count
};
int error;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
struct inode *inode;
#endif
if (!access_ok(VERIFY_WRITE, dirent, count))
return -EFAULT;
@@ -1060,27 +966,6 @@ COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd,
f = fdget_pos(fd);
if (!f.file)
return -EBADF;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
buf.sb = f.file->f_inode->i_sb;
inode = f.file->f_path.dentry->d_inode;
if (f.file->f_path.dentry && inode) {
if (susfs_is_base_dentry_android_data_dir(f.file->f_path.dentry))
{
buf.is_base_dentry_android_data_root_dir = true;
buf.is_base_dentry_sdcard_root_dir = false;
goto orig_flow;
}
if (susfs_is_base_dentry_sdcard_dir(f.file->f_path.dentry))
{
buf.is_base_dentry_sdcard_root_dir = true;
buf.is_base_dentry_android_data_root_dir = false;
goto orig_flow;
}
}
buf.is_base_dentry_android_data_root_dir = false;
buf.is_base_dentry_sdcard_root_dir = false;
orig_flow:
#endif
error = iterate_dir(f.file, &buf.ctx);
if (error >= 0)

View File

@@ -40,10 +40,8 @@
#include <asm/uaccess.h>
#if defined(CONFIG_KSU_SUSFS_SUS_PATH) || defined(CONFIG_KSU_SUSFS_OPEN_REDIRECT)
#include <linux/susfs_def.h>
#endif
#include "internal.h"
#include "mount.h"
#endif
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
extern bool susfs_is_sus_android_data_d_name_found(const char *d_name);
extern bool susfs_is_sus_sdcard_d_name_found(const char *d_name);
@@ -53,6 +51,9 @@ extern bool susfs_is_base_dentry_sdcard_dir(struct dentry* base);
extern const struct qstr susfs_fake_qstr_name;
#endif
#include "internal.h"
#include "mount.h"
/* [Feb-1997 T. Schoebel-Theuer]
* Fundamental changes in the pathname lookup mechanisms (namei)
* were necessary because of omirr. The reason is that omirr needs
@@ -537,7 +538,7 @@ struct nameidata {
struct inode *inode; /* path.dentry.d_inode */
unsigned int flags;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
unsigned int state;
unsigned int state;
#endif
unsigned seq, m_seq;
int last_type;
@@ -948,6 +949,12 @@ static inline int may_follow_link(struct nameidata *nd)
const struct inode *parent;
kuid_t puid;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (nd->inode && unlikely(nd->inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) {
return -ENOENT;
}
#endif
if (!sysctl_protected_symlinks)
return 0;
@@ -1024,6 +1031,12 @@ static int may_linkat(struct path *link)
{
struct inode *inode;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (link->dentry->d_inode && unlikely(link->dentry->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) {
return -ENOENT;
}
#endif
if (!sysctl_protected_hardlinks)
return 0;
@@ -1063,6 +1076,12 @@ static int may_linkat(struct path *link)
static int may_create_in_sticky(umode_t dir_mode, kuid_t dir_uid,
struct inode * const inode)
{
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (unlikely(inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) {
return -ENOENT;
}
#endif
if ((!sysctl_protected_fifos && S_ISFIFO(inode->i_mode)) ||
(!sysctl_protected_regular && S_ISREG(inode->i_mode)) ||
likely(!(dir_mode & S_ISVTX)) ||
@@ -1592,7 +1611,11 @@ static struct dentry *__lookup_hash(const struct qstr *name,
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
struct dentry *dentry;
bool found_sus_path = false;
#else
struct dentry *dentry = lookup_dcache(name, base, flags);
#endif
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (base && base->d_inode && !found_sus_path) {
if (susfs_is_base_dentry_android_data_dir(base) &&
susfs_is_sus_android_data_d_name_found(name->name))
@@ -1613,23 +1636,18 @@ static struct dentry *__lookup_hash(const struct qstr *name,
}
dentry = lookup_dcache(name, base, flags);
retry:
#else
struct dentry *dentry = lookup_dcache(name, base, flags);
#endif
if (dentry)
if (dentry) {
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
{
if (!found_sus_path && !IS_ERR(dentry) && dentry->d_inode && susfs_is_inode_sus_path(dentry->d_inode)) {
dentry = lookup_dcache(&susfs_fake_qstr_name, base, flags);
found_sus_path = true;
goto retry;
}
#endif
return dentry;
}
#else
return dentry;
#endif
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (found_sus_path) {
@@ -1647,7 +1665,6 @@ skip_orig_flow:
return lookup_real(base->d_inode, dentry, flags);
}
static int lookup_fast(struct nameidata *nd,
struct path *path, struct inode **inode,
unsigned *seqp)
@@ -1655,10 +1672,11 @@ static int lookup_fast(struct nameidata *nd,
struct vfsmount *mnt = nd->path.mnt;
struct dentry *dentry, *parent = nd->path.dentry;
int status = 1;
int err;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
bool is_nd_state_lookup_last_and_open_last = (nd->state & ND_STATE_LOOKUP_LAST || nd->state & ND_STATE_OPEN_LAST);
bool is_nd_state_lookup_last_and_open_last =
(nd->state & ND_STATE_LOOKUP_LAST || nd->state & ND_STATE_OPEN_LAST);
#endif
int err;
/*
* Rename seqlock is not required here because in the off chance
@@ -1687,7 +1705,7 @@ static int lookup_fast(struct nameidata *nd,
#endif
dentry = __d_lookup_rcu(parent, &nd->last, &seq);
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (is_nd_state_lookup_last_and_open_last && dentry && !IS_ERR(dentry) && dentry->d_inode && parent->d_inode) {
if (is_nd_state_lookup_last_and_open_last && dentry && !IS_ERR(dentry) && dentry->d_inode) {
if (susfs_is_inode_sus_path(dentry->d_inode)) {
dentry = __d_lookup_rcu(parent, &susfs_fake_qstr_name, &backup_next_seq);
}
@@ -1759,7 +1777,7 @@ skip_orig_flow1:
#endif
dentry = __d_lookup(parent, &nd->last);
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (is_nd_state_lookup_last_and_open_last && dentry && !IS_ERR(dentry) && dentry->d_inode && parent->d_inode) {
if (is_nd_state_lookup_last_and_open_last && dentry && !IS_ERR(dentry) && dentry->d_inode) {
if (susfs_is_inode_sus_path(dentry->d_inode)) {
dentry = __d_lookup(parent, &susfs_fake_qstr_name);
}
@@ -1822,7 +1840,7 @@ again:
found_sus_path = true;
goto retry;
} else if (susfs_is_base_dentry_sdcard_dir(dir) &&
susfs_is_sus_sdcard_d_name_found(name->name))
susfs_is_sus_sdcard_d_name_found(name->name))
{
dentry = d_alloc_parallel(dir, &susfs_fake_qstr_name, &sus_wq);
found_sus_path = true;
@@ -2252,6 +2270,9 @@ static inline u64 hash_name(const void *salt, const char *name)
static int link_path_walk(const char *name, struct nameidata *nd)
{
int err;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
struct dentry *dentry;
#endif
while (*name=='/')
name++;
@@ -2262,13 +2283,11 @@ static int link_path_walk(const char *name, struct nameidata *nd)
for(;;) {
u64 hash_len;
int type;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
struct dentry *dentry;
#endif
err = may_lookup(nd);
if (err)
return err;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
dentry = nd->path.dentry;
if (dentry->d_inode && susfs_is_inode_sus_path(dentry->d_inode)) {
@@ -2493,6 +2512,7 @@ static inline int lookup_last(struct nameidata *nd)
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
nd->state |= ND_STATE_LOOKUP_LAST;
#endif
nd->flags &= ~LOOKUP_PARENT;
return walk_component(nd,
nd->flags & LOOKUP_FOLLOW
@@ -2554,6 +2574,12 @@ static int filename_lookup(int dfd, struct filename *name, unsigned flags,
if (likely(!retval))
audit_inode(name, path->dentry, flags & LOOKUP_PARENT);
restore_nameidata();
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (!retval && path->dentry->d_inode && unlikely(path->dentry->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) {
putname(name);
return -ENOENT;
}
#endif
putname(name);
return retval;
}
@@ -3036,6 +3062,12 @@ static int may_delete(struct vfsmount *mnt, struct inode *dir, struct dentry *vi
if (IS_APPEND(dir))
return -EPERM;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (unlikely(inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) {
return -ENOENT;
}
#endif
if (check_sticky(dir, inode) || IS_APPEND(inode) ||
IS_IMMUTABLE(inode) || IS_SWAPFILE(inode) || HAS_UNMAPPED_ID(inode))
return -EPERM;
@@ -3064,8 +3096,20 @@ static int may_delete(struct vfsmount *mnt, struct inode *dir, struct dentry *vi
*/
static inline int may_create(struct vfsmount *mnt, struct inode *dir, struct dentry *child)
{
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
int error;
#endif
struct user_namespace *s_user_ns;
audit_inode_child(dir, child, AUDIT_TYPE_CHILD_CREATE);
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (child->d_inode && unlikely(child->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) {
error = inode_permission2(mnt, dir, MAY_WRITE | MAY_EXEC);
if (error) {
return error;
}
return -ENOENT;
}
#endif
if (child->d_inode)
return -EEXIST;
if (IS_DEADDIR(dir))
@@ -3170,6 +3214,12 @@ static int may_open(struct path *path, int acc_mode, int flag)
if (!inode)
return -ENOENT;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (unlikely(inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) {
return -ENOENT;
}
#endif
switch (inode->i_mode & S_IFMT) {
case S_IFLNK:
return -ELOOP;
@@ -3241,7 +3291,20 @@ static inline int open_to_namei_flags(int flag)
static int may_o_create(const struct path *dir, struct dentry *dentry, umode_t mode)
{
struct user_namespace *s_user_ns;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
int error;
if (dentry->d_inode && unlikely(dentry->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) {
error = inode_permission2(dir->mnt, dir->dentry->d_inode, MAY_WRITE | MAY_EXEC);
if (error) {
return error;
}
return -ENOENT;
}
error = security_path_mknod(dir, dentry, mode, 0);
#else
int error = security_path_mknod(dir, dentry, mode, 0);
#endif
if (error)
return error;
@@ -3375,9 +3438,9 @@ static int lookup_open(struct nameidata *nd, struct path *path,
{
dentry = d_lookup(dir, &susfs_fake_qstr_name);
found_sus_path = true;
goto skip_orig_flow1;
goto skip_orig_flow1;
} else if (susfs_is_base_dentry_sdcard_dir(dir) &&
susfs_is_sus_sdcard_d_name_found(nd->last.name))
susfs_is_sus_sdcard_d_name_found(nd->last.name))
{
dentry = d_lookup(dir, &susfs_fake_qstr_name);
found_sus_path = true;
@@ -3427,6 +3490,12 @@ skip_orig_flow2:
}
if (dentry->d_inode) {
/* Cached positive dentry: will open in f_op->open */
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (unlikely(dentry->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) {
dput(dentry);
return -ENOENT;
}
#endif
goto out_no_open;
}
@@ -3470,6 +3539,16 @@ skip_orig_flow2:
mode, opened);
if (unlikely(error == -ENOENT) && create_error)
error = create_error;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (!IS_ERR(dentry) && dentry->d_inode && unlikely(dentry->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) {
if (create_error) {
dput(dentry);
return create_error;
}
dput(dentry);
return -ENOENT;
}
#endif
return error;
}
@@ -3485,6 +3564,12 @@ no_open:
}
dput(dentry);
dentry = res;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (dentry->d_inode && unlikely(dentry->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) {
dput(dentry);
return -ENOENT;
}
#endif
}
}
@@ -3538,6 +3623,7 @@ static int do_last(struct nameidata *nd,
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
nd->state |= ND_STATE_OPEN_LAST;
#endif
nd->flags &= ~LOOKUP_PARENT;
nd->flags |= op->intent;

View File

@@ -25,12 +25,11 @@
#include <linux/magic.h>
#include <linux/bootmem.h>
#include <linux/task_work.h>
#include "pnode.h"
#include "internal.h"
#if defined(CONFIG_KSU_SUSFS_SUS_MOUNT) || defined(CONFIG_KSU_SUSFS_TRY_UMOUNT)
#include <linux/susfs_def.h>
#endif
#include "pnode.h"
#include "internal.h"
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
extern bool susfs_is_current_ksu_domain(void);
@@ -127,11 +126,6 @@ static inline struct hlist_head *mp_hash(struct dentry *dentry)
return &mountpoint_hashtable[tmp & mp_hash_mask];
}
/*
* allocation is serialized by namespace_sem, but we need the spinlock to
* serialize with freeing.
*/
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
// Our own mnt_alloc_id() that assigns mnt_id starting from DEFAULT_SUS_MNT_ID
static int susfs_mnt_alloc_id(struct mount *mnt)
@@ -151,6 +145,10 @@ retry:
return res;
}
#endif
/*
* allocation is serialized by namespace_sem, but we need the spinlock to
* serialize with freeing.
*/
static int mnt_alloc_id(struct mount *mnt)
{
int res;
@@ -2078,7 +2076,6 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
p = mnt;
list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) {
struct mount *s;
if (!is_subdir(r->mnt_mountpoint, dentry))
continue;
@@ -2110,7 +2107,7 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
goto out;
lock_mount_hash();
list_add_tail(&q->mnt_list, &res->mnt_list);
attach_mnt(q, parent, p->mnt_mp);
attach_mnt(q, parent, p->mnt_mp);
unlock_mount_hash();
}
}
@@ -3181,7 +3178,7 @@ long do_mount(const char *dev_name, const char __user *dir_name,
retval = do_move_mount(&path, dev_name);
else
retval = do_new_mount(&path, type_page, flags, mnt_flags,
dev_name, data_page);
dev_name, data_page);
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
// For both Legacy and Magic Mount KernelSU
if (!retval && susfs_is_auto_add_sus_ksu_default_mount_enabled &&
@@ -3931,4 +3928,4 @@ bool susfs_is_mnt_devname_ksu(struct path *path) {
}
return false;
}
#endif
#endif

View File

@@ -102,6 +102,7 @@ static void inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark)
inode = igrab(mark->inode);
if (inode) {
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
u32 mask = mark->mask & IN_ALL_EVENTS;
if (likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC) &&
unlikely(inode->i_state & INODE_STATE_SUS_KSTAT)) {
struct path path;
@@ -117,9 +118,9 @@ static void inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark)
if (kern_path(dpath, 0, &path)) {
goto out_free_pathname;
}
seq_printf(m, "inotify wd:%x ino:%lx sdev:%x mask:%x ignored_mask:0 ",
seq_printf(m, "inotify wd:%x ino:%lx sdev:%x mask:%x ignored_mask:%x ",
inode_mark->wd, path.dentry->d_inode->i_ino, path.dentry->d_inode->i_sb->s_dev,
inotify_mark_user_mask(mark));
mask, mark->ignored_mask);
show_mark_fhandle(m, path.dentry->d_inode);
seq_putc(m, '\n');
iput(inode);

View File

@@ -112,6 +112,16 @@ static int ovl_getattr(struct vfsmount *mnt, struct dentry *dentry,
const struct cred *old_cred;
int err;
#ifdef CONFIG_KSU_SUSFS_SUS_OVERLAYFS
ovl_path_lowerdata(dentry, &realpath);
if (likely(realpath.mnt && realpath.dentry)) {
old_cred = ovl_override_creds(dentry->d_sb);
err = vfs_getattr(&realpath, stat);
ovl_revert_creds(old_cred);
return err;
}
#endif
ovl_path_real(dentry, &realpath);
old_cred = ovl_override_creds(dentry->d_sb);
err = vfs_getattr(&realpath, stat);

View File

@@ -149,6 +149,9 @@ u64 ovl_dentry_version_get(struct dentry *dentry);
void ovl_dentry_version_inc(struct dentry *dentry);
void ovl_path_upper(struct dentry *dentry, struct path *path);
void ovl_path_lower(struct dentry *dentry, struct path *path);
#ifdef CONFIG_KSU_SUSFS_SUS_OVERLAYFS
void ovl_path_lowerdata(struct dentry *dentry, struct path *path);
#endif
enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path);
int ovl_path_next(int idx, struct dentry *dentry, struct path *path);
struct dentry *ovl_dentry_upper(struct dentry *dentry);

View File

@@ -500,6 +500,7 @@ static int ovl_dir_open(struct inode *inode, struct file *file)
return -ENOMEM;
type = ovl_path_real(file->f_path.dentry, &realpath);
realfile = ovl_path_open(&realpath, file->f_flags);
if (IS_ERR(realfile)) {
kfree(od);

View File

@@ -186,6 +186,20 @@ void ovl_path_lower(struct dentry *dentry, struct path *path)
*path = oe->numlower ? oe->lowerstack[0] : (struct path) { NULL, NULL };
}
#ifdef CONFIG_KSU_SUSFS_SUS_OVERLAYFS
void ovl_path_lowerdata(struct dentry *dentry, struct path *path)
{
struct ovl_entry *oe = dentry->d_fsdata;
if (oe->numlower) {
path->mnt = oe->lowerstack[oe->numlower - 1].mnt;
path->dentry = oe->lowerstack[oe->numlower - 1].dentry;
} else {
*path = (struct path) { };
}
}
#endif
int ovl_want_write(struct dentry *dentry)
{
struct ovl_fs *ofs = dentry->d_sb->s_fs_info;

View File

@@ -15,6 +15,7 @@ static int cmdline_proc_show(struct seq_file *m, void *v)
return 0;
}
#endif
seq_printf(m, "%s\n", saved_command_line);
return 0;
}

View File

@@ -71,8 +71,8 @@ static int seq_show(struct seq_file *m, void *v)
seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n",
(long long)file->f_pos, f_flags,
real_mount(file->f_path.mnt)->mnt_id);
#endif
#endif
show_fd_locks(m, file, files);
if (seq_has_overflowed(m))
goto out;

View File

@@ -10,6 +10,7 @@
#include <linux/user_namespace.h>
#include "internal.h"
static const struct proc_ns_operations *ns_entries[] = {
#ifdef CONFIG_NET_NS
&netns_operations,

View File

@@ -16,7 +16,7 @@
#include <linux/page_idle.h>
#include <linux/shmem_fs.h>
#include <linux/mm_inline.h>
#include <linux/ctype.h>
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
#include <linux/susfs_def.h>
#endif

View File

@@ -10,12 +10,11 @@
#include <linux/nsproxy.h>
#include <linux/security.h>
#include <linux/fs_struct.h>
#include "proc/internal.h" /* only for get_proc_task() in ->open() */
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
#include <linux/susfs_def.h>
#endif
#include "proc/internal.h" /* only for get_proc_task() in ->open() */
#include "pnode.h"
#include "internal.h"
@@ -109,7 +108,8 @@ static int show_vfsmnt(struct seq_file *m, struct vfsmount *mnt)
int err;
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
if (unlikely(r->mnt_id >= DEFAULT_SUS_MNT_ID)&&(susfs_hide_sus_mnts_for_all_procs || !susfs_is_current_ksu_domain()))
if (unlikely(r->mnt_id >= DEFAULT_SUS_MNT_ID) &&
(susfs_hide_sus_mnts_for_all_procs || !susfs_is_current_ksu_domain()))
return 0;
#endif
@@ -150,7 +150,8 @@ static int show_mountinfo(struct seq_file *m, struct vfsmount *mnt)
int err;
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
if (unlikely(r->mnt_id >= DEFAULT_SUS_MNT_ID)&&(susfs_hide_sus_mnts_for_all_procs || !susfs_is_current_ksu_domain()))
if (unlikely(r->mnt_id >= DEFAULT_SUS_MNT_ID) &&
(susfs_hide_sus_mnts_for_all_procs || !susfs_is_current_ksu_domain()))
return 0;
#endif
@@ -219,7 +220,8 @@ static int show_vfsstat(struct seq_file *m, struct vfsmount *mnt)
int err;
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
if (unlikely(r->mnt_id >= DEFAULT_SUS_MNT_ID)&&(susfs_hide_sus_mnts_for_all_procs || !susfs_is_current_ksu_domain()))
if (unlikely(r->mnt_id >= DEFAULT_SUS_MNT_ID) &&
(susfs_hide_sus_mnts_for_all_procs || !susfs_is_current_ksu_domain()))
return 0;
#endif

View File

@@ -18,9 +18,6 @@
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/unistd.h>
#include <asm/uaccess.h>
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
#include <linux/susfs_def.h>
extern bool susfs_is_inode_sus_path(struct inode *inode);
@@ -29,6 +26,9 @@ extern bool susfs_is_sus_sdcard_d_name_found(const char *d_name);
extern bool susfs_is_base_dentry_android_data_dir(struct dentry* base);
extern bool susfs_is_base_dentry_sdcard_dir(struct dentry* base);
#endif
#include <asm/uaccess.h>
int iterate_dir(struct file *file, struct dir_context *ctx)
{
struct inode *inode = file_inode(file);
@@ -207,6 +207,7 @@ SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
if (!f.file)
return -EBADF;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
buf.sb = f.file->f_inode->i_sb;
inode = f.file->f_path.dentry->d_inode;
@@ -228,7 +229,6 @@ SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
buf.is_base_dentry_sdcard_root_dir = false;
orig_flow:
#endif
error = iterate_dir(f.file, &buf.ctx);
if (buf.result)
error = buf.result;
@@ -253,12 +253,12 @@ struct linux_dirent {
struct getdents_callback {
struct dir_context ctx;
struct linux_dirent __user * current_dir;
struct linux_dirent __user * previous;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
struct super_block *sb;
bool is_base_dentry_android_data_root_dir;
bool is_base_dentry_sdcard_root_dir;
#endif
struct linux_dirent __user * previous;
int count;
int error;
};
@@ -272,10 +272,10 @@ static int filldir(struct dir_context *ctx, const char *name, int namlen,
unsigned long d_ino;
int reclen = ALIGN(offsetof(struct linux_dirent, d_name) + namlen + 2,
sizeof(long));
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
struct inode *inode;
#endif
buf->error = verify_dirent_name(name, namlen);
if (unlikely(buf->error))
return buf->error;
@@ -358,6 +358,7 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd,
f = fdget_pos(fd);
if (!f.file)
return -EBADF;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
buf.sb = f.file->f_inode->i_sb;
inode = f.file->f_path.dentry->d_inode;
@@ -379,7 +380,6 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd,
buf.is_base_dentry_sdcard_root_dir = false;
orig_flow:
#endif
error = iterate_dir(f.file, &buf.ctx);
if (error >= 0)
error = buf.error;
@@ -397,12 +397,12 @@ orig_flow:
struct getdents_callback64 {
struct dir_context ctx;
struct linux_dirent64 __user * current_dir;
struct linux_dirent64 __user * previous;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
struct super_block *sb;
bool is_base_dentry_android_data_root_dir;
bool is_base_dentry_sdcard_root_dir;
#endif
struct linux_dirent64 __user * previous;
int count;
int error;
};
@@ -429,9 +429,6 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen,
if (dirent) {
if (signal_pending(current))
return -EINTR;
if (__put_user(offset, &dirent->d_off))
goto efault;
}
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (buf->is_base_dentry_android_data_root_dir) {
if (susfs_is_sus_android_data_d_name_found(name)) {
@@ -454,6 +451,9 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen,
iput(inode);
orig_flow:
#endif
if (__put_user(offset, &dirent->d_off))
goto efault;
}
dirent = buf->current_dir;
if (__put_user(ino, &dirent->d_ino))
goto efault;
@@ -498,6 +498,7 @@ SYSCALL_DEFINE3(getdents64, unsigned int, fd,
f = fdget_pos(fd);
if (!f.file)
return -EBADF;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
buf.sb = f.file->f_inode->i_sb;
inode = f.file->f_path.dentry->d_inode;

View File

@@ -21,15 +21,6 @@
#include <asm/uaccess.h>
#include <asm/unistd.h>
/**
* generic_fillattr - Fill in the basic attributes from the inode struct
* @inode: Inode to use as the source
* @stat: Where to fill in the attributes
*
* Fill in the basic attributes in the kstat structure from data that's to be
* found on the VFS inode structure. This is the default if no getattr inode
* operation is supplied.
*/
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
extern void susfs_sus_ino_for_generic_fillattr(unsigned long ino, struct kstat *stat);
#endif

View File

@@ -1034,61 +1034,6 @@ struct filename* susfs_get_redirected_path(unsigned long ino) {
}
#endif // #ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT
/* sus_su */
#ifdef CONFIG_KSU_SUSFS_SUS_SU
extern int susfs_sus_su_working_mode;
extern void ksu_susfs_enable_sus_su(void);
extern void ksu_susfs_disable_sus_su(void);
int susfs_get_sus_su_working_mode(void) {
return susfs_sus_su_working_mode;
}
int susfs_sus_su(struct st_sus_su* __user user_info) {
struct st_sus_su info;
int last_working_mode = susfs_sus_su_working_mode;
if (copy_from_user(&info, user_info, sizeof(struct st_sus_su))) {
SUSFS_LOGE("failed copying from userspace\n");
return 1;
}
if (info.mode == SUS_SU_WITH_HOOKS) {
if (last_working_mode == SUS_SU_WITH_HOOKS) {
SUSFS_LOGE("current sus_su mode is already %d\n", SUS_SU_WITH_HOOKS);
return 1;
}
if (last_working_mode != SUS_SU_DISABLED) {
SUSFS_LOGE("please make sure the current sus_su mode is %d first\n", SUS_SU_DISABLED);
return 2;
}
ksu_susfs_enable_sus_su();
SUSFS_LOGI("core kprobe hooks for ksu are disabled!\n");
SUSFS_LOGI("non-kprobe hook sus_su is enabled!\n");
SUSFS_LOGI("sus_su mode: %d\n", SUS_SU_WITH_HOOKS);
return 0;
} else if (info.mode == SUS_SU_DISABLED) {
if (last_working_mode == SUS_SU_DISABLED) {
SUSFS_LOGE("current sus_su mode is already %d\n", SUS_SU_DISABLED);
return 1;
}
ksu_susfs_disable_sus_su();
if (last_working_mode == SUS_SU_WITH_HOOKS) {
SUSFS_LOGI("core kprobe hooks for ksu are enabled!\n");
goto out;
}
out:
if (copy_to_user(user_info, &info, sizeof(info)))
SUSFS_LOGE("copy_to_user() failed\n");
return 0;
} else if (info.mode == SUS_SU_WITH_OVERLAY) {
SUSFS_LOGE("sus_su mode %d is deprecated\n", SUS_SU_WITH_OVERLAY);
return 1;
}
return 1;
}
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_SU
static int copy_config_to_buf(const char *config_string, char *buf_ptr, size_t *copied_size, size_t bufsize) {
size_t tmp_size = strlen(config_string);

View File

@@ -2208,6 +2208,10 @@ struct task_struct {
atomic_t stack_refcount;
#endif
/* CPU-specific state of this task */
#ifdef CONFIG_KSU_SUSFS
u64 susfs_task_state;
u64 susfs_last_fake_mnt_id;
#endif
struct thread_struct thread;
/*
* WARNING: on x86, 'thread_struct' contains a variable-sized
@@ -2215,11 +2219,6 @@ struct task_struct {
*
* Do not put anything below here!
*/
#ifdef CONFIG_KSU_SUSFS
u64 susfs_task_state;
u64 susfs_last_fake_mnt_id;
#endif
};
#ifdef CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT

View File

@@ -29,7 +29,7 @@
struct st_susfs_sus_path {
unsigned long target_ino;
char target_pathname[SUSFS_MAX_LEN_PATHNAME];
unsigned int i_uid;
unsigned int i_uid;
};
struct st_susfs_sus_path_list {
@@ -127,13 +127,6 @@ struct st_susfs_open_redirect_hlist {
};
#endif
/* sus_su */
#ifdef CONFIG_KSU_SUSFS_SUS_SU
struct st_sus_su {
int mode;
};
#endif
/***********************/
/* FORWARD DECLARATION */
/***********************/
@@ -187,11 +180,6 @@ int susfs_spoof_cmdline_or_bootconfig(struct seq_file *m);
int susfs_add_open_redirect(struct st_susfs_open_redirect* __user user_info);
struct filename* susfs_get_redirected_path(unsigned long ino);
#endif
/* sus_su */
#ifdef CONFIG_KSU_SUSFS_SUS_SU
int susfs_get_sus_su_working_mode(void);
int susfs_sus_su(struct st_sus_su* __user user_info);
#endif
int susfs_get_enabled_features(char __user* buf, size_t bufsize);

View File

@@ -12,7 +12,6 @@
#define CMD_SUSFS_SET_SDCARD_ROOT_PATH 0x55552
#define CMD_SUSFS_ADD_SUS_MOUNT 0x55560
#define CMD_SUSFS_HIDE_SUS_MNTS_FOR_ALL_PROCS 0x55561
#define CMD_SUSFS_UMOUNT_FOR_ZYGOTE_ISO_SERVICE 0x55562
#define CMD_SUSFS_ADD_SUS_KSTAT 0x55570
#define CMD_SUSFS_UPDATE_SUS_KSTAT 0x55571
#define CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY 0x55572
@@ -25,9 +24,6 @@
#define CMD_SUSFS_SHOW_VERSION 0x555e1
#define CMD_SUSFS_SHOW_ENABLED_FEATURES 0x555e2
#define CMD_SUSFS_SHOW_VARIANT 0x555e3
#define CMD_SUSFS_SHOW_SUS_SU_WORKING_MODE 0x555e4
#define CMD_SUSFS_IS_SUS_SU_READY 0x555f0
#define CMD_SUSFS_SUS_SU 0x60000
#define SUSFS_MAX_LEN_PATHNAME 256 // 256 should address many paths already unless you are doing some strange experimental stuff, then set your own desired length
#define SUSFS_FAKE_CMDLINE_OR_BOOTCONFIG_SIZE 4096
@@ -35,10 +31,6 @@
#define TRY_UMOUNT_DEFAULT 0 /* used by susfs_try_umount() */
#define TRY_UMOUNT_DETACH 1 /* used by susfs_try_umount() */
#define SUS_SU_DISABLED 0
#define SUS_SU_WITH_OVERLAY 1 /* deprecated */
#define SUS_SU_WITH_HOOKS 2
#define DEFAULT_SUS_MNT_ID 100000 /* used by mount->mnt_id */
#define DEFAULT_SUS_MNT_ID_FOR_KSU_PROC_UNSHARE 1000000 /* used by vfsmount->susfs_mnt_id_backup */
#define DEFAULT_SUS_MNT_GROUP_ID 1000 /* used by mount->mnt_group_id */
@@ -48,6 +40,7 @@
* mount->mnt.susfs_mnt_id_backup => storing original mnt_id of normal mounts or custom sus mnt_id of sus mounts
* task_struct->susfs_task_state => storing flag 'TASK_STRUCT_'
*/
#define INODE_STATE_SUS_PATH BIT(24)
#define INODE_STATE_SUS_MOUNT BIT(25)
#define INODE_STATE_SUS_KSTAT BIT(26)
@@ -67,7 +60,6 @@
#define MAGIC_MOUNT_WORKDIR "/debug_ramdisk/workdir"
#define DATA_ADB_UMOUNT_FOR_ZYGOTE_SYSTEM_PROCESS "/data/adb/susfs_umount_for_zygote_system_process"
#define DATA_ADB_UMOUNT_FOR_ZYGOTE_ISO_SERVICE "/data/adb/susfs_umount_for_zygote_iso_service"
#define DATA_ADB_NO_AUTO_ADD_SUS_BIND_MOUNT "/data/adb/susfs_no_auto_add_sus_bind_mount"
#define DATA_ADB_NO_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT "/data/adb/susfs_no_auto_add_sus_ksu_default_mount"
#define DATA_ADB_NO_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT "/data/adb/susfs_no_auto_add_try_umount_for_bind_mount"