#include "su.h"
-static void kill_child(pid_t pid) {
- LOGD("killing child %d", pid);
- if (pid) {
- sigset_t set, old;
-
- sigemptyset(&set);
- sigaddset(&set, SIGCHLD);
- if (sigprocmask(SIG_BLOCK, &set, &old)) {
- PLOGE("sigprocmask(SIG_BLOCK)");
- return;
- }
- if (kill(pid, SIGKILL))
- PLOGE("kill (%d)", pid);
- else if (sigsuspend(&old) && errno != EINTR)
- PLOGE("sigsuspend");
- if (sigprocmask(SIG_SETMASK, &old, NULL))
- PLOGE("sigprocmask(SIG_BLOCK)");
- }
-}
+/* intent actions */
+#define ACTION_REQUEST "start", "-n", REQUESTOR "/" REQUESTOR_PREFIX ".RequestActivity"
+#define ACTION_NOTIFY "start", "-n", REQUESTOR "/" REQUESTOR_PREFIX ".NotifyActivity"
+#define ACTION_RESULT "broadcast", "-n", REQUESTOR "/" REQUESTOR_PREFIX ".SuReceiver"
+
+#define AM_PATH "/system/bin/app_process", "/system/bin", "com.android.commands.am.Am"
// TODO: leverage this with exec_log?
-static int silent_run(char* command) {
- char *args[] = { "sh", "-c", command, NULL, };
+int silent_run(char* const args[]) {
set_identity(0);
pid_t pid;
pid = fork();
int null = open("/dev/null", O_WRONLY | O_CLOEXEC);
dup2(null, 1);
dup2(null, 2);
- execv(_PATH_BSHELL, args);
+ setenv("CLASSPATH", "/system/framework/am.jar", 1);
+ execv(args[0], args);
PLOGE("exec am");
_exit(EXIT_FAILURE);
return -1;
}
-int send_result(struct su_context *ctx, policy_t allow) {
- return 0;
-}
-
-int send_request(struct su_context *ctx) {
- // if su is operating in MULTIUSER_MODEL_OWNER,
- // and the user requestor is not the owner,
- // the owner needs to be notified of the request.
- // so there will be two activities shown.
+int get_owner_login_user_args(struct su_context *ctx, char* user, int user_len) {
int needs_owner_login_prompt = 0;
- char user[64];
- if (ctx->user.multiuser_mode == MULTIUSER_MODE_OWNER_ONLY) {
- snprintf(user, sizeof(user), "");
- }
- else if (ctx->user.multiuser_mode == MULTIUSER_MODE_OWNER) {
+
+ if (ctx->user.multiuser_mode == MULTIUSER_MODE_OWNER_MANAGED) {
if (0 != ctx->user.android_user_id) {
needs_owner_login_prompt = 1;
}
- snprintf(user, sizeof(user), "--user 0");
+ snprintf(user, user_len, "0");
}
else if (ctx->user.multiuser_mode == MULTIUSER_MODE_USER) {
- snprintf(user, sizeof(user), "--user %d", ctx->user.android_user_id);
+ snprintf(user, user_len, "%d", ctx->user.android_user_id);
+ }
+ else if (ctx->user.multiuser_mode == MULTIUSER_MODE_NONE) {
+ user[0] = '\0';
}
else {
- // unknown mode?
- return -1;
+ snprintf(user, user_len, "0");
+ }
+
+ return needs_owner_login_prompt;
+}
+
+int send_result(struct su_context *ctx, policy_t policy) {
+ char binary_version[256];
+ sprintf(binary_version, "%d", VERSION_CODE);
+
+ char uid[256];
+ sprintf(uid, "%d", ctx->from.uid);
+
+ char desired_uid[256];
+ sprintf(desired_uid, "%d", ctx->to.uid);
+
+ char user[64];
+ get_owner_login_user_args(ctx, user, sizeof(user));
+
+ if (0 != ctx->user.android_user_id) {
+ char android_user_id[256];
+ sprintf(android_user_id, "%d", ctx->user.android_user_id);
+
+ char *user_result_command[] = {
+ AM_PATH,
+ ACTION_RESULT,
+ "--ei",
+ "binary_version",
+ binary_version,
+ "--es",
+ "from_name",
+ ctx->from.name,
+ "--es",
+ "desired_name",
+ ctx->to.name,
+ "--ei",
+ "uid",
+ uid,
+ "--ei",
+ "desired_uid",
+ desired_uid,
+ "--es",
+ "command",
+ get_command(&ctx->to),
+ "--es",
+ "action",
+ policy == ALLOW ? "allow" : "deny",
+ user[0] ? "--user" : NULL,
+ android_user_id,
+ NULL
+ };
+ silent_run(user_result_command);
}
+ char *result_command[] = {
+ AM_PATH,
+ ACTION_RESULT,
+ "--ei",
+ "binary_version",
+ binary_version,
+ "--es",
+ "from_name",
+ ctx->from.name,
+ "--es",
+ "desired_name",
+ ctx->to.name,
+ "--ei",
+ "uid",
+ uid,
+ "--ei",
+ "desired_uid",
+ desired_uid,
+ "--es",
+ "command",
+ get_command(&ctx->to),
+ "--es",
+ "action",
+ policy == ALLOW ? "allow" : "deny",
+ user[0] ? "--user" : NULL,
+ user,
+ NULL
+ };
+ return silent_run(result_command);
+}
+
+int send_request(struct su_context *ctx) {
+ // if su is operating in MULTIUSER_MODEL_OWNER,
+ // and the user requestor is not the owner,
+ // the owner needs to be notified of the request.
+ // so there will be two activities shown.
+ char user[64];
+ int needs_owner_login_prompt = get_owner_login_user_args(ctx, user, sizeof(user));
int ret;
if (needs_owner_login_prompt) {
- // in multiuser mode, the owner gets the su prompt
- char notify_command[ARG_MAX];
+ char uid[256];
+ sprintf(uid, "%d", ctx->from.uid);
+
+ char android_user_id[256];
+ sprintf(android_user_id, "%d", ctx->user.android_user_id);
- // start the activity that confirms the request
- snprintf(notify_command, sizeof(notify_command),
- "exec /system/bin/am " ACTION_NOTIFY " --ei caller_uid %d --user %d",
- ctx->from.uid, ctx->user.android_user_id);
+ // in multiuser mode, the owner gets the su prompt
+ char *notify_command[] = {
+ AM_PATH,
+ ACTION_NOTIFY,
+ "--ei",
+ "caller_uid",
+ uid,
+ "--user",
+ android_user_id,
+ NULL
+ };
int ret = silent_run(notify_command);
if (ret) {
}
}
- char request_command[ARG_MAX];
-
- // start the activity that confirms the request
- snprintf(request_command, sizeof(request_command),
- "exec /system/bin/am " ACTION_REQUEST " --es socket '%s' %s",
- ctx->sock_path, user);
+ char *request_command[] = {
+ AM_PATH,
+ ACTION_REQUEST,
+ "--es",
+ "socket",
+ ctx->sock_path,
+ user[0] ? "--user" : NULL,
+ user,
+ NULL
+ };
return silent_run(request_command);
}