kernel: don't use 0(root uid) as manager init uid
This commit is contained in:
@@ -233,7 +233,7 @@ exit:
|
|||||||
filp_close(fp, 0);
|
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 *np = NULL;
|
||||||
struct perm_data *n = NULL;
|
struct perm_data *n = NULL;
|
||||||
|
|||||||
63
kernel/ksu.c
63
kernel/ksu.c
@@ -1,50 +1,38 @@
|
|||||||
|
#include <asm-generic/errno-base.h>
|
||||||
|
#include <linux/cpu.h>
|
||||||
#include <linux/cred.h>
|
#include <linux/cred.h>
|
||||||
#include <linux/gfp.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/init.h>
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/kprobes.h>
|
|
||||||
#include <linux/printk.h>
|
|
||||||
#include <linux/string.h>
|
|
||||||
#include <linux/kernel.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 <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/fdtable.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/fs_struct.h>
|
#include <linux/fs_struct.h>
|
||||||
#include <linux/namei.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 "allowlist.h"
|
||||||
|
#include "apk_sign.h"
|
||||||
#include "arch.h"
|
#include "arch.h"
|
||||||
|
#include "klog.h"
|
||||||
|
#include "ksu.h"
|
||||||
|
#include "selinux/selinux.h"
|
||||||
#include "uid_observer.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) };
|
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()
|
void escape_to_root()
|
||||||
{
|
{
|
||||||
@@ -66,7 +54,8 @@ void escape_to_root()
|
|||||||
memset(&cred->cap_ambient, 0xff, sizeof(cred->cap_ambient));
|
memset(&cred->cap_ambient, 0xff, sizeof(cred->cap_ambient));
|
||||||
|
|
||||||
// disable seccomp
|
// 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;
|
current_thread_info()->syscall_work &= ~SYSCALL_WORK_SECCOMP;
|
||||||
#else
|
#else
|
||||||
current_thread_info()->flags &= ~(TIF_SECCOMP | _TIF_SECCOMP);
|
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);
|
return strcmp(s + slen - tlen, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool is_manager()
|
static bool is_manager()
|
||||||
{
|
{
|
||||||
return ksu_manager_uid == current_uid().val;
|
return ksu_manager_uid == current_uid().val;
|
||||||
@@ -109,13 +97,14 @@ static bool become_manager(char *pkg)
|
|||||||
char *buf;
|
char *buf;
|
||||||
bool result = false;
|
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) {
|
if (task_uid(current->real_parent).val != 0) {
|
||||||
pr_info("parent is not zygote!\n");
|
pr_info("parent is not zygote!\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ksu_manager_uid != 0) {
|
if (ksu_is_manager_uid_valid()) {
|
||||||
pr_info("manager already exist: %d\n", ksu_manager_uid);
|
pr_info("manager already exist: %d\n", ksu_manager_uid);
|
||||||
return is_manager();
|
return is_manager();
|
||||||
}
|
}
|
||||||
@@ -150,7 +139,7 @@ static bool become_manager(char *pkg)
|
|||||||
uid_t uid = current_uid().val;
|
uid_t uid = current_uid().val;
|
||||||
pr_info("manager uid: %d\n", uid);
|
pr_info("manager uid: %d\n", uid);
|
||||||
|
|
||||||
ksu_manager_uid = uid;
|
ksu_set_manager_uid(uid);
|
||||||
|
|
||||||
result = true;
|
result = true;
|
||||||
goto clean;
|
goto clean;
|
||||||
@@ -259,12 +248,11 @@ static int handler_pre(struct kprobe *p, struct pt_regs *regs)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Both root manager and root processes should be allowed to get version
|
// Both root manager and root processes should be allowed to get version
|
||||||
if (arg2 == CMD_GET_VERSION) {
|
if (arg2 == CMD_GET_VERSION) {
|
||||||
if (is_manager() || 0 == current_uid().val) {
|
if (is_manager() || 0 == current_uid().val) {
|
||||||
u32 version = KERNEL_SU_VERSION;
|
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);
|
pr_err("prctl reply error, cmd: %d\n", arg2);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -361,5 +349,6 @@ MODULE_AUTHOR("weishu");
|
|||||||
MODULE_DESCRIPTION("Android GKI KernelSU");
|
MODULE_DESCRIPTION("Android GKI KernelSU");
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
|
#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
|
#endif
|
||||||
|
|||||||
38
kernel/ksu.h
Normal file
38
kernel/ksu.h
Normal 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
|
||||||
@@ -15,12 +15,11 @@
|
|||||||
#include "allowlist.h"
|
#include "allowlist.h"
|
||||||
#include "arch.h"
|
#include "arch.h"
|
||||||
#include "klog.h"
|
#include "klog.h"
|
||||||
|
#include "ksu.h"
|
||||||
|
|
||||||
#define SYSTEM_PACKAGES_LIST_PATH "/data/system/packages.list"
|
#define SYSTEM_PACKAGES_LIST_PATH "/data/system/packages.list"
|
||||||
static struct work_struct ksu_update_uid_work;
|
static struct work_struct ksu_update_uid_work;
|
||||||
|
|
||||||
extern uid_t ksu_manager_uid;
|
|
||||||
|
|
||||||
struct uid_data {
|
struct uid_data {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
u32 uid;
|
u32 uid;
|
||||||
@@ -100,15 +99,15 @@ static void do_update_uid(struct work_struct *work)
|
|||||||
// first, check if manager_uid exist!
|
// first, check if manager_uid exist!
|
||||||
bool manager_exist = false;
|
bool manager_exist = false;
|
||||||
list_for_each_entry (np, &uid_list, list) {
|
list_for_each_entry (np, &uid_list, list) {
|
||||||
if (np->uid == ksu_manager_uid) {
|
if (np->uid == ksu_get_manager_uid()) {
|
||||||
manager_exist = true;
|
manager_exist = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!manager_exist) {
|
if (!manager_exist && ksu_is_manager_uid_valid()) {
|
||||||
pr_info("manager is uninstalled, reset it!\n");
|
pr_info("manager is uninstalled, invalidate it!\n");
|
||||||
ksu_manager_uid = 0;
|
ksu_invalidate_manager_uid();
|
||||||
}
|
}
|
||||||
|
|
||||||
// then prune the allowlist
|
// then prune the allowlist
|
||||||
|
|||||||
Reference in New Issue
Block a user