kernel: improve manager validation
This commit is contained in:
40
kernel/ksu.c
40
kernel/ksu.c
@@ -25,7 +25,7 @@
|
|||||||
#include "allowlist.h"
|
#include "allowlist.h"
|
||||||
#include "arch.h"
|
#include "arch.h"
|
||||||
|
|
||||||
#define KERNEL_SU_VERSION 5
|
#define KERNEL_SU_VERSION 6
|
||||||
|
|
||||||
#define KERNEL_SU_OPTION 0xDEADBEEF
|
#define KERNEL_SU_OPTION 0xDEADBEEF
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ static bool is_manager() {
|
|||||||
return __manager_uid == current_uid().val;
|
return __manager_uid == current_uid().val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool become_manager() {
|
static bool become_manager(char* pkg) {
|
||||||
struct fdtable *files_table;
|
struct fdtable *files_table;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
struct path files_path;
|
struct path files_path;
|
||||||
@@ -124,6 +124,11 @@ static bool become_manager() {
|
|||||||
if (startswith(cwd, "/data/app/") == 0 && endswith(cwd, "/base.apk") == 0) {
|
if (startswith(cwd, "/data/app/") == 0 && endswith(cwd, "/base.apk") == 0) {
|
||||||
// we have found the apk!
|
// we have found the apk!
|
||||||
pr_info("found apk: %s", cwd);
|
pr_info("found apk: %s", cwd);
|
||||||
|
if (!strstr(cwd, pkg)) {
|
||||||
|
pr_info("apk path not match package name!\n");
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (is_manager_apk(cwd) == 0) {
|
if (is_manager_apk(cwd) == 0) {
|
||||||
// check passed
|
// check passed
|
||||||
uid_t uid = current_uid().val;
|
uid_t uid = current_uid().val;
|
||||||
@@ -180,10 +185,37 @@ static int handler_pre(struct kprobe *p, struct pt_regs *regs) {
|
|||||||
|
|
||||||
if (arg2 == CMD_BECOME_MANAGER) {
|
if (arg2 == CMD_BECOME_MANAGER) {
|
||||||
// someone wants to be root manager, just check it!
|
// someone wants to be root manager, just check it!
|
||||||
bool success = become_manager();
|
// arg3 should be `/data/data/<manager_package_name>`
|
||||||
|
char param[128];
|
||||||
|
const char* prefix = "/data/data/";
|
||||||
|
if (copy_from_user(param, arg3, sizeof(param))) {
|
||||||
|
pr_err("become_manager: copy param err\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startswith(param, (char*) prefix) != 0) {
|
||||||
|
pr_info("become_manager: invalid param: %s\n", param);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// stat the param, app must have permission to do this
|
||||||
|
// otherwise it may fake the path!
|
||||||
|
struct path path;
|
||||||
|
if (kern_path(param, LOOKUP_DIRECTORY, &path)) {
|
||||||
|
pr_err("become_manager: kern_path err\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (path.dentry->d_inode->i_uid.val != current_uid().val) {
|
||||||
|
pr_err("become_manager: path uid != current uid\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
char* pkg = param + strlen(prefix);
|
||||||
|
pr_info("become_manager: param pkg: %s\n", pkg);
|
||||||
|
|
||||||
|
bool success = become_manager(pkg);
|
||||||
if (success) {
|
if (success) {
|
||||||
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
|
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
|
||||||
pr_err("prctl reply error\n");
|
pr_err("become_manager: prctl reply error\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user