Fix su_info cache bug
This commit is contained in:
parent
8cf475f708
commit
cdb53ca049
@ -22,9 +22,6 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#define LOCK_CACHE() pthread_mutex_lock(&cache_lock)
|
|
||||||
#define UNLOCK_CACHE() pthread_mutex_unlock(&cache_lock)
|
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
@ -86,53 +83,56 @@ static void database_check(const shared_ptr<su_info> &info) {
|
|||||||
validate_manager(info->str[SU_MANAGER], uid / 100000, &info->mgr_st);
|
validate_manager(info->str[SU_MANAGER], uid / 100000, &info->mgr_st);
|
||||||
}
|
}
|
||||||
|
|
||||||
static shared_ptr<su_info> get_su_info(unsigned uid) {
|
static void update_su_info(unsigned uid) {
|
||||||
shared_ptr<su_info> info;
|
LOGD("su: request from uid=[%d]\n", uid);
|
||||||
|
|
||||||
// Get from cache or new instance
|
RunFinally refresh([] {
|
||||||
LOCK_CACHE();
|
cached->refresh();
|
||||||
if (!cached || cached->uid != uid || !cached->is_fresh())
|
|
||||||
cached = make_shared<su_info>(uid);
|
|
||||||
info = cached;
|
|
||||||
info->refresh();
|
|
||||||
UNLOCK_CACHE();
|
|
||||||
|
|
||||||
LOGD("su: request from uid=[%d]\n", info->uid);
|
|
||||||
|
|
||||||
// Lock before the policy is determined
|
|
||||||
info->lock();
|
|
||||||
RunFinally unlock([&] {
|
|
||||||
info->unlock();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (info->access.policy == QUERY) {
|
// Get from cache or new instance
|
||||||
|
{
|
||||||
|
MutexGuard lock(cache_lock);
|
||||||
|
if (!cached || cached->uid != uid || !cached->is_fresh())
|
||||||
|
cached = make_shared<su_info>(uid);
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lock before the policy is determined
|
||||||
|
cached->lock();
|
||||||
|
RunFinally unlock([&] {
|
||||||
|
cached->unlock();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (cached->access.policy == QUERY) {
|
||||||
// Not cached, get data from database
|
// Not cached, get data from database
|
||||||
database_check(info);
|
database_check(cached);
|
||||||
|
|
||||||
// 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 || (info->uid % 100000) == (info->mgr_st.st_uid % 100000)) {
|
if (cached->uid == UID_ROOT || (cached->uid % 100000) == (cached->mgr_st.st_uid % 100000)) {
|
||||||
info->access = SILENT_SU_ACCESS;
|
cached->access = SILENT_SU_ACCESS;
|
||||||
return info;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check su access settings
|
// Check su access settings
|
||||||
switch (info->cfg[ROOT_ACCESS]) {
|
switch (cached->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;
|
cached->access = NO_SU_ACCESS;
|
||||||
return info;
|
return;
|
||||||
case ROOT_ACCESS_ADB_ONLY:
|
case ROOT_ACCESS_ADB_ONLY:
|
||||||
if (info->uid != UID_SHELL) {
|
if (cached->uid != UID_SHELL) {
|
||||||
LOGW("Root access limited to ADB only!\n");
|
LOGW("Root access limited to ADB only!\n");
|
||||||
info->access = NO_SU_ACCESS;
|
cached->access = NO_SU_ACCESS;
|
||||||
return info;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ROOT_ACCESS_APPS_ONLY:
|
case ROOT_ACCESS_APPS_ONLY:
|
||||||
if (info->uid == UID_SHELL) {
|
if (cached->uid == UID_SHELL) {
|
||||||
LOGW("Root access is disabled for ADB!\n");
|
LOGW("Root access is disabled for ADB!\n");
|
||||||
info->access = NO_SU_ACCESS;
|
cached->access = NO_SU_ACCESS;
|
||||||
return info;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ROOT_ACCESS_APPS_AND_ADB:
|
case ROOT_ACCESS_APPS_AND_ADB:
|
||||||
@ -140,13 +140,13 @@ static shared_ptr<su_info> get_su_info(unsigned uid) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->access.policy != QUERY)
|
if (cached->access.policy != QUERY)
|
||||||
return info;
|
return;
|
||||||
|
|
||||||
// If still not determined, check if manager exists
|
// If still not determined, check if manager exists
|
||||||
if (info->str[SU_MANAGER][0] == '\0') {
|
if (cached->str[SU_MANAGER][0] == '\0') {
|
||||||
info->access = NO_SU_ACCESS;
|
cached->access = NO_SU_ACCESS;
|
||||||
return info;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,19 +155,17 @@ static shared_ptr<su_info> get_su_info(unsigned uid) {
|
|||||||
int sockfd = create_rand_socket(&addr);
|
int sockfd = create_rand_socket(&addr);
|
||||||
|
|
||||||
// Connect manager
|
// Connect manager
|
||||||
app_connect(addr.sun_path + 1, info);
|
app_connect(addr.sun_path + 1, cached);
|
||||||
int fd = socket_accept(sockfd, 60);
|
int fd = socket_accept(sockfd, 60);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
info->access.policy = DENY;
|
cached->access.policy = DENY;
|
||||||
} else {
|
} else {
|
||||||
socket_send_request(fd, info);
|
socket_send_request(fd, cached);
|
||||||
int ret = read_int_be(fd);
|
int ret = read_int_be(fd);
|
||||||
info->access.policy = ret < 0 ? DENY : static_cast<policy_t>(ret);
|
cached->access.policy = ret < 0 ? DENY : static_cast<policy_t>(ret);
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
close(sockfd);
|
close(sockfd);
|
||||||
|
|
||||||
return info;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_identity(unsigned uid) {
|
static void set_identity(unsigned uid) {
|
||||||
@ -189,8 +187,9 @@ static void set_identity(unsigned uid) {
|
|||||||
void su_daemon_handler(int client, struct ucred *credential) {
|
void su_daemon_handler(int client, struct ucred *credential) {
|
||||||
LOGD("su: request from pid=[%d], client=[%d]\n", credential->pid, client);
|
LOGD("su: request from pid=[%d], client=[%d]\n", credential->pid, client);
|
||||||
|
|
||||||
|
update_su_info(credential->uid);
|
||||||
su_context ctx = {
|
su_context ctx = {
|
||||||
.info = get_su_info(credential->uid),
|
.info = cached,
|
||||||
.req = su_request(true),
|
.req = su_request(true),
|
||||||
.pid = credential->pid
|
.pid = credential->pid
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user