Simplify su_info caches
No more lists. 99.999% it will only handle a single excessive requestor anyways.
This commit is contained in:
parent
58ae596b0f
commit
6a06c92fa6
@ -9,7 +9,6 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "db.h"
|
#include "db.h"
|
||||||
#include "list.h"
|
|
||||||
|
|
||||||
#define DEFAULT_SHELL "/system/bin/sh"
|
#define DEFAULT_SHELL "/system/bin/sh"
|
||||||
|
|
||||||
@ -24,10 +23,9 @@ struct su_info {
|
|||||||
struct su_access access;
|
struct su_access access;
|
||||||
struct stat manager_stat;
|
struct stat manager_stat;
|
||||||
|
|
||||||
/* These should be guarded with global list lock */
|
/* These should be guarded with global cache lock */
|
||||||
struct list_head pos;
|
|
||||||
int ref;
|
int ref;
|
||||||
int clock;
|
int life;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct su_request {
|
struct su_request {
|
||||||
@ -57,7 +55,6 @@ void set_identity(unsigned uid);
|
|||||||
// connect.c
|
// connect.c
|
||||||
|
|
||||||
void app_log();
|
void app_log();
|
||||||
|
|
||||||
void app_connect(const char *socket);
|
void app_connect(const char *socket);
|
||||||
void socket_send_request(int fd);
|
void socket_send_request(int fd);
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "su.h"
|
#include "su.h"
|
||||||
#include "pts.h"
|
#include "pts.h"
|
||||||
#include "list.h"
|
|
||||||
#include "selinux.h"
|
#include "selinux.h"
|
||||||
|
|
||||||
// Constants for the atty bitfield
|
// Constants for the atty bitfield
|
||||||
@ -29,13 +28,13 @@
|
|||||||
|
|
||||||
#define TIMEOUT 3
|
#define TIMEOUT 3
|
||||||
|
|
||||||
#define LOCK_LIST() pthread_mutex_lock(&list_lock)
|
#define LOCK_CACHE() pthread_mutex_lock(&cache_lock)
|
||||||
#define LOCK_UID() pthread_mutex_lock(&info->lock)
|
#define LOCK_INFO() pthread_mutex_lock(&info->lock)
|
||||||
#define UNLOCK_LIST() pthread_mutex_unlock(&list_lock)
|
#define UNLOCK_CACHE() pthread_mutex_unlock(&cache_lock)
|
||||||
#define UNLOCK_UID() pthread_mutex_unlock(&ctx.info->lock)
|
#define UNLOCK_INFO() pthread_mutex_unlock(&ctx.info->lock)
|
||||||
|
|
||||||
static struct list_head info_cache = { .prev = &info_cache, .next = &info_cache };
|
static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
static pthread_mutex_t list_lock = PTHREAD_MUTEX_INITIALIZER;
|
static struct su_info *cache;
|
||||||
|
|
||||||
static void sighandler(int sig) {
|
static void sighandler(int sig) {
|
||||||
restore_stdin();
|
restore_stdin();
|
||||||
@ -64,12 +63,13 @@ static void *info_collector(void *node) {
|
|||||||
struct su_info *info = node;
|
struct su_info *info = node;
|
||||||
while (1) {
|
while (1) {
|
||||||
sleep(1);
|
sleep(1);
|
||||||
if (info->clock && --info->clock == 0) {
|
if (info->life) {
|
||||||
LOCK_LIST();
|
LOCK_CACHE();
|
||||||
list_pop(&info->pos);
|
if (--info->life == 0 && cache && info->uid == cache->uid)
|
||||||
UNLOCK_LIST();
|
cache = NULL;
|
||||||
|
UNLOCK_CACHE();
|
||||||
}
|
}
|
||||||
if (!info->clock && !info->ref) {
|
if (!info->life && !info->ref) {
|
||||||
pthread_mutex_destroy(&info->lock);
|
pthread_mutex_destroy(&info->lock);
|
||||||
free(info);
|
free(info);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -111,22 +111,15 @@ static void database_check(struct su_info *info) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct su_info *get_su_info(unsigned uid) {
|
static struct su_info *get_su_info(unsigned uid) {
|
||||||
struct su_info *info = NULL, *node;
|
struct su_info *info;
|
||||||
|
int cache_miss = 0;
|
||||||
|
|
||||||
LOCK_LIST();
|
LOCK_CACHE();
|
||||||
|
|
||||||
// Search for existing info in cache
|
if (cache && cache->uid == uid) {
|
||||||
list_for_each(node, &info_cache, struct su_info, pos) {
|
info = cache;
|
||||||
if (node->uid == uid) {
|
} else {
|
||||||
info = node;
|
cache_miss = 1;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int cache_miss = info == NULL;
|
|
||||||
|
|
||||||
if (cache_miss) {
|
|
||||||
// If cache miss, create a new one and push to cache
|
|
||||||
info = malloc(sizeof(*info));
|
info = malloc(sizeof(*info));
|
||||||
info->uid = uid;
|
info->uid = uid;
|
||||||
info->dbs = DEFAULT_DB_SETTINGS;
|
info->dbs = DEFAULT_DB_SETTINGS;
|
||||||
@ -135,26 +128,26 @@ static struct su_info *get_su_info(unsigned uid) {
|
|||||||
info->ref = 0;
|
info->ref = 0;
|
||||||
info->count = 0;
|
info->count = 0;
|
||||||
pthread_mutex_init(&info->lock, NULL);
|
pthread_mutex_init(&info->lock, NULL);
|
||||||
list_insert_end(&info_cache, &info->pos);
|
cache = info;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the cache status
|
// Update the cache status
|
||||||
info->clock = TIMEOUT;
|
info->life = TIMEOUT;
|
||||||
++info->ref;
|
++info->ref;
|
||||||
|
|
||||||
// Start a thread to maintain the info cache
|
// Start a thread to maintain the cache
|
||||||
if (cache_miss) {
|
if (cache_miss) {
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
xpthread_create(&thread, NULL, info_collector, info);
|
xpthread_create(&thread, NULL, info_collector, info);
|
||||||
pthread_detach(thread);
|
pthread_detach(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
UNLOCK_LIST();
|
UNLOCK_CACHE();
|
||||||
|
|
||||||
LOGD("su: request from uid=[%d] (#%d)\n", info->uid, ++info->count);
|
LOGD("su: request from uid=[%d] (#%d)\n", info->uid, ++info->count);
|
||||||
|
|
||||||
// Lock before the policy is determined
|
// Lock before the policy is determined
|
||||||
LOCK_UID();
|
LOCK_INFO();
|
||||||
|
|
||||||
if (info->access.policy == QUERY) {
|
if (info->access.policy == QUERY) {
|
||||||
// Not cached, get data from database
|
// Not cached, get data from database
|
||||||
@ -318,7 +311,7 @@ void su_daemon_receiver(int client, struct ucred *credential) {
|
|||||||
|
|
||||||
// Fail fast
|
// Fail fast
|
||||||
if (ctx.info->access.policy == DENY && !ctx.info->access.log && !ctx.info->access.notify) {
|
if (ctx.info->access.policy == DENY && !ctx.info->access.log && !ctx.info->access.notify) {
|
||||||
UNLOCK_UID();
|
UNLOCK_INFO();
|
||||||
write_int(client, DENY);
|
write_int(client, DENY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -346,7 +339,7 @@ void su_daemon_receiver(int client, struct ucred *credential) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The policy is determined, unlock
|
// The policy is determined, unlock
|
||||||
UNLOCK_UID();
|
UNLOCK_INFO();
|
||||||
|
|
||||||
// Info is now useless to us, decrement reference count
|
// Info is now useless to us, decrement reference count
|
||||||
--ctx.info->ref;
|
--ctx.info->ref;
|
||||||
|
Loading…
Reference in New Issue
Block a user