Synchronise some modifications

Co-authored-by: Ylarod <me@ylarod.cn>
Co-authored-by: 5ec1cff <56485584+5ec1cff@users.noreply.github.com>
Co-authored-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
Co-authored-by: u9521 <63995396+u9521@users.noreply.github.com>
Co-authored-by: Wang Han <416810799@qq.com>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
Co-authored-by: Faris <rissu.ntk@gmail.com>
This commit is contained in:
ShirkNeko
2025-11-18 21:27:22 +08:00
parent 07e7d129a0
commit e79b702fd6
29 changed files with 2435 additions and 2282 deletions

View File

@@ -22,7 +22,6 @@ config KSU_MULTI_MANAGER_SUPPORT
help help
Enable multi KernelSU manager support Enable multi KernelSU manager support
config KSU_ALLOWLIST_WORKAROUND config KSU_ALLOWLIST_WORKAROUND
bool "KernelSU Session Keyring Init workaround" bool "KernelSU Session Keyring Init workaround"
depends on KSU depends on KSU

View File

@@ -1,25 +1,25 @@
kernelsu-objs := ksu.o kernelsu-objs := ksu.o
kernelsu-objs += allowlist.o kernelsu-objs += allowlist.o
kernelsu-objs += app_profile.o
kernelsu-objs += dynamic_manager.o kernelsu-objs += dynamic_manager.o
kernelsu-objs += app_profile.o
kernelsu-objs += apk_sign.o kernelsu-objs += apk_sign.o
kernelsu-objs += sucompat.o kernelsu-objs += sucompat.o
kernelsu-objs += syscall_hook_manager.o kernelsu-objs += syscall_hook_manager.o
kernelsu-objs += throne_tracker.o kernelsu-objs += throne_tracker.o
kernelsu-objs += pkg_observer.o kernelsu-objs += pkg_observer.o
kernelsu-objs += setuid_hook.o kernelsu-objs += setuid_hook.o
kernelsu-objs += lsm_hooks.o
kernelsu-objs += kernel_compat.o kernelsu-objs += kernel_compat.o
kernelsu-objs += kernel_umount.o kernelsu-objs += kernel_umount.o
kernelsu-objs += supercalls.o kernelsu-objs += supercalls.o
kernelsu-objs += feature.o kernelsu-objs += feature.o
kernelsu-objs += throne_tracker.o
kernelsu-objs += ksud.o kernelsu-objs += ksud.o
kernelsu-objs += embed_ksud.o kernelsu-objs += embed_ksud.o
kernelsu-objs += seccomp_cache.o kernelsu-objs += seccomp_cache.o
kernelsu-objs += file_wrapper.o kernelsu-objs += file_wrapper.o
kernelsu-objs += throne_comm.o kernelsu-objs += throne_comm.o
kernelsu-objs += sulog.o kernelsu-objs += sulog.o
kernelsu-objs += lsm_hook.o
ifeq ($(CONFIG_KSU_MANUAL_SU), y) ifeq ($(CONFIG_KSU_MANUAL_SU), y)
ccflags-y += -DCONFIG_KSU_MANUAL_SU ccflags-y += -DCONFIG_KSU_MANUAL_SU
kernelsu-objs += manual_su.o kernelsu-objs += manual_su.o
@@ -93,6 +93,8 @@ endif
ccflags-y += -DKSU_VERSION=$(KSU_VERSION) ccflags-y += -DKSU_VERSION=$(KSU_VERSION)
ccflags-y += -DKSU_VERSION_FULL=\"$(KSU_VERSION_FULL)\" ccflags-y += -DKSU_VERSION_FULL=\"$(KSU_VERSION_FULL)\"
$(info -- Supported Unofficial Manager: 5ec1cff (GKI) rsuntk (Non-GKI) ShirkNeko udochina (GKI and non-GKI and KPM))
ifeq ($(CONFIG_KSU_MANUAL_HOOK), y) ifeq ($(CONFIG_KSU_MANUAL_HOOK), y)
ccflags-y += -DKSU_MANUAL_HOOK ccflags-y += -DKSU_MANUAL_HOOK
$(info -- SukiSU: KSU_MANUAL_HOOK) $(info -- SukiSU: KSU_MANUAL_HOOK)
@@ -126,6 +128,14 @@ else
$(info -- KPM is disabled) $(info -- KPM is disabled)
endif endif
# SELinux drivers check
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
# Handle optional backports # Handle optional backports
ifeq ($(shell grep -q "strncpy_from_user_nofault" $(srctree)/include/linux/uaccess.h; echo $$?),0) ifeq ($(shell grep -q "strncpy_from_user_nofault" $(srctree)/include/linux/uaccess.h; echo $$?),0)
ccflags-y += -DKSU_OPTIONAL_STRNCPY ccflags-y += -DKSU_OPTIONAL_STRNCPY
@@ -136,36 +146,42 @@ endif
ifeq ($(shell grep "ssize_t kernel_write" $(srctree)/fs/read_write.c | grep -q "const void" ; echo $$?),0) ifeq ($(shell grep "ssize_t kernel_write" $(srctree)/fs/read_write.c | grep -q "const void" ; echo $$?),0)
ccflags-y += -DKSU_OPTIONAL_KERNEL_WRITE ccflags-y += -DKSU_OPTIONAL_KERNEL_WRITE
endif endif
ifeq ($(shell grep -q "int\s\+path_umount" $(srctree)/fs/namespace.c; echo $$?),0)
ccflags-y += -DKSU_HAS_PATH_UMOUNT
endif
ifeq ($(shell grep -q "inode_security_struct\s\+\*selinux_inode" $(srctree)/security/selinux/include/objsec.h; echo $$?),0) ifeq ($(shell grep -q "inode_security_struct\s\+\*selinux_inode" $(srctree)/security/selinux/include/objsec.h; echo $$?),0)
ccflags-y += -DKSU_OPTIONAL_SELINUX_INODE ccflags-y += -DKSU_OPTIONAL_SELINUX_INODE
endif endif
ifeq ($(shell grep -q "int\s\+path_umount" $(srctree)/fs/namespace.c; echo $$?),0) ifeq ($(shell grep -q "task_security_struct\s\+\*selinux_cred" $(srctree)/security/selinux/include/objsec.h; echo $$?),0)
ccflags-y += -DKSU_HAS_PATH_UMOUNT ccflags-y += -DKSU_OPTIONAL_SELINUX_CRED
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 -- KernelSU: SusFS: Adding 'int path_umount(struct path *path, int flags);' to $(srctree)/fs/internal.h)
endif endif
# seccomp_types.h were added on 6.7
ifeq ($(shell grep -q "atomic_t\s\+filter_count" $(srctree)/include/linux/seccomp.h $(srctree)/include/linux/seccomp_types.h; echo $$?),0)
ccflags-y += -DKSU_OPTIONAL_SECCOMP_FILTER_CNT
endif endif
# Checks Samsung UH drivers # some old kernel backport this, let's check if put_seccomp_filter still exist
ifneq ($(shell grep -wq "put_seccomp_filter" $(srctree)/kernel/seccomp.c $(srctree)/include/linux/seccomp.h; echo $$?),0)
ccflags-y += -DKSU_OPTIONAL_SECCOMP_FILTER_RELEASE
endif
ifeq ($(shell grep -q "anon_inode_getfd_secure" $(srctree)/fs/anon_inodes.c; echo $$?),0)
ccflags-y += -DKSU_HAS_GETFD_SECURE
endif
ifeq ($(shell grep -A1 "^int vfs_getattr" $(srctree)/fs/stat.c | grep -q "query_flags"; echo $$?),0)
ccflags-y += -DKSU_HAS_NEW_VFS_GETATTR
endif
# Checks Samsung
ifeq ($(shell grep -q "CONFIG_KDP_CRED" $(srctree)/kernel/cred.c; echo $$?),0) ifeq ($(shell grep -q "CONFIG_KDP_CRED" $(srctree)/kernel/cred.c; echo $$?),0)
ccflags-y += -DSAMSUNG_UH_DRIVER_EXIST ccflags-y += -DSAMSUNG_UH_DRIVER_EXIST
endif endif
# Samsung SELinux Porting
ifeq ($(shell grep -q "SEC_SELINUX_PORTING_COMMON" $(srctree)/security/selinux/avc.c; echo $$?),0) ifeq ($(shell grep -q "SEC_SELINUX_PORTING_COMMON" $(srctree)/security/selinux/avc.c; echo $$?),0)
ccflags-y += -DSAMSUNG_SELINUX_PORTING ccflags-y += -DSAMSUNG_SELINUX_PORTING
endif endif
# Function proc_ops check # Function proc_ops check
ifeq ($(shell grep -q "struct proc_ops " $(srctree)/include/linux/proc_fs.h; echo $$?),0) ifeq ($(shell grep -q "struct proc_ops " $(srctree)/include/linux/proc_fs.h; echo $$?),0)
ccflags-y += -DKSU_COMPAT_HAS_PROC_OPS ccflags-y += -DKSU_COMPAT_HAS_PROC_OPS
endif endif
# Struct selinux_state check
ifeq ($(shell grep -q "struct selinux_state " $(srctree)/security/selinux/include/security.h; echo $$?),0)
ccflags-y += -DKSU_COMPAT_HAS_SELINUX_STATE
endif
# Custom Signs # Custom Signs
ifdef KSU_EXPECTED_SIZE ifdef KSU_EXPECTED_SIZE
ccflags-y += -DEXPECTED_SIZE=$(KSU_EXPECTED_SIZE) ccflags-y += -DEXPECTED_SIZE=$(KSU_EXPECTED_SIZE)
@@ -182,7 +198,6 @@ ccflags-y += -DKSU_MANAGER_PACKAGE=\"$(KSU_MANAGER_PACKAGE)\"
$(info -- SukiSU Manager package name: $(KSU_MANAGER_PACKAGE)) $(info -- SukiSU Manager package name: $(KSU_MANAGER_PACKAGE))
endif endif
$(info -- Supported Unofficial Manager: 5ec1cff (GKI) rsuntk (Non-GKI) ShirkNeko udochina (GKI and non-GKI and KPM))
ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat
ccflags-y += -Wno-declaration-after-statement -Wno-unused-function -Wno-unused-variable ccflags-y += -Wno-declaration-after-statement -Wno-unused-function -Wno-unused-variable

View File

