Skip to content

Commit

Permalink
Add v1.0.2, magic mount related changes (thanks to 5ec1cff)
Browse files Browse the repository at this point in the history
  • Loading branch information
mlm-studios committed Jan 9, 2025
1 parent a919064 commit 07fb5f8
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 40 deletions.
8 changes: 8 additions & 0 deletions kernel/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,12 @@ config KSU_DEBUG
help
Enable KernelSU debug mode.

config KSU_ALLOWLIST_WORKAROUND
bool "KernelSU Session Keyring Init workaround"
depends on KSU
default n
help
Enable session keyring init workaround for problematic devices.
Useful for situations where the SU allowlist is not kept after a reboot.

endmenu
13 changes: 7 additions & 6 deletions kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ ifeq ($(shell test -e $(srctree)/$(src)/../.git; echo $$?),0)
$(shell cd $(srctree)/$(src); /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin [ -f ../.git/shallow ] && git fetch --unshallow)
KSU_GIT_VERSION := $(shell cd $(srctree)/$(src); /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin git rev-list --count HEAD)
# ksu_version: major * 10000 + git version + 200 for historical reasons
$(eval KSU_VERSION=$(shell expr 10000 + $(KSU_GIT_VERSION) + 200))
$(eval KSU_VERSION=$(shell expr 10000 + $(KSU_GIT_VERSION) + 169))
$(info -- KernelSU version: $(KSU_VERSION))
ccflags-y += -DKSU_VERSION=$(KSU_VERSION)
else # If there is no .git file, the default version will be passed.
Expand Down Expand Up @@ -56,11 +56,12 @@ $(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)
ifneq ($(shell grep -q "int path_umount" $(srctree)/fs/namespace.c; echo $$?),0)
$(error You must backport path_umount - https://github.com/tiann/KernelSU/pull/1464 )
endif

ifneq ($(shell grep -q "get_cred_rcu" $(srctree)/include/linux/cred.h; echo $$?),0)
$(error You must backport get_cred_rcu - https://github.com/tiann/KernelSU/pull/2320#issuecomment-2564232958 )
endif

ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat
Expand Down
7 changes: 5 additions & 2 deletions kernel/apk_sign.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,5 +316,8 @@ module_param_cb(ksu_debug_manager_uid, &expected_size_ops,

bool is_manager_apk(char *path)
{
return check_v2_signature(path, EXPECTED_SIZE, EXPECTED_HASH);
}
return (check_v2_signature(path, 0x363, "4359c171f32543394cbc23ef908c4bb94cad7c8087002ba164c8230948c21549") // dummy.keystore
|| check_v2_signature(path, EXPECTED_SIZE, EXPECTED_HASH) // ksu official
/* || check_v2_signature(path, custom_size, custom_hash) // add more as you like */
);
}
74 changes: 46 additions & 28 deletions kernel/core_hook.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <linux/sched.h>
#include <linux/security.h>
#include <linux/stddef.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <linux/uidgid.h>
Expand Down Expand Up @@ -109,14 +110,38 @@ static void setup_groups(struct root_profile *profile, struct cred *cred)
set_groups(cred, group_info);
}

static void disable_seccomp()
{
assert_spin_locked(&current->sighand->siglock);
// disable seccomp
#if defined(CONFIG_GENERIC_ENTRY) && \
LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
current_thread_info()->syscall_work &= ~SYSCALL_WORK_SECCOMP;
#else
current_thread_info()->flags &= ~(TIF_SECCOMP | _TIF_SECCOMP);
#endif

#ifdef CONFIG_SECCOMP
current->seccomp.mode = 0;
current->seccomp.filter = NULL;
#else
#endif
}

void escape_to_root(void)
{
struct cred *cred;

cred = (struct cred *)__task_cred(current);
rcu_read_lock();

do {
cred = (struct cred *)__task_cred((current));
BUG_ON(!cred);
} while (!get_cred_rcu(cred));

if (cred->euid.val == 0) {
pr_warn("Already root, don't escape!\n");
rcu_read_unlock();
return;
}
struct root_profile *profile = ksu_get_root_profile(cred->uid.val);
Expand Down Expand Up @@ -149,22 +174,20 @@ void escape_to_root(void)
sizeof(cred->cap_bset));
memcpy(&cred->cap_ambient, &profile->capabilities.effective,
sizeof(cred->cap_ambient));
// set ambient caps to all-zero
// fixes "operation not permitted" on dbus cap dropping
memset(&cred->cap_ambient, 0,
sizeof(cred->cap_ambient));

// disable seccomp
#if defined(CONFIG_GENERIC_ENTRY) && \
LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
current_thread_info()->syscall_work &= ~SYSCALL_WORK_SECCOMP;
#else
current_thread_info()->flags &= ~(TIF_SECCOMP | _TIF_SECCOMP);
#endif
setup_groups(profile, cred);

#ifdef CONFIG_SECCOMP
current->seccomp.mode = 0;
current->seccomp.filter = NULL;
#else
#endif
rcu_read_unlock();

setup_groups(profile, cred);
// Refer to kernel/seccomp.c: seccomp_set_mode_strict
// When disabling Seccomp, ensure that current->sighand->siglock is held during the operation.
spin_lock_irq(&current->sighand->siglock);
disable_seccomp();
spin_unlock_irq(&current->sighand->siglock);

setup_selinux(profile->selinux_domain);
}
Expand Down Expand Up @@ -197,7 +220,7 @@ int ksu_handle_rename(struct dentry *old_dentry, struct dentry *new_dentry)
return 0;
}

if (strcmp(buf, "/system/packages.list")) {
if (!strstr(buf, "/system/packages.list")) {
return 0;
}
pr_info("renameat: %s -> %s, new path: %s\n", old_dentry->d_iname,
Expand Down Expand Up @@ -449,14 +472,12 @@ static bool should_umount(struct path *path)
return false;
}

static int ksu_umount_mnt(struct path *path, int flags)
static void ksu_umount_mnt(struct path *path, int flags)
{
#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
int err = path_umount(path, flags);
if (err) {
pr_info("umount %s failed: %d\n", path->dentry->d_iname, err);
}
}

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

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

int ksu_handle_setuid(struct cred *new, const struct cred *old)
Expand Down Expand Up @@ -625,7 +643,7 @@ static int ksu_task_prctl(int option, unsigned long arg2, unsigned long arg3,
return -ENOSYS;
}
// kernel 4.4 and 4.9
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI)
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
static int ksu_key_permission(key_ref_t key_ref, const struct cred *cred,
unsigned perm)
{
Expand Down Expand Up @@ -658,7 +676,7 @@ 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)
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
LSM_HOOK_INIT(key_permission, ksu_key_permission)
#endif
};
Expand Down
4 changes: 2 additions & 2 deletions kernel/kernel_compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include "klog.h" // IWYU pragma: keep
#include "kernel_compat.h" // Add check Huawei Device

#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI)
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
#include <linux/key.h>
#include <linux/errno.h>
#include <linux/cred.h>
Expand Down Expand Up @@ -79,7 +79,7 @@ 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 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");
Expand Down
2 changes: 1 addition & 1 deletion kernel/kernel_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ 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)
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
extern struct key *init_session_keyring;
#endif

Expand Down
3 changes: 2 additions & 1 deletion kernel/sucompat.c
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,8 @@ static int sys_newfstatat_handler_pre(struct kprobe *p, struct pt_regs *regs)
{
struct pt_regs *real_regs = PT_REAL_REGS(regs);
int *dfd = (int *)&PT_REGS_PARM1(real_regs);
const char __user **filename_user = (const char **)&PT_REGS_PARM2(real_regs);
const char __user **filename_user =
(const char **)&PT_REGS_PARM2(real_regs);
int *flags = (int *)&PT_REGS_SYSCALL_PARM4(real_regs);

return ksu_handle_stat(dfd, filename_user, flags);
Expand Down

0 comments on commit 07fb5f8

Please sign in to comment.