Skip to content

Commit

Permalink
Re-add Non-GKI Support
Browse files Browse the repository at this point in the history
Revert "[1.0] Drop Non-GKI Support (tiann#1483)"
This reverts commit 898e9d4.

Revert "Drop some legacy codes (tiann#1981)"

This reverts commit fd09ccf.
  • Loading branch information
natsumerinchan committed Aug 17, 2024
1 parent 221c834 commit 28bb1d0
Show file tree
Hide file tree
Showing 18 changed files with 703 additions and 46 deletions.
15 changes: 15 additions & 0 deletions kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ $(warning "KSU_GIT_VERSION not defined! It is better to make KernelSU a git subm
ccflags-y += -DKSU_VERSION=16
endif

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

ifndef KSU_EXPECTED_SIZE
KSU_EXPECTED_SIZE := 0x033b
endif
Expand All @@ -48,6 +56,13 @@ $(info -- KernelSU Manager signature hash: $(KSU_EXPECTED_HASH))
ccflags-y += -DEXPECTED_SIZE=$(KSU_EXPECTED_SIZE)
ccflags-y += -DEXPECTED_HASH=\"$(KSU_EXPECTED_HASH)\"

ifeq ($(shell grep -q "int path_umount" $(srctree)/fs/namespace.c; echo $$?),0)
ccflags-y += -DKSU_UMOUNT
else
$(info -- Did you know you can backport path_umount to fs/namespace.c from 5.9?)
$(info -- Read: https://kernelsu.org/guide/how-to-integrate-for-non-gki.html#how-to-backport-path-umount)
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

Expand Down
2 changes: 2 additions & 0 deletions kernel/allowlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
#include <linux/compiler_types.h>
#endif

#include "ksu.h"
#include "klog.h" // IWYU pragma: keep
Expand Down
20 changes: 20 additions & 0 deletions kernel/arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,19 @@
#define __PT_SP_REG sp
#define __PT_IP_REG pc

#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
#define PRCTL_SYMBOL "__arm64_sys_prctl"
#define SYS_READ_SYMBOL "__arm64_sys_read"
#define SYS_NEWFSTATAT_SYMBOL "__arm64_sys_newfstatat"
#define SYS_FACCESSAT_SYMBOL "__arm64_sys_faccessat"
#define SYS_EXECVE_SYMBOL "__arm64_sys_execve"
#else
#define PRCTL_SYMBOL "sys_prctl"
#define SYS_READ_SYMBOL "sys_read"
#define SYS_NEWFSTATAT_SYMBOL "sys_newfstatat"
#define SYS_FACCESSAT_SYMBOL "sys_faccessat"
#define SYS_EXECVE_SYMBOL "sys_execve"
#endif

#elif defined(__x86_64__)

Expand All @@ -39,11 +47,19 @@
#define __PT_RC_REG ax
#define __PT_SP_REG sp
#define __PT_IP_REG ip
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
#define PRCTL_SYMBOL "__x64_sys_prctl"
#define SYS_READ_SYMBOL "__x64_sys_read"
#define SYS_NEWFSTATAT_SYMBOL "__x64_sys_newfstatat"
#define SYS_FACCESSAT_SYMBOL "__x64_sys_faccessat"
#define SYS_EXECVE_SYMBOL "__x64_sys_execve"
#else
#define PRCTL_SYMBOL "sys_prctl"
#define SYS_READ_SYMBOL "sys_read"
#define SYS_NEWFSTATAT_SYMBOL "sys_newfstatat"
#define SYS_FACCESSAT_SYMBOL "sys_faccessat"
#define SYS_EXECVE_SYMBOL "sys_execve"
#endif

#else
#error "Unsupported arch"
Expand All @@ -67,6 +83,10 @@
#define PT_REGS_SP(x) (__PT_REGS_CAST(x)->__PT_SP_REG)
#define PT_REGS_IP(x) (__PT_REGS_CAST(x)->__PT_IP_REG)

#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
#define PT_REAL_REGS(regs) ((struct pt_regs *)PT_REGS_PARM1(regs))
#else
#define PT_REAL_REGS(regs) ((regs))
#endif

#endif
53 changes: 46 additions & 7 deletions kernel/core_hook.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,11 @@ static void setup_groups(struct root_profile *profile, struct cred *cred)
put_group_info(group_info);
return;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
group_info->gid[i] = kgid;
#else
GROUP_AT(group_info, i) = kgid;
#endif
}

groups_sort(group_info);
Expand Down Expand Up @@ -445,12 +449,14 @@ static bool should_umount(struct path *path)
return false;
}

static void ksu_umount_mnt(struct path *path, int flags)
static int ksu_umount_mnt(struct path *path, int flags)
{
int err = path_umount(path, flags);
if (err) {
pr_info("umount %s failed: %d\n", path->dentry->d_iname, err);
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) || defined(KSU_UMOUNT)
return path_umount(path, flags);
#else
// TODO: umount for non GKI kernel
return -ENOSYS;
#endif
}

static void try_umount(const char *mnt, bool check_mnt, int flags)
Expand All @@ -471,7 +477,10 @@ static void try_umount(const char *mnt, bool check_mnt, int flags)
return;
}

ksu_umount_mnt(&path, flags);
err = ksu_umount_mnt(&path, flags);
if (err) {
pr_warn("umount %s failed: %d\n", mnt, err);
}
}