@@ -21,10 +21,10 @@
#include "klog.h" // IWYU pragma: keep #include "klog.h" // IWYU pragma: keep
#include "ksud.h" #include "ksud.h"
#include "kernel_compat.h"
#include "selinux/selinux.h" #include "selinux/selinux.h"
#include "allowlist.h" #include "allowlist.h"
#include "manager.h" #include "manager.h"
#include "kernel_compat.h"
#ifndef CONFIG_KSU_SUSFS #ifndef CONFIG_KSU_SUSFS
#include "syscall_hook_manager.h" #include "syscall_hook_manager.h"
#endif // #ifndef CONFIG_KSU_SUSFS #endif // #ifndef CONFIG_KSU_SUSFS
@@ -41,8 +41,6 @@ static DEFINE_MUTEX(allowlist_mutex);
static struct root_profile default_root_profile; static struct root_profile default_root_profile;
static struct non_root_profile default_non_root_profile; static struct non_root_profile default_non_root_profile;
void persistent_allow_list(void);
static int allow_list_arr[PAGE_SIZE / sizeof(int)] __read_mostly static int allow_list_arr[PAGE_SIZE / sizeof(int)] __read_mostly
__aligned(PAGE_SIZE); __aligned(PAGE_SIZE);
static int allow_list_pointer __read_mostly = 0; static int allow_list_pointer __read_mostly = 0;
@@ -105,6 +103,8 @@ static uint8_t allow_list_bitmap[PAGE_SIZE] __read_mostly __aligned(PAGE_SIZE);
#define KERNEL_SU_ALLOWLIST "/data/adb/ksu/.allowlist" #define KERNEL_SU_ALLOWLIST "/data/adb/ksu/.allowlist"
void persistent_allow_list(void);
void ksu_show_allow_list(void) void ksu_show_allow_list(void)
{ {
struct perm_data *p = NULL; struct perm_data *p = NULL;
@@ -246,7 +246,8 @@ out:
WARN_ON(1); WARN_ON(1);
return false; return false;
} }
allow_list_arr[allow_list_pointer++] = profile->current_uid; allow_list_arr[allow_list_pointer++] =
profile->current_uid;
} else { } else {
remove_uid_from_arr(profile->current_uid); remove_uid_from_arr(profile->current_uid);
} }
@@ -268,10 +269,8 @@ out:
if (persist) { if (persist) {
persistent_allow_list(); persistent_allow_list();
#ifndef CONFIG_KSU_SUSFS
// FIXME: use a new flag // FIXME: use a new flag
ksu_mark_running_process(); ksu_mark_running_process();
#endif // #ifndef CONFIG_KSU_SUSFS
} }
return result; return result;
@@ -384,20 +383,23 @@ static void do_persistent_allow_list(struct callback_head *_cb)
loff_t off = 0; loff_t off = 0;
mutex_lock(&allowlist_mutex); mutex_lock(&allowlist_mutex);
struct file *fp = struct file *fp = ksu_filp_open_compat(
filp_open(KERNEL_SU_ALLOWLIST, O_WRONLY | O_CREAT | O_TRUNC, 0644); KERNEL_SU_ALLOWLIST, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (IS_ERR(fp)) { if (IS_ERR(fp)) {
pr_err("save_allow_list create file failed: %ld\n", PTR_ERR(fp)); pr_err("save_allow_list create file failed: %ld\n",
PTR_ERR(fp));
goto unlock; goto unlock;
} }
// store magic and version // store magic and version
if (kernel_write(fp, &magic, sizeof(magic), &off) != sizeof(magic)) { if (ksu_kernel_write_compat(fp, &magic, sizeof(magic), &off) !=
sizeof(magic)) {
pr_err("save_allow_list write magic failed.\n"); pr_err("save_allow_list write magic failed.\n");
goto close_file; goto close_file;
} }
if (kernel_write(fp, &version, sizeof(version), &off) != sizeof(version)) { if (ksu_kernel_write_compat(fp, &version, sizeof(version), &off) !=
sizeof(version)) {
pr_err("save_allow_list write version failed.\n"); pr_err("save_allow_list write version failed.\n");
goto close_file; goto close_file;
} }
@@ -405,9 +407,11 @@ static void do_persistent_allow_list(struct callback_head *_cb)
list_for_each (pos, &allow_list) { list_for_each (pos, &allow_list) {
p = list_entry(pos, struct perm_data, list); p = list_entry(pos, struct perm_data, list);
pr_info("save allow list, name: %s uid :%d, allow: %d\n", pr_info("save allow list, name: %s uid :%d, allow: %d\n",
p->profile.key, p->profile.current_uid, p->profile.allow_su); p->profile.key, p->profile.current_uid,
p->profile.allow_su);
kernel_write(fp, &p->profile, sizeof(p->profile), &off); ksu_kernel_write_compat(fp, &p->profile, sizeof(p->profile),
&off);
} }
close_file: close_file:
@@ -417,7 +421,7 @@ unlock:
kfree(_cb); kfree(_cb);
} }
void persistent_allow_list() void persistent_allow_list(void)
{ {
struct task_struct *tsk; struct task_struct *tsk;
@@ -440,7 +444,7 @@ put_task:
put_task_struct(tsk); put_task_struct(tsk);
} }
void ksu_load_allow_list() void ksu_load_allow_list(void)
{ {
loff_t off = 0; loff_t off = 0;
ssize_t ret = 0; ssize_t ret = 0;
@@ -454,20 +458,22 @@ void ksu_load_allow_list()
#endif #endif
// load allowlist now! // load allowlist now!
fp = filp_open(KERNEL_SU_ALLOWLIST, O_RDONLY, 0); fp = ksu_filp_open_compat(KERNEL_SU_ALLOWLIST, O_RDONLY, 0);
if (IS_ERR(fp)) { if (IS_ERR(fp)) {
pr_err("load_allow_list open file failed: %ld\n", PTR_ERR(fp)); pr_err("load_allow_list open file failed: %ld\n", PTR_ERR(fp));
return; return;
} }
// verify magic // verify magic
if (kernel_read(fp, &magic, sizeof(magic), &off) != sizeof(magic) || if (ksu_kernel_read_compat(fp, &magic, sizeof(magic), &off) !=
sizeof(magic) ||
magic != FILE_MAGIC) { magic != FILE_MAGIC) {
pr_err("allowlist file invalid: %d!\n", magic); pr_err("allowlist file invalid: %d!\n", magic);
goto exit; goto exit;
} }
if (kernel_read(fp, &version, sizeof(version), &off) != sizeof(version)) { if (ksu_kernel_read_compat(fp, &version, sizeof(version), &off) !=
sizeof(version)) {
pr_err("allowlist read version: %d failed\n", version); pr_err("allowlist read version: %d failed\n", version);
goto exit; goto exit;
} }
@@ -477,15 +483,16 @@ void ksu_load_allow_list()
while (true) { while (true) {
struct app_profile profile; struct app_profile profile;
ret = kernel_read(fp, &profile, sizeof(profile), &off); ret = ksu_kernel_read_compat(fp, &profile, sizeof(profile),
&off);
if (ret <= 0) { if (ret <= 0) {
pr_info("load_allow_list read err: %zd\n", ret); pr_info("load_allow_list read err: %zd\n", ret);
break; break;
} }
pr_info("load_allow_uid, name: %s, uid: %d, allow: %d\n", profile.key, pr_info("load_allow_uid, name: %s, uid: %d, allow: %d\n",
profile.current_uid, profile.allow_su); profile.key, profile.current_uid, profile.allow_su);
ksu_set_app_profile(&profile, false); ksu_set_app_profile(&profile, false);
} }
@@ -553,8 +560,6 @@ void ksu_allowlist_exit(void)
struct perm_data *np = NULL; struct perm_data *np = NULL;
struct perm_data *n = NULL; struct perm_data *n = NULL;
persistent_allow_list();
// free allowlist // free allowlist
mutex_lock(&allowlist_mutex); mutex_lock(&allowlist_mutex);
list_for_each_entry_safe (np, n, &allow_list, list) { list_for_each_entry_safe (np, n, &allow_list, list) {

View File

@@ -23,11 +23,13 @@ bool __ksu_is_allow_uid(uid_t uid);
// Check if the uid is in allow list, or current is ksu domain root // Check if the uid is in allow list, or current is ksu domain root
bool __ksu_is_allow_uid_for_current(uid_t uid); bool __ksu_is_allow_uid_for_current(uid_t uid);
#define ksu_is_allow_uid_for_current(uid) unlikely(__ksu_is_allow_uid_for_current(uid)) #define ksu_is_allow_uid_for_current(uid) \
unlikely(__ksu_is_allow_uid_for_current(uid))
bool ksu_get_allow_list(int *array, int *length, bool allow); bool ksu_get_allow_list(int *array, int *length, bool allow);
void ksu_prune_allowlist(bool (*is_uid_exist)(uid_t, char *, void *), void *data); void ksu_prune_allowlist(bool (*is_uid_exist)(uid_t, char *, void *),
void *data);
bool ksu_get_app_profile(struct app_profile *); bool ksu_get_app_profile(struct app_profile *);
bool ksu_set_app_profile(struct app_profile *, bool persist); bool ksu_set_app_profile(struct app_profile *, bool persist);

View File

@@ -18,6 +18,7 @@
#include "dynamic_manager.h" #include "dynamic_manager.h"
#include "klog.h" // IWYU pragma: keep #include "klog.h" // IWYU pragma: keep
#include "manager_sign.h" #include "manager_sign.h"
#include "kernel_compat.h"
struct sdesc { struct sdesc {
struct shash_desc shash; struct shash_desc shash;
@@ -107,7 +108,7 @@ static bool check_dynamic_sign(struct file *fp, u32 size4, loff_t *pos, int *mat
return false; return false;
} }
kernel_read(fp, cert, size4, pos); ksu_kernel_read_compat(fp, cert, size4, pos);
unsigned char digest[SHA256_DIGEST_SIZE]; unsigned char digest[SHA256_DIGEST_SIZE];
if (ksu_sha256(cert, size4, digest) < 0) { if (ksu_sha256(cert, size4, digest) < 0) {
@@ -137,19 +138,19 @@ static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset, i
apk_sign_key_t sign_key; apk_sign_key_t sign_key;
bool signature_valid = false; bool signature_valid = false;
kernel_read(fp, size4, 0x4, pos); // signer-sequence length ksu_kernel_read_compat(fp, size4, 0x4, pos); // signer-sequence length
kernel_read(fp, size4, 0x4, pos); // signer length ksu_kernel_read_compat(fp, size4, 0x4, pos); // signer length
kernel_read(fp, size4, 0x4, pos); // signed data length ksu_kernel_read_compat(fp, size4, 0x4, pos); // signed data length
*offset += 0x4 * 3; *offset += 0x4 * 3;
kernel_read(fp, size4, 0x4, pos); // digests-sequence length ksu_kernel_read_compat(fp, size4, 0x4, pos); // digests-sequence length
*pos += *size4; *pos += *size4;
*offset += 0x4 + *size4; *offset += 0x4 + *size4;
kernel_read(fp, size4, 0x4, pos); // certificates length ksu_kernel_read_compat(fp, size4, 0x4, pos); // certificates length
kernel_read(fp, size4, 0x4, pos); // certificate length ksu_kernel_read_compat(fp, size4, 0x4, pos); // certificate length
*offset += 0x4 * 2; *offset += 0x4 * 2;
if (ksu_is_dynamic_manager_enabled()) { if (ksu_is_dynamic_manager_enabled()) {
@@ -174,7 +175,7 @@ static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset, i
pr_info("cert length overlimit\n"); pr_info("cert length overlimit\n");
return false; return false;
} }
kernel_read(fp, cert, *size4, pos); ksu_kernel_read_compat(fp, cert, *size4, pos);
unsigned char digest[SHA256_DIGEST_SIZE]; unsigned char digest[SHA256_DIGEST_SIZE];
if (ksu_sha256(cert, *size4, digest) < 0 ) { if (ksu_sha256(cert, *size4, digest) < 0 ) {
pr_info("sha256 error\n"); pr_info("sha256 error\n");
@@ -220,7 +221,7 @@ static bool has_v1_signature_file(struct file *fp)
loff_t pos = 0; loff_t pos = 0;
while (kernel_read(fp, &header, while (ksu_kernel_read_compat(fp, &header,
sizeof(struct zip_entry_header), &pos) == sizeof(struct zip_entry_header), &pos) ==
sizeof(struct zip_entry_header)) { sizeof(struct zip_entry_header)) {
if (header.signature != 0x04034b50) { if (header.signature != 0x04034b50) {
@@ -230,7 +231,7 @@ static bool has_v1_signature_file(struct file *fp)
// Read the entry file name // Read the entry file name
if (header.file_name_length == sizeof(MANIFEST) - 1) { if (header.file_name_length == sizeof(MANIFEST) - 1) {
char fileName[sizeof(MANIFEST)]; char fileName[sizeof(MANIFEST)];
kernel_read(fp, fileName, ksu_kernel_read_compat(fp, fileName,
header.file_name_length, &pos); header.file_name_length, &pos);
fileName[header.file_name_length] = '\0'; fileName[header.file_name_length] = '\0';
@@ -265,7 +266,7 @@ static __always_inline bool check_v2_signature(char *path, bool check_multi_mana
bool v3_1_signing_exist = false; bool v3_1_signing_exist = false;
int matched_index = -1; int matched_index = -1;
int i; int i;
struct file *fp = filp_open(path, O_RDONLY, 0); struct file *fp = ksu_filp_open_compat(path, O_RDONLY, 0);
if (IS_ERR(fp)) { if (IS_ERR(fp)) {
pr_err("open %s error.\n", path); pr_err("open %s error.\n", path);
return false; return false;
@@ -284,10 +285,10 @@ static __always_inline bool check_v2_signature(char *path, bool check_multi_mana
for (i = 0;; ++i) { for (i = 0;; ++i) {
unsigned short n; unsigned short n;
pos = generic_file_llseek(fp, -i - 2, SEEK_END); pos = generic_file_llseek(fp, -i - 2, SEEK_END);
kernel_read(fp, &n, 2, &pos); ksu_kernel_read_compat(fp, &n, 2, &pos);
if (n == i) { if (n == i) {
pos -= 22; pos -= 22;
kernel_read(fp, &size4, 4, &pos); ksu_kernel_read_compat(fp, &size4, 4, &pos);
if ((size4 ^ 0xcafebabeu) == 0xccfbf1eeu) { if ((size4 ^ 0xcafebabeu) == 0xccfbf1eeu) {
break; break;
} }
@@ -300,17 +301,17 @@ static __always_inline bool check_v2_signature(char *path, bool check_multi_mana
pos += 12; pos += 12;
// offset // offset
kernel_read(fp, &size4, 0x4, &pos); ksu_kernel_read_compat(fp, &size4, 0x4, &pos);
pos = size4 - 0x18; pos = size4 - 0x18;
kernel_read(fp, &size8, 0x8, &pos); ksu_kernel_read_compat(fp, &size8, 0x8, &pos);
kernel_read(fp, buffer, 0x10, &pos); ksu_kernel_read_compat(fp, buffer, 0x10, &pos);
if (strcmp((char *)buffer, "APK Sig Block 42")) { if (strcmp((char *)buffer, "APK Sig Block 42")) {
goto clean; goto clean;
} }
pos = size4 - (size8 + 0x8); pos = size4 - (size8 + 0x8);
kernel_read(fp, &size_of_block, 0x8, &pos); ksu_kernel_read_compat(fp, &size_of_block, 0x8, &pos);
if (size_of_block != size8) { if (size_of_block != size8) {
goto clean; goto clean;
} }
@@ -319,12 +320,12 @@ static __always_inline bool check_v2_signature(char *path, bool check_multi_mana
while (loop_count++ < 10) { while (loop_count++ < 10) {
uint32_t id; uint32_t id;
uint32_t offset; uint32_t offset;
kernel_read(fp, &size8, 0x8, ksu_kernel_read_compat(fp, &size8, 0x8,
&pos); // sequence length &pos); // sequence length
if (size8 == size_of_block) { if (size8 == size_of_block) {
break; break;
} }
kernel_read(fp, &id, 0x4, &pos); // id ksu_kernel_read_compat(fp, &id, 0x4, &pos); // id
offset = 4; offset = 4;
if (id == 0x7109871au) { if (id == 0x7109871au) {
v2_signing_blocks++; v2_signing_blocks++;

View File

@@ -1,21 +1,31 @@
#include <linux/version.h>
#include <linux/capability.h> #include <linux/capability.h>
#include <linux/cred.h> #include <linux/cred.h>
#include <linux/err.h>
#include <linux/fdtable.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/proc_ns.h>
#include <linux/pid.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
#include <linux/sched/signal.h> // signal_struct
#include <linux/sched/task.h>
#endif
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/sched/signal.h>
#include <linux/seccomp.h> #include <linux/seccomp.h>
#include <linux/thread_info.h> #include <linux/thread_info.h>
#include <linux/uidgid.h> #include <linux/uidgid.h>
#include <linux/version.h> #include <linux/syscalls.h>
#include "objsec.h"
#include "allowlist.h" #include "allowlist.h"
#include "app_profile.h" #include "app_profile.h"
#include "arch.h"
#include "kernel_compat.h"
#include "klog.h" // IWYU pragma: keep #include "klog.h" // IWYU pragma: keep
#include "selinux/selinux.h" #include "selinux/selinux.h"
#ifndef CONFIG_KSU_SUSFS #ifndef CONFIG_KSU_SUSFS
#include "syscall_hook_manager.h" #include "syscall_hook_manager.h"
#endif #endif
#include "sucompat.h"
#include "sulog.h" #include "sulog.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION (6, 7, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION (6, 7, 0)
@@ -68,9 +78,13 @@ static void setup_groups(struct root_profile *profile, struct cred *cred)
put_group_info(group_info); put_group_info(group_info);
} }
void disable_seccomp(void) void disable_seccomp(struct task_struct *tsk)
{ {
assert_spin_locked(&current->sighand->siglock); if (unlikely(!tsk))
return;
assert_spin_locked(&tsk->sighand->siglock);
// disable seccomp // disable seccomp
#if defined(CONFIG_GENERIC_ENTRY) && \ #if defined(CONFIG_GENERIC_ENTRY) && \
LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
@@ -80,20 +94,42 @@ void disable_seccomp(void)
#endif #endif
#ifdef CONFIG_SECCOMP #ifdef CONFIG_SECCOMP
current->seccomp.mode = 0; tsk->seccomp.mode = 0;
current->seccomp.filter = NULL; if (tsk->seccomp.filter) {
atomic_set(&current->seccomp.filter_count, 0); // 5.9+ have filter_count, but optional.
#ifdef KSU_OPTIONAL_SECCOMP_FILTER_CNT
atomic_set(&tsk->seccomp.filter_count, 0);
#endif
// some old kernel backport seccomp_filter_release..
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0) && \
defined(KSU_OPTIONAL_SECCOMP_FILTER_RELEASE)
seccomp_filter_release(tsk);
#else #else
// never, ever call seccomp_filter_release on 6.10+ (no effect)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) && \
LINUX_VERSION_CODE < KERNEL_VERSION(6, 10, 0))
seccomp_filter_release(tsk);
#else
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0)
put_seccomp_filter(tsk);
#endif
tsk->seccomp.filter = NULL;
#endif
#endif
}
#endif #endif
} }
void escape_with_root_profile(void) void escape_with_root_profile(void)
{ {
struct cred *cred; struct cred *cred;
#ifndef CONFIG_KSU_SUSFS // a bit useless, but we just want less ifdefs
struct task_struct *p = current; struct task_struct *p = current;
struct task_struct *t;
#endif if (current_euid().val == 0) {
pr_warn("Already root, don't escape!\n");
return;
}
cred = prepare_creds(); cred = prepare_creds();
if (!cred) { if (!cred) {
@@ -101,15 +137,6 @@ void escape_with_root_profile(void)
return; return;
} }
if (cred->euid.val == 0) {
pr_warn("Already root, don't escape!\n");
#if __SULOG_GATE
ksu_sulog_report_su_grant(current_euid().val, NULL, "escape_to_root_failed");
#endif
abort_creds(cred);
return;
}
struct root_profile *profile = ksu_get_root_profile(cred->uid.val); struct root_profile *profile = ksu_get_root_profile(cred->uid.val);
cred->uid.val = profile->uid; cred->uid.val = profile->uid;
@@ -144,9 +171,9 @@ void escape_with_root_profile(void)
// Refer to kernel/seccomp.c: seccomp_set_mode_strict // Refer to kernel/seccomp.c: seccomp_set_mode_strict
// When disabling Seccomp, ensure that current->sighand->siglock is held during the operation. // When disabling Seccomp, ensure that current->sighand->siglock is held during the operation.
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&p->sighand->siglock);
disable_seccomp(); disable_seccomp(p);
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&p->sighand->siglock);
setup_selinux(profile->selinux_domain); setup_selinux(profile->selinux_domain);
#if __SULOG_GATE #if __SULOG_GATE
@@ -154,6 +181,7 @@ void escape_with_root_profile(void)
#endif #endif
#ifndef CONFIG_KSU_SUSFS #ifndef CONFIG_KSU_SUSFS
struct task_struct *t;
for_each_thread (p, t) { for_each_thread (p, t) {
ksu_set_task_tracepoint_flag(t); ksu_set_task_tracepoint_flag(t);
} }
@@ -220,10 +248,6 @@ void escape_to_root_for_cmd_su(uid_t target_uid, pid_t target_pid)
{ {
struct cred *newcreds; struct cred *newcreds;
struct task_struct *target_task; struct task_struct *target_task;
#ifndef CONFIG_KSU_SUSFS
struct task_struct *p = current;
struct task_struct *t;
#endif
pr_info("cmd_su: escape_to_root_for_cmd_su called for UID: %d, PID: %d\n", target_uid, target_pid); pr_info("cmd_su: escape_to_root_for_cmd_su called for UID: %d, PID: %d\n", target_uid, target_pid);
@@ -306,6 +330,8 @@ void escape_to_root_for_cmd_su(uid_t target_uid, pid_t target_pid)
ksu_sulog_report_su_grant(target_uid, "cmd_su", "manual_escalation"); ksu_sulog_report_su_grant(target_uid, "cmd_su", "manual_escalation");
#endif #endif
#ifndef CONFIG_KSU_SUSFS #ifndef CONFIG_KSU_SUSFS
struct task_struct *p = current;
struct task_struct *t;
for_each_thread (p, t) { for_each_thread (p, t) {
ksu_set_task_tracepoint_flag(t); ksu_set_task_tracepoint_flag(t);
} }

View File

@@ -62,9 +62,6 @@ struct app_profile {
// Escalate current process to root with the appropriate profile // Escalate current process to root with the appropriate profile
void escape_with_root_profile(void); void escape_with_root_profile(void);
void escape_to_root_for_cmd_su(uid_t target_uid, pid_t target_pid); void escape_to_root_for_cmd_su(uid_t target_uid, pid_t target_pid);
void disable_seccomp(void);
#endif #endif

View File

@@ -19,26 +19,16 @@
#define __PT_IP_REG pc #define __PT_IP_REG pc
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
#define PRCTL_SYMBOL "__arm64_sys_prctl"
#define REBOOT_SYMBOL "__arm64_sys_reboot" #define REBOOT_SYMBOL "__arm64_sys_reboot"
#define SYS_READ_SYMBOL "__arm64_sys_read" #define SYS_READ_SYMBOL "__arm64_sys_read"
#define SYS_EXECVE_SYMBOL "__arm64_sys_execve" #define SYS_EXECVE_SYMBOL "__arm64_sys_execve"
#define SYS_EXECVE_COMPAT_SYMBOL "__arm64_compat_sys_execve" #define SYS_SETNS_SYMBOL __arm64_sys_setns
#else #else
#define PRCTL_SYMBOL "sys_prctl"
#define REBOOT_SYMBOL "sys_reboot" #define REBOOT_SYMBOL "sys_reboot"
#define SYS_READ_SYMBOL "sys_read" #define SYS_READ_SYMBOL "sys_read"
#define SYS_NEWFSTATAT_SYMBOL "sys_newfstatat"
#define SYS_FSTATAT64_SYMBOL "sys_fstatat64"
#define SYS_FACCESSAT_SYMBOL "sys_faccessat"
#define SYS_EXECVE_SYMBOL "sys_execve" #define SYS_EXECVE_SYMBOL "sys_execve"
#define SYS_EXECVE_COMPAT_SYMBOL "compat_sys_execve" #define SYS_SETNS_SYMBOL sys_setns
#endif #endif
/*LSM HOOK*/
#define SECURITY_TASK_FIX_SETUID_SYMBOL "security_task_fix_setuid"
#define INODE_PERMISSION_SYMBOL "security_inode_permission"
#define BPRM_CHECK_SECURITY_SYMBOL "security_bprm_check"
#define TASK_ALLOC_SYMBOL "security_task_alloc"
#elif defined(__x86_64__) #elif defined(__x86_64__)
@@ -55,28 +45,18 @@
#define __PT_RC_REG ax #define __PT_RC_REG ax
#define __PT_SP_REG sp #define __PT_SP_REG sp
#define __PT_IP_REG ip #define __PT_IP_REG ip
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
#define PRCTL_SYMBOL "__x64_sys_prctl"
#define REBOOT_SYMBOL "__x64_sys_reboot" #define REBOOT_SYMBOL "__x64_sys_reboot"
#define SYS_READ_SYMBOL "__x64_sys_read" #define SYS_READ_SYMBOL "__x64_sys_read"
#define SYS_EXECVE_SYMBOL "__x64_sys_execve" #define SYS_EXECVE_SYMBOL "__x64_sys_execve"
#define SYS_EXECVE_COMPAT_SYMBOL "__x64_compat_sys_execve" #define SYS_SETNS_SYMBOL __x64_sys_setns
#else #else
#define PRCTL_SYMBOL "sys_prctl"
#define REBOOT_SYMBOL "sys_reboot" #define REBOOT_SYMBOL "sys_reboot"
#define SYS_READ_SYMBOL "sys_read" #define SYS_READ_SYMBOL "sys_read"
#define SYS_NEWFSTATAT_SYMBOL "sys_newfstatat"
#define SYS_FSTATAT64_SYMBOL "sys_fstatat64"
#define SYS_FACCESSAT_SYMBOL "sys_faccessat"
#define SYS_EXECVE_SYMBOL "sys_execve" #define SYS_EXECVE_SYMBOL "sys_execve"
#define SYS_EXECVE_COMPAT_SYMBOL "compat_sys_execve" #define SYS_SETNS_SYMBOL sys_setns
#endif #endif
/*LSM HOOK*/
#define SECURITY_TASK_FIX_SETUID_SYMBOL "security_task_fix_setuid"
#define PRCTL_SYMBOL "__arm64_sys_prctl"
#define INODE_PERMISSION_SYMBOL "security_inode_permission"
#define BPRM_CHECK_SECURITY_SYMBOL "security_bprm_check"
#define TASK_ALLOC_SYMBOL "security_task_alloc"
#else #else
#ifdef KSU_KPROBES_HOOK #ifdef KSU_KPROBES_HOOK

View File

@@ -18,6 +18,7 @@
#include "dynamic_manager.h" #include "dynamic_manager.h"
#include "klog.h" // IWYU pragma: keep #include "klog.h" // IWYU pragma: keep
#include "manager.h" #include "manager.h"
#include "kernel_compat.h"
#define MAX_MANAGERS 2 #define MAX_MANAGERS 2
@@ -232,23 +233,23 @@ static void do_save_dynamic_manager(struct work_struct *work)
return; return;
} }
fp = filp_open(KERNEL_SU_DYNAMIC_MANAGER, O_WRONLY | O_CREAT | O_TRUNC, 0644); fp = ksu_filp_open_compat(KERNEL_SU_DYNAMIC_MANAGER, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (IS_ERR(fp)) { if (IS_ERR(fp)) {
pr_err("save_dynamic_manager create file failed: %ld\n", PTR_ERR(fp)); pr_err("save_dynamic_manager create file failed: %ld\n", PTR_ERR(fp));
return; return;
} }
if (kernel_write(fp, &magic, sizeof(magic), &off) != sizeof(magic)) { if (ksu_kernel_write_compat(fp, &magic, sizeof(magic), &off) != sizeof(magic)) {
pr_err("save_dynamic_manager write magic failed.\n"); pr_err("save_dynamic_manager write magic failed.\n");
goto exit; goto exit;
} }
if (kernel_write(fp, &version, sizeof(version), &off) != sizeof(version)) { if (ksu_kernel_write_compat(fp, &version, sizeof(version), &off) != sizeof(version)) {
pr_err("save_dynamic_manager write version failed.\n"); pr_err("save_dynamic_manager write version failed.\n");
goto exit; goto exit;
} }
if (kernel_write(fp, &config_to_save, sizeof(config_to_save), &off) != sizeof(config_to_save)) { if (ksu_kernel_write_compat(fp, &config_to_save, sizeof(config_to_save), &off) != sizeof(config_to_save)) {
pr_err("save_dynamic_manager write config failed.\n"); pr_err("save_dynamic_manager write config failed.\n");
goto exit; goto exit;
} }
@@ -270,7 +271,7 @@ static void do_load_dynamic_manager(struct work_struct *work)
unsigned long flags; unsigned long flags;
int i; int i;
fp = filp_open(KERNEL_SU_DYNAMIC_MANAGER, O_RDONLY, 0); fp = ksu_filp_open_compat(KERNEL_SU_DYNAMIC_MANAGER, O_RDONLY, 0);
if (IS_ERR(fp)) { if (IS_ERR(fp)) {
if (PTR_ERR(fp) == -ENOENT) { if (PTR_ERR(fp) == -ENOENT) {
pr_info("No saved dynamic manager config found\n"); pr_info("No saved dynamic manager config found\n");
@@ -280,20 +281,20 @@ static void do_load_dynamic_manager(struct work_struct *work)
return; return;
} }
if (kernel_read(fp, &magic, sizeof(magic), &off) != sizeof(magic) || if (ksu_kernel_read_compat(fp, &magic, sizeof(magic), &off) != sizeof(magic) ||
magic != DYNAMIC_MANAGER_FILE_MAGIC) { magic != DYNAMIC_MANAGER_FILE_MAGIC) {
pr_err("dynamic manager file invalid magic: %x!\n", magic); pr_err("dynamic manager file invalid magic: %x!\n", magic);
goto exit; goto exit;
} }
if (kernel_read(fp, &version, sizeof(version), &off) != sizeof(version)) { if (ksu_kernel_read_compat(fp, &version, sizeof(version), &off) != sizeof(version)) {
pr_err("dynamic manager read version failed\n"); pr_err("dynamic manager read version failed\n");
goto exit; goto exit;
} }
pr_info("dynamic manager file version: %d\n", version); pr_info("dynamic manager file version: %d\n", version);
ret = kernel_read(fp, &loaded_config, sizeof(loaded_config), &off); ret = ksu_kernel_read_compat(fp, &loaded_config, sizeof(loaded_config), &off);
if (ret <= 0) { if (ret <= 0) {
pr_info("load_dynamic_manager read err: %zd\n", ret); pr_info("load_dynamic_manager read err: %zd\n", ret);
goto exit; goto exit;
@@ -347,14 +348,14 @@ static void do_clear_dynamic_manager(struct work_struct *work)
memset(zero_buffer, 0, sizeof(zero_buffer)); memset(zero_buffer, 0, sizeof(zero_buffer));
fp = filp_open(KERNEL_SU_DYNAMIC_MANAGER, O_WRONLY | O_CREAT | O_TRUNC, 0644); fp = ksu_filp_open_compat(KERNEL_SU_DYNAMIC_MANAGER, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (IS_ERR(fp)) { if (IS_ERR(fp)) {
pr_err("clear_dynamic_manager create file failed: %ld\n", PTR_ERR(fp)); pr_err("clear_dynamic_manager create file failed: %ld\n", PTR_ERR(fp));
return; return;
} }
// Write null bytes to overwrite the file content // Write null bytes to overwrite the file content
if (kernel_write(fp, zero_buffer, sizeof(zero_buffer), &off) != sizeof(zero_buffer)) { if (ksu_kernel_write_compat(fp, zero_buffer, sizeof(zero_buffer), &off) != sizeof(zero_buffer)) {
pr_err("clear_dynamic_manager write null bytes failed.\n"); pr_err("clear_dynamic_manager write null bytes failed.\n");
} else { } else {
pr_info("Dynamic sign config file cleared successfully\n"); pr_info("Dynamic sign config file cleared successfully\n");

View File

@@ -20,7 +20,8 @@ int ksu_register_feature_handler(const struct ksu_feature_handler *handler)
} }
if (!handler->get_handler && !handler->set_handler) { if (!handler->get_handler && !handler->set_handler) {
pr_err("feature: no handler provided for feature %u\n", handler->feature_id); pr_err("feature: no handler provided for feature %u\n",
handler->feature_id);
return -EINVAL; return -EINVAL;
} }
@@ -102,7 +103,8 @@ int ksu_get_feature(u32 feature_id, u64 *value, bool *supported)
ret = handler->get_handler(value); ret = handler->get_handler(value);
if (ret) { if (ret) {
pr_err("feature: get_handler for %u failed: %d\n", feature_id, ret); pr_err("feature: get_handler for %u failed: %d\n", feature_id,
ret);
} }
out: out:
@@ -138,7 +140,8 @@ int ksu_set_feature(u32 feature_id, u64 value)
ret = handler->set_handler(value); ret = handler->set_handler(value);
if (ret) { if (ret) {
pr_err("feature: set_handler for %u failed: %d\n", feature_id, ret); pr_err("feature: set_handler for %u failed: %d\n", feature_id,
ret);
} }
out: out:

View File

@@ -1,5 +1,6 @@
#include <linux/export.h> #include <linux/export.h>
#include <linux/anon_inodes.h> #include <linux/anon_inodes.h>
#include <linux/aio.h> // kernel 3.18
#include <linux/capability.h> #include <linux/capability.h>
#include <linux/cred.h> #include <linux/cred.h>
#include <linux/err.h> #include <linux/err.h>
@@ -33,6 +34,7 @@ static ssize_t ksu_wrapper_write(struct file *fp, const char __user *ptr, size_t
return orig->f_op->write(orig, ptr, sz, off); return orig->f_op->write(orig, ptr, sz, off);
} }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
static ssize_t ksu_wrapper_read_iter(struct kiocb *iocb, struct iov_iter *iovi) { static ssize_t ksu_wrapper_read_iter(struct kiocb *iocb, struct iov_iter *iovi) {
struct ksu_file_wrapper* data = iocb->ki_filp->private_data; struct ksu_file_wrapper* data = iocb->ki_filp->private_data;
struct file* orig = data->orig; struct file* orig = data->orig;
@@ -46,8 +48,8 @@ static ssize_t ksu_wrapper_write_iter(struct kiocb *iocb, struct iov_iter *iovi)
iocb->ki_filp = orig; iocb->ki_filp = orig;
return orig->f_op->write_iter(iocb, iovi); return orig->f_op->write_iter(iocb, iovi);
} }
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
static int ksu_wrapper_iopoll(struct kiocb *kiocb, struct io_comp_batch* icb, unsigned int v) { static int ksu_wrapper_iopoll(struct kiocb *kiocb, struct io_comp_batch* icb, unsigned int v) {
struct ksu_file_wrapper* data = kiocb->ki_filp->private_data; struct ksu_file_wrapper* data = kiocb->ki_filp->private_data;
@@ -55,7 +57,7 @@ static int ksu_wrapper_iopoll(struct kiocb *kiocb, struct io_comp_batch* icb, un
kiocb->ki_filp = orig; kiocb->ki_filp = orig;
return orig->f_op->iopoll(kiocb, icb, v); return orig->f_op->iopoll(kiocb, icb, v);
} }
#else #elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0)
static int ksu_wrapper_iopoll(struct kiocb *kiocb, bool spin) { static int ksu_wrapper_iopoll(struct kiocb *kiocb, bool spin) {
struct ksu_file_wrapper* data = kiocb->ki_filp->private_data; struct ksu_file_wrapper* data = kiocb->ki_filp->private_data;
struct file* orig = data->orig; struct file* orig = data->orig;
@@ -63,9 +65,8 @@ static int ksu_wrapper_iopoll(struct kiocb *kiocb, bool spin) {
return orig->f_op->iopoll(kiocb, spin); return orig->f_op->iopoll(kiocb, spin);
} }
#endif #endif
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0) #if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0) && (LINUX_VERSION_CODE > KERNEL_VERSION(3, 11, 0) || defined(KSU_HAS_ITERATE_DIR))
static int ksu_wrapper_iterate (struct file *fp, struct dir_context *dc) { static int ksu_wrapper_iterate (struct file *fp, struct dir_context *dc) {
struct ksu_file_wrapper* data = fp->private_data; struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig; struct file* orig = data->orig;
@@ -73,13 +74,25 @@ static int ksu_wrapper_iterate (struct file *fp, struct dir_context *dc) {
} }
#endif #endif
// int (*readdir) (struct file *, void *, filldir_t);
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) && !defined(KSU_HAS_ITERATE_DIR)
static int ksu_wrapper_readdir(struct file *fp, void *ptr, filldir_t filler) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
return orig->f_op->readdir(orig, ptr, filler);
}
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
static int ksu_wrapper_iterate_shared(struct file *fp, struct dir_context *dc) { static int ksu_wrapper_iterate_shared(struct file *fp, struct dir_context *dc) {
struct ksu_file_wrapper* data = fp->private_data; struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig; struct file* orig = data->orig;
return orig->f_op->iterate_shared(orig, dc); return orig->f_op->iterate_shared(orig, dc);
} }
#endif
static __poll_t ksu_wrapper_poll(struct file *fp, struct poll_table_struct *pts) { // typedef unsigned __bitwise __poll_t;
static unsigned __bitwise ksu_wrapper_poll(struct file *fp, struct poll_table_struct *pts) {
struct ksu_file_wrapper* data = fp->private_data; struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig; struct file* orig = data->orig;
return orig->f_op->poll(orig, pts); return orig->f_op->poll(orig, pts);
@@ -215,7 +228,7 @@ static int ksu_wrapper_setlease(struct file *fp, int arg1, struct file_lock **fl
} }
return -EINVAL; return -EINVAL;
} }
#else #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) // int (*setlease)(struct file *, long, struct file_lock **, void **);
static int ksu_wrapper_setlease(struct file *fp, long arg1, struct file_lock **fl, void **p) { static int ksu_wrapper_setlease(struct file *fp, long arg1, struct file_lock **fl, void **p) {
struct ksu_file_wrapper* data = fp->private_data; struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig; struct file* orig = data->orig;
@@ -224,6 +237,15 @@ static int ksu_wrapper_setlease(struct file *fp, long arg1, struct file_lock **f
} }
return -EINVAL; return -EINVAL;
} }
#else // int (*setlease)(struct file *, long, struct file_lock **);
static int ksu_wrapper_setlease(struct file *fp, long arg1, struct file_lock **fl) {
struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig;
if (orig->f_op->setlease) {
return orig->f_op->setlease(orig, arg1, fl);
}
return -EINVAL;
}
#endif #endif
static long ksu_wrapper_fallocate(struct file *fp, int mode, loff_t offset, loff_t len) { static long ksu_wrapper_fallocate(struct file *fp, int mode, loff_t offset, loff_t len) {
@@ -235,6 +257,7 @@ static long ksu_wrapper_fallocate(struct file *fp, int mode, loff_t offset, loff
return -EINVAL; return -EINVAL;
} }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
static void ksu_wrapper_show_fdinfo(struct seq_file *m, struct file *f) { static void ksu_wrapper_show_fdinfo(struct seq_file *m, struct file *f) {
struct ksu_file_wrapper* data = f->private_data; struct ksu_file_wrapper* data = f->private_data;
struct file* orig = data->orig; struct file* orig = data->orig;
@@ -242,31 +265,49 @@ static void ksu_wrapper_show_fdinfo(struct seq_file *m, struct file *f) {
orig->f_op->show_fdinfo(m, orig); orig->f_op->show_fdinfo(m, orig);
} }
} }
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
static ssize_t ksu_wrapper_copy_file_range(struct file *f1, loff_t off1, struct file *f2, static int ksu_wrapper_show_fdinfo(struct seq_file *m, struct file *f) {
loff_t off2, size_t sz, unsigned int flags) { struct ksu_file_wrapper* data = f->private_data;
// TODO: determine which file to use
struct ksu_file_wrapper* data = f1->private_data;
struct file* orig = data->orig; struct file* orig = data->orig;
if (orig->f_op->copy_file_range) { if (orig->f_op->show_fdinfo) {
return orig->f_op->copy_file_range(orig, off1, f2, off2, sz, flags); orig->f_op->show_fdinfo(m, orig);
} }
return -EINVAL; return -EINVAL;
} }
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
// https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/fs/read_write.c;l=1593-1606;drc=398da7defe218d3e51b0f3bdff75147e28125b60
static ssize_t ksu_wrapper_copy_file_range(struct file *file_in, loff_t pos_in, struct file *file_out,
loff_t pos_out, size_t len, unsigned int flags) {
struct ksu_file_wrapper* data = file_out->private_data;
struct file* orig = data->orig;
return orig->f_op->copy_file_range(file_in, pos_in, orig, pos_out, len, flags);
}
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
// no REMAP_FILE_DEDUP: use file_in
// https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/fs/read_write.c;l=1598-1599;drc=398da7defe218d3e51b0f3bdff75147e28125b60
// https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/fs/remap_range.c;l=403-404;drc=398da7defe218d3e51b0f3bdff75147e28125b60
// REMAP_FILE_DEDUP: use file_out
// https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/fs/remap_range.c;l=483-484;drc=398da7defe218d3e51b0f3bdff75147e28125b60
static loff_t ksu_wrapper_remap_file_range(struct file *file_in, loff_t pos_in, static loff_t ksu_wrapper_remap_file_range(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out, struct file *file_out, loff_t pos_out,
loff_t len, unsigned int remap_flags) { loff_t len, unsigned int remap_flags) {
// TODO: determine which file to use if (remap_flags & REMAP_FILE_DEDUP) {
struct ksu_file_wrapper* data = file_out->private_data;
struct file* orig = data->orig;
return orig->f_op->remap_file_range(file_in, pos_in, orig, pos_out, len, remap_flags);
} else {
struct ksu_file_wrapper* data = file_in->private_data; struct ksu_file_wrapper* data = file_in->private_data;
struct file* orig = data->orig; struct file* orig = data->orig;
if (orig->f_op->remap_file_range) {
return orig->f_op->remap_file_range(orig, pos_in, file_out, pos_out, len, remap_flags); return orig->f_op->remap_file_range(orig, pos_in, file_out, pos_out, len, remap_flags);
} }
return -EINVAL;
} }
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)
static int ksu_wrapper_fadvise(struct file *fp, loff_t off1, loff_t off2, int flags) { static int ksu_wrapper_fadvise(struct file *fp, loff_t off1, loff_t off2, int flags) {
struct ksu_file_wrapper* data = fp->private_data; struct ksu_file_wrapper* data = fp->private_data;
struct file* orig = data->orig; struct file* orig = data->orig;
@@ -275,28 +316,6 @@ static int ksu_wrapper_fadvise(struct file *fp, loff_t off1, loff_t off2, int fl
} }
return -EINVAL; return -EINVAL;
} }
#else
static int ksu_wrapper_clone_file_range(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out, u64 len) {
// TODO: determine which file to use
struct ksu_file_wrapper* data = file_in->private_data;
struct file* orig = data->orig;
if (orig->f_op->clone_file_range) {
return orig->f_op->clone_file_range(orig, pos_in, file_out, pos_out, len);
}
return -EINVAL;
}
static ssize_t ksu_wrapper_dedupe_file_range(struct file *src_file, u64 loff,
u64 len, struct file *dst_file, u64 dst_loff) {
// TODO: determine which file to use
struct ksu_file_wrapper* data = src_file->private_data;
struct file* orig = data->orig;
if (orig->f_op->dedupe_file_range) {
return orig->f_op->dedupe_file_range(orig, loff, len, dst_file, dst_loff);
}
return -EINVAL;
}
#endif #endif
static int ksu_wrapper_release(struct inode *inode, struct file *filp) { static int ksu_wrapper_release(struct inode *inode, struct file *filp) {
@@ -317,15 +336,22 @@ struct ksu_file_wrapper* ksu_create_file_wrapper(struct file* fp) {
p->ops.llseek = fp->f_op->llseek ? ksu_wrapper_llseek : NULL; p->ops.llseek = fp->f_op->llseek ? ksu_wrapper_llseek : NULL;
p->ops.read = fp->f_op->read ? ksu_wrapper_read : NULL; p->ops.read = fp->f_op->read ? ksu_wrapper_read : NULL;
p->ops.write = fp->f_op->write ? ksu_wrapper_write : NULL; p->ops.write = fp->f_op->write ? ksu_wrapper_write : NULL;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
p->ops.read_iter = fp->f_op->read_iter ? ksu_wrapper_read_iter : NULL; p->ops.read_iter = fp->f_op->read_iter ? ksu_wrapper_read_iter : NULL;
p->ops.write_iter = fp->f_op->write_iter ? ksu_wrapper_write_iter : NULL; p->ops.write_iter = fp->f_op->write_iter ? ksu_wrapper_write_iter : NULL;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) #endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
p->ops.iopoll = fp->f_op->iopoll ? ksu_wrapper_iopoll : NULL; p->ops.iopoll = fp->f_op->iopoll ? ksu_wrapper_iopoll : NULL;
#endif #endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0) #if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0) && (LINUX_VERSION_CODE > KERNEL_VERSION(3, 11, 0) || defined(KSU_HAS_ITERATE_DIR))
p->ops.iterate = fp->f_op->iterate ? ksu_wrapper_iterate : NULL; p->ops.iterate = fp->f_op->iterate ? ksu_wrapper_iterate : NULL;
#endif #endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) && !defined(KSU_HAS_ITERATE_DIR)
p->ops.readdir = fp->f_op->readdir ? ksu_wrapper_readdir : NULL;
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
p->ops.iterate_shared = fp->f_op->iterate_shared ? ksu_wrapper_iterate_shared : NULL; p->ops.iterate_shared = fp->f_op->iterate_shared ? ksu_wrapper_iterate_shared : NULL;
#endif
p->ops.poll = fp->f_op->poll ? ksu_wrapper_poll : NULL; p->ops.poll = fp->f_op->poll ? ksu_wrapper_poll : NULL;
p->ops.unlocked_ioctl = fp->f_op->unlocked_ioctl ? ksu_wrapper_unlocked_ioctl : NULL; p->ops.unlocked_ioctl = fp->f_op->unlocked_ioctl ? ksu_wrapper_unlocked_ioctl : NULL;
p->ops.compat_ioctl = fp->f_op->compat_ioctl ? ksu_wrapper_compat_ioctl : NULL; p->ops.compat_ioctl = fp->f_op->compat_ioctl ? ksu_wrapper_compat_ioctl : NULL;
@@ -351,16 +377,18 @@ struct ksu_file_wrapper* ksu_create_file_wrapper(struct file* fp) {
p->ops.splice_read = fp->f_op->splice_read ? ksu_wrapper_splice_read : NULL; p->ops.splice_read = fp->f_op->splice_read ? ksu_wrapper_splice_read : NULL;
p->ops.setlease = fp->f_op->setlease ? ksu_wrapper_setlease : NULL; p->ops.setlease = fp->f_op->setlease ? ksu_wrapper_setlease : NULL;
p->ops.fallocate = fp->f_op->fallocate ? ksu_wrapper_fallocate : NULL; p->ops.fallocate = fp->f_op->fallocate ? ksu_wrapper_fallocate : NULL;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
p->ops.show_fdinfo = fp->f_op->show_fdinfo ? ksu_wrapper_show_fdinfo : NULL; p->ops.show_fdinfo = fp->f_op->show_fdinfo ? ksu_wrapper_show_fdinfo : NULL;
p->ops.copy_file_range = fp->f_op->copy_file_range ? ksu_wrapper_copy_file_range : NULL;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)
p->ops.remap_file_range = fp->f_op->remap_file_range ? ksu_wrapper_remap_file_range : NULL;
p->ops.fadvise = fp->f_op->fadvise ? ksu_wrapper_fadvise : NULL;
#else
p->ops.clone_file_range = fp->f_op->clone_file_range ? ksu_wrapper_clone_file_range : NULL;
p->ops.dedupe_file_range = fp->f_op->dedupe_file_range ? ksu_wrapper_dedupe_file_range : NULL;
#endif #endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
p->ops.copy_file_range = fp->f_op->copy_file_range ? ksu_wrapper_copy_file_range : NULL;
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
p->ops.remap_file_range = fp->f_op->remap_file_range ? ksu_wrapper_remap_file_range : NULL;
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)
p->ops.fadvise = fp->f_op->fadvise ? ksu_wrapper_fadvise : NULL;
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
p->ops.splice_eof = fp->f_op->splice_eof ? ksu_wrapper_splice_eof : NULL; p->ops.splice_eof = fp->f_op->splice_eof ? ksu_wrapper_splice_eof : NULL;
#endif #endif

View File

@@ -4,15 +4,11 @@
#include <linux/file.h> #include <linux/file.h>
#include <linux/fs.h> #include <linux/fs.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
typedef unsigned int __poll_t;
#endif
struct ksu_file_wrapper { struct ksu_file_wrapper {
struct file* orig; struct file *orig;
struct file_operations ops; struct file_operations ops;
}; };
struct ksu_file_wrapper* ksu_create_file_wrapper(struct file* fp); struct ksu_file_wrapper *ksu_create_file_wrapper(struct file *fp);
void ksu_delete_file_wrapper(struct ksu_file_wrapper* data); void ksu_delete_file_wrapper(struct ksu_file_wrapper *data);
#endif // KSU_FILE_WRAPPER_H #endif // KSU_FILE_WRAPPER_H

View File

@@ -1,8 +1,5 @@
#include <linux/version.h> #include <linux/version.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/nsproxy.h>
#include <linux/filter.h>
#include <linux/seccomp.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
#include <linux/sched/task.h> #include <linux/sched/task.h>
#else #else
@@ -13,14 +10,16 @@
#include "kernel_compat.h" #include "kernel_compat.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || \ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || \
defined(CONFIG_IS_HW_HISI) || \ defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
#include <linux/key.h> #include <linux/key.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/cred.h> #include <linux/cred.h>
#include <linux/lsm_hooks.h>
extern int install_session_keyring_to_cred(struct cred *, struct key *);
struct key *init_session_keyring = NULL; struct key *init_session_keyring = NULL;
static inline int install_session_keyring(struct key *keyring) static int install_session_keyring(struct key *keyring)
{ {
struct cred *new; struct cred *new;
int ret; int ret;
@@ -39,7 +38,53 @@ static inline int install_session_keyring(struct key *keyring)
} }
#endif #endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) || defined(KSU_OPTIONAL_STRNCPY) 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)
if (init_session_keyring != NULL && !current_cred()->session_keyring &&
(current->flags & PF_WQ_WORKER)) {
pr_info("installing init session keyring for older kernel\n");
install_session_keyring(init_session_keyring);
}
#endif
return filp_open(filename, flags, mode);
}
ssize_t ksu_kernel_read_compat(struct file *p, void *buf, size_t count,
loff_t *pos)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) || \
defined(KSU_OPTIONAL_KERNEL_READ)
return kernel_read(p, buf, count, pos);
#else
loff_t offset = pos ? *pos : 0;
ssize_t result = kernel_read(p, offset, (char *)buf, count);
if (pos && result > 0) {
*pos = offset + result;
}
return result;
#endif
}
ssize_t ksu_kernel_write_compat(struct file *p, const void *buf, size_t count,
loff_t *pos)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) || \
defined(KSU_OPTIONAL_KERNEL_WRITE)
return kernel_write(p, buf, count, pos);
#else
loff_t offset = pos ? *pos : 0;
ssize_t result = kernel_write(p, buf, count, offset);
if (pos && result > 0) {
*pos = offset + result;
}
return result;
#endif
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) || \
defined(KSU_OPTIONAL_STRNCPY)
long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr, long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
long count) long count)
{ {

View File

@@ -3,7 +3,24 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/version.h> #include <linux/version.h>
#include <linux/cred.h> #include <linux/task_work.h>
#include <linux/fdtable.h>
#include "ss/policydb.h"
#include "linux/key.h"
/*
* Adapt to Huawei HISI kernel without affecting other kernels ,
* Huawei Hisi Kernel EBITMAP Enable or Disable Flag ,
* From ss/ebitmap.h
*/
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) && \
(LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) || \
(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) && \
(LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0))
#ifdef HISI_SELINUX_EBITMAP_RO
#define CONFIG_IS_HW_HISI
#endif
#endif
// Checks for UH, KDP and RKP // Checks for UH, KDP and RKP
#ifdef SAMSUNG_UH_DRIVER_EXIST #ifdef SAMSUNG_UH_DRIVER_EXIST
@@ -16,9 +33,15 @@ extern long ksu_strncpy_from_user_nofault(char *dst,
const void __user *unsafe_addr, const void __user *unsafe_addr,
long count); long count);
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,
loff_t *pos);
extern ssize_t ksu_kernel_write_compat(struct file *p, const void *buf,
size_t count, loff_t *pos);
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || \ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || \
defined(CONFIG_IS_HW_HISI) || \ defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
extern struct key *init_session_keyring; extern struct key *init_session_keyring;
#endif #endif
@@ -28,14 +51,23 @@ extern struct key *init_session_keyring;
#define ksu_access_ok(addr, size) access_ok(VERIFY_READ, addr, size) #define ksu_access_ok(addr, size) access_ok(VERIFY_READ, addr, size)
#endif #endif
// Linux >= 5.7
// task_work_add (struct, struct, enum)
// Linux pre-5.7
// task_work_add (struct, struct, bool)
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 7, 0) #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 7, 0)
#ifndef TWA_RESUME
#define TWA_RESUME true #define TWA_RESUME true
#endif #endif
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) static inline int do_close_fd(unsigned int fd)
#define ksu_force_sig(sig) force_sig(sig); {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
return close_fd(fd);
#else #else
#define ksu_force_sig(sig) force_sig(sig, current); return __close_fd(current->files, fd);
#endif #endif
}
#endif #endif

View File

@@ -1,20 +1,16 @@
#include <linux/version.h> #include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/nsproxy.h> #include <linux/sched/task.h>
#include <linux/uaccess.h>
#include <linux/filter.h> #include <linux/filter.h>
#include <linux/seccomp.h> #include <linux/seccomp.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
#include <linux/sched/task.h>
#else
#include <linux/sched.h>
#endif
#include <linux/uaccess.h>
#include "klog.h" // IWYU pragma: keep #include "klog.h" // IWYU pragma: keep
#include "seccomp_cache.h" #include "seccomp_cache.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 2) // Android backport this feature in 5.10.2
struct action_cache { struct action_cache {
DECLARE_BITMAP(allow_native, NR_syscalls); DECLARE_BITMAP(allow_native, SECCOMP_ARCH_NATIVE_NR);
#ifdef SECCOMP_ARCH_COMPAT #ifdef SECCOMP_ARCH_COMPAT
DECLARE_BITMAP(allow_compat, SECCOMP_ARCH_COMPAT_NR); DECLARE_BITMAP(allow_compat, SECCOMP_ARCH_COMPAT_NR);
#endif #endif
@@ -41,7 +37,7 @@ void ksu_seccomp_clear_cache(struct seccomp_filter *filter, int nr)
return; return;
} }
if (nr >= 0 && nr < NR_syscalls) { if (nr >= 0 && nr < SECCOMP_ARCH_NATIVE_NR) {
clear_bit(nr, filter->cache.allow_native); clear_bit(nr, filter->cache.allow_native);
} }
@@ -58,7 +54,7 @@ void ksu_seccomp_allow_cache(struct seccomp_filter *filter, int nr)
return; return;
} }
if (nr >= 0 && nr < NR_syscalls) { if (nr >= 0 && nr < SECCOMP_ARCH_NATIVE_NR) {
set_bit(nr, filter->cache.allow_native); set_bit(nr, filter->cache.allow_native);
} }

View File

@@ -4,7 +4,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/version.h> #include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 2) // Android backport this feature in 5.10.2 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
extern void ksu_seccomp_clear_cache(struct seccomp_filter *filter, int nr); extern void ksu_seccomp_clear_cache(struct seccomp_filter *filter, int nr);
extern void ksu_seccomp_allow_cache(struct seccomp_filter *filter, int nr); extern void ksu_seccomp_allow_cache(struct seccomp_filter *filter, int nr);
#endif #endif

View File

@@ -6,7 +6,7 @@
#include "selinux.h" #include "selinux.h"
#include "sepolicy.h" #include "sepolicy.h"
#include "ss/services.h" #include "ss/services.h"
#include "linux/lsm_audit.h" #include "linux/lsm_audit.h" // IWYU pragma: keep
#include "xfrm.h" #include "xfrm.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
@@ -37,6 +37,7 @@ static struct policydb *get_policydb(void)
} }
static DEFINE_MUTEX(ksu_rules); static DEFINE_MUTEX(ksu_rules);
void apply_kernelsu_rules(void) void apply_kernelsu_rules(void)
{ {
struct policydb *db; struct policydb *db;
@@ -95,7 +96,6 @@ void apply_kernelsu_rules(void)
ksu_allow(db, "init", "adb_data_file", "file", ALL); ksu_allow(db, "init", "adb_data_file", "file", ALL);
ksu_allow(db, "init", "adb_data_file", "dir", ALL); // #1289 ksu_allow(db, "init", "adb_data_file", "dir", ALL); // #1289
ksu_allow(db, "init", KERNEL_SU_DOMAIN, ALL, ALL); ksu_allow(db, "init", KERNEL_SU_DOMAIN, ALL, ALL);
// we need to umount modules in zygote // we need to umount modules in zygote
ksu_allow(db, "zygote", "adb_data_file", "dir", "search"); ksu_allow(db, "zygote", "adb_data_file", "dir", "search");
@@ -139,9 +139,6 @@ void apply_kernelsu_rules(void)
ksu_allow(db, "system_server", KERNEL_SU_DOMAIN, "process", "getpgid"); ksu_allow(db, "system_server", KERNEL_SU_DOMAIN, "process", "getpgid");
ksu_allow(db, "system_server", KERNEL_SU_DOMAIN, "process", "sigkill"); ksu_allow(db, "system_server", KERNEL_SU_DOMAIN, "process", "sigkill");
// https://android-review.googlesource.com/c/platform/system/logging/+/3725346
ksu_dontaudit(db, "untrusted_app", KERNEL_SU_DOMAIN, "dir", "getattr");
#ifdef CONFIG_KSU_SUSFS #ifdef CONFIG_KSU_SUSFS
// Allow umount in zygote process without installing zygisk // Allow umount in zygote process without installing zygisk
ksu_allow(db, "zygote", "labeledfs", "filesystem", "unmount"); ksu_allow(db, "zygote", "labeledfs", "filesystem", "unmount");
@@ -150,7 +147,6 @@ void apply_kernelsu_rules(void)
susfs_set_ksu_sid(); susfs_set_ksu_sid();
susfs_set_zygote_sid(); susfs_set_zygote_sid();
#endif #endif
mutex_unlock(&ksu_rules); mutex_unlock(&ksu_rules);
} }
@@ -167,15 +163,15 @@ void apply_kernelsu_rules(void)
#define CMD_GENFSCON 9 #define CMD_GENFSCON 9
struct sepol_data { struct sepol_data {
uint32_t cmd; u32 cmd;
uint32_t subcmd; u32 subcmd;
uint64_t sepol1; u64 sepol1;
uint64_t sepol2; u64 sepol2;
uint64_t sepol3; u64 sepol3;
uint64_t sepol4; u64 sepol4;
uint64_t sepol5; u64 sepol5;
uint64_t sepol6; u64 sepol6;
uint64_t sepol7; u64 sepol7;
}; };
static int get_object(char *buf, char __user *user_object, size_t buf_sz, static int get_object(char *buf, char __user *user_object, size_t buf_sz,
@@ -194,14 +190,12 @@ static int get_object(char *buf, char __user *user_object, size_t buf_sz,
return 0; return 0;
} }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0) || \ #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0) || \
!defined(KSU_COMPAT_USE_SELINUX_STATE) !defined(KSU_COMPAT_USE_SELINUX_STATE)
extern int avc_ss_reset(u32 seqno); extern int avc_ss_reset(u32 seqno);
#else #else
extern int avc_ss_reset(struct selinux_avc *avc, u32 seqno); extern int avc_ss_reset(struct selinux_avc *avc, u32 seqno);
#endif #endif
// reset avc cache table, otherwise the new rules will not take effect if already denied // reset avc cache table, otherwise the new rules will not take effect if already denied
static void reset_avc_cache(void) static void reset_avc_cache(void)
{ {
@@ -231,7 +225,7 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
pr_info("SELinux permissive or disabled when handle policy!\n"); pr_info("SELinux permissive or disabled when handle policy!\n");
} }
struct sepol_data data = { 0 }; struct sepol_data data;
if (copy_from_user(&data, arg4, sizeof(struct sepol_data))) { if (copy_from_user(&data, arg4, sizeof(struct sepol_data))) {
pr_err("sepol: copy sepol_data failed.\n"); pr_err("sepol: copy sepol_data failed.\n");
return -EINVAL; return -EINVAL;
@@ -245,7 +239,6 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
db = get_policydb(); db = get_policydb();
int ret = -EINVAL; int ret = -EINVAL;
switch (cmd) { switch (cmd) {
case CMD_NORMAL_PERM: { case CMD_NORMAL_PERM: {
char src_buf[MAX_SEPOL_LEN]; char src_buf[MAX_SEPOL_LEN];

View File

@@ -1,6 +1,7 @@
#include "linux/cred.h" #include "linux/cred.h"
#include "linux/sched.h" #include "linux/sched.h"
#include <linux/version.h> #include "linux/security.h"
#include "linux/version.h"
#include "selinux_defs.h" #include "selinux_defs.h"
#include "../klog.h" // IWYU pragma: keep #include "../klog.h" // IWYU pragma: keep
@@ -26,19 +27,18 @@ static int transive_to_domain(const char *domain)
pr_info("security_secctx_to_secid %s -> sid: %d, error: %d\n", pr_info("security_secctx_to_secid %s -> sid: %d, error: %d\n",
domain, sid, error); domain, sid, error);
} }
if (!error) { if (!error) {
tsec->sid = sid; tsec->sid = sid;
tsec->create_sid = 0; tsec->create_sid = 0;
tsec->keycreate_sid = 0; tsec->keycreate_sid = 0;
tsec->sockcreate_sid = 0; tsec->sockcreate_sid = 0;
} }
return error; return error;
} }
#if LINUX_VERSION_CODE <= KERNEL_VERSION(4, 19, 0) #if LINUX_VERSION_CODE <= KERNEL_VERSION(4, 19, 0)
bool __maybe_unused is_ksu_transition(const struct task_security_struct *old_tsec, bool __maybe_unused
is_ksu_transition(const struct task_security_struct *old_tsec,
const struct task_security_struct *new_tsec) const struct task_security_struct *new_tsec)
{ {
static u32 ksu_sid; static u32 ksu_sid;
@@ -47,7 +47,8 @@ bool __maybe_unused is_ksu_transition(const struct task_security_struct *old_tse
bool allowed = false; bool allowed = false;
if (!ksu_sid) if (!ksu_sid)
security_secctx_to_secid(KERNEL_SU_DOMAIN, strlen(KERNEL_SU_DOMAIN), &ksu_sid); security_secctx_to_secid(KERNEL_SU_DOMAIN,
strlen(KERNEL_SU_DOMAIN), &ksu_sid);
if (security_secid_to_secctx(old_tsec->sid, &secdata, &seclen)) if (security_secid_to_secctx(old_tsec->sid, &secdata, &seclen))
return false; return false;
@@ -58,6 +59,7 @@ bool __maybe_unused is_ksu_transition(const struct task_security_struct *old_tse
} }
#endif #endif
void setup_selinux(const char *domain) void setup_selinux(const char *domain)
{ {
if (transive_to_domain(domain)) { if (transive_to_domain(domain)) {
@@ -80,6 +82,19 @@ bool getenforce(void)
return __is_selinux_enforcing(); return __is_selinux_enforcing();
} }
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)) && \
!defined(KSU_COMPAT_HAS_CURRENT_SID)
/*
* get the subjective security ID of the current task
*/
static inline u32 current_sid(void)
{
const struct task_security_struct *tsec = current_security();
return tsec->sid;
}
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 14, 0) #if LINUX_VERSION_CODE < KERNEL_VERSION(6, 14, 0)
struct lsm_context { struct lsm_context {
char *context; char *context;
@@ -92,21 +107,21 @@ static int __security_secid_to_secctx(u32 secid, struct lsm_context *cp)
} }
static void __security_release_secctx(struct lsm_context *cp) static void __security_release_secctx(struct lsm_context *cp)
{ {
return security_release_secctx(cp->context, cp->len); security_release_secctx(cp->context, cp->len);
} }
#else #else
#define __security_secid_to_secctx security_secid_to_secctx #define __security_secid_to_secctx security_secid_to_secctx
#define __security_release_secctx security_release_secctx #define __security_release_secctx security_release_secctx
#endif #endif
bool is_task_ksu_domain(const struct cred* cred) bool is_task_ksu_domain(const struct cred *cred)
{ {
struct lsm_context ctx; struct lsm_context ctx;
bool result; bool result;
if (!cred) { if (!cred) {
return false; return false;
} }
const struct task_security_struct *tsec = selinux_cred(cred); const struct task_security_struct *tsec = __selinux_cred(cred);
if (!tsec) { if (!tsec) {
return false; return false;
} }
@@ -119,18 +134,18 @@ bool is_task_ksu_domain(const struct cred* cred)
return result; return result;
} }
bool is_ksu_domain() bool is_ksu_domain(void)
{ {
current_sid(); current_sid();
return is_task_ksu_domain(current_cred()); return is_task_ksu_domain(current_cred());
} }
bool is_context(const struct cred* cred, const char* context) bool is_context(const struct cred *cred, const char *context)
{ {
if (!cred) { if (!cred) {
return false; return false;
} }
const struct task_security_struct * tsec = selinux_cred(cred); const struct task_security_struct *tsec = __selinux_cred(cred);
if (!tsec) { if (!tsec) {
return false; return false;
} }
@@ -145,22 +160,23 @@ bool is_context(const struct cred* cred, const char* context)
return result; return result;
} }
bool is_zygote(const struct cred* cred) bool is_zygote(const struct cred *cred)
{ {
return is_context(cred, "u:r:zygote:s0"); return is_context(cred, "u:r:zygote:s0");
} }
bool is_init(const struct cred* cred) { bool is_init(const struct cred *cred)
{
return is_context(cred, "u:r:init:s0"); return is_context(cred, "u:r:init:s0");
} }
#define KSU_FILE_DOMAIN "u:object_r:ksu_file:s0" #define KSU_FILE_DOMAIN "u:object_r:ksu_file:s0"
u32 ksu_get_ksu_file_sid() u32 ksu_get_ksu_file_sid(void)
{ {
u32 ksu_file_sid = 0; u32 ksu_file_sid = 0;
int err = security_secctx_to_secid(KSU_FILE_DOMAIN, strlen(KSU_FILE_DOMAIN), int err = security_secctx_to_secid(
&ksu_file_sid); KSU_FILE_DOMAIN, strlen(KSU_FILE_DOMAIN), &ksu_file_sid);
if (err) { if (err) {
pr_info("get ksufile sid err %d\n", err); pr_info("get ksufile sid err %d\n", err);
} }

View File

@@ -1,11 +1,12 @@
#ifndef __KSU_H_SELINUX #ifndef __KSU_H_SELINUX
#define __KSU_H_SELINUX #define __KSU_H_SELINUX
#include <linux/types.h> #include "linux/types.h"
#include <linux/version.h> #include "linux/version.h"
#include "linux/sched.h" #include "linux/cred.h"
#ifdef KSU_COMPAT_HAS_SELINUX_STATE #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) || \
defined(KSU_COMPAT_HAS_SELINUX_STATE)
#define KSU_COMPAT_USE_SELINUX_STATE #define KSU_COMPAT_USE_SELINUX_STATE
#endif #endif
@@ -15,13 +16,13 @@ void setenforce(bool);
bool getenforce(void); bool getenforce(void);
bool is_task_ksu_domain(const struct cred* cred); bool is_task_ksu_domain(const struct cred *cred);
bool is_ksu_domain(void); bool is_ksu_domain(void);
bool is_zygote(const struct cred* cred); bool is_zygote(const struct cred *cred);
bool is_init(const struct cred* cred); bool is_init(const struct cred *cred);
void apply_kernelsu_rules(void); void apply_kernelsu_rules(void);

View File

@@ -33,4 +33,10 @@
#define __setenforce(val) #define __setenforce(val)
#endif #endif
#ifdef KSU_OPTIONAL_SELINUX_CRED
#define __selinux_cred(cred) (selinux_cred(cred))
#else
#define __selinux_cred(cred) (cred->security)
#endif
#endif #endif

View File

@@ -6,6 +6,7 @@
#include "sepolicy.h" #include "sepolicy.h"
#include "../klog.h" // IWYU pragma: keep #include "../klog.h" // IWYU pragma: keep
#include "ss/symtab.h" #include "ss/symtab.h"
#include "../kernel_compat.h" // Add check Huawei Device
#define KSU_SUPPORT_ADD_TYPE #define KSU_SUPPORT_ADD_TYPE
@@ -551,8 +552,8 @@ static bool add_filename_trans(struct policydb *db, const char *s,
} }
if (trans == NULL) { if (trans == NULL) {
trans = (struct filename_trans_datum *)kcalloc(1 ,sizeof(*trans), trans = (struct filename_trans_datum *)kcalloc(sizeof(*trans),
GFP_ATOMIC); 1, GFP_ATOMIC);
struct filename_trans_key *new_key = struct filename_trans_key *new_key =
(struct filename_trans_key *)kzalloc(sizeof(*new_key), (struct filename_trans_key *)kzalloc(sizeof(*new_key),
GFP_ATOMIC); GFP_ATOMIC);
@@ -584,7 +585,7 @@ static bool add_filename_trans(struct policydb *db, const char *s,
return false; return false;
} }
struct filename_trans *new_key = struct filename_trans *new_key =
(struct filename_trans *)kmalloc(sizeof(*new_key), (struct filename_trans *)kzalloc(sizeof(*new_key),
GFP_ATOMIC); GFP_ATOMIC);
if (!new_key) { if (!new_key) {
pr_err("add_filename_trans: Failed to alloc new_key\n"); pr_err("add_filename_trans: Failed to alloc new_key\n");

View File

@@ -1,10 +1,12 @@
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
#include <linux/sched/signal.h> #include <linux/sched/signal.h>
#endif
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/task_work.h> #include <linux/task_work.h>
#include <linux/thread_info.h> #include <linux/thread_info.h>
#include <linux/seccomp.h> #include <linux/seccomp.h>
#include <linux/bpf.h>
#include <linux/capability.h> #include <linux/capability.h>
#include <linux/cred.h> #include <linux/cred.h>
#include <linux/dcache.h> #include <linux/dcache.h>
@@ -12,7 +14,6 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/init_task.h> #include <linux/init_task.h>
#include <linux/kallsyms.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/kprobes.h> #include <linux/kprobes.h>
#include <linux/mm.h> #include <linux/mm.h>
@@ -22,34 +23,20 @@
#include <linux/path.h> #include <linux/path.h>
#include <linux/printk.h> #include <linux/printk.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/security.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/uidgid.h> #include <linux/uidgid.h>
#include <linux/version.h>
#include <linux/binfmts.h>
#include <linux/tty.h>
#ifdef CONFIG_KSU_SUSFS #ifdef CONFIG_KSU_SUSFS
#include <linux/susfs.h> #include <linux/susfs.h>
#endif // #ifdef CONFIG_KSU_SUSFS #endif // #ifdef CONFIG_KSU_SUSFS
#ifdef MODULE
#include <linux/list.h>
#include <linux/irqflags.h>
#include <linux/mm_types.h>
#include <linux/rcupdate.h>
#include <linux/vmalloc.h>
#endif
#include "allowlist.h" #include "allowlist.h"
#include "setuid_hook.h" #include "setuid_hook.h"
#include "feature.h" #include "feature.h"
#include "klog.h" // IWYU pragma: keep #include "klog.h" // IWYU pragma: keep
#include "kernel_compat.h"
#include "ksu.h"
#include "manager.h" #include "manager.h"
#include "selinux/selinux.h" #include "selinux/selinux.h"
#include "seccomp_cache.h" #include "seccomp_cache.h"
@@ -58,8 +45,6 @@
#include "syscall_hook_manager.h" #include "syscall_hook_manager.h"
#endif #endif
#include "kernel_umount.h" #include "kernel_umount.h"
#include "app_profile.h"
#include "sulog.h" #include "sulog.h"
#ifdef CONFIG_KSU_SUSFS #ifdef CONFIG_KSU_SUSFS
@@ -128,12 +113,23 @@ static inline bool is_allow_su(void)
return ksu_is_allow_uid_for_current(current_uid().val); return ksu_is_allow_uid_for_current(current_uid().val);
} }
// force_sig kcompat, TODO: move it out of core_hook.c
// https://elixir.bootlin.com/linux/v5.3-rc1/source/kernel/signal.c#L1613
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
#define __force_sig(sig) force_sig(sig)
#else
#define __force_sig(sig) force_sig(sig, current)
#endif
extern void disable_seccomp(struct task_struct *tsk);
#ifndef CONFIG_KSU_SUSFS #ifndef CONFIG_KSU_SUSFS
int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid) int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid)
{ {
// we rely on the fact that zygote always call setresuid(3) with same uids
uid_t new_uid = ruid; uid_t new_uid = ruid;
uid_t old_uid = current_uid().val; uid_t old_uid = current_uid().val;
if (old_uid != new_uid)
pr_info("handle_setresuid from %d to %d\n", old_uid, new_uid); pr_info("handle_setresuid from %d to %d\n", old_uid, new_uid);
// if old process is root, ignore it. // if old process is root, ignore it.
@@ -143,17 +139,20 @@ int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid)
if (unlikely(euid == 0)) { if (unlikely(euid == 0)) {
if (!is_ksu_domain()) { if (!is_ksu_domain()) {
pr_warn("find suspicious EoP: %d %s, from %d to %d\n", pr_warn("find suspicious EoP: %d %s, from %d to %d\n",
current->pid, current->comm, old_uid, new_uid); current->pid, current->comm, old_uid,
ksu_force_sig(SIGKILL); new_uid);
__force_sig(SIGKILL);
return 0; return 0;
} }
} }
// disallow appuid decrease to any other uid if it is not allowed to su // disallow appuid decrease to any other uid if it is not allowed to su
if (is_appuid(old_uid)) { if (is_appuid(old_uid)) {
if (euid < current_euid().val && !ksu_is_allow_uid_for_current(old_uid)) { if (euid < current_euid().val &&
!ksu_is_allow_uid_for_current(old_uid)) {
pr_warn("find suspicious EoP: %d %s, from %d to %d\n", pr_warn("find suspicious EoP: %d %s, from %d to %d\n",
current->pid, current->comm, old_uid, new_uid); current->pid, current->comm, old_uid,
ksu_force_sig(SIGKILL); new_uid);
__force_sig(SIGKILL);
return 0; return 0;
} }
} }
@@ -161,13 +160,14 @@ int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid)
} }
// if on private space, see if its possibly the manager // if on private space, see if its possibly the manager
if (new_uid > PER_USER_RANGE && new_uid % PER_USER_RANGE == ksu_get_manager_uid()) { if (new_uid > PER_USER_RANGE &&
new_uid % PER_USER_RANGE == ksu_get_manager_uid()) {
ksu_set_manager_uid(new_uid); ksu_set_manager_uid(new_uid);
} }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
if (ksu_get_manager_uid() == new_uid) { if (ksu_get_manager_uid() == new_uid) {
pr_info("install fd for manager: %d\n", new_uid); pr_info("install fd for ksu manager(uid=%d)\n", new_uid);
ksu_install_fd(); ksu_install_fd();
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
ksu_seccomp_allow_cache(current->seccomp.filter, __NR_reboot); ksu_seccomp_allow_cache(current->seccomp.filter, __NR_reboot);
@@ -180,7 +180,8 @@ int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid)
if (current->seccomp.mode == SECCOMP_MODE_FILTER && if (current->seccomp.mode == SECCOMP_MODE_FILTER &&
current->seccomp.filter) { current->seccomp.filter) {
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
ksu_seccomp_allow_cache(current->seccomp.filter, __NR_reboot); ksu_seccomp_allow_cache(current->seccomp.filter,
__NR_reboot);
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
} }
ksu_set_task_tracepoint_flag(current); ksu_set_task_tracepoint_flag(current);
@@ -190,7 +191,7 @@ int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid)
#else #else
if (ksu_is_allow_uid_for_current(new_uid)) { if (ksu_is_allow_uid_for_current(new_uid)) {
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
disable_seccomp(); disable_seccomp(current);
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
if (ksu_get_manager_uid() == new_uid) { if (ksu_get_manager_uid() == new_uid) {
@@ -224,7 +225,7 @@ int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid){
if (!is_ksu_domain()) { if (!is_ksu_domain()) {
pr_warn("find suspicious EoP: %d %s, from %d to %d\n", pr_warn("find suspicious EoP: %d %s, from %d to %d\n",
current->pid, current->comm, old_uid, new_uid); current->pid, current->comm, old_uid, new_uid);
ksu_force_sig(SIGKILL); __force_sig(SIGKILL);
return 0; return 0;
} }
} }
@@ -233,7 +234,7 @@ int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid){
if (euid < current_euid().val && !ksu_is_allow_uid_for_current(old_uid)) { if (euid < current_euid().val && !ksu_is_allow_uid_for_current(old_uid)) {
pr_warn("find suspicious EoP: %d %s, from %d to %d\n", pr_warn("find suspicious EoP: %d %s, from %d to %d\n",
current->pid, current->comm, old_uid, new_uid); current->pid, current->comm, old_uid, new_uid);
ksu_force_sig(SIGKILL); __force_sig(SIGKILL);
return 0; return 0;
} }
} }
@@ -260,18 +261,30 @@ int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid){
// will always return true, that's why we need to explicitly check if new_uid belongs to // will always return true, that's why we need to explicitly check if new_uid belongs to
// ksu manager // ksu manager
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
if (ksu_get_manager_uid() == new_uid % 100000) { if (ksu_get_manager_uid() == new_uid) {
pr_info("install fd for manager: %d\n", new_uid); pr_info("install fd for ksu manager(uid=%d)\n", new_uid);
ksu_install_fd(); ksu_install_fd();
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
ksu_seccomp_allow_cache(current->seccomp.filter, __NR_reboot); ksu_seccomp_allow_cache(current->seccomp.filter, __NR_reboot);
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
return 0; return 0;
} }
if (ksu_is_allow_uid_for_current(new_uid)) {
if (current->seccomp.mode == SECCOMP_MODE_FILTER &&
current->seccomp.filter) {
spin_lock_irq(&current->sighand->siglock);
ksu_seccomp_allow_cache(current->seccomp.filter,
__NR_reboot);
spin_unlock_irq(&current->sighand->siglock);
}
} else {
ksu_clear_task_tracepoint_flag_if_needed(current);
}
#else #else
if (ksu_is_allow_uid_for_current(new_uid)) { if (ksu_is_allow_uid_for_current(new_uid)) {
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
disable_seccomp(); disable_seccomp(current);
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
if (ksu_get_manager_uid() == new_uid) { if (ksu_get_manager_uid() == new_uid) {
@@ -293,16 +306,6 @@ int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid){
if (unlikely(is_some_system_uid(new_uid) && susfs_is_umount_for_zygote_system_process_enabled)) { if (unlikely(is_some_system_uid(new_uid) && susfs_is_umount_for_zygote_system_process_enabled)) {
goto do_umount; goto do_umount;
} }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
if (ksu_is_allow_uid_for_current(new_uid)) {
if (current->seccomp.mode == SECCOMP_MODE_FILTER &&
current->seccomp.filter) {
spin_lock_irq(&current->sighand->siglock);
ksu_seccomp_allow_cache(current->seccomp.filter, __NR_reboot);
spin_unlock_irq(&current->sighand->siglock);
}
}
#endif
return 0; return 0;

View File

@@ -1,10 +1,8 @@
#ifndef __KSU_H_KSU_CORE #ifndef __KSU_H_KSU_SETUID_HOOK
#define __KSU_H_KSU_CORE #define __KSU_H_KSU_SETUID_HOOK
#include <linux/init.h> #include <linux/init.h>
#include <linux/types.h> #include <linux/types.h>
#include "apk_sign.h"
#include <linux/thread_info.h>
void ksu_setuid_hook_init(void); void ksu_setuid_hook_init(void);
void ksu_setuid_hook_exit(void); void ksu_setuid_hook_exit(void);

View File

@@ -13,8 +13,9 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include "klog.h"
#include "sulog.h" #include "sulog.h"
#include "klog.h"
#include "kernel_compat.h"
#include "ksu.h" #include "ksu.h"
#include "feature.h" #include "feature.h"
@@ -164,7 +165,7 @@ static void sulog_work_handler(struct work_struct *work)
if (list_empty(&local_queue)) if (list_empty(&local_queue))
return; return;
fp = filp_open(SULOG_PATH, O_WRONLY | O_CREAT | O_APPEND, 0640); fp = ksu_filp_open_compat(SULOG_PATH, O_WRONLY | O_CREAT | O_APPEND, 0640);
if (IS_ERR(fp)) { if (IS_ERR(fp)) {
pr_err("sulog: failed to open log file: %ld\n", PTR_ERR(fp)); pr_err("sulog: failed to open log file: %ld\n", PTR_ERR(fp));
goto cleanup; goto cleanup;
@@ -179,7 +180,7 @@ static void sulog_work_handler(struct work_struct *work)
} }
list_for_each_entry(entry, &local_queue, list) list_for_each_entry(entry, &local_queue, list)
kernel_write(fp, entry->content, strlen(entry->content), &pos); ksu_kernel_write_compat(fp, entry->content, strlen(entry->content), &pos);
vfs_fsync(fp, 0); vfs_fsync(fp, 0);
filp_close(fp, 0); filp_close(fp, 0);

View File

@@ -421,7 +421,19 @@ static int do_set_feature(void __user *arg)
return 0; return 0;
} }
static int do_get_wrapper_fd(void __user *arg) { // kcompat for older kernel
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
#define getfd_secure anon_inode_create_getfd
#elif defined(KSU_HAS_GETFD_SECURE)
#define getfd_secure anon_inode_getfd_secure
#else
// technically not a secure inode, but, this is the only way so.
#define getfd_secure(name, ops, data, flags, __unused) \
anon_inode_getfd(name, ops, data, flags)
#endif
static int do_get_wrapper_fd(void __user *arg)
{
if (!ksu_file_sid) { if (!ksu_file_sid) {
return -EINVAL; return -EINVAL;
} }
@@ -434,7 +446,7 @@ static int do_get_wrapper_fd(void __user *arg) {
return -EFAULT; return -EFAULT;
} }
struct file* f = fget(cmd.fd); struct file *f = fget(cmd.fd);
if (!f) { if (!f) {
return -EBADF; return -EBADF;
} }
@@ -445,28 +457,26 @@ static int do_get_wrapper_fd(void __user *arg) {
goto put_orig_file; goto put_orig_file;
} }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0) ret = getfd_secure("[ksu_fdwrapper]", &data->ops, data, f->f_flags,
#define getfd_secure anon_inode_create_getfd NULL);
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
#define getfd_secure anon_inode_getfd_secure
#else
#define getfd_secure anon_inode_getfd
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
ret = getfd_secure("[ksu_fdwrapper]", &data->ops, data, f->f_flags, NULL);
#else
ret = getfd_secure("[ksu_fdwrapper]", &data->ops, data, f->f_flags);
#endif
if (ret < 0) { if (ret < 0) {
pr_err("ksu_fdwrapper: getfd failed: %d\n", ret); pr_err("ksu_fdwrapper: getfd failed: %d\n", ret);
goto put_wrapper_data; goto put_wrapper_data;
} }
struct file* pf = fget(ret); struct file *pf = fget(ret);
struct inode* wrapper_inode = file_inode(pf); struct inode *wrapper_inode = file_inode(pf);
// copy original inode mode // copy original inode mode
wrapper_inode->i_mode = file_inode(f)->i_mode; wrapper_inode->i_mode = file_inode(f)->i_mode;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) || \
defined(KSU_OPTIONAL_SELINUX_INODE)
struct inode_security_struct *sec = selinux_inode(wrapper_inode); struct inode_security_struct *sec = selinux_inode(wrapper_inode);
#else
struct inode_security_struct *sec =
(struct inode_security_struct *)wrapper_inode->i_security;
#endif
if (sec) { if (sec) {
sec->sid = ksu_file_sid; sec->sid = ksu_file_sid;
} }
@@ -950,11 +960,7 @@ static void ksu_install_fd_tw_func(struct callback_head *cb)
if (copy_to_user(tw->outp, &fd, sizeof(fd))) { if (copy_to_user(tw->outp, &fd, sizeof(fd))) {
pr_err("install ksu fd reply err\n"); pr_err("install ksu fd reply err\n");
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) do_close_fd(fd);
close_fd(fd);
#else
__close_fd(current->files, fd);
#endif
} }
kfree(tw); kfree(tw);

View File

@@ -7,8 +7,9 @@
#include "ksu.h" #include "ksu.h"
#include "klog.h" #include "klog.h"
#include "throne_comm.h"
#include "ksu.h" #include "ksu.h"
#include "kernel_compat.h"
#include "throne_comm.h"
#define PROC_UID_SCANNER "ksu_uid_scanner" #define PROC_UID_SCANNER "ksu_uid_scanner"
#define UID_SCANNER_STATE_FILE "/data/adb/ksu/.uid_scanner" #define UID_SCANNER_STATE_FILE "/data/adb/ksu/.uid_scanner"
@@ -49,13 +50,13 @@ static void do_save_throne_state(struct work_struct *work)
char state_char = ksu_uid_scanner_enabled ? '1' : '0'; char state_char = ksu_uid_scanner_enabled ? '1' : '0';
loff_t off = 0; loff_t off = 0;
fp = filp_open(UID_SCANNER_STATE_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0644); fp = ksu_filp_open_compat(UID_SCANNER_STATE_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (IS_ERR(fp)) { if (IS_ERR(fp)) {
pr_err("save_throne_state create file failed: %ld\n", PTR_ERR(fp)); pr_err("save_throne_state create file failed: %ld\n", PTR_ERR(fp));
return; return;
} }
if (kernel_write(fp, &state_char, sizeof(state_char), &off) != sizeof(state_char)) { if (ksu_kernel_write_compat(fp, &state_char, sizeof(state_char), &off) != sizeof(state_char)) {
pr_err("save_throne_state write failed\n"); pr_err("save_throne_state write failed\n");
goto exit; goto exit;
} }
@@ -73,14 +74,14 @@ void do_load_throne_state(struct work_struct *work)
loff_t off = 0; loff_t off = 0;
ssize_t ret; ssize_t ret;
fp = filp_open(UID_SCANNER_STATE_FILE, O_RDONLY, 0); fp = ksu_filp_open_compat(UID_SCANNER_STATE_FILE, O_RDONLY, 0);
if (IS_ERR(fp)) { if (IS_ERR(fp)) {
pr_info("throne state file not found, using default: disabled\n"); pr_info("throne state file not found, using default: disabled\n");
ksu_uid_scanner_enabled = false; ksu_uid_scanner_enabled = false;
return; return;
} }
ret = kernel_read(fp, &state_char, sizeof(state_char), &off); ret = ksu_kernel_read_compat(fp, &state_char, sizeof(state_char), &off);
if (ret != sizeof(state_char)) { if (ret != sizeof(state_char)) {
pr_err("load_throne_state read err: %zd\n", ret); pr_err("load_throne_state read err: %zd\n", ret);
ksu_uid_scanner_enabled = false; ksu_uid_scanner_enabled = false;

View File

@@ -13,6 +13,7 @@
#include "manager.h" #include "manager.h"
#include "throne_tracker.h" #include "throne_tracker.h"
#include "apk_sign.h" #include "apk_sign.h"
#include "kernel_compat.h"
#include "dynamic_manager.h" #include "dynamic_manager.h"
#include "throne_comm.h" #include "throne_comm.h"
@@ -38,7 +39,7 @@ static int uid_from_um_list(struct list_head *uid_list)
ssize_t nr; ssize_t nr;
int cnt = 0; int cnt = 0;
fp = filp_open(KSU_UID_LIST_PATH, O_RDONLY, 0); fp = ksu_filp_open_compat(KSU_UID_LIST_PATH, O_RDONLY, 0);
if (IS_ERR(fp)) if (IS_ERR(fp))
return -ENOENT; return -ENOENT;
@@ -55,7 +56,7 @@ static int uid_from_um_list(struct list_head *uid_list)
return -ENOMEM; return -ENOMEM;
} }
nr = kernel_read(fp, buf, size, &pos); nr = ksu_kernel_read_compat(fp, buf, size, &pos);
filp_close(fp, NULL); filp_close(fp, NULL);
if (nr != size) { if (nr != size) {
pr_err("uid_list: short read %zd/%lld\n", nr, size); pr_err("uid_list: short read %zd/%lld\n", nr, size);
@@ -361,7 +362,7 @@ void search_manager(const char *path, int depth, struct list_head *uid_data)
struct file *file; struct file *file;
if (!stop) { if (!stop) {
file = filp_open(pos->dirpath, O_RDONLY | O_NOFOLLOW, 0); file = ksu_filp_open_compat(pos->dirpath, O_RDONLY | O_NOFOLLOW, 0);
if (IS_ERR(file)) { if (IS_ERR(file)) {
pr_err("Failed to open directory: %s, err: %ld\n", pr_err("Failed to open directory: %s, err: %ld\n",
pos->dirpath, PTR_ERR(file)); pos->dirpath, PTR_ERR(file));
@@ -452,7 +453,7 @@ void track_throne(bool prune_only)
} }
{ {
fp = filp_open(SYSTEM_PACKAGES_LIST_PATH, O_RDONLY, 0); fp = ksu_filp_open_compat(SYSTEM_PACKAGES_LIST_PATH, O_RDONLY, 0);
if (IS_ERR(fp)) { if (IS_ERR(fp)) {
pr_err("%s: open " SYSTEM_PACKAGES_LIST_PATH " failed: %ld\n", __func__, PTR_ERR(fp)); pr_err("%s: open " SYSTEM_PACKAGES_LIST_PATH " failed: %ld\n", __func__, PTR_ERR(fp));
return; return;
@@ -460,13 +461,13 @@ void track_throne(bool prune_only)
for (;;) { for (;;) {
ssize_t count = ssize_t count =
kernel_read(fp, &chr, sizeof(chr), &pos); ksu_kernel_read_compat(fp, &chr, sizeof(chr), &pos);
if (count != sizeof(chr)) if (count != sizeof(chr))
break; break;
if (chr != '\n') if (chr != '\n')
continue; continue;
count = kernel_read(fp, buf, sizeof(buf), count = ksu_kernel_read_compat(fp, buf, sizeof(buf),
&line_start); &line_start);
struct uid_data *data = struct uid_data *data =
kzalloc(sizeof(struct uid_data), GFP_ATOMIC); kzalloc(sizeof(struct uid_data), GFP_ATOMIC);