Store hidelist in magisk database

This commit is contained in:
topjohnwu 2018-11-01 13:23:12 -04:00
parent 3e2afd4b1d
commit 27c688252d
13 changed files with 209 additions and 148 deletions

View File

@ -40,9 +40,9 @@ LOCAL_SRC_FILES := \
daemon/bootstages.c \
daemon/socket.c \
daemon/db.c \
magiskhide/magiskhide.c \
magiskhide/proc_monitor.c \
magiskhide/hide_utils.c \
magiskhide/magiskhide.cpp \
magiskhide/proc_monitor.cpp \
magiskhide/hide_utils.cpp \
resetprop/persist_properties.c \
resetprop/resetprop.c \
resetprop/system_property_api.cpp \

View File

@ -8,7 +8,7 @@
#include "magisk.h"
#include "db.h"
#define DB_VERSION 6
#define DB_VERSION 7
static int ver_cb(void *v, int col_num, char **data, char **col_name) {
*((int *) v) = atoi(data[0]);
@ -79,6 +79,16 @@ static sqlite3 *open_and_init_db() {
ver = 6;
upgrade = 1;
}
if (ver == 5 || ver == 6) {
// Hide list
sqlite3_exec(db,
"CREATE TABLE IF NOT EXISTS hidelist "
"(process TEXT, PRIMARY KEY(process))",
NULL, NULL, &err);
err_abort(err);
ver = 7;
upgrade =1 ;
}
if (upgrade) {
// Set version

View File

@ -8,6 +8,10 @@
#include <sys/un.h>
#include <sys/socket.h>
#ifdef __cplusplus
extern "C" {
#endif
extern int setup_done;
extern int seperate_vendor;
@ -95,4 +99,8 @@ void ls_hide_list(int client);
void su_daemon_handler(int client, struct ucred *credential);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -4,12 +4,16 @@
#include <sqlite3.h>
#include <sys/stat.h>
#ifdef __cplusplus
extern "C" {
#endif
/***************
* DB Settings *
***************/
#define DB_SETTING_KEYS \
((char *[]) { \
((const char *[]) { \
"root_access", \
"multiuser_mode", \
"mnt_ns" \
@ -62,7 +66,7 @@ NAMESPACE_MODE_REQUESTER, \
**************/
#define DB_STRING_KEYS \
((char *[]) { \
((const char *[]) { \
"requester", \
})
@ -122,4 +126,8 @@ int get_uid_policy(sqlite3 *db, int uid, struct su_access *su);
int validate_manager(char *alt_pkg, int userid, struct stat *st);
int exec_sql(const char *sql);
#ifdef __cplusplus
}
#endif
#endif //DB_H

View File

@ -6,6 +6,10 @@
#include "logging.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MAIN_SOCKET "d30138f2310a9fb9c54a3e0c21f58591"
#define LOG_SOCKET "5864cd77f2f8c59b3882e2d35dbf51e4"
#define JAVA_PACKAGE_NAME "com.topjohnwu.magisk"
@ -19,7 +23,6 @@
#define MOUNTPOINT MAGISKTMP "/img"
#define COREDIR MOUNTPOINT "/.core"
#define HOSTSFILE COREDIR "/hosts"
#define HIDELIST COREDIR "/hidelist"
#define SECURE_DIR "/data/adb"
#define MAINIMG SECURE_DIR "/magisk.img"
#define DATABIN SECURE_DIR "/magisk"
@ -55,4 +58,8 @@ int su_client_main(int argc, char *argv[]);
int resetprop_main(int argc, char *argv[]);
int imgtool_main(int argc, char *argv[]);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -4,6 +4,10 @@
#ifndef _RESETPROP_H_
#define _RESETPROP_H_
#ifdef __cplusplus
extern "C" {
#endif
int prop_exist(const char *name);
int setprop(const char *name, const char *value);
int setprop2(const char *name, const char *value, const int trigger);
@ -14,4 +18,8 @@ int deleteprop2(const char *name, const int persist);
int read_prop_file(const char* filename, const int trigger);
void getprop_all(void (*callback)(const char *, const char *, void *), void *cookie);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,6 +1,3 @@
/* hide_utils.c - Some utility functions for MagiskHide
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@ -12,20 +9,23 @@
#include <sys/stat.h>
#include "magisk.h"
#include "utils.h"
#include "utils.hpp"
#include "resetprop.h"
#include "magiskhide.h"
#include "daemon.h"
#include "db.h"
static char *prop_key[] =
{ "ro.boot.vbmeta.device_state", "ro.boot.verifiedbootstate", "ro.boot.flash.locked", "ro.boot.veritymode",
"ro.boot.warranty_bit", "ro.warranty_bit", "ro.debuggable", "ro.secure",
"ro.build.type", "ro.build.tags", "ro.build.selinux", NULL };
auto hide_list = Array<char *>();
static char *prop_value[] =
{ "locked", "green", "1", "enforcing",
"0", "0", "0", "1",
"user", "release-keys", "0", NULL };
static const char *prop_key[] =
{ "ro.boot.vbmeta.device_state", "ro.boot.verifiedbootstate", "ro.boot.flash.locked",
"ro.boot.veritymode", "ro.boot.warranty_bit", "ro.warranty_bit", "ro.debuggable",
"ro.secure", "ro.build.type", "ro.build.tags", "ro.build.selinux", nullptr };
static const char *prop_value[] =
{ "locked", "green", "1",
"enforcing", "0", "0", "0",
"1", "user", "release-keys", "0", nullptr };
static const char *proc_name;
static gid_t proc_gid;
@ -57,12 +57,6 @@ void hide_sensitive_props() {
}
}
static void rm_magisk_prop(const char *name, const char *value, void *v) {
if (strstr(name, "magisk")) {
deleteprop2(name, 0);
}
}
/* Call func for each process */
static void ps(void (*func)(int)) {
DIR *dir;
@ -139,123 +133,128 @@ static void kill_process(const char *name) {
void clean_magisk_props() {
LOGD("hide_utils: Cleaning magisk props\n");
getprop_all(rm_magisk_prop, NULL);
getprop_all([] (const char *name, auto, auto) -> void
{
if (strstr(name, "magisk"))
deleteprop2(name, 0);
}, nullptr);
}
int add_list(char *proc) {
if (!hideEnabled) {
free(proc);
return HIDE_NOT_ENABLED;
}
char *line;
struct vector *new_list = xmalloc(sizeof(*new_list));
if (new_list == NULL)
return DAEMON_ERROR;
vec_init(new_list);
vec_for_each(hide_list, line) {
static int add_list(sqlite3 *db, char *proc) {
for (auto &s : hide_list) {
// They should be unique
if (strcmp(line, proc) == 0) {
if (strcmp(s, proc) == 0) {
free(proc);
vec_destroy(new_list);
free(new_list);
return HIDE_ITEM_EXIST;
}
vec_push_back(new_list, line);
}
vec_push_back(new_list, proc);
LOGI("hide_list add: [%s]\n", proc);
kill_process(proc);
// Critical region
pthread_mutex_lock(&hide_lock);
vec_destroy(hide_list);
free(hide_list);
hide_list = new_list;
pthread_mutex_unlock(&hide_lock);
pthread_mutex_lock(&list_lock);
hide_list.push_back(proc);
pthread_mutex_unlock(&list_lock);
// Add to database
char sql[128];
sprintf(sql, "INSERT INTO hidelist (process) VALUES('%s')", proc);
sqlite3_exec(db, sql, nullptr, nullptr, nullptr);
pthread_mutex_lock(&file_lock);
vector_to_file(HIDELIST, hide_list); // Do not complain if file not found
pthread_mutex_unlock(&file_lock);
return DAEMON_SUCCESS;
}
int add_list(char *proc) {
if (!hide_enabled) {
free(proc);
return HIDE_NOT_ENABLED;
}
sqlite3 *db = get_magiskdb();
if (db) {
int ret = add_list(db, proc);
sqlite3_close_v2(db);
return ret;
}
return DAEMON_ERROR;
}
int rm_list(char *proc) {
if (!hideEnabled) {
if (!hide_enabled) {
free(proc);
return HIDE_NOT_ENABLED;
}
int ret = DAEMON_ERROR;
char *line;
int do_rm = 0;
struct vector *new_list = xmalloc(sizeof(*new_list));
if (new_list == NULL)
goto error;
vec_init(new_list);
vec_for_each(hide_list, line) {
if (strcmp(line, proc) == 0) {
free(proc);
proc = line;
do_rm = 1;
continue;
// Update list in critical region
bool do_rm = false;
pthread_mutex_lock(&list_lock);
for (auto it = hide_list.begin(); it != hide_list.end(); ++it) {
if (strcmp(*it, proc) == 0) {
do_rm = true;
LOGI("hide_list rm: [%s]\n", proc);
free(*it);
hide_list.erase(it);
break;
}
vec_push_back(new_list, line);
}
pthread_mutex_unlock(&list_lock);
if (do_rm) {
LOGI("hide_list rm: [%s]\n", proc);
kill_process(proc);
// Critical region
pthread_mutex_lock(&hide_lock);
vec_destroy(hide_list);
free(hide_list);
hide_list = new_list;
pthread_mutex_unlock(&hide_lock);
sqlite3 *db = get_magiskdb();
if (db == nullptr)
goto error;
char sql[128];
sprintf(sql, "DELETE FROM hidelist WHERE process='%s'", proc);
sqlite3_exec(db, sql, nullptr, nullptr, nullptr);
sqlite3_close_v2(db);
ret = DAEMON_SUCCESS;
pthread_mutex_lock(&file_lock);
vector_to_file(HIDELIST, hide_list); // Do not complain if file not found
pthread_mutex_unlock(&file_lock);
} else {
ret = HIDE_ITEM_NOT_EXIST;
vec_destroy(new_list);
free(new_list);
}
error:
error:
free(proc);
return ret;
}
#define LEGACY_LIST MOUNTPOINT "/.core/hidelist"
int init_list() {
LOGD("hide_list: initialize...\n");
if ((hide_list = xmalloc(sizeof(*hide_list))) == NULL)
LOGD("hide_list: initialize\n");
sqlite3 *db = get_magiskdb();
if (db == nullptr)
return 1;
vec_init(hide_list);
// Might error if file doesn't exist, no need to report
file_to_vector(HIDELIST, hide_list);
sqlite3_exec(db, "SELECT process FROM hidelist",
[] (auto, auto, char **data, auto) -> int
{
LOGI("hide_list: [%s]\n", data[0]);
hide_list.push_back(strdup(data[0]));
return 0;
}, nullptr, nullptr);
char *line;
vec_for_each(hide_list, line) {
LOGI("hide_list: [%s]\n", line);
kill_process(line);
// Migrate old hide list into database
if (access(LEGACY_LIST, R_OK) == 0) {
auto tmp = Array<char *>();
file_to_array(LEGACY_LIST, tmp);
for (auto &s : tmp)
add_list(db, s);
unlink(LEGACY_LIST);
}
sqlite3_close_v2(db);
return 0;
}
int destroy_list() {
char *line;
vec_for_each(hide_list, line) {
kill_process(line);
}
vec_deep_destroy(hide_list);
free(hide_list);
hide_list = NULL;
for (auto &str : hide_list)
free(str);
hide_list.clear();
return 0;
}
@ -274,15 +273,13 @@ void rm_hide_list(int client) {
}
void ls_hide_list(int client) {
if (!hideEnabled) {
if (!hide_enabled) {
write_int(client, HIDE_NOT_ENABLED);
return;
}
write_int(client, DAEMON_SUCCESS);
write_int(client, vec_size(hide_list));
char *s;
vec_for_each(hide_list, s) {
write_int(client, hide_list.size());
for (auto &s : hide_list)
write_string(client, s);
}
close(client);
}

View File

@ -1,6 +1,3 @@
/* magiskhide.c - initialize the environment for Magiskhide
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@ -17,11 +14,9 @@
#include "resetprop.h"
#include "flags.h"
struct vector *hide_list = NULL;
int hideEnabled = 0;
int hide_enabled = 0;
static pthread_t proc_monitor_thread;
pthread_mutex_t hide_lock, file_lock;
pthread_mutex_t list_lock;
static void usage(char *arg0) {
fprintf(stderr,
@ -38,7 +33,7 @@ static void usage(char *arg0) {
}
void launch_magiskhide(int client) {
if (hideEnabled) {
if (hide_enabled) {
if (client > 0) {
write_int(client, HIDE_IS_ENABLED);
close(client);
@ -57,7 +52,7 @@ void launch_magiskhide(int client) {
return;
}
hideEnabled = 1;
hide_enabled = 1;
LOGI("* Starting MagiskHide\n");
deleteprop2(MAGISKHIDE_PROP, 1);
@ -65,8 +60,7 @@ void launch_magiskhide(int client) {
hide_sensitive_props();
// Initialize the mutex lock
pthread_mutex_init(&hide_lock, NULL);
pthread_mutex_init(&file_lock, NULL);
pthread_mutex_init(&list_lock, nullptr);
// Initialize the hide list
if (init_list())
@ -87,7 +81,7 @@ void launch_magiskhide(int client) {
return;
error:
hideEnabled = 0;
hide_enabled = 0;
if (client > 0) {
write_int(client, DAEMON_ERROR);
close(client);
@ -96,7 +90,7 @@ error:
}
void stop_magiskhide(int client) {
if (!hideEnabled) {
if (!hide_enabled) {
write_int(client, HIDE_NOT_ENABLED);
close(client);
return;
@ -104,7 +98,7 @@ void stop_magiskhide(int client) {
LOGI("* Stopping MagiskHide\n");
hideEnabled = 0;
hide_enabled = 0;
setprop(MAGISKHIDE_PROP, "0");
// Remove without actually removing persist props
deleteprop2(MAGISKHIDE_PROP, 0);

View File

@ -2,6 +2,7 @@
#define MAGISK_HIDE_H
#include <pthread.h>
#include "array.h"
#define TERM_THREAD SIGUSR1
@ -19,8 +20,8 @@ int rm_list(char *proc);
int init_list();
int destroy_list();
extern int hideEnabled;
extern struct vector *hide_list;
extern pthread_mutex_t hide_lock, file_lock;
extern int hide_enabled;
extern pthread_mutex_t list_lock;
extern Array<char *> hide_list;
#endif

View File

@ -1,4 +1,4 @@
/* proc_monitor.c - Monitor am_proc_start events and unmount
/* proc_monitor.cpp - Monitor am_proc_start events and unmount
*
* We monitor the logcat am_proc_start events. When a target starts up,
* we pause it ASAP, and fork a new process to join its mount namespace
@ -18,22 +18,21 @@
#include "magisk.h"
#include "daemon.h"
#include "utils.h"
#include "utils.hpp"
#include "magiskhide.h"
#include "flags.h"
static int sockfd = -1;
// Workaround for the lack of pthread_cancel
static void term_thread(int sig) {
static void term_thread(int) {
LOGD("proc_monitor: running cleanup\n");
destroy_list();
hideEnabled = 0;
hide_enabled = 0;
close(sockfd);
sockfd = -1;
pthread_mutex_destroy(&hide_lock);
pthread_mutex_destroy(&file_lock);
LOGD("proc_monitor: terminating...\n");
pthread_mutex_destroy(&list_lock);
LOGD("proc_monitor: terminating\n");
pthread_exit(NULL);
}
@ -63,8 +62,8 @@ static int parse_ppid(int pid) {
static void hide_daemon(int pid) {
LOGD("hide_daemon: start unmount for pid=[%d]\n", pid);
char *line, buffer[PATH_MAX];
struct vector mount_list;
char buffer[PATH_MAX];
auto mounts = Array<char *>();
manage_selinux();
clean_magisk_props();
@ -73,33 +72,31 @@ static void hide_daemon(int pid) {
goto exit;
snprintf(buffer, sizeof(buffer), "/proc/%d/mounts", pid);
vec_init(&mount_list);
file_to_vector(buffer, &mount_list);
file_to_array(buffer, mounts);
// Unmount dummy skeletons and /sbin links
vec_for_each(&mount_list, line) {
if (strstr(line, "tmpfs /system/") || strstr(line, "tmpfs /vendor/") || strstr(line, "tmpfs /sbin")) {
sscanf(line, "%*s %4096s", buffer);
for (auto &s : mounts) {
if (strstr(s, "tmpfs /system/") || strstr(s, "tmpfs /vendor/") || strstr(s, "tmpfs /sbin")) {
sscanf(s, "%*s %4096s", buffer);
lazy_unmount(buffer);
}
free(line);
free(s);
}
vec_destroy(&mount_list);
mounts.clear();
// Re-read mount infos
snprintf(buffer, sizeof(buffer), "/proc/%d/mounts", pid);
vec_init(&mount_list);
file_to_vector(buffer, &mount_list);
file_to_array(buffer, mounts);
// Unmount everything under /system, /vendor, and loop mounts
vec_for_each(&mount_list, line) {
if (strstr(line, "/dev/block/loop") || strstr(line, " /system/") || strstr(line, " /vendor/")) {
sscanf(line, "%*s %4096s", buffer);
for (auto &s : mounts) {
if (strstr(s, "/dev/block/loop") || strstr(s, " /system/") || strstr(s, " /vendor/")) {
sscanf(s, "%*s %4096s", buffer);
lazy_unmount(buffer);
}
free(line);
free(s);
}
vec_destroy(&mount_list);
mounts.clear();
exit:
// Send resume signal
@ -159,16 +156,15 @@ void proc_monitor() {
if (colon)
*colon = '\0';
int hide = 0;
pthread_mutex_lock(&hide_lock);
char *line;
vec_for_each(hide_list, line) {
if (strcmp(proc, line) == 0) {
hide = 1;
bool hide = false;
pthread_mutex_lock(&list_lock);
for (auto &s : hide_list) {
if (strcmp(proc, s) == 0) {
hide = true;
break;
}
}
pthread_mutex_unlock(&hide_lock);
pthread_mutex_unlock(&list_lock);
if (!hide)
continue;

View File

@ -4,6 +4,7 @@ include $(CLEAR_VARS)
LOCAL_MODULE:= libutils
LOCAL_C_INCLUDES := jni/include $(LIBUTILS)
LOCAL_SRC_FILES := \
utils.cpp \
file.c \
list.c \
misc.c \

View File

@ -0,0 +1,6 @@
#pragma once
#include "utils.h"
#include "array.h"
int file_to_array(const char* filename, Array<char *> &arr);

View File

@ -0,0 +1,25 @@
#include <unistd.h>
#include "utils.hpp"
int file_to_array(const char *filename, Array<char *> &arr) {
if (access(filename, R_OK) != 0)
return 1;
char *line = NULL;
size_t len = 0;
ssize_t read;
FILE *fp = xfopen(filename, "r");
if (fp == NULL)
return 1;
while ((read = getline(&line, &len, fp)) != -1) {
// Remove end newline
if (line[read - 1] == '\n')
line[read - 1] = '\0';
arr.push_back(line);
line = NULL;
}
fclose(fp);
return 0;
}