int ksu_handle_setuid(struct cred *new, const struct cred *old)
Expand Down Expand Up @@ -548,8 +557,14 @@ static int handler_pre(struct kprobe *p, struct pt_regs *regs)
int option = (int)PT_REGS_PARM1(real_regs);
unsigned long arg2 = (unsigned long)PT_REGS_PARM2(real_regs);
unsigned long arg3 = (unsigned long)PT_REGS_PARM3(real_regs);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
// PRCTL_SYMBOL is the arch-specificed one, which receive raw pt_regs from syscall
unsigned long arg4 = (unsigned long)PT_REGS_SYSCALL_PARM4(real_regs);
#else
// PRCTL_SYMBOL is the common one, called by C convention in do_syscall_64
// https://elixir.bootlin.com/linux/v4.15.18/source/arch/x86/entry/common.c#L287
unsigned long arg4 = (unsigned long)PT_REGS_CCALL_PARM4(real_regs);
#endif
unsigned long arg5 = (unsigned long)PT_REGS_PARM5(real_regs);

return ksu_handle_prctl(option, arg2, arg3, arg4, arg5);
Expand Down Expand Up @@ -609,7 +624,23 @@ static int ksu_task_prctl(int option, unsigned long arg2, unsigned long arg3,
ksu_handle_prctl(option, arg2, arg3, arg4, arg5);
return -ENOSYS;
}

// kernel 4.4 and 4.9
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI)
static int ksu_key_permission(key_ref_t key_ref, const struct cred *cred,
unsigned perm)
{
if (init_session_keyring != NULL) {
return 0;
}
if (strcmp(current->comm, "init")) {
// we are only interested in `init` process
return 0;
}
init_session_keyring = cred->session_keyring;
pr_info("kernel_compat: got init_session_keyring\n");
return 0;
}
#endif
static int ksu_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
struct inode *new_inode, struct dentry *new_dentry)
{
Expand All @@ -627,11 +658,19 @@ static struct security_hook_list ksu_hooks[] = {
LSM_HOOK_INIT(task_prctl, ksu_task_prctl),
LSM_HOOK_INIT(inode_rename, ksu_inode_rename),
LSM_HOOK_INIT(task_fix_setuid, ksu_task_fix_setuid),
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI)
LSM_HOOK_INIT(key_permission, ksu_key_permission)
#endif
};

void __init ksu_lsm_hook_init(void)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
security_add_hooks(ksu_hooks, ARRAY_SIZE(ksu_hooks), "ksu");
#else
// https://elixir.bootlin.com/linux/v4.10.17/source/include/linux/lsm_hooks.h#L1892
security_add_hooks(ksu_hooks, ARRAY_SIZE(ksu_hooks));
#endif
}

#else
Expand Down
90 changes: 89 additions & 1 deletion kernel/kernel_compat.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,39 @@
#include <linux/version.h>
#include <linux/fs.h>
#include <linux/nsproxy.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 "kernel_compat.h"
#include "kernel_compat.h" // Add check Huawei Device

#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI)
#include <linux/key.h>
#include <linux/errno.h>
#include <linux/cred.h>
struct key *init_session_keyring = NULL;

static inline int install_session_keyring(struct key *keyring)
{
struct cred *new;
int ret;

new = prepare_creds();
if (!new)
return -ENOMEM;

ret = install_session_keyring_to_cred(new, keyring);
if (ret < 0) {
abort_creds(new);
return ret;
}

return commit_creds(new);
}
#endif

extern struct task_struct init_task;

Expand Down Expand Up @@ -50,6 +79,13 @@ void ksu_android_ns_fs_check()

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)
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
// switch mnt_ns even if current is not wq_worker, to ensure what we open is the correct file in android mnt_ns, rather than user created mnt_ns
struct ksu_ns_fs_saved saved;
if (android_context_saved_enabled) {
Expand All @@ -72,17 +108,69 @@ struct file *ksu_filp_open_compat(const char *filename, int flags, umode_t 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)
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)
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)
long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
long count)
{
return strncpy_from_user_nofault(dst, unsafe_addr, count);
}
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
long count)
{
return strncpy_from_unsafe_user(dst, unsafe_addr, count);
}
#else
// Copied from: https://elixir.bootlin.com/linux/v4.9.337/source/mm/maccess.c#L201
long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
long count)
{
mm_segment_t old_fs = get_fs();
long ret;

if (unlikely(count <= 0))
return 0;

set_fs(USER_DS);
pagefault_disable();
ret = strncpy_from_user(dst, unsafe_addr, count);
pagefault_enable();
set_fs(old_fs);

if (ret >= count) {
ret = count;
dst[ret - 1] = '\0';
} else if (ret > 0) {
ret++;
}

return ret;
}
#endif
4 changes: 4 additions & 0 deletions kernel/kernel_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ extern long ksu_strncpy_from_user_nofault(char *dst,
const void __user *unsafe_addr,
long count);

#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI)
extern struct key *init_session_keyring;
#endif

extern void ksu_android_ns_fs_check();
extern struct file *ksu_filp_open_compat(const char *filename, int flags,
umode_t mode);
Expand Down
3 changes: 3 additions & 0 deletions kernel/ksu.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,7 @@ module_exit(kernelsu_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("weishu");
MODULE_DESCRIPTION("Android KernelSU");

#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver);
#endif
Loading

0 comments on commit 28bb1d0

Please sign in to comment.