OSDN Git Service

su: update CyanogenMod's latest version ics-x86
authorChih-Wei Huang <cwhuang@linux.org.tw>
Fri, 6 Jul 2012 06:56:29 +0000 (14:56 +0800)
committerChih-Wei Huang <cwhuang@linux.org.tw>
Sat, 7 Jul 2012 06:48:13 +0000 (14:48 +0800)
Update to commit 5369a56c0e1ddd4d080b0d90db47921d0eded862 but
disable static executable since we don't have libsqlite.a.

su/Android.mk
su/activity.c [new file with mode: 0644]
su/activity.cpp [deleted file]
su/su.c
su/utils.c [new file with mode: 0644]
su/utils.h [new file with mode: 0644]

index d458a05..a5ec9c4 100644 (file)
@@ -2,9 +2,10 @@ LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := \
-    activity.cpp \
+    activity.c \
     db.c \
     su.c\
+    utils.c \
 
 LOCAL_MODULE := su
 
@@ -13,9 +14,6 @@ LOCAL_C_INCLUDES += external/sqlite/dist
 LOCAL_SHARED_LIBRARIES := \
     liblog \
     libsqlite \
-    libcutils \
-    libbinder \
-    libutils \
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
 LOCAL_MODULE_TAGS := optional
diff --git a/su/activity.c b/su/activity.c
new file mode 100644 (file)
index 0000000..ee12f87
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+** Copyright 2010, Adam Shanks (@ChainsDD)
+** Copyright 2008, Zinx Verituse (@zinxv)
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <unistd.h>
+
+#include "su.h"
+#include "utils.h"
+
+int send_intent(struct su_initiator *from, struct su_request *to, const char *socket_path, int allow, int type)
+{
+    char command[PATH_MAX];
+    char action[PATH_MAX];
+    if (type == 0) {
+        strcpy(action, "com.noshufou.android.su.REQUEST");
+    } else {
+        strcpy(action, "com.noshufou.android.su.RESULT");
+    }
+    sprintf(command, "/system/bin/am broadcast -a '%s' --es socket '%s' --ei caller_uid '%d' --es caller_bin '%s' --ei desired_uid '%d' --es desired_cmd '%s' --ei allow '%d' --ei version_code '%d' > /dev/null", action, socket_path, from->uid, from->bin, to->uid, to->command, allow, VERSION_CODE);
+    // before sending the intent, make sure the (uid and euid) and (gid and egid) match,
+    // otherwise LD_LIBRARY_PATH is wiped in Android 4.0+.
+    // Also, sanitize all secure environment variables (from linker_environ.c in linker).
+
+    /* The same list than GLibc at this point */
+    static const char* const unsec_vars[] = {
+        "GCONV_PATH",
+        "GETCONF_DIR",
+        "HOSTALIASES",
+        "LD_AUDIT",
+        "LD_DEBUG",
+        "LD_DEBUG_OUTPUT",
+        "LD_DYNAMIC_WEAK",
+        "LD_LIBRARY_PATH",
+        "LD_ORIGIN_PATH",
+        "LD_PRELOAD",
+        "LD_PROFILE",
+        "LD_SHOW_AUXV",
+        "LD_USE_LOAD_BIAS",
+        "LOCALDOMAIN",
+        "LOCPATH",
+        "MALLOC_TRACE",
+        "MALLOC_CHECK_",
+        "NIS_PATH",
+        "NLSPATH",
+        "RESOLV_HOST_CONF",
+        "RES_OPTIONS",
+        "TMPDIR",
+        "TZDIR",
+        "LD_AOUT_LIBRARY_PATH",
+        "LD_AOUT_PRELOAD",
+        // not listed in linker, used due to system() call
+        "IFS",
+    };
+    const char* const* cp   = unsec_vars;
+    const char* const* endp = cp + sizeof(unsec_vars)/sizeof(unsec_vars[0]);
+    while (cp < endp) {
+        unsetenv(*cp);
+        cp++;
+    }
+
+    // sane value so "am" works
+    setenv("LD_LIBRARY_PATH", "/vendor/lib:/system/lib", 1);
+    setresgid(0, 0, 0);
+    setresuid(0, 0, 0);
+    return system(command);
+}
diff --git a/su/activity.cpp b/su/activity.cpp
deleted file mode 100644 (file)
index f58c7d0..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
-** Copyright 2010, Adam Shanks (@ChainsDD)
-** Copyright 2008, Zinx Verituse (@zinxv)
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#include <unistd.h>
-#include <android_runtime/ActivityManager.h>
-#include <binder/IBinder.h>
-#include <binder/IServiceManager.h>
-#include <binder/Parcel.h>
-#include <utils/String8.h>
-#include <assert.h>
-
-extern "C" {
-#include "su.h"
-#include <private/android_filesystem_config.h>
-#include <cutils/properties.h>
-}
-
-using namespace android;
-
-static const int BROADCAST_INTENT_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 13;
-
-static const int NULL_TYPE_ID = 0;
-
-static const int VAL_STRING = 0;
-static const int VAL_INTEGER = 1;
-
-static const int START_SUCCESS = 0;
-
-int send_intent(struct su_initiator *from, struct su_request *to, const char *socket_path, int allow, int type)
-{
-    char sdk_version_prop[PROPERTY_VALUE_MAX] = "0";
-    property_get("ro.build.version.sdk", sdk_version_prop, "0");
-
-    int sdk_version = atoi(sdk_version_prop);
-
-    sp<IServiceManager> sm = defaultServiceManager();
-    sp<IBinder> am = sm->checkService(String16("activity"));
-    assert(am != NULL);
-
-    Parcel data, reply;
-    data.writeInterfaceToken(String16("android.app.IActivityManager"));
-
-    data.writeStrongBinder(NULL); /* caller */
-
-    /* intent */
-    if (type == 0) {
-        data.writeString16(String16("com.noshufou.android.su.REQUEST")); /* action */
-    } else {
-        data.writeString16(String16("com.noshufou.android.su.RESULT")); /* action */
-    }
-    data.writeInt32(NULL_TYPE_ID); /* Uri - data */
-    data.writeString16(NULL, 0); /* type */
-    data.writeInt32(0); /* flags */
-    if (sdk_version >= 4) {
-        // added in donut
-        data.writeString16(NULL, 0); /* package name - DONUT ONLY, NOT IN CUPCAKE. */
-    }
-    data.writeString16(NULL, 0); /* ComponentName - package */
-    data.writeInt32(0); /* Categories - size */
-    if (sdk_version >= 7) {
-        // added in eclair rev 7
-        data.writeInt32(0);
-    }
-    if (sdk_version >= 15) {
-        // added in IceCreamSandwich 4.0.3
-        data.writeInt32(0); /* Selector */
-    }
-    { /* Extras */
-        data.writeInt32(-1); /* dummy, will hold length */
-        int oldPos = data.dataPosition();
-        data.writeInt32(0x4C444E42); // 'B' 'N' 'D' 'L'
-        { /* writeMapInternal */
-            data.writeInt32(7); /* writeMapInternal - size */
-
-            data.writeInt32(VAL_STRING);
-            data.writeString16(String16("caller_uid"));
-            data.writeInt32(VAL_INTEGER);
-            data.writeInt32(from->uid);
-
-            data.writeInt32(VAL_STRING);
-            data.writeString16(String16("caller_bin"));
-            data.writeInt32(VAL_STRING);
-            data.writeString16(String16(from->bin));
-
-            data.writeInt32(VAL_STRING);
-            data.writeString16(String16("desired_uid"));
-            data.writeInt32(VAL_INTEGER);
-            data.writeInt32(to->uid);
-
-            data.writeInt32(VAL_STRING);
-            data.writeString16(String16("desired_cmd"));
-            data.writeInt32(VAL_STRING);
-            data.writeString16(String16(to->command));
-
-            data.writeInt32(VAL_STRING);
-            data.writeString16(String16("socket"));
-            data.writeInt32(VAL_STRING);
-            data.writeString16(String16(socket_path));
-
-            data.writeInt32(VAL_STRING);
-            data.writeString16(String16("allow"));
-            data.writeInt32(VAL_INTEGER);
-            data.writeInt32(allow);
-
-            data.writeInt32(VAL_STRING);
-            data.writeString16(String16("version_code"));
-            data.writeInt32(VAL_INTEGER);
-            data.writeInt32(VERSION_CODE);
-        }
-        int newPos = data.dataPosition();
-        data.setDataPosition(oldPos - 4);
-        data.writeInt32(newPos - oldPos); /* length */
-        data.setDataPosition(newPos);
-    }
-
-    data.writeString16(NULL, 0); /* resolvedType */
-
-    data.writeInt32(-1); /* Not sure what this is for, but it prevents a warning */
-
-    data.writeStrongBinder(NULL); /* resultTo */
-    data.writeInt32(-1); /* resultCode */
-    data.writeString16(NULL, 0); /* resultData */
-
-    data.writeInt32(-1); /* resultExtras */
-
-    data.writeString16(String16("com.noshufou.android.su.RESPOND")); /* perm */
-    data.writeInt32(0); /* serialized */
-    data.writeInt32(0); /* sticky */
-    data.writeInt32(-1);
-
-    status_t ret = am->transact(BROADCAST_INTENT_TRANSACTION, data, &reply);
-    if (ret < START_SUCCESS) return -1;
-
-    return 0;
-}
diff --git a/su/su.c b/su/su.c
index f4b35f8..773178c 100644 (file)
--- a/su/su.c
+++ b/su/su.c
 
 #include <private/android_filesystem_config.h>
 #include <cutils/log.h>
