OSDN Git Service

Merge pull request #87 from alvinhkh/master
[android-x86/external-koush-Superuser.git] / Superuser / jni / su / su.c
index 887d226..32166a7 100644 (file)
 #include <sys/stat.h>
 #include <stdarg.h>
 #include <sys/types.h>
-#include <pwd.h>
 
 #include "su.h"
 #include "utils.h"
 
-int get_shell_uid() {
+unsigned get_shell_uid() {
   struct passwd* ppwd = getpwnam("shell");
   if (NULL == ppwd) {
-    return -1;
+    return 2000;
   }
   
   return ppwd->pw_uid;
@@ -168,18 +167,17 @@ static int get_multiuser_mode() {
     free(data);
 
     int sdk = atoi(sdk_ver);
-    if (sdk < 16)
+    if (sdk < 17)
         return MULTIUSER_MODE_NONE;
 
     int ret = MULTIUSER_MODE_OWNER_ONLY;
     char mode[12];
     FILE *fp;
     if ((fp = fopen(REQUESTOR_MULTIUSER_MODE, "r"))) {
+        fgets(mode, sizeof(mode), fp);
         int last = strlen(mode) - 1;
         if (mode[last] == '\n')
             mode[last] = '\0';
-        fgets(mode, sizeof(mode), fp);
-        LOGD("multiuser mode: %s", mode);
         if (strcmp(mode, MULTIUSER_VALUE_USER) == 0) {
             ret = MULTIUSER_MODE_USER;
         } else if (strcmp(mode, MULTIUSER_VALUE_OWNER_MANAGED) == 0) {
@@ -267,11 +265,6 @@ static void cleanup_signal(int sig) {
     exit(128 + sig);
 }
 
-void sigchld_handler(int sig) {
-    child_cleanup(su_ctx);
-    (void)sig;
-}
-
 static int socket_create_temp(char *path, size_t len) {
     int fd;
     struct sockaddr_un sun;
@@ -325,7 +318,6 @@ static int socket_accept(int serv_fd) {
     tv.tv_usec = 0;
     FD_ZERO(&fds);
     FD_SET(serv_fd, &fds);
-    LOGD("select");
     do {
         rc = select(serv_fd + 1, &fds, NULL, NULL, &tv);
     } while (rc < 0 && errno == EINTR);
@@ -375,8 +367,8 @@ do {                                        \
 
     write_token(fd, "version", PROTO_VERSION);
     write_token(fd, "pid", ctx->from.pid);
-    write_token(fd, "from.name", ctx->from.name);
-    write_token(fd, "to.name", ctx->to.name);
+    write_string(fd, "from.name", ctx->from.name);
+    write_string(fd, "to.name", ctx->to.name);
     write_token(fd, "from.uid", ctx->from.uid);
     write_token(fd, "to.uid", ctx->to.uid);
     write_string(fd, "from.bin", ctx->from.bin);
@@ -711,35 +703,48 @@ int main(int argc, char *argv[]) {
     read_options(&ctx);
     user_init(&ctx);
     
-    if (ctx.user.multiuser_mode == MULTIUSER_MODE_OWNER_ONLY && ctx.user.android_user_id != 0) {
-        deny(&ctx);
-    }
-
-    if (access_disabled(&ctx.from)) {
-        LOGD("access_disabled");
-        deny(&ctx);
-    }
-
-    ctx.umask = umask(027);
-
+    // TODO: customizable behavior for shell? It can currently be toggled via settings.
     if (ctx.from.uid == AID_ROOT || ctx.from.uid == AID_SHELL) {
         LOGD("Allowing root/shell.");
         allow(&ctx);
     }
 
+    // verify superuser is installed
     if (stat(ctx.user.base_path, &st) < 0) {
+        // send to market
+        if (0 == strcmp(JAVA_PACKAGE_NAME, REQUESTOR))
+            silent_run("am start -d http://www.clockworkmod.com/superuser/install.html -a android.intent.action.VIEW");
         PLOGE("stat %s", ctx.user.base_path);
         deny(&ctx);
     }
 
+    // odd perms on superuser data dir
     if (st.st_gid != st.st_uid) {
         LOGE("Bad uid/gid %d/%d for Superuser Requestor application",
                 (int)st.st_uid, (int)st.st_gid);
         deny(&ctx);
     }
+    
+    // always allow if this is the superuser uid
+    // superuser needs to be able to reenable itself when disabled...
+    if (ctx.from.uid == st.st_uid) {
+        allow(&ctx);
+    }
+
+    // check if superuser is disabled completely
+    if (access_disabled(&ctx.from)) {
+        LOGD("access_disabled");
+        deny(&ctx);
+    }
+
+    // deny if this is a non owner request and owner mode only
+    if (ctx.user.multiuser_mode == MULTIUSER_MODE_OWNER_ONLY && ctx.user.android_user_id != 0) {
+        deny(&ctx);
+    }
+
+    ctx.umask = umask(027);
 
     int ret = mkdir(REQUESTOR_CACHE_PATH, 0770);
-    LOGD("mkdir: %d", ret);
     if (chown(REQUESTOR_CACHE_PATH, st.st_uid, st.st_gid)) {
         PLOGE("chown (%s, %ld, %ld)", REQUESTOR_CACHE_PATH, st.st_uid, st.st_gid);
         deny(&ctx);