kernel: add uid observer, correctly prune uid allowlist when app is installed/uninstalled.

This commit is contained in:
weishu
2023-01-17 12:44:22 +07:00
parent 2ab60750d4
commit ab36e1fa0c
7 changed files with 256 additions and 10 deletions

View File

@@ -1,3 +1,4 @@
#include <linux/list.h>
#include <linux/cpu.h>
#include <linux/errno.h>
#include <linux/init.h>
@@ -25,6 +26,8 @@
#define FILE_MAGIC 0x7f4b5355 // ' KSU', u32
#define FILE_FORMAT_VERSION 1 // u32
static DEFINE_MUTEX(allowlist_mutex);
struct perm_data {
struct list_head list;
uid_t uid;
@@ -137,7 +140,7 @@ void do_persistent_allow_list(struct work_struct *work)
}
if (kernel_write(fp, &version, sizeof(version), &off) !=
sizeof(version)) {
sizeof(version)) {
pr_err("save_allow_list write version failed.\n");
goto exit;
}
@@ -186,7 +189,8 @@ void do_load_allow_list(struct work_struct *work)
if (errno == -ENOENT) {
ksu_allow_uid(2000, true); // allow adb shell by default
} else {
pr_err("load_allow_list open file failed: %d\n", PTR_ERR(fp));
pr_err("load_allow_list open file failed: %d\n",
PTR_ERR(fp));
}
#else
pr_err("load_allow_list open file failed: %d\n", PTR_ERR(fp));
@@ -196,13 +200,13 @@ void do_load_allow_list(struct work_struct *work)
// verify magic
if (kernel_read(fp, &magic, sizeof(magic), &off) != sizeof(magic) ||
magic != FILE_MAGIC) {
magic != FILE_MAGIC) {
pr_err("allowlist file invalid: %d!\n", magic);
goto exit;
}
if (kernel_read(fp, &version, sizeof(version), &off) !=
sizeof(version)) {
sizeof(version)) {
pr_err("allowlist read version: %d failed\n", version);
goto exit;
}
@@ -229,6 +233,30 @@ exit:
filp_close(fp, 0);
}
void ksu_prune_allowlist(bool (*is_uid_exist)(uid_t, void *), void* data)
{
struct perm_data *np = NULL;
struct perm_data *n = NULL;
bool modified = false;
// TODO: use RCU!
mutex_lock(&allowlist_mutex);
list_for_each_entry_safe (np, n, &allow_list, list) {
uid_t uid = np->uid;
if (!is_uid_exist(uid, data)) {
modified = true;
pr_info("prune uid: %d\n", uid);
list_del(&np->list);
kfree(np);
}
}
mutex_unlock(&allowlist_mutex);
if (modified) {
persistent_allow_list();
}
}
static int init_work(void)
{
ksu_workqueue = alloc_workqueue("kernelsu_work_queue", 0, 0);