Fix MULTIUSER_MODE_OWNER_MANAGED

This commit is contained in:
topjohnwu 2022-02-06 06:45:58 -08:00
parent 3eb1a7e384
commit a7392ed3d7
3 changed files with 43 additions and 46 deletions

View File

@ -20,10 +20,6 @@ exe, "/system/bin", "com.android.commands.am.Am", \
// 0x18000020 = FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_MULTIPLE_TASK|FLAG_INCLUDE_STOPPED_PACKAGES
#define get_user(info) \
((info)->cfg[SU_MULTIUSER_MODE] == MULTIUSER_MODE_USER \
? to_user_id((info)->uid) : 0)
#define get_cmd(to) \
((to).command.empty() ? \
((to).shell.empty() ? DEFAULT_SHELL : (to).shell.data()) : \
@ -108,7 +104,7 @@ static void exec_cmd(const char *action, vector<Extra> &data,
char exe[128];
char target[128];
char user[4];
snprintf(user, sizeof(user), "%d", get_user(info));
snprintf(user, sizeof(user), "%d", to_user_id(info->eval_uid));
if (zygisk_enabled) {
#if defined(__LP64__)
@ -206,7 +202,7 @@ int app_request(const shared_ptr<su_info> &info) {
vector<Extra> extras;
extras.reserve(2);
extras.emplace_back("fifo", fifo);
extras.emplace_back("uid", info->uid);
extras.emplace_back("uid", info->eval_uid);
exec_cmd("request", extras, info, false);
// Wait for data input for at most 70 seconds

View File

@ -15,26 +15,29 @@
class su_info {
public:
/* Unique key */
// Unique key
const int uid;
/* These should be guarded with internal lock */
// These should be guarded with internal lock
int eval_uid; // The effective UID, taking multiuser settings into consideration
db_settings cfg;
su_access access;
std::string mgr_pkg;
struct stat mgr_st;
void check_db();
/* This should be guarded with global cache lock */
long timestamp;
su_info(unsigned uid = 0);
~su_info();
mutex_guard lock();
// These should be guarded with global cache lock
bool is_fresh();
void refresh();
su_info(int uid);
~su_info();
mutex_guard lock();
private:
pthread_mutex_t _lock; /* Internal lock */
long timestamp;
// Internal lock
pthread_mutex_t _lock;
};
struct su_req_base {

View File

@ -19,8 +19,8 @@ using namespace std;
static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER;
static shared_ptr<su_info> cached;
su_info::su_info(unsigned uid) :
uid(uid), access(DEFAULT_SU_ACCESS), mgr_st({}),
su_info::su_info(int uid) :
uid(uid), eval_uid(-1), access(DEFAULT_SU_ACCESS), mgr_st{},
timestamp(0), _lock(PTHREAD_MUTEX_INITIALIZER) {}
su_info::~su_info() {
@ -44,47 +44,45 @@ void su_info::refresh() {
timestamp = ts.tv_sec * 1000L + ts.tv_nsec / 1000000L;
}
static void database_check(const shared_ptr<su_info> &info) {
int uid = info->uid;
get_db_settings(info->cfg);
void su_info::check_db() {
eval_uid = uid;
get_db_settings(cfg);
// Check multiuser settings
switch (info->cfg[SU_MULTIUSER_MODE]) {
switch (cfg[SU_MULTIUSER_MODE]) {
case MULTIUSER_MODE_OWNER_ONLY:
if (to_user_id(uid) != 0) {
uid = -1;
info->access = NO_SU_ACCESS;
eval_uid = -1;
access = NO_SU_ACCESS;
}
break;
case MULTIUSER_MODE_OWNER_MANAGED:
uid = to_app_id(uid);
eval_uid = to_app_id(uid);
break;
case MULTIUSER_MODE_USER:
default:
break;
}
su_access &su = info->access;
if (uid > 0) {
if (eval_uid > 0) {
char query[256], *err;
sprintf(query,
snprintf(query, sizeof(query),
"SELECT policy, logging, notification FROM policies "
"WHERE uid=%d AND (until=0 OR until>%li)", uid, time(nullptr));
"WHERE uid=%d AND (until=0 OR until>%li)", eval_uid, time(nullptr));
err = db_exec(query, [&](db_row &row) -> bool {
su.policy = (policy_t) parse_int(row["policy"]);
su.log = parse_int(row["logging"]);
su.notify = parse_int(row["notification"]);
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",
su.policy, su.log, su.notify);
access.policy, access.log, access.notify);
return true;
});
db_err_cmd(err, return);
}
// We need to check our manager
if (su.log || su.notify)
get_manager(to_user_id(uid), &info->mgr_pkg, &info->mgr_st);
if (access.log || access.notify)
get_manager(to_user_id(eval_uid), &mgr_pkg, &mgr_st);
}
bool uid_granted_root(int uid) {
@ -156,7 +154,7 @@ static shared_ptr<su_info> get_su_info(unsigned uid) {
if (info->access.policy == QUERY) {
// Not cached, get data from database
database_check(info);
info->check_db();
// If it's root or the manager, allow it silently
if (info->uid == UID_ROOT || to_app_id(info->uid) == to_app_id(info->mgr_st.st_uid)) {