diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 86d1c906b..7a536d0f7 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -43,10 +43,15 @@
+ android:exported="false"
+ tools:ignore="AppLinkUrlError">
+
+
+
+
+
() {
@@ -28,13 +30,28 @@ open class SuRequestActivity : BaseActivitycfg[SU_MULTIUSER_MODE] == MULTIUSER_MODE_USER \
-? info->uid / 100000 \
-: 0)
+? info->uid / 100000 : 0)
#define get_uid(info) \
(info->cfg[SU_MULTIUSER_MODE] == MULTIUSER_MODE_OWNER_MANAGED \
-? info->uid % 100000 \
-: info->uid)
+? info->uid % 100000 : info->uid)
-static const char *get_command(const su_request *to) {
- if (to->command[0])
- return to->command;
- if (to->shell[0])
- return to->shell;
- return DEFAULT_SHELL;
+#define get_cmd(to) \
+(to.command[0] ? to.command : to.shell[0] ? to.shell : DEFAULT_SHELL)
+
+class Extra {
+ const char *key;
+ enum {
+ INT,
+ BOOL,
+ STRING
+ } type;
+ union {
+ int int_val;
+ bool bool_val;
+ const char * str_val;
+ };
+ char i_buf[16];
+ char b_buf[32];
+public:
+ Extra(const char *k, int v): key(k), type(INT), int_val(v) {}
+ Extra(const char *k, bool v): key(k), type(BOOL), bool_val(v) {}
+ Extra(const char *k, const char *v): key(k), type(STRING), str_val(v) {}
+
+ void add_intent(vector &vec) {
+ const char *val;
+ switch (type) {
+ case INT:
+ vec.push_back("--ei");
+ sprintf(i_buf, "%d", int_val);
+ val = i_buf;
+ break;
+ case BOOL:
+ vec.push_back("--ez");
+ val = bool_val ? "true" : "false";
+ break;
+ case STRING:
+ vec.push_back("--es");
+ val = str_val;
+ break;
+ }
+ vec.push_back(key);
+ vec.push_back(val);
+ }
+
+ void add_bind(vector &vec) {
+ switch (type) {
+ case INT:
+ sprintf(b_buf, "%s:i:%d", key, int_val);
+ break;
+ case BOOL:
+ sprintf(b_buf, "%s:b:%s", key, bool_val ? "true" : "false");
+ break;
+ case STRING:
+ sprintf(b_buf, "%s:s:%s", key, str_val);
+ break;
+ }
+ vec.push_back("--extra");
+ vec.push_back(b_buf);
+ }
+};
+
+static bool check_error(int fd) {
+ char buf[1024];
+ unique_ptr out(xfdopen(fd, "r"), fclose);
+ while (fgets(buf, sizeof(buf), out.get())) {
+ if (strncmp(buf, "Error", 5) == 0)
+ return false;
+ }
+ return true;
}
-static void exec_content_cmd(const char **args, const su_info *info) {
+static void exec_cmd(const char *action, vector &data,
+ const shared_ptr &info, int mode = CONTENT_PROVIDER) {
char target[128];
- sprintf(target, "content://%s.provider", info->str[SU_MANAGER].data());
char user[4];
sprintf(user, "%d", get_user(info));
- // Fill in non static arguments
- args[5] = target;
- args[7] = user;
+ // First try content provider call method
+ if (mode >= CONTENT_PROVIDER) {
+ sprintf(target, "content://%s.provider", info->str[SU_MANAGER].data());
+ vector args{ CALL_PROVIDER };
+ for (auto &e : data) {
+ e.add_bind(args);
+ }
+ args.push_back(nullptr);
+ exec_t exec {
+ .err = true,
+ .fd = -1,
+ .pre_exec = [] { setenv("CLASSPATH", "/system/framework/content.jar", 1); },
+ .argv = args.data()
+ };
+ exec_command_sync(exec);
+ if (check_error(exec.fd))
+ return;
+ }
+ vector args{ START_ACTIVITY };
+ for (auto &e : data) {
+ e.add_intent(args);
+ }
+ args.push_back(nullptr);
exec_t exec {
- .pre_exec = [] {
- int null = xopen("/dev/null", O_WRONLY | O_CLOEXEC);
- dup2(null, STDOUT_FILENO);
- dup2(null, STDERR_FILENO);
- setenv("CLASSPATH", "/system/framework/content.jar", 1);
- },
- .fork = fork_dont_care,
- .argv = args
+ .err = true,
+ .fd = -1,
+ .pre_exec = [] { setenv("CLASSPATH", "/system/framework/am.jar", 1); },
+ .argv = args.data()
};
+
+ if (mode >= PKG_ACTIVITY) {
+ // Then try start activity without component name
+ strcpy(target, info->str[SU_MANAGER].data());
+ exec_command_sync(exec);
+ if (check_error(exec.fd))
+ return;
+ }
+
+ // Finally, fallback to start activity with component name
+ args[4] = "-n";
+ sprintf(target, "%s/a.m", info->str[SU_MANAGER].data());
+ exec.fd = -2;
+ exec.fork = fork_dont_care;
exec_command(exec);
}
-#define LOG_BODY \
-"log", \
-ex(fromUid), ex(toUid), ex(pid), ex(policy), \
-ex(command.data()), ex(notify)
-
void app_log(const su_context &ctx) {
- char fromUid[32];
- sprintf(fromUid, "from.uid:i:%d", get_uid(ctx.info));
+ if (fork_dont_care() == 0) {
+ vector extras;
+ extras.reserve(6);
+ extras.emplace_back("from.uid", get_uid(ctx.info));
+ extras.emplace_back("to.uid", ctx.req.uid);
+ extras.emplace_back("pid", ctx.pid);
+ extras.emplace_back("policy", ctx.info->access.policy);
+ extras.emplace_back("command", get_cmd(ctx.req));
+ extras.emplace_back("notify", (bool) ctx.info->access.notify);
- char toUid[32];
- sprintf(toUid, "to.uid:i:%d", ctx.req.uid);
-
- char pid[16];
- sprintf(pid, "pid:i:%d", ctx.pid);
-
- char policy[16];
- sprintf(policy, "policy:i:%d", ctx.info->access.policy);
-
- string command("command:s:");
- command += get_command(&ctx.req);
-
- char notify[16];
- sprintf(notify, "notify:b:%s", ctx.info->access.notify ? "true" : "false");
-
- content_exec(LOG_BODY)
+ exec_cmd("log", extras, ctx.info);
+ exit(0);
+ }
}
-#define NOTIFY_BODY \
-"notify", ex(fromUid), ex(policy)
-
void app_notify(const su_context &ctx) {
- char fromUid[32];
- sprintf(fromUid, "from.uid:i:%d", get_uid(ctx.info));
+ if (fork_dont_care() == 0) {
+ vector extras;
+ extras.reserve(2);
+ extras.emplace_back("from.uid", get_uid(ctx.info));
+ extras.emplace_back("policy", ctx.info->access.policy);
- char policy[16];
- sprintf(policy, "policy:i:%d", ctx.info->access.policy);
-
- content_exec(NOTIFY_BODY)
+ exec_cmd("notify", extras, ctx.info);
+ exit(0);
+ }
}
-#define SOCKET_BODY \
-"request", ex(sock)
-
void app_socket(const char *socket, const shared_ptr &info) {
- char sock[128];
- sprintf(sock, "socket:s:%s", socket);
- content_exec_info(info.get(), SOCKET_BODY)
+ vector extras;
+ extras.reserve(1);
+ extras.emplace_back("socket", socket);
+
+ exec_cmd("request", extras, info, PKG_ACTIVITY);
}
void socket_send_request(int fd, const shared_ptr &info) {
diff --git a/native/jni/su/su.h b/native/jni/su/su.h
index 2c18fc5c8..02fc0aebc 100644
--- a/native/jni/su/su.h
+++ b/native/jni/su/su.h
@@ -17,7 +17,7 @@
class su_info {
public:
/* Unique key */
- const unsigned uid;
+ const int uid;
/* These should be guarded with internal lock */
db_settings cfg;
@@ -39,7 +39,7 @@ private:
};
struct su_req_base {
- unsigned uid = UID_ROOT;
+ int uid = UID_ROOT;
bool login = false;
bool keepenv = false;
bool mount_master = false;
@@ -63,7 +63,7 @@ private:
struct su_context {
std::shared_ptr info;
su_request req;
- pid_t pid;
+ int pid;
};
void app_log(const su_context &ctx);
diff --git a/native/jni/utils/misc.cpp b/native/jni/utils/misc.cpp
index 4678fb41e..2db95f556 100644
--- a/native/jni/utils/misc.cpp
+++ b/native/jni/utils/misc.cpp
@@ -73,7 +73,8 @@ int strend(const char *s1, const char *s2) {
}
int exec_command(exec_t &exec) {
- int pipefd[2] = {-1, -1}, outfd = -1;
+ int pipefd[] = {-1, -1};
+ int outfd = -1;
if (exec.fd == -1) {
if (xpipe2(pipefd, O_CLOEXEC) == -1)
@@ -113,10 +114,10 @@ int exec_command(exec_t &exec) {
}
int exec_command_sync(exec_t &exec) {
- int pid, status;
- pid = exec_command(exec);
+ int pid = exec_command(exec);
if (pid < 0)
return -1;
+ int status;
waitpid(pid, &status, 0);
return WEXITSTATUS(status);
}
diff --git a/shared/src/main/AndroidManifest.xml b/shared/src/main/AndroidManifest.xml
index c42a2dd7f..bcec9546e 100644
--- a/shared/src/main/AndroidManifest.xml
+++ b/shared/src/main/AndroidManifest.xml
@@ -9,11 +9,11 @@
android:icon="@drawable/ic_launcher"
android:installLocation="internalOnly"
android:label="Magisk Manager"
- android:supportsRtl="true">
+ android:supportsRtl="true"
+ android:theme="@android:style/Theme.Translucent.NoTitleBar">
+ android:exported="false"
+ tools:ignore="AppLinkUrlError">
+
+
+
+
+