OSDN Git Service

assign user before use
[android-x86/external-koush-Superuser.git] / Superuser / jni / su / activity.c
index 250fdbc..a3ef9c7 100644 (file)
 
 #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();
@@ -65,50 +51,141 @@ static int silent_run(char* command) {
     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) {
@@ -116,12 +193,16 @@ int send_request(struct su_context *ctx) {
         }
     }
 
-    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);
 }