mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-04-30 14:34:28 +02:00
Use better C++ SQL APIs
This commit is contained in:
parent
3ca6d06f69
commit
2722875190
@ -137,7 +137,7 @@ static bool check_safe_mode() {
|
|||||||
int bootloop_cnt;
|
int bootloop_cnt;
|
||||||
db_settings dbs;
|
db_settings dbs;
|
||||||
get_db_settings(dbs, BOOTLOOP_COUNT);
|
get_db_settings(dbs, BOOTLOOP_COUNT);
|
||||||
bootloop_cnt = dbs[BOOTLOOP_COUNT];
|
bootloop_cnt = dbs.bootloop;
|
||||||
// Increment the bootloop counter
|
// Increment the bootloop counter
|
||||||
set_db_settings(BOOTLOOP_COUNT, bootloop_cnt + 1);
|
set_db_settings(BOOTLOOP_COUNT, bootloop_cnt + 1);
|
||||||
return bootloop_cnt >= 2 || get_prop("persist.sys.safemode", true) == "1" ||
|
return bootloop_cnt >= 2 || get_prop("persist.sys.safemode", true) == "1" ||
|
||||||
@ -187,7 +187,7 @@ bool MagiskD::post_fs_data() const noexcept {
|
|||||||
exec_common_scripts("post-fs-data");
|
exec_common_scripts("post-fs-data");
|
||||||
db_settings dbs;
|
db_settings dbs;
|
||||||
get_db_settings(dbs, ZYGISK_CONFIG);
|
get_db_settings(dbs, ZYGISK_CONFIG);
|
||||||
zygisk_enabled = dbs[ZYGISK_CONFIG];
|
zygisk_enabled = dbs.zygisk;
|
||||||
initialize_denylist();
|
initialize_denylist();
|
||||||
setup_mounts();
|
setup_mounts();
|
||||||
handle_modules();
|
handle_modules();
|
||||||
|
@ -11,41 +11,9 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
static sqlite3 *mDB = nullptr;
|
|
||||||
|
|
||||||
#define DBLOGV(...)
|
#define DBLOGV(...)
|
||||||
//#define DBLOGV(...) LOGD("magiskdb: " __VA_ARGS__)
|
//#define DBLOGV(...) LOGD("magiskdb: " __VA_ARGS__)
|
||||||
|
|
||||||
int db_strings::get_idx(string_view key) const {
|
|
||||||
int idx = 0;
|
|
||||||
for (const char *k : DB_STRING_KEYS) {
|
|
||||||
if (key == k)
|
|
||||||
break;
|
|
||||||
++idx;
|
|
||||||
}
|
|
||||||
return idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
db_settings::db_settings() {
|
|
||||||
// Default settings
|
|
||||||
data[ROOT_ACCESS] = ROOT_ACCESS_APPS_AND_ADB;
|
|
||||||
data[SU_MULTIUSER_MODE] = MULTIUSER_MODE_OWNER_ONLY;
|
|
||||||
data[SU_MNT_NS] = NAMESPACE_MODE_REQUESTER;
|
|
||||||
data[DENYLIST_CONFIG] = false;
|
|
||||||
data[ZYGISK_CONFIG] = MagiskD().is_emulator();
|
|
||||||
data[BOOTLOOP_COUNT] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int db_settings::get_idx(string_view key) const {
|
|
||||||
int idx = 0;
|
|
||||||
for (const char *k : DB_SETTING_KEYS) {
|
|
||||||
if (key == k)
|
|
||||||
break;
|
|
||||||
++idx;
|
|
||||||
}
|
|
||||||
return idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct db_result {
|
struct db_result {
|
||||||
db_result() = default;
|
db_result() = default;
|
||||||
db_result(const char *s) : err(s) {}
|
db_result(const char *s) : err(s) {}
|
||||||
@ -61,11 +29,11 @@ private:
|
|||||||
string err;
|
string err;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int sql_exec(sqlite3 *db, const char *sql, sqlite_row_callback callback = nullptr, void *v = nullptr) {
|
static int sql_exec(sqlite3 *db, const char *sql, sql_exec_callback callback = nullptr, void *v = nullptr) {
|
||||||
return sql_exec(db, sql, {}, callback, v);
|
return sql_exec(db, sql, nullptr, nullptr, callback, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
static db_result open_and_init_db() {
|
static db_result open_and_init_db_impl(sqlite3 **dbOut) {
|
||||||
if (!load_sqlite())
|
if (!load_sqlite())
|
||||||
return "Cannot load libsqlite.so";
|
return "Cannot load libsqlite.so";
|
||||||
|
|
||||||
@ -79,8 +47,8 @@ static db_result open_and_init_db() {
|
|||||||
|
|
||||||
int ver = 0;
|
int ver = 0;
|
||||||
bool upgrade = false;
|
bool upgrade = false;
|
||||||
auto ver_cb = [](void *ver, auto, StringSlice data) {
|
auto ver_cb = [](void *ver, auto, DbValues &data) {
|
||||||
*((int *) ver) = parse_int(data[0].c_str());
|
*static_cast<int *>(ver) = data.get_int(0);
|
||||||
};
|
};
|
||||||
fn_run_ret(sql_exec, db.get(), "PRAGMA user_version", ver_cb, &ver);
|
fn_run_ret(sql_exec, db.get(), "PRAGMA user_version", ver_cb, &ver);
|
||||||
if (ver > DB_VERSION) {
|
if (ver > DB_VERSION) {
|
||||||
@ -190,40 +158,48 @@ static db_result open_and_init_db() {
|
|||||||
sprintf(query, "PRAGMA user_version=%d", ver);
|
sprintf(query, "PRAGMA user_version=%d", ver);
|
||||||
fn_run_ret(sql_exec, db.get(), query);
|
fn_run_ret(sql_exec, db.get(), query);
|
||||||
}
|
}
|
||||||
mDB = db.release();
|
|
||||||
|
*dbOut = db.release();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static db_result ensure_db() {
|
sqlite3 *open_and_init_db() {
|
||||||
if (mDB == nullptr) {
|
sqlite3 *db = nullptr;
|
||||||
db_result res = open_and_init_db();
|
if (!open_and_init_db_impl(&db))
|
||||||
if (!res) {
|
return nullptr;
|
||||||
// Open fails, remove and reconstruct
|
return db;
|
||||||
|
}
|
||||||
|
|
||||||
|
static sqlite3 *get_db() {
|
||||||
|
static sqlite3 *db = nullptr;
|
||||||
|
if (db == nullptr) {
|
||||||
|
db = open_and_init_db();
|
||||||
|
if (db == nullptr) {
|
||||||
|
// Open failed, remove and reconstruct
|
||||||
unlink(MAGISKDB);
|
unlink(MAGISKDB);
|
||||||
return open_and_init_db();
|
db = open_and_init_db();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
return db;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool db_exec(const char *sql) {
|
bool db_exec(const char *sql, db_bind_callback bind_fn, db_exec_callback exec_fn) {
|
||||||
if (ensure_db() && mDB) {
|
if (sqlite3 *db = get_db()) {
|
||||||
db_result res = sql_exec(mDB, sql);
|
sql_bind_callback bind_cb = nullptr;
|
||||||
return res;
|
if (bind_fn) {
|
||||||
}
|
bind_cb = [](void *v, int index, DbStatement &stmt) {
|
||||||
return false;
|
auto fn = static_cast<db_bind_callback*>(v);
|
||||||
}
|
fn->operator()(index, stmt);
|
||||||
|
};
|
||||||
bool db_exec(const char *sql, const db_row_cb &fn) {
|
}
|
||||||
if (ensure_db() && mDB) {
|
sql_exec_callback exec_cb = nullptr;
|
||||||
auto convert = [](void *cb, StringSlice columns, StringSlice data) {
|
if (exec_fn) {
|
||||||
auto &func = *static_cast<const db_row_cb*>(cb);
|
exec_cb = [](void *v, StringSlice columns, DbValues &data) {
|
||||||
db_row row;
|
auto fn = static_cast<db_exec_callback*>(v);
|
||||||
for (int i = 0; i < columns.size(); ++i)
|
fn->operator()(columns, data);
|
||||||
row[columns[i].c_str()] = data[i].c_str();
|
};
|
||||||
func(row);
|
}
|
||||||
};
|
db_result res = sql_exec(db, sql, bind_cb, &bind_fn, exec_cb, &exec_fn);
|
||||||
db_result res = sql_exec(mDB, sql, convert, (void *) &fn);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -231,17 +207,12 @@ bool db_exec(const char *sql, const db_row_cb &fn) {
|
|||||||
|
|
||||||
int get_db_settings(db_settings &cfg, int key) {
|
int get_db_settings(db_settings &cfg, int key) {
|
||||||
bool res;
|
bool res;
|
||||||
auto settings_cb = [&](db_row &row) -> bool {
|
|
||||||
cfg[row["key"]] = parse_int(row["value"]);
|
|
||||||
DBLOGV("query %s=[%s]\n", row["key"].data(), row["value"].data());
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
if (key >= 0) {
|
if (key >= 0) {
|
||||||
char query[128];
|
char query[128];
|
||||||
ssprintf(query, sizeof(query), "SELECT * FROM settings WHERE key='%s'", DB_SETTING_KEYS[key]);
|
ssprintf(query, sizeof(query), "SELECT * FROM settings WHERE key='%s'", DB_SETTING_KEYS[key]);
|
||||||
res = db_exec(query, settings_cb);
|
res = db_exec(query, cfg);
|
||||||
} else {
|
} else {
|
||||||
res = db_exec("SELECT * FROM settings", settings_cb);
|
res = db_exec("SELECT * FROM settings", cfg);
|
||||||
}
|
}
|
||||||
return res ? 0 : 1;
|
return res ? 0 : 1;
|
||||||
}
|
}
|
||||||
@ -255,17 +226,12 @@ int set_db_settings(int key, int value) {
|
|||||||
|
|
||||||
int get_db_strings(db_strings &str, int key) {
|
int get_db_strings(db_strings &str, int key) {
|
||||||
bool res;
|
bool res;
|
||||||
auto string_cb = [&](db_row &row) -> bool {
|
|
||||||
str[row["key"]] = row["value"];
|
|
||||||
DBLOGV("query %s=[%s]\n", row["key"].data(), row["value"].data());
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
if (key >= 0) {
|
if (key >= 0) {
|
||||||
char query[128];
|
char query[128];
|
||||||
ssprintf(query, sizeof(query), "SELECT * FROM strings WHERE key='%s'", DB_STRING_KEYS[key]);
|
ssprintf(query, sizeof(query), "SELECT * FROM strings WHERE key='%s'", DB_STRING_KEYS[key]);
|
||||||
res = db_exec(query, string_cb);
|
res = db_exec(query, str);
|
||||||
} else {
|
} else {
|
||||||
res = db_exec("SELECT * FROM strings", string_cb);
|
res = db_exec("SELECT * FROM strings", str);
|
||||||
}
|
}
|
||||||
return res ? 0 : 1;
|
return res ? 0 : 1;
|
||||||
}
|
}
|
||||||
@ -278,18 +244,65 @@ void rm_db_strings(int key) {
|
|||||||
|
|
||||||
void exec_sql(owned_fd client) {
|
void exec_sql(owned_fd client) {
|
||||||
string sql = read_string(client);
|
string sql = read_string(client);
|
||||||
db_exec(sql.data(), [fd = (int) client](db_row &row) -> bool {
|
db_exec(sql.data(), [fd = (int) client](StringSlice columns, DbValues &data) {
|
||||||
string out;
|
string out;
|
||||||
bool first = true;
|
for (int i = 0; i < columns.size(); ++i) {
|
||||||
for (auto it : row) {
|
if (i != 0) out += '|';
|
||||||
if (first) first = false;
|
out += columns[i].c_str();
|
||||||
else out += '|';
|
|
||||||
out += it.first;
|
|
||||||
out += '=';
|
out += '=';
|
||||||
out += it.second;
|
out += data.get_text(i);
|
||||||
}
|
}
|
||||||
write_string(fd, out);
|
write_string(fd, out);
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
write_int(client, 0);
|
write_int(client, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db_settings::db_settings() :
|
||||||
|
root_access(ROOT_ACCESS_APPS_AND_ADB),
|
||||||
|
multiuser_mode(MULTIUSER_MODE_OWNER_ONLY),
|
||||||
|
mnt_ns(NAMESPACE_MODE_REQUESTER),
|
||||||
|
bootloop(0),
|
||||||
|
denylist(false),
|
||||||
|
zygisk(MagiskD().is_emulator()) {}
|
||||||
|
|
||||||
|
void db_settings::operator()(StringSlice columns, DbValues &data) {
|
||||||
|
string_view key;
|
||||||
|
int val;
|
||||||
|
for (int i = 0; i < columns.size(); ++i) {
|
||||||
|
const auto &name = columns[i];
|
||||||
|
if (name == "key") {
|
||||||
|
key = data.get_text(i);
|
||||||
|
} else if (name == "value") {
|
||||||
|
val = data.get_int(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (key == DB_SETTING_KEYS[ROOT_ACCESS]) {
|
||||||
|
root_access = val;
|
||||||
|
} else if (key == DB_SETTING_KEYS[SU_MULTIUSER_MODE]) {
|
||||||
|
multiuser_mode = val;
|
||||||
|
} else if (key == DB_SETTING_KEYS[SU_MNT_NS]) {
|
||||||
|
mnt_ns = val;
|
||||||
|
} else if (key == DB_SETTING_KEYS[BOOTLOOP_COUNT]) {
|
||||||
|
bootloop = val;
|
||||||
|
} else if (key == DB_SETTING_KEYS[DENYLIST_CONFIG]) {
|
||||||
|
denylist = val;
|
||||||
|
} else if (key == DB_SETTING_KEYS[ZYGISK_CONFIG]) {
|
||||||
|
zygisk = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void db_strings::operator()(StringSlice columns, DbValues &data) {
|
||||||
|
string_view key;
|
||||||
|
const char *val;
|
||||||
|
for (int i = 0; i < columns.size(); ++i) {
|
||||||
|
const auto &name = columns[i];
|
||||||
|
if (name == "key") {
|
||||||
|
key = data.get_text(i);
|
||||||
|
} else if (name == "value") {
|
||||||
|
val = data.get_text(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (key == DB_STRING_KEYS[SU_MANAGER]) {
|
||||||
|
su_manager = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -222,9 +222,18 @@ static bool ensure_data() {
|
|||||||
LOGI("denylist: initializing internal data structures\n");
|
LOGI("denylist: initializing internal data structures\n");
|
||||||
|
|
||||||
default_new(pkg_to_procs_);
|
default_new(pkg_to_procs_);
|
||||||
bool res = db_exec("SELECT * FROM denylist", [](db_row &row) -> bool {
|
bool res = db_exec("SELECT * FROM denylist", [](StringSlice columns, DbValues &data) {
|
||||||
add_hide_set(row["package_name"].data(), row["process"].data());
|
const char *package_name;
|
||||||
return true;
|
const char *process;
|
||||||
|
for (int i = 0; i < columns.size(); ++i) {
|
||||||
|
const auto &name = columns[i];
|
||||||
|
if (name == "package_name") {
|
||||||
|
package_name = data.get_text(i);
|
||||||
|
} else if (name == "process") {
|
||||||
|
process = data.get_text(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
add_hide_set(package_name, process);
|
||||||
});
|
});
|
||||||
if (!res)
|
if (!res)
|
||||||
goto error;
|
goto error;
|
||||||
@ -392,7 +401,7 @@ void initialize_denylist() {
|
|||||||
if (!denylist_enforced) {
|
if (!denylist_enforced) {
|
||||||
db_settings dbs;
|
db_settings dbs;
|
||||||
get_db_settings(dbs, DENYLIST_CONFIG);
|
get_db_settings(dbs, DENYLIST_CONFIG);
|
||||||
if (dbs[DENYLIST_CONFIG])
|
if (dbs.denylist)
|
||||||
enable_deny();
|
enable_deny();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,29 +6,8 @@
|
|||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
template <class T, size_t N>
|
#include <base.hpp>
|
||||||
class db_dict {
|
#include <sqlite.hpp>
|
||||||
public:
|
|
||||||
T& operator [](std::string_view key) {
|
|
||||||
return data[get_idx(key)];
|
|
||||||
}
|
|
||||||
|
|
||||||
const T& operator [](std::string_view key) const {
|
|
||||||
return data[get_idx(key)];
|
|
||||||
}
|
|
||||||
|
|
||||||
T& operator [](int key) {
|
|
||||||
return data[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
const T& operator [](int key) const {
|
|
||||||
return data[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
T data[N + 1];
|
|
||||||
virtual int get_idx(std::string_view key) const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/***************
|
/***************
|
||||||
* DB Settings *
|
* DB Settings *
|
||||||
@ -75,11 +54,16 @@ enum {
|
|||||||
NAMESPACE_MODE_ISOLATE
|
NAMESPACE_MODE_ISOLATE
|
||||||
};
|
};
|
||||||
|
|
||||||
class db_settings : public db_dict<int, std::size(DB_SETTING_KEYS)> {
|
struct db_settings {
|
||||||
public:
|
int root_access;
|
||||||
|
int multiuser_mode;
|
||||||
|
int mnt_ns;
|
||||||
|
int bootloop;
|
||||||
|
bool denylist;
|
||||||
|
bool zygisk;
|
||||||
|
|
||||||
db_settings();
|
db_settings();
|
||||||
protected:
|
void operator()(StringSlice columns, DbValues &data);
|
||||||
int get_idx(std::string_view key) const override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**************
|
/**************
|
||||||
@ -93,43 +77,34 @@ enum {
|
|||||||
SU_MANAGER = 0
|
SU_MANAGER = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
class db_strings : public db_dict<std::string, std::size(DB_STRING_KEYS)> {
|
struct db_strings {
|
||||||
protected:
|
std::string su_manager;
|
||||||
int get_idx(std::string_view key) const override;
|
|
||||||
|
void operator()(StringSlice columns, DbValues &data);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************
|
|
||||||
* SU Access *
|
|
||||||
*************/
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
QUERY = 0,
|
|
||||||
DENY = 1,
|
|
||||||
ALLOW = 2,
|
|
||||||
} policy_t;
|
|
||||||
|
|
||||||
struct su_access {
|
|
||||||
policy_t policy;
|
|
||||||
int log;
|
|
||||||
int notify;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DEFAULT_SU_ACCESS { QUERY, 1, 1 }
|
|
||||||
#define SILENT_SU_ACCESS { ALLOW, 0, 0 }
|
|
||||||
#define NO_SU_ACCESS { DENY, 0, 0 }
|
|
||||||
|
|
||||||
/********************
|
/********************
|
||||||
* Public Functions *
|
* Public Functions *
|
||||||
********************/
|
********************/
|
||||||
|
|
||||||
using db_row = std::map<std::string_view, std::string_view>;
|
using db_exec_callback = std::function<void(StringSlice, DbValues&)>;
|
||||||
using db_row_cb = std::function<bool(db_row&)>;
|
using db_bind_callback = std::function<void(int, DbStatement&)>;
|
||||||
struct owned_fd;
|
|
||||||
|
|
||||||
int get_db_settings(db_settings &cfg, int key = -1);
|
int get_db_settings(db_settings &cfg, int key = -1);
|
||||||
int set_db_settings(int key, int value);
|
int set_db_settings(int key, int value);
|
||||||
int get_db_strings(db_strings &str, int key = -1);
|
int get_db_strings(db_strings &str, int key = -1);
|
||||||
void rm_db_strings(int key);
|
void rm_db_strings(int key);
|
||||||
void exec_sql(owned_fd client);
|
void exec_sql(owned_fd client);
|
||||||
bool db_exec(const char *sql);
|
bool db_exec(const char *sql, db_bind_callback bind_fn = {}, db_exec_callback exec_fn = {});
|
||||||
bool db_exec(const char *sql, const db_row_cb &fn);
|
|
||||||
|
static inline bool db_exec(const char *sql, db_exec_callback exec_fn) {
|
||||||
|
return db_exec(sql, {}, std::move(exec_fn));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept DbData = requires(T t, StringSlice s, DbValues &v) { t(s, v); };
|
||||||
|
|
||||||
|
template<DbData T>
|
||||||
|
bool db_exec(const char *sql, T &data) {
|
||||||
|
return db_exec(sql, (db_exec_callback) std::ref(data));
|
||||||
|
}
|
||||||
|
@ -15,23 +15,29 @@ struct sqlite3_stmt;
|
|||||||
|
|
||||||
extern int (*sqlite3_open_v2)(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs);
|
extern int (*sqlite3_open_v2)(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs);
|
||||||
extern int (*sqlite3_close)(sqlite3 *db);
|
extern int (*sqlite3_close)(sqlite3 *db);
|
||||||
extern int (*sqlite3_prepare_v2)(sqlite3 *db, const char *zSql, int nByte, sqlite3_stmt **ppStmt, const char **pzTail);
|
|
||||||
extern int (*sqlite3_bind_parameter_count)(sqlite3_stmt*);
|
|
||||||
extern int (*sqlite3_bind_int)(sqlite3_stmt*, int, int);
|
|
||||||
extern int (*sqlite3_bind_text)(sqlite3_stmt*,int,const char*,int,void(*)(void*));
|
|
||||||
extern int (*sqlite3_column_count)(sqlite3_stmt *pStmt);
|
|
||||||
extern const char *(*sqlite3_column_name)(sqlite3_stmt*, int N);
|
|
||||||
extern const char *(*sqlite3_column_text)(sqlite3_stmt*, int iCol);
|
|
||||||
extern int (*sqlite3_step)(sqlite3_stmt*);
|
|
||||||
extern int (*sqlite3_finalize)(sqlite3_stmt *pStmt);
|
|
||||||
extern const char *(*sqlite3_errstr)(int);
|
extern const char *(*sqlite3_errstr)(int);
|
||||||
|
|
||||||
using StringVec = rust::Vec<rust::String>;
|
// Transparent wrapper of sqlite3_stmt
|
||||||
|
struct DbValues {
|
||||||
|
const char *get_text(int index);
|
||||||
|
int get_int(int index);
|
||||||
|
~DbValues() = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DbStatement {
|
||||||
|
int bind_text(int index, const char *val);
|
||||||
|
int bind_text(int index, rust::Str val);
|
||||||
|
int bind_int64(int index, int64_t val);
|
||||||
|
};
|
||||||
|
|
||||||
using StringSlice = rust::Slice<rust::String>;
|
using StringSlice = rust::Slice<rust::String>;
|
||||||
using StrSlice = rust::Slice<rust::Str>;
|
using sql_bind_callback = void(*)(void*, int, DbStatement&);
|
||||||
using sqlite_row_callback = void(*)(void*, StringSlice, StringSlice);
|
using sql_exec_callback = void(*)(void*, StringSlice, DbValues&);
|
||||||
|
|
||||||
#define fn_run_ret(fn, ...) if (int rc = fn(__VA_ARGS__); rc != SQLITE_OK) return rc
|
#define fn_run_ret(fn, ...) if (int rc = fn(__VA_ARGS__); rc != SQLITE_OK) return rc
|
||||||
|
|
||||||
bool load_sqlite();
|
bool load_sqlite();
|
||||||
int sql_exec(sqlite3 *db, rust::Str zSql, StrSlice args, sqlite_row_callback callback, void *v);
|
sqlite3 *open_and_init_db();
|
||||||
|
int sql_exec(sqlite3 *db, rust::Str zSql,
|
||||||
|
sql_bind_callback bind_cb, void *bind_cookie,
|
||||||
|
sql_exec_callback exec_cb, void *exec_cookie);
|
||||||
|
@ -197,7 +197,7 @@ int get_manager(int user, string *pkg, bool install) {
|
|||||||
|
|
||||||
db_strings str;
|
db_strings str;
|
||||||
get_db_strings(str, SU_MANAGER);
|
get_db_strings(str, SU_MANAGER);
|
||||||
string db_pkg(std::move(str[SU_MANAGER]));
|
string db_pkg(std::move(str.su_manager));
|
||||||
|
|
||||||
// If database changed, always re-check files
|
// If database changed, always re-check files
|
||||||
if (db_pkg != repackaged_pkg) {
|
if (db_pkg != repackaged_pkg) {
|
||||||
|
@ -9,17 +9,19 @@ using namespace std;
|
|||||||
|
|
||||||
int (*sqlite3_open_v2)(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs);
|
int (*sqlite3_open_v2)(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs);
|
||||||
int (*sqlite3_close)(sqlite3 *db);
|
int (*sqlite3_close)(sqlite3 *db);
|
||||||
int (*sqlite3_prepare_v2)(sqlite3 *db, const char *zSql, int nByte, sqlite3_stmt **ppStmt, const char **pzTail);
|
|
||||||
int (*sqlite3_bind_parameter_count)(sqlite3_stmt*);
|
|
||||||
int (*sqlite3_bind_int)(sqlite3_stmt*, int, int);
|
|
||||||
int (*sqlite3_bind_text)(sqlite3_stmt*,int,const char*,int,void(*)(void*));
|
|
||||||
int (*sqlite3_column_count)(sqlite3_stmt *pStmt);
|
|
||||||
const char *(*sqlite3_column_name)(sqlite3_stmt*, int N);
|
|
||||||
const char *(*sqlite3_column_text)(sqlite3_stmt*, int iCol);
|
|
||||||
int (*sqlite3_step)(sqlite3_stmt*);
|
|
||||||
int (*sqlite3_finalize)(sqlite3_stmt *pStmt);
|
|
||||||
const char *(*sqlite3_errstr)(int);
|
const char *(*sqlite3_errstr)(int);
|
||||||
|
|
||||||
|
static int (*sqlite3_prepare_v2)(sqlite3 *db, const char *zSql, int nByte, sqlite3_stmt **ppStmt, const char **pzTail);
|
||||||
|
static int (*sqlite3_bind_parameter_count)(sqlite3_stmt*);
|
||||||
|
static int (*sqlite3_bind_int64)(sqlite3_stmt*, int, int64_t);
|
||||||
|
static int (*sqlite3_bind_text)(sqlite3_stmt*,int,const char*,int,void(*)(void*));
|
||||||
|
static int (*sqlite3_column_count)(sqlite3_stmt *pStmt);
|
||||||
|
static const char *(*sqlite3_column_name)(sqlite3_stmt*, int N);
|
||||||
|
static const char *(*sqlite3_column_text)(sqlite3_stmt*, int iCol);
|
||||||
|
static int (*sqlite3_column_int)(sqlite3_stmt*, int iCol);
|
||||||
|
static int (*sqlite3_step)(sqlite3_stmt*);
|
||||||
|
static int (*sqlite3_finalize)(sqlite3_stmt *pStmt);
|
||||||
|
|
||||||
// Internal Android linker APIs
|
// Internal Android linker APIs
|
||||||
|
|
||||||
static void (*android_get_LD_LIBRARY_PATH)(char *buffer, size_t buffer_size);
|
static void (*android_get_LD_LIBRARY_PATH)(char *buffer, size_t buffer_size);
|
||||||
@ -72,24 +74,28 @@ bool load_sqlite() {
|
|||||||
|
|
||||||
DLOAD(sqlite, sqlite3_open_v2);
|
DLOAD(sqlite, sqlite3_open_v2);
|
||||||
DLOAD(sqlite, sqlite3_close);
|
DLOAD(sqlite, sqlite3_close);
|
||||||
|
DLOAD(sqlite, sqlite3_errstr);
|
||||||
DLOAD(sqlite, sqlite3_prepare_v2);
|
DLOAD(sqlite, sqlite3_prepare_v2);
|
||||||
DLOAD(sqlite, sqlite3_bind_parameter_count);
|
DLOAD(sqlite, sqlite3_bind_parameter_count);
|
||||||
DLOAD(sqlite, sqlite3_bind_int);
|
DLOAD(sqlite, sqlite3_bind_int64);
|
||||||
DLOAD(sqlite, sqlite3_bind_text);
|
DLOAD(sqlite, sqlite3_bind_text);
|
||||||
DLOAD(sqlite, sqlite3_step);
|
DLOAD(sqlite, sqlite3_step);
|
||||||
DLOAD(sqlite, sqlite3_column_count);
|
DLOAD(sqlite, sqlite3_column_count);
|
||||||
DLOAD(sqlite, sqlite3_column_name);
|
DLOAD(sqlite, sqlite3_column_name);
|
||||||
DLOAD(sqlite, sqlite3_column_text);
|
DLOAD(sqlite, sqlite3_column_text);
|
||||||
|
DLOAD(sqlite, sqlite3_column_int);
|
||||||
DLOAD(sqlite, sqlite3_finalize);
|
DLOAD(sqlite, sqlite3_finalize);
|
||||||
DLOAD(sqlite, sqlite3_errstr);
|
|
||||||
|
|
||||||
dl_init = 1;
|
dl_init = 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sql_exec(sqlite3 *db, rust::Str zSql, StrSlice args, sqlite_row_callback callback, void *v) {
|
using StringVec = rust::Vec<rust::String>;
|
||||||
|
using sql_exec_callback_real = void(*)(void*, StringSlice, sqlite3_stmt*);
|
||||||
|
using sql_bind_callback_real = void(*)(void*, int, sqlite3_stmt*);
|
||||||
|
|
||||||
|
int sql_exec(sqlite3 *db, rust::Str zSql, sql_bind_callback bind_cb, void *bind_cookie, sql_exec_callback exec_cb, void *exec_cookie) {
|
||||||
const char *sql = zSql.begin();
|
const char *sql = zSql.begin();
|
||||||
auto arg_it = args.begin();
|
|
||||||
unique_ptr<sqlite3_stmt, decltype(sqlite3_finalize)> stmt(nullptr, sqlite3_finalize);
|
unique_ptr<sqlite3_stmt, decltype(sqlite3_finalize)> stmt(nullptr, sqlite3_finalize);
|
||||||
|
|
||||||
while (sql != zSql.end()) {
|
while (sql != zSql.end()) {
|
||||||
@ -102,9 +108,12 @@ int sql_exec(sqlite3 *db, rust::Str zSql, StrSlice args, sqlite_row_callback cal
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Step 2: bind arguments
|
// Step 2: bind arguments
|
||||||
if (int count = sqlite3_bind_parameter_count(stmt.get())) {
|
if (bind_cb) {
|
||||||
for (int i = 1; i <= count && arg_it != args.end(); ++i, ++arg_it) {
|
if (int count = sqlite3_bind_parameter_count(stmt.get())) {
|
||||||
fn_run_ret(sqlite3_bind_text, stmt.get(), i, arg_it->data(), arg_it->size(), nullptr);
|
auto real_cb = reinterpret_cast<sql_bind_callback_real>(bind_cb);
|
||||||
|
for (int i = 1; i <= count; ++i) {
|
||||||
|
real_cb(bind_cookie, i, stmt.get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +124,7 @@ int sql_exec(sqlite3 *db, rust::Str zSql, StrSlice args, sqlite_row_callback cal
|
|||||||
int rc = sqlite3_step(stmt.get());
|
int rc = sqlite3_step(stmt.get());
|
||||||
if (rc == SQLITE_DONE) break;
|
if (rc == SQLITE_DONE) break;
|
||||||
if (rc != SQLITE_ROW) return rc;
|
if (rc != SQLITE_ROW) return rc;
|
||||||
if (callback == nullptr) continue;
|
if (exec_cb == nullptr) continue;
|
||||||
if (first) {
|
if (first) {
|
||||||
int count = sqlite3_column_count(stmt.get());
|
int count = sqlite3_column_count(stmt.get());
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
@ -123,13 +132,30 @@ int sql_exec(sqlite3 *db, rust::Str zSql, StrSlice args, sqlite_row_callback cal
|
|||||||
}
|
}
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
StringVec data;
|
auto real_cb = reinterpret_cast<sql_exec_callback_real>(exec_cb);
|
||||||
for (int i = 0; i < columns.size(); ++i) {
|
real_cb(exec_cookie, StringSlice(columns), stmt.get());
|
||||||
data.emplace_back(sqlite3_column_text(stmt.get(), i));
|
|
||||||
}
|
|
||||||
callback(v, StringSlice(columns), StringSlice(data));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int DbValues::get_int(int index) {
|
||||||
|
return sqlite3_column_int(reinterpret_cast<sqlite3_stmt*>(this), index);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *DbValues::get_text(int index) {
|
||||||
|
return sqlite3_column_text(reinterpret_cast<sqlite3_stmt*>(this), index);
|
||||||
|
}
|
||||||
|
|
||||||
|
int DbStatement::bind_int64(int index, int64_t val) {
|
||||||
|
return sqlite3_bind_int64(reinterpret_cast<sqlite3_stmt*>(this), index, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
int DbStatement::bind_text(int index, rust::Str val) {
|
||||||
|
return sqlite3_bind_text(reinterpret_cast<sqlite3_stmt*>(this), index, val.data(), val.size(), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int DbStatement::bind_text(int index, const char *val) {
|
||||||
|
return sqlite3_bind_text(reinterpret_cast<sqlite3_stmt*>(this), index, val, -1, nullptr);
|
||||||
|
}
|
||||||
|
@ -14,6 +14,32 @@
|
|||||||
#define ATTY_OUT (1 << 1)
|
#define ATTY_OUT (1 << 1)
|
||||||
#define ATTY_ERR (1 << 2)
|
#define ATTY_ERR (1 << 2)
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
QUERY = 0,
|
||||||
|
DENY = 1,
|
||||||
|
ALLOW = 2,
|
||||||
|
} policy_t;
|
||||||
|
|
||||||
|
struct su_access {
|
||||||
|
policy_t policy;
|
||||||
|
int log;
|
||||||
|
int notify;
|
||||||
|
|
||||||
|
su_access() : policy(QUERY), log(1), notify(1) {}
|
||||||
|
|
||||||
|
void operator()(StringSlice columns, DbValues &data);
|
||||||
|
void silent_deny() {
|
||||||
|
policy = DENY;
|
||||||
|
log = 0;
|
||||||
|
notify = 0;
|
||||||
|
}
|
||||||
|
void silent_allow() {
|
||||||
|
policy = ALLOW;
|
||||||
|
log = 0;
|
||||||
|
notify = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class su_info {
|
class su_info {
|
||||||
public:
|
public:
|
||||||
// Unique key
|
// Unique key
|
||||||
|
@ -18,8 +18,7 @@ static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER;
|
|||||||
static shared_ptr<su_info> cached;
|
static shared_ptr<su_info> cached;
|
||||||
|
|
||||||
su_info::su_info(int uid) :
|
su_info::su_info(int uid) :
|
||||||
uid(uid), eval_uid(-1), access(DEFAULT_SU_ACCESS), mgr_uid(-1),
|
uid(uid), eval_uid(-1), mgr_uid(-1), timestamp(0), _lock(PTHREAD_MUTEX_INITIALIZER) {}
|
||||||
timestamp(0), _lock(PTHREAD_MUTEX_INITIALIZER) {}
|
|
||||||
|
|
||||||
su_info::~su_info() {
|
su_info::~su_info() {
|
||||||
pthread_mutex_destroy(&_lock);
|
pthread_mutex_destroy(&_lock);
|
||||||
@ -42,16 +41,30 @@ void su_info::refresh() {
|
|||||||
timestamp = ts.tv_sec * 1000L + ts.tv_nsec / 1000000L;
|
timestamp = ts.tv_sec * 1000L + ts.tv_nsec / 1000000L;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void su_access::operator()(StringSlice columns, DbValues &data) {
|
||||||
|
for (int i = 0; i < columns.size(); ++i) {
|
||||||
|
const auto &name = columns[i];
|
||||||
|
if (name == "policy") {
|
||||||
|
policy = (policy_t) data.get_int(i);
|
||||||
|
} else if (name == "logging") {
|
||||||
|
log = data.get_int(i);
|
||||||
|
} else if (name == "notification") {
|
||||||
|
notify = data.get_int(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOGD("magiskdb: query policy=[%d] log=[%d] notify=[%d]\n", policy, log, notify);
|
||||||
|
}
|
||||||
|
|
||||||
void su_info::check_db() {
|
void su_info::check_db() {
|
||||||
eval_uid = uid;
|
eval_uid = uid;
|
||||||
get_db_settings(cfg);
|
get_db_settings(cfg);
|
||||||
|
|
||||||
// Check multiuser settings
|
// Check multiuser settings
|
||||||
switch (cfg[SU_MULTIUSER_MODE]) {
|
switch (cfg.multiuser_mode) {
|
||||||
case MULTIUSER_MODE_OWNER_ONLY:
|
case MULTIUSER_MODE_OWNER_ONLY:
|
||||||
if (to_user_id(uid) != 0) {
|
if (to_user_id(uid) != 0) {
|
||||||
eval_uid = -1;
|
eval_uid = -1;
|
||||||
access = NO_SU_ACCESS;
|
access.silent_deny();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MULTIUSER_MODE_OWNER_MANAGED:
|
case MULTIUSER_MODE_OWNER_MANAGED:
|
||||||
@ -67,15 +80,7 @@ void su_info::check_db() {
|
|||||||
ssprintf(query, sizeof(query),
|
ssprintf(query, sizeof(query),
|
||||||
"SELECT policy, logging, notification FROM policies "
|
"SELECT policy, logging, notification FROM policies "
|
||||||
"WHERE uid=%d AND (until=0 OR until>%li)", eval_uid, time(nullptr));
|
"WHERE uid=%d AND (until=0 OR until>%li)", eval_uid, time(nullptr));
|
||||||
bool res = db_exec(query, [&](db_row &row) -> bool {
|
if (!db_exec(query, access))
|
||||||
access.policy = (policy_t) parse_int(row["policy"]);
|
|
||||||
access.log = parse_int(row["logging"]);
|
|
||||||
access.notify = parse_int(row["notification"]);
|
|
||||||
LOGD("magiskdb: query policy=[%d] log=[%d] notify=[%d]\n",
|
|
||||||
access.policy, access.log, access.notify);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
if (!res)
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +98,7 @@ bool uid_granted_root(int uid) {
|
|||||||
get_db_settings(cfg);
|
get_db_settings(cfg);
|
||||||
|
|
||||||
// Check user root access settings
|
// Check user root access settings
|
||||||
switch (cfg[ROOT_ACCESS]) {
|
switch (cfg.root_access) {
|
||||||
case ROOT_ACCESS_DISABLED:
|
case ROOT_ACCESS_DISABLED:
|
||||||
return false;
|
return false;
|
||||||
case ROOT_ACCESS_APPS_ONLY:
|
case ROOT_ACCESS_APPS_ONLY:
|
||||||
@ -109,7 +114,7 @@ bool uid_granted_root(int uid) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check multiuser settings
|
// Check multiuser settings
|
||||||
switch (cfg[SU_MULTIUSER_MODE]) {
|
switch (cfg.multiuser_mode) {
|
||||||
case MULTIUSER_MODE_OWNER_ONLY:
|
case MULTIUSER_MODE_OWNER_ONLY:
|
||||||
if (to_user_id(uid) != 0)
|
if (to_user_id(uid) != 0)
|
||||||
return false;
|
return false;
|
||||||
@ -122,28 +127,31 @@ bool uid_granted_root(int uid) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool granted = false;
|
|
||||||
|
|
||||||
char query[256];
|
char query[256];
|
||||||
ssprintf(query, sizeof(query),
|
ssprintf(query, sizeof(query),
|
||||||
"SELECT policy FROM policies WHERE uid=%d AND (until=0 OR until>%li)",
|
"SELECT policy FROM policies WHERE uid=%d AND (until=0 OR until>%li)",
|
||||||
uid, time(nullptr));
|
uid, time(nullptr));
|
||||||
bool res = db_exec(query, [&](db_row &row) -> bool {
|
su_access access;
|
||||||
granted = parse_int(row["policy"]) == ALLOW;
|
access.policy = QUERY;
|
||||||
return true;
|
if (!db_exec(query, access))
|
||||||
});
|
|
||||||
if (!res)
|
|
||||||
return false;
|
return false;
|
||||||
|
return access.policy == ALLOW;
|
||||||
return granted;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct policy_uid_list : public vector<int> {
|
||||||
|
void operator()(StringSlice, DbValues &data) {
|
||||||
|
push_back(data.get_int(0));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void prune_su_access() {
|
void prune_su_access() {
|
||||||
cached.reset();
|
cached.reset();
|
||||||
|
policy_uid_list uids;
|
||||||
|
if (!db_exec("SELECT uid FROM policies", uids))
|
||||||
|
return;
|
||||||
vector<bool> app_no_list = get_app_no_list();
|
vector<bool> app_no_list = get_app_no_list();
|
||||||
vector<int> rm_uids;
|
vector<int> rm_uids;
|
||||||
bool res = db_exec("SELECT uid FROM policies", [&](db_row &row) -> bool {
|
for (int uid : uids) {
|
||||||
int uid = parse_int(row["uid"]);
|
|
||||||
int app_id = to_app_id(uid);
|
int app_id = to_app_id(uid);
|
||||||
if (app_id >= AID_APP_START && app_id <= AID_APP_END) {
|
if (app_id >= AID_APP_START && app_id <= AID_APP_END) {
|
||||||
int app_no = app_id - AID_APP_START;
|
int app_no = app_id - AID_APP_START;
|
||||||
@ -152,11 +160,7 @@ void prune_su_access() {
|
|||||||
rm_uids.push_back(uid);
|
rm_uids.push_back(uid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
}
|
||||||
});
|
|
||||||
if (!res)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (int uid : rm_uids) {
|
for (int uid : rm_uids) {
|
||||||
char query[256];
|
char query[256];
|
||||||
ssprintf(query, sizeof(query), "DELETE FROM policies WHERE uid == %d", uid);
|
ssprintf(query, sizeof(query), "DELETE FROM policies WHERE uid == %d", uid);
|
||||||
@ -167,7 +171,7 @@ void prune_su_access() {
|
|||||||
static shared_ptr<su_info> get_su_info(unsigned uid) {
|
static shared_ptr<su_info> get_su_info(unsigned uid) {
|
||||||
if (uid == AID_ROOT) {
|
if (uid == AID_ROOT) {
|
||||||
auto info = make_shared<su_info>(uid);
|
auto info = make_shared<su_info>(uid);
|
||||||
info->access = SILENT_SU_ACCESS;
|
info->access.silent_allow();
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,26 +192,26 @@ static shared_ptr<su_info> get_su_info(unsigned uid) {
|
|||||||
|
|
||||||
// If it's the manager, allow it silently
|
// If it's the manager, allow it silently
|
||||||
if (to_app_id(info->uid) == to_app_id(info->mgr_uid)) {
|
if (to_app_id(info->uid) == to_app_id(info->mgr_uid)) {
|
||||||
info->access = SILENT_SU_ACCESS;
|
info->access.silent_allow();
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check su access settings
|
// Check su access settings
|
||||||
switch (info->cfg[ROOT_ACCESS]) {
|
switch (info->cfg.root_access) {
|
||||||
case ROOT_ACCESS_DISABLED:
|
case ROOT_ACCESS_DISABLED:
|
||||||
LOGW("Root access is disabled!\n");
|
LOGW("Root access is disabled!\n");
|
||||||
info->access = NO_SU_ACCESS;
|
info->access.silent_deny();
|
||||||
break;
|
break;
|
||||||
case ROOT_ACCESS_ADB_ONLY:
|
case ROOT_ACCESS_ADB_ONLY:
|
||||||
if (info->uid != AID_SHELL) {
|
if (info->uid != AID_SHELL) {
|
||||||
LOGW("Root access limited to ADB only!\n");
|
LOGW("Root access limited to ADB only!\n");
|
||||||
info->access = NO_SU_ACCESS;
|
info->access.silent_deny();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ROOT_ACCESS_APPS_ONLY:
|
case ROOT_ACCESS_APPS_ONLY:
|
||||||
if (info->uid == AID_SHELL) {
|
if (info->uid == AID_SHELL) {
|
||||||
LOGW("Root access is disabled for ADB!\n");
|
LOGW("Root access is disabled for ADB!\n");
|
||||||
info->access = NO_SU_ACCESS;
|
info->access.silent_deny();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ROOT_ACCESS_APPS_AND_ADB:
|
case ROOT_ACCESS_APPS_AND_ADB:
|
||||||
@ -220,7 +224,7 @@ static shared_ptr<su_info> get_su_info(unsigned uid) {
|
|||||||
|
|
||||||
// If still not determined, check if manager exists
|
// If still not determined, check if manager exists
|
||||||
if (info->mgr_uid < 0) {
|
if (info->mgr_uid < 0) {
|
||||||
info->access = NO_SU_ACCESS;
|
info->access.silent_deny();
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -396,10 +400,10 @@ void su_daemon_handler(int client, const sock_cred *cred) {
|
|||||||
if (ctx.req.target == -1)
|
if (ctx.req.target == -1)
|
||||||
ctx.req.target = ctx.pid;
|
ctx.req.target = ctx.pid;
|
||||||
else if (ctx.req.target == 0)
|
else if (ctx.req.target == 0)
|
||||||
ctx.info->cfg[SU_MNT_NS] = NAMESPACE_MODE_GLOBAL;
|
ctx.info->cfg.mnt_ns = NAMESPACE_MODE_GLOBAL;
|
||||||
else if (ctx.info->cfg[SU_MNT_NS] == NAMESPACE_MODE_GLOBAL)
|
else if (ctx.info->cfg.mnt_ns == NAMESPACE_MODE_GLOBAL)
|
||||||
ctx.info->cfg[SU_MNT_NS] = NAMESPACE_MODE_REQUESTER;
|
ctx.info->cfg.mnt_ns = NAMESPACE_MODE_REQUESTER;
|
||||||
switch (ctx.info->cfg[SU_MNT_NS]) {
|
switch (ctx.info->cfg.mnt_ns) {
|
||||||
case NAMESPACE_MODE_GLOBAL:
|
case NAMESPACE_MODE_GLOBAL:
|
||||||
LOGD("su: use global namespace\n");
|
LOGD("su: use global namespace\n");
|
||||||
break;
|
break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user