mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-10-15 22:13:11 +00:00
Fully migrate Magisk to C++
This commit is contained in:
@@ -19,7 +19,7 @@
|
||||
|
||||
#define AM_PATH "/system/bin/app_process", "/system/bin", "com.android.commands.am.Am"
|
||||
|
||||
static char *get_command(const struct su_request *to) {
|
||||
static const char *get_command(const struct su_request *to) {
|
||||
if (to->command[0])
|
||||
return to->command;
|
||||
if (to->shell[0])
|
||||
@@ -27,7 +27,7 @@ static char *get_command(const struct su_request *to) {
|
||||
return DEFAULT_SHELL;
|
||||
}
|
||||
|
||||
static void silent_run(char * const args[]) {
|
||||
static void silent_run(const char *args[]) {
|
||||
if (fork_dont_care())
|
||||
return;
|
||||
int zero = open("/dev/zero", O_RDONLY | O_CLOEXEC);
|
||||
@@ -36,7 +36,7 @@ static void silent_run(char * const args[]) {
|
||||
xdup2(null, 1);
|
||||
xdup2(null, 2);
|
||||
setenv("CLASSPATH", "/system/framework/am.jar", 1);
|
||||
execv(args[0], args);
|
||||
execv(args[0], (char **) args);
|
||||
PLOGE("exec am");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
@@ -71,7 +71,7 @@ void app_log(struct su_context *ctx) {
|
||||
char policy[2];
|
||||
sprintf(policy, "%d", ctx->info->access.policy);
|
||||
|
||||
char *cmd[] = {
|
||||
const char *cmd[] = {
|
||||
AM_PATH, "broadcast",
|
||||
"-a", "android.intent.action.BOOT_COMPLETED",
|
||||
"-p", DB_STR(ctx->info, SU_MANAGER),
|
||||
@@ -84,7 +84,7 @@ void app_log(struct su_context *ctx) {
|
||||
"--ei", "policy", policy,
|
||||
"--es", "command", get_command(&ctx->req),
|
||||
"--ez", "notify", ctx->info->access.notify ? "true" : "false",
|
||||
NULL
|
||||
nullptr
|
||||
};
|
||||
silent_run(cmd);
|
||||
}
|
||||
@@ -101,7 +101,7 @@ void app_notify(struct su_context *ctx) {
|
||||
char policy[2];
|
||||
sprintf(policy, "%d", ctx->info->access.policy);
|
||||
|
||||
char *cmd[] = {
|
||||
const char *cmd[] = {
|
||||
AM_PATH, "broadcast",
|
||||
"-a", "android.intent.action.BOOT_COMPLETED",
|
||||
"-p", DB_STR(ctx->info, SU_MANAGER),
|
||||
@@ -110,7 +110,7 @@ void app_notify(struct su_context *ctx) {
|
||||
"--es", "action", "notify",
|
||||
"--ei", "from.uid", fromUid,
|
||||
"--ei", "policy", policy,
|
||||
NULL
|
||||
nullptr
|
||||
};
|
||||
silent_run(cmd);
|
||||
}
|
||||
@@ -118,15 +118,15 @@ void app_notify(struct su_context *ctx) {
|
||||
void app_connect(const char *socket, struct su_info *info) {
|
||||
char user[8];
|
||||
setup_user(user, info);
|
||||
char *cmd[] = {
|
||||
const char *cmd[] = {
|
||||
AM_PATH, "broadcast",
|
||||
"-a", "android.intent.action.BOOT_COMPLETED",
|
||||
"-p", DB_STR(info, SU_MANAGER),
|
||||
"-f", "0x00000020",
|
||||
"--user", user,
|
||||
"--es", "action", "request",
|
||||
"--es", "socket", (char *) socket,
|
||||
NULL
|
||||
"--es", "socket", socket,
|
||||
nullptr
|
||||
};
|
||||
silent_run(cmd);
|
||||
}
|
||||
@@ -135,4 +135,3 @@ void socket_send_request(int fd, struct su_info *info) {
|
||||
write_key_token(fd, "uid", info->uid);
|
||||
write_string_be(fd, "eof");
|
||||
}
|
||||
|
@@ -9,7 +9,6 @@
|
||||
* helper functions to handle raw input mode and terminal window resizing
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
@@ -8,7 +8,6 @@
|
||||
/* su.c - The main function running in the daemon
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -95,6 +94,12 @@ static void setup_sighandlers(void (*handler)(int)) {
|
||||
}
|
||||
}
|
||||
|
||||
// Default values
|
||||
su_req_base::su_req_base()
|
||||
: uid(UID_ROOT), login(false), keepenv(false), mount_master(false) {}
|
||||
su_request::su_request()
|
||||
: shell(DEFAULT_SHELL), command("") {}
|
||||
|
||||
/*
|
||||
* Connect daemon, send argc, argv, cwd, pts slave
|
||||
*/
|
||||
@@ -112,15 +117,7 @@ int su_client_main(int argc, char *argv[]) {
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
|
||||
struct su_request su_req = {
|
||||
.uid = UID_ROOT,
|
||||
.login = 0,
|
||||
.keepenv = 0,
|
||||
.mount_master = 0,
|
||||
.shell = DEFAULT_SHELL,
|
||||
.command = "",
|
||||
};
|
||||
|
||||
su_request su_req;
|
||||
|
||||
for (int i = 0; i < argc; i++) {
|
||||
// Replace -cn with -z, -mm with -M for supporting getopt_long
|
||||
@@ -140,11 +137,11 @@ int su_client_main(int argc, char *argv[]) {
|
||||
usage(EXIT_SUCCESS);
|
||||
break;
|
||||
case 'l':
|
||||
su_req.login = 1;
|
||||
su_req.login = true;
|
||||
break;
|
||||
case 'm':
|
||||
case 'p':
|
||||
su_req.keepenv = 1;
|
||||
su_req.keepenv = true;
|
||||
break;
|
||||
case 's':
|
||||
su_req.shell = optarg;
|
||||
@@ -159,7 +156,7 @@ int su_client_main(int argc, char *argv[]) {
|
||||
// Do nothing, placed here for legacy support :)
|
||||
break;
|
||||
case 'M':
|
||||
su_req.mount_master = 1;
|
||||
su_req.mount_master = true;
|
||||
break;
|
||||
default:
|
||||
/* Bionic getopt_long doesn't terminate its error output by newline */
|
||||
@@ -169,7 +166,7 @@ int su_client_main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
if (optind < argc && strcmp(argv[optind], "-") == 0) {
|
||||
su_req.login = 1;
|
||||
su_req.login = true;
|
||||
optind++;
|
||||
}
|
||||
/* username or uid */
|
||||
@@ -200,7 +197,7 @@ int su_client_main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
// Send su_request
|
||||
xwrite(fd, &su_req, 4 * sizeof(unsigned));
|
||||
xwrite(fd, &su_req, sizeof(su_req_base));
|
||||
write_string(fd, su_req.shell);
|
||||
write_string(fd, su_req.command);
|
||||
|
||||
@@ -242,4 +239,4 @@ int su_client_main(int argc, char *argv[]) {
|
||||
close(fd);
|
||||
|
||||
return code;
|
||||
}
|
||||
}
|
@@ -17,9 +17,9 @@
|
||||
#define ATTY_OUT 2
|
||||
#define ATTY_ERR 4
|
||||
|
||||
struct su_info {
|
||||
class su_info {
|
||||
public:
|
||||
unsigned uid; /* Unique key to find su_info */
|
||||
pthread_mutex_t lock; /* Internal lock */
|
||||
int count; /* Just a count for debugging purpose */
|
||||
|
||||
/* These values should be guarded with internal lock */
|
||||
@@ -31,19 +31,33 @@ struct su_info {
|
||||
/* These should be guarded with global cache lock */
|
||||
int ref;
|
||||
int life;
|
||||
|
||||
su_info(unsigned uid);
|
||||
~su_info();
|
||||
void lock();
|
||||
void unlock();
|
||||
|
||||
private:
|
||||
pthread_mutex_t _lock; /* Internal lock */
|
||||
};
|
||||
|
||||
#define DB_SET(i, e) (i)->dbs.v[e]
|
||||
#define DB_STR(i, e) (i)->str.s[e]
|
||||
|
||||
struct su_request {
|
||||
struct su_req_base {
|
||||
unsigned uid;
|
||||
unsigned login;
|
||||
unsigned keepenv;
|
||||
unsigned mount_master;
|
||||
char *shell;
|
||||
char *command;
|
||||
};
|
||||
bool login;
|
||||
bool keepenv;
|
||||
bool mount_master;
|
||||
protected:
|
||||
su_req_base();
|
||||
} __attribute__((packed));
|
||||
|
||||
struct su_request : public su_req_base {
|
||||
const char *shell;
|
||||
const char *command;
|
||||
su_request();
|
||||
} __attribute__((packed));
|
||||
|
||||
struct su_context {
|
||||
struct su_info *info;
|
||||
|
@@ -1,8 +1,3 @@
|
||||
/* su_daemon.c - The entrypoint for su, connect to daemon and send correct info
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
@@ -25,32 +20,45 @@
|
||||
#define TIMEOUT 3
|
||||
|
||||
#define LOCK_CACHE() pthread_mutex_lock(&cache_lock)
|
||||
#define LOCK_INFO() pthread_mutex_lock(&info->lock)
|
||||
#define UNLOCK_CACHE() pthread_mutex_unlock(&cache_lock)
|
||||
#define UNLOCK_INFO() pthread_mutex_unlock(&info->lock)
|
||||
|
||||
static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static struct su_info *cache;
|
||||
static su_info *cache;
|
||||
|
||||
su_info::su_info(unsigned uid) :
|
||||
uid(uid), access(DEFAULT_SU_ACCESS), _lock(PTHREAD_MUTEX_INITIALIZER),
|
||||
count(0), ref(0), life(0), mgr_st({}) {}
|
||||
|
||||
su_info::~su_info() {
|
||||
pthread_mutex_destroy(&_lock);
|
||||
}
|
||||
|
||||
void su_info::lock() {
|
||||
pthread_mutex_lock(&_lock);
|
||||
}
|
||||
|
||||
void su_info::unlock() {
|
||||
pthread_mutex_unlock(&_lock);
|
||||
}
|
||||
|
||||
static void *info_collector(void *node) {
|
||||
struct su_info *info = node;
|
||||
su_info *info = (su_info *) node;
|
||||
while (1) {
|
||||
sleep(1);
|
||||
if (info->life) {
|
||||
LOCK_CACHE();
|
||||
if (--info->life == 0 && cache && info->uid == cache->uid)
|
||||
cache = NULL;
|
||||
cache = nullptr;
|
||||
UNLOCK_CACHE();
|
||||
}
|
||||
if (!info->life && !info->ref) {
|
||||
pthread_mutex_destroy(&info->lock);
|
||||
free(info);
|
||||
return NULL;
|
||||
delete info;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void database_check(struct su_info *info) {
|
||||
static void database_check(su_info *info) {
|
||||
int uid = info->uid;
|
||||
sqlite3 *db = get_magiskdb();
|
||||
if (db) {
|
||||
@@ -84,20 +92,16 @@ static void database_check(struct su_info *info) {
|
||||
}
|
||||
|
||||
static struct su_info *get_su_info(unsigned uid) {
|
||||
struct su_info *info;
|
||||
int cache_miss = 0;
|
||||
su_info *info;
|
||||
bool cache_miss = false;
|
||||
|
||||
LOCK_CACHE();
|
||||
|
||||
if (cache && cache->uid == uid) {
|
||||
info = cache;
|
||||
} else {
|
||||
cache_miss = 1;
|
||||
info = xcalloc(1, sizeof(*info));
|
||||
info->uid = uid;
|
||||
info->dbs = DEFAULT_DB_SETTINGS;
|
||||
info->access = DEFAULT_SU_ACCESS;
|
||||
pthread_mutex_init(&info->lock, NULL);
|
||||
cache_miss = true;
|
||||
info = new su_info(uid);
|
||||
cache = info;
|
||||
}
|
||||
|
||||
@@ -108,7 +112,7 @@ static struct su_info *get_su_info(unsigned uid) {
|
||||
// Start a thread to maintain the cache
|
||||
if (cache_miss) {
|
||||
pthread_t thread;
|
||||
xpthread_create(&thread, NULL, info_collector, info);
|
||||
xpthread_create(&thread, nullptr, info_collector, info);
|
||||
pthread_detach(thread);
|
||||
}
|
||||
|
||||
@@ -117,7 +121,7 @@ static struct su_info *get_su_info(unsigned uid) {
|
||||
LOGD("su: request from uid=[%d] (#%d)\n", info->uid, ++info->count);
|
||||
|
||||
// Lock before the policy is determined
|
||||
LOCK_INFO();
|
||||
info->lock();
|
||||
|
||||
if (info->access.policy == QUERY) {
|
||||
// Not cached, get data from database
|
||||
@@ -173,14 +177,14 @@ static struct su_info *get_su_info(unsigned uid) {
|
||||
} else {
|
||||
socket_send_request(fd, info);
|
||||
int ret = read_int_be(fd);
|
||||
info->access.policy = ret < 0 ? DENY : ret;
|
||||
info->access.policy = ret < 0 ? DENY : static_cast<policy_t>(ret);
|
||||
close(fd);
|
||||
}
|
||||
close(sockfd);
|
||||
}
|
||||
|
||||
// Unlock
|
||||
UNLOCK_INFO();
|
||||
info->unlock();
|
||||
|
||||
return info;
|
||||
}
|
||||
@@ -224,7 +228,7 @@ static void set_identity(unsigned uid) {
|
||||
void su_daemon_handler(int client, struct ucred *credential) {
|
||||
LOGD("su: request from client: %d\n", client);
|
||||
|
||||
struct su_info *info = get_su_info(credential->uid);
|
||||
su_info *info = get_su_info(credential->uid);
|
||||
|
||||
// Fail fast
|
||||
if (info->access.policy == DENY && DB_STR(info, SU_MANAGER)[0] == '\0') {
|
||||
@@ -289,7 +293,7 @@ void su_daemon_handler(int client, struct ucred *credential) {
|
||||
}
|
||||
|
||||
// Read su_request
|
||||
xxread(client, &ctx.req, 4 * sizeof(unsigned));
|
||||
xxread(client, &ctx.req, sizeof(su_req_base));
|
||||
ctx.req.shell = read_string(client);
|
||||
ctx.req.command = read_string(client);
|
||||
|
||||
@@ -367,7 +371,7 @@ void su_daemon_handler(int client, struct ucred *credential) {
|
||||
app_notify(&ctx);
|
||||
|
||||
if (info->access.policy == ALLOW) {
|
||||
char* argv[] = { NULL, NULL, NULL, NULL };
|
||||
const char *argv[] = { nullptr, nullptr, nullptr, nullptr };
|
||||
|
||||
argv[0] = ctx.req.login ? "-" : ctx.req.shell;
|
||||
|
||||
@@ -381,7 +385,7 @@ void su_daemon_handler(int client, struct ucred *credential) {
|
||||
populate_environment(&ctx.req);
|
||||
set_identity(ctx.req.uid);
|
||||
|
||||
execvp(ctx.req.shell, argv);
|
||||
execvp(ctx.req.shell, (char **) argv);
|
||||
fprintf(stderr, "Cannot execute %s: %s\n", ctx.req.shell, strerror(errno));
|
||||
PLOGE("exec");
|
||||
exit(EXIT_FAILURE);
|
||||
@@ -391,4 +395,3 @@ void su_daemon_handler(int client, struct ucred *credential) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user