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 // 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) \ #define get_cmd(to) \
((to).command.empty() ? \ ((to).command.empty() ? \
((to).shell.empty() ? DEFAULT_SHELL : (to).shell.data()) : \ ((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 exe[128];
char target[128]; char target[128];
char user[4]; 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 (zygisk_enabled) {
#if defined(__LP64__) #if defined(__LP64__)
@ -206,7 +202,7 @@ int app_request(const shared_ptr<su_info> &info) {
vector<Extra> extras; vector<Extra> extras;
extras.reserve(2); extras.reserve(2);
extras.emplace_back("fifo", fifo); extras.emplace_back("fifo", fifo);
extras.emplace_back("uid", info->uid); extras.emplace_back("uid", info->eval_uid);
exec_cmd("request", extras, info, false); exec_cmd("request", extras, info, false);
// Wait for data input for at most 70 seconds // Wait for data input for at most 70 seconds

View File

@ -15,26 +15,29 @@
class su_info { class su_info {
public: public:
/* Unique key */ // Unique key
const int uid; 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; db_settings cfg;
su_access access; su_access access;
std::string mgr_pkg; std::string mgr_pkg;
struct stat mgr_st; struct stat mgr_st;
void check_db();
/* This should be guarded with global cache lock */ // These should be guarded with global cache lock
long timestamp;
su_info(unsigned uid = 0);
~su_info();
mutex_guard lock();
bool is_fresh(); bool is_fresh();
void refresh(); void refresh();
su_info(int uid);
~su_info();
mutex_guard lock();
private: private:
pthread_mutex_t _lock; /* Internal lock */ long timestamp;
// Internal lock
pthread_mutex_t _lock;
}; };
struct su_req_base { struct su_req_base {

View File

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