+#include <cutils/properties.h>
 
 #include <sqlite3.h>
 
+#include "utils.h"
 #include "su.h"
 
 //extern char* _mktemp(char*); /* mktemp doesn't link right.  Don't ask me why. */
@@ -294,9 +296,13 @@ int main(int argc, char *argv[])
 {
     struct stat st;
     static int socket_serv_fd = -1;
-    char buf[64], shell[PATH_MAX], *result;
-    int i, dballow;
+    char buf[64], shell[PATH_MAX], *result, debuggable[PROPERTY_VALUE_MAX];
+    char enabled[PROPERTY_VALUE_MAX], build_type[PROPERTY_VALUE_MAX];
+    char cm_version[PROPERTY_VALUE_MAX];
+    int i, dballow, len;
     mode_t orig_umask;
+    char *data;
+    unsigned sz;
 
     for (i = 1; i < argc; i++) {
         if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--command")) {
@@ -345,8 +351,52 @@ int main(int argc, char *argv[])
         deny();
     }
 
+    // we can't simply use the property service, since we aren't launched from init and
+    // can't trust the location of the property workspace. find the properties ourselves.
+    data = read_file("/default.prop", &sz);
+    get_property(data, debuggable, "ro.debuggable", "0");
+    free(data);
+
+    data = read_file("/system/build.prop", &sz);
+    get_property(data, cm_version, "ro.cm.version", "");
+    get_property(data, build_type, "ro.build.type", "");
+    free(data);
+
+    data = read_file("/data/property/persist.sys.root_access", &sz);
+    if (data != NULL) {
+        len = strlen(data);
+        if (len >= PROPERTY_VALUE_MAX)
+            memcpy(enabled, "1", 2);
+        else
+            memcpy(enabled, data, len + 1);
+        free(data);
+    } else
+        memcpy(enabled, "1", 2);
+
     orig_umask = umask(027);
 
+    // CyanogenMod-specific behavior
+    if (strlen(cm_version) > 0) {
+        // only allow su on debuggable builds
+        if (strcmp("1", debuggable) != 0) {
+            LOGE("Root access is disabled on non-debug builds");
+            deny();
+        }
+
+        // enforce persist.sys.root_access on non-eng builds
+        if (strcmp("eng", build_type) != 0 &&
+               (atoi(enabled) & 1) != 1 ) {
+            LOGE("Root access is disabled by system setting - enable it under settings -> developer options");
+            deny();
+        }
+
+        // disallow su in a shell if appropriate
+        if (su_from.uid == AID_SHELL && (atoi(enabled) == 1)) {
+            LOGE("Root access is disabled by a system setting - enable it under settings -> developer options");
+            deny();
+        }
+    }
+
     if (su_from.uid == AID_ROOT || su_from.uid == AID_SHELL)
         allow(shell, orig_umask);
 
diff --git a/su/utils.c b/su/utils.c
new file mode 100644 (file)
index 0000000..54056e0
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+** Copyright 2012, The CyanogenMod Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <unistd.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <endian.h>
+#include <ctype.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <cutils/properties.h>
+
+/* reads a file, making sure it is terminated with \n \0 */
+char* read_file(const char *fn, unsigned *_sz)
+{
+    char *data;
+    int sz;
+    int fd;
+
+    data = 0;
+    fd = open(fn, O_RDONLY);
+    if(fd < 0) return 0;
+
+    sz = lseek(fd, 0, SEEK_END);
+    if(sz < 0) goto oops;
+
+    if(lseek(fd, 0, SEEK_SET) != 0) goto oops;
+
+    data = (char*) malloc(sz + 2);
+    if(data == 0) goto oops;
+
+    if(read(fd, data, sz) != sz) goto oops;
+    close(fd);
+    data[sz] = '\n';
+    data[sz+1] = 0;
+    if(_sz) *_sz = sz;
+    return data;
+
+oops:
+    close(fd);
+    if(data != 0) free(data);
+    return 0;
+}
+
+int get_property(const char *data, char *found, const char *searchkey, const char *not_found)
+{
+    char *key, *value, *eol, *sol, *tmp;
+    if (data == NULL) goto defval;
+    int matched = 0;
+    sol = strdup(data);
+    while((eol = strchr(sol, '\n'))) {
+        key = sol;
+        *eol++ = 0;
+        sol = eol;
+
+        value = strchr(key, '=');
+        if(value == 0) continue;
+        *value++ = 0;
+
+        while(isspace(*key)) key++;
+        if(*key == '#') continue;
+        tmp = value - 2;
+        while((tmp > key) && isspace(*tmp)) *tmp-- = 0;
+
+        while(isspace(*value)) value++;
+        tmp = eol - 2;
+        while((tmp > value) && isspace(*tmp)) *tmp-- = 0;
+
+        if (strncmp(searchkey, key, strlen(searchkey)) == 0) {
+            matched = 1;
+            break;
+        }
+    }
+    int len;
+    if (matched) {
+        len = strlen(value);
+        if (len >= PROPERTY_VALUE_MAX)
+            return -1;
+        memcpy(found, value, len + 1);
+    } else goto defval;
+    return len;
+
+defval:
+    len = strlen(not_found);
+    memcpy(found, not_found, len + 1);
+    return len;
+}
+
diff --git a/su/utils.h b/su/utils.h
new file mode 100644 (file)
index 0000000..a329123
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+** Copyright 2012, The CyanogenMod Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef _UTILS_H_
+#define _UTILS_H_
+
+/* reads a file, making sure it is terminated with \n \0 */
+char* read_file(const char *fn, unsigned *_sz);
+
+int get_property(const char *data, char *found, const char *searchkey, const char *not_found);
+#endif