From 076e5d3655c9eecd30493ea6561ec2371b937e9e Mon Sep 17 00:00:00 2001 From: weishu Date: Sun, 4 Jun 2023 17:28:56 +0800 Subject: [PATCH] kernel: make the profile uid, gid, capabilities really work --- kernel/allowlist.c | 20 +++++++++++++++++++- kernel/allowlist.h | 3 ++- kernel/core_hook.c | 45 +++++++++++++++++++++++++++------------------ kernel/ksu.h | 5 ++--- 4 files changed, 50 insertions(+), 23 deletions(-) diff --git a/kernel/allowlist.c b/kernel/allowlist.c index 87669e32..e281f341 100644 --- a/kernel/allowlist.c +++ b/kernel/allowlist.c @@ -181,7 +181,7 @@ bool ksu_is_allow_uid(uid_t uid) return false; } -bool ksu_is_uid_should_umount(uid_t uid) +bool ksu_uid_should_umount(uid_t uid) { struct app_profile profile = { .current_uid = uid }; bool found = ksu_get_app_profile(&profile); @@ -202,6 +202,24 @@ bool ksu_is_uid_should_umount(uid_t uid) } } +struct root_profile *ksu_get_root_profile(uid_t uid) +{ + struct perm_data *p = NULL; + struct list_head *pos = NULL; + + list_for_each (pos, &allow_list) { + p = list_entry(pos, struct perm_data, list); + if (uid == p->profile.current_uid && p->profile.allow_su) { + if (!p->profile.rp_config.use_default) { + return &p->profile.rp_config.profile; + } + } + } + + // use default profile + return &default_root_profile; +} + bool ksu_get_allow_list(int *array, int *length, bool allow) { struct perm_data *p = NULL; diff --git a/kernel/allowlist.h b/kernel/allowlist.h index 1ff2b907..63332268 100644 --- a/kernel/allowlist.h +++ b/kernel/allowlist.h @@ -21,5 +21,6 @@ void ksu_prune_allowlist(bool (*is_uid_exist)(uid_t, void *), void *data); bool ksu_get_app_profile(struct app_profile *); bool ksu_set_app_profile(struct app_profile *, bool persist); -bool ksu_is_uid_should_umount(uid_t uid); +bool ksu_uid_should_umount(uid_t uid); +struct root_profile *ksu_get_root_profile(uid_t uid); #endif \ No newline at end of file diff --git a/kernel/core_hook.c b/kernel/core_hook.c index 5564ebcc..20b4eb40 100644 --- a/kernel/core_hook.c +++ b/kernel/core_hook.c @@ -1,3 +1,4 @@ +#include "linux/capability.h" #include "linux/cred.h" #include "linux/dcache.h" #include "linux/err.h" @@ -59,18 +60,26 @@ void escape_to_root(void) cred = (struct cred *)__task_cred(current); - memset(&cred->uid, 0, sizeof(cred->uid)); - memset(&cred->gid, 0, sizeof(cred->gid)); - memset(&cred->suid, 0, sizeof(cred->suid)); - memset(&cred->euid, 0, sizeof(cred->euid)); - memset(&cred->egid, 0, sizeof(cred->egid)); - memset(&cred->fsuid, 0, sizeof(cred->fsuid)); - memset(&cred->fsgid, 0, sizeof(cred->fsgid)); - memset(&cred->cap_inheritable, 0xff, sizeof(cred->cap_inheritable)); - memset(&cred->cap_permitted, 0xff, sizeof(cred->cap_permitted)); - memset(&cred->cap_effective, 0xff, sizeof(cred->cap_effective)); - memset(&cred->cap_bset, 0xff, sizeof(cred->cap_bset)); - memset(&cred->cap_ambient, 0xff, sizeof(cred->cap_ambient)); + struct root_profile *profile = ksu_get_root_profile(cred->uid.val); + + cred->uid.val = profile->uid; + cred->suid.val = profile->uid; + cred->euid.val = profile->uid; + cred->fsuid.val = profile->uid; + + cred->gid.val = profile->gid; + cred->fsgid.val = profile->gid; + cred->sgid.val = profile->gid; + cred->egid.val = profile->gid; + + BUILD_BUG_ON(sizeof(profile->capabilities.effective) != sizeof(kernel_cap_t)); + + // capabilities + memcpy(&cred->cap_effective, &profile->capabilities.effective, sizeof(cred->cap_effective)); + memcpy(&cred->cap_inheritable, &profile->capabilities.effective, sizeof(cred->cap_inheritable)); + memcpy(&cred->cap_permitted, &profile->capabilities.effective, sizeof(cred->cap_permitted)); + memcpy(&cred->cap_bset, &profile->capabilities.effective, sizeof(cred->cap_bset)); + memcpy(&cred->cap_ambient, &profile->capabilities.effective, sizeof(cred->cap_ambient)); // disable seccomp #if defined(CONFIG_GENERIC_ENTRY) && \ @@ -322,15 +331,15 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3, return 0; } - if (arg2 == CMD_IS_UID_GRANTED_ROOT || - arg2 == CMD_IS_UID_SHOULD_UMOUNT) { + if (arg2 == CMD_UID_GRANTED_ROOT || + arg2 == CMD_UID_SHOULD_UMOUNT) { if (is_manager() || 0 == current_uid().val) { uid_t target_uid = (uid_t)arg3; bool allow = false; - if (arg2 == CMD_IS_UID_GRANTED_ROOT) { + if (arg2 == CMD_UID_GRANTED_ROOT) { allow = ksu_is_allow_uid(target_uid); - } else if (arg2 == CMD_IS_UID_SHOULD_UMOUNT) { - allow = ksu_is_uid_should_umount(target_uid); + } else if (arg2 == CMD_UID_SHOULD_UMOUNT) { + allow = ksu_uid_should_umount(target_uid); } else { pr_err("unknown cmd: %d\n", arg2); } @@ -418,7 +427,7 @@ static bool should_umount(struct path *path) if (path->mnt && path->mnt->mnt_sb && path->mnt->mnt_sb->s_type) { const char *fstype = path->mnt->mnt_sb->s_type->name; if (strcmp(fstype, "overlay") == 0) { - return ksu_is_uid_should_umount(current_uid().val); + return ksu_uid_should_umount(current_uid().val); } #ifdef CONFIG_KSU_DEBUG pr_info("uid: %d should not umount!\n", current_uid().val); diff --git a/kernel/ksu.h b/kernel/ksu.h index 98f44d9d..e4191ea9 100644 --- a/kernel/ksu.h +++ b/kernel/ksu.h @@ -1,7 +1,6 @@ #ifndef __KSU_H_KSU #define __KSU_H_KSU -#include "linux/capability.h" #include "linux/types.h" #include "linux/workqueue.h" @@ -29,8 +28,8 @@ #define CMD_CHECK_SAFEMODE 9 #define CMD_GET_APP_PROFILE 10 #define CMD_SET_APP_PROFILE 11 -#define CMD_IS_UID_GRANTED_ROOT 12 -#define CMD_IS_UID_SHOULD_UMOUNT 13 +#define CMD_UID_GRANTED_ROOT 12 +#define CMD_UID_SHOULD_UMOUNT 13 #define EVENT_POST_FS_DATA 1 #define EVENT_BOOT_COMPLETED 2