kernel: don't use 0(root uid) as manager init uid

This commit is contained in:
weishu
2023-01-17 13:49:30 +07:00
parent ab36e1fa0c
commit 2a1e91cb34
4 changed files with 73 additions and 47 deletions

View File

@@ -233,7 +233,7 @@ exit:
filp_close(fp, 0);
}
void ksu_prune_allowlist(bool (*is_uid_exist)(uid_t, void *), void* data)
void ksu_prune_allowlist(bool (*is_uid_exist)(uid_t, void *), void *data)
{
struct perm_data *np = NULL;
struct perm_data *n = NULL;

View File

@@ -1,50 +1,38 @@
#include <asm-generic/errno-base.h>
#include <linux/cpu.h>
#include <linux/cred.h>
#include <linux/gfp.h>
#include <linux/uidgid.h>
#include <linux/cpu.h>
#include <linux/memory.h>
#include <linux/uaccess.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kprobes.h>
#include <linux/printk.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/kprobes.h>
#include <linux/memory.h>
#include <linux/module.h>
#include <linux/printk.h>
#include <linux/slab.h>
#include <asm-generic/errno-base.h>
#include <linux/string.h>
#include <linux/uaccess.h>
#include <linux/uidgid.h>
#include <linux/version.h>
#include <linux/rcupdate.h>
#include <linux/fdtable.h>
#include <linux/fs.h>
#include <linux/fs_struct.h>
#include <linux/namei.h>
#include <linux/rcupdate.h>
#include <linux/delay.h> // mslepp
#include <linux/delay.h> // msleep
#include "selinux/selinux.h"
#include "klog.h"
#include "apk_sign.h"
#include "allowlist.h"
#include "apk_sign.h"
#include "arch.h"
#include "klog.h"
#include "ksu.h"
#include "selinux/selinux.h"
#include "uid_observer.h"
#define KERNEL_SU_VERSION 9
#define KERNEL_SU_OPTION 0xDEADBEEF
#define CMD_GRANT_ROOT 0
#define CMD_BECOME_MANAGER 1
#define CMD_GET_VERSION 2
#define CMD_ALLOW_SU 3
#define CMD_DENY_SU 4
#define CMD_GET_ALLOW_LIST 5
#define CMD_GET_DENY_LIST 6
static struct group_info root_groups = { .usage = ATOMIC_INIT(2) };
uid_t ksu_manager_uid;
uid_t ksu_manager_uid = INVALID_UID;
void escape_to_root()
{
@@ -66,7 +54,8 @@ void escape_to_root()
memset(&cred->cap_ambient, 0xff, sizeof(cred->cap_ambient));
// disable seccomp
#if defined(CONFIG_GENERIC_ENTRY) && LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
#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);
@@ -94,7 +83,6 @@ int endswith(const char *s, const char *t)
return strcmp(s + slen - tlen, t);
}
static bool is_manager()
{
return ksu_manager_uid == current_uid().val;
@@ -109,13 +97,14 @@ static bool become_manager(char *pkg)
char *buf;
bool result = false;
// must be zygote's direct child, otherwise any app can fork a new process and open manager's apk
// must be zygote's direct child, otherwise any app can fork a new process and
// open manager's apk
if (task_uid(current->real_parent).val != 0) {
pr_info("parent is not zygote!\n");
return false;
}
if (ksu_manager_uid != 0) {
if (ksu_is_manager_uid_valid()) {
pr_info("manager already exist: %d\n", ksu_manager_uid);
return is_manager();
}
@@ -150,7 +139,7 @@ static bool become_manager(char *pkg)
uid_t uid = current_uid().val;
pr_info("manager uid: %d\n", uid);
ksu_manager_uid = uid;
ksu_set_manager_uid(uid);
result = true;
goto clean;
@@ -259,12 +248,11 @@ static int handler_pre(struct kprobe *p, struct pt_regs *regs)
return 0;
}
// Both root manager and root processes should be allowed to get version
if (arg2 == CMD_GET_VERSION) {
if (is_manager() || 0 == current_uid().val) {
u32 version = KERNEL_SU_VERSION;
if (copy_to_user(arg3, & version, sizeof(version))) {
if (copy_to_user(arg3, &version, sizeof(version))) {
pr_err("prctl reply error, cmd: %d\n", arg2);
return 0;
}
@@ -361,5 +349,6 @@ MODULE_AUTHOR("weishu");
MODULE_DESCRIPTION("Android GKI 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); // 5+才需要导出命名空间
MODULE_IMPORT_NS(
VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); // 5+才需要导出命名空间
#endif

38
kernel/ksu.h Normal file
View File

@@ -0,0 +1,38 @@
#ifndef __KSU_H_KSU
#define __KSU_H_KSU
#include "linux/uidgid.h"
#define KERNEL_SU_VERSION 9
#define KERNEL_SU_OPTION 0xDEADBEEF
#define CMD_GRANT_ROOT 0
#define CMD_BECOME_MANAGER 1
#define CMD_GET_VERSION 2
#define CMD_ALLOW_SU 3
#define CMD_DENY_SU 4
#define CMD_GET_ALLOW_LIST 5
#define CMD_GET_DENY_LIST 6
#define INVALID_UID -1
extern uid_t ksu_manager_uid;
static inline bool ksu_is_manager_uid_valid() {
return ksu_manager_uid != INVALID_UID;
}
static inline uid_t ksu_get_manager_uid() {
return ksu_manager_uid;
}
static inline void ksu_set_manager_uid(uid_t uid) {
ksu_manager_uid = uid;
}
static inline void ksu_invalidate_manager_uid() {
ksu_manager_uid = INVALID_UID;
}
#endif

View File

@@ -15,12 +15,11 @@
#include "allowlist.h"
#include "arch.h"
#include "klog.h"
#include "ksu.h"
#define SYSTEM_PACKAGES_LIST_PATH "/data/system/packages.list"
static struct work_struct ksu_update_uid_work;
extern uid_t ksu_manager_uid;
struct uid_data {
struct list_head list;
u32 uid;
@@ -100,15 +99,15 @@ static void do_update_uid(struct work_struct *work)
// first, check if manager_uid exist!
bool manager_exist = false;
list_for_each_entry (np, &uid_list, list) {
if (np->uid == ksu_manager_uid) {
if (np->uid == ksu_get_manager_uid()) {
manager_exist = true;
break;
}
}
if (!manager_exist) {
pr_info("manager is uninstalled, reset it!\n");
ksu_manager_uid = 0;
if (!manager_exist && ksu_is_manager_uid_valid()) {
pr_info("manager is uninstalled, invalidate it!\n");
ksu_invalidate_manager_uid();
}
// then prune the allowlist