From efabb451cb92d9adfd38f9d0fbe11caa1b4250ef Mon Sep 17 00:00:00 2001 From: Adam Shanks Date: Mon, 28 Feb 2011 23:34:32 +0000 Subject: [PATCH 1/6] Modifications for compatibility with cupcake and donut. --- activity.cpp | 6 +++--- su.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/activity.cpp b/activity.cpp index 4b21abd..39b166c 100644 --- a/activity.cpp +++ b/activity.cpp @@ -1,8 +1,8 @@ #include #include -#include -#include -#include +#include +#include +#include #include #include diff --git a/su.h b/su.h index 2052eab..a6c9e96 100644 --- a/su.h +++ b/su.h @@ -12,7 +12,7 @@ #define DEFAULT_COMMAND "/system/bin/sh" -#define VERSION "2.3.1-efg" +#define VERSION "2.3.1-cd" struct su_initiator { pid_t pid; From 3e7ad76c827f1b2ff846fa079738f7d94ca59938 Mon Sep 17 00:00:00 2001 From: Adam Shanks Date: Fri, 17 Jun 2011 19:28:48 +0100 Subject: [PATCH 2/6] Bump version so that it matches efgh version --- su.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/su.h b/su.h index a6c9e96..c69a50d 100644 --- a/su.h +++ b/su.h @@ -12,7 +12,7 @@ #define DEFAULT_COMMAND "/system/bin/sh" -#define VERSION "2.3.1-cd" +#define VERSION "2.3.2-cd" struct su_initiator { pid_t pid; From e925f912ef5e0f7ee2669e4bf70095b47d59882c Mon Sep 17 00:00:00 2001 From: Adam Shanks Date: Tue, 27 Sep 2011 13:11:51 +0100 Subject: [PATCH 3/6] Merge legacy-dev into legacy --- Android.mk | 2 +- activity.cpp | 33 ++++++- db.c | 89 +++++++++++++++++ su.c | 264 ++++++++++++++++++--------------------------------- su.h | 41 ++++++-- 5 files changed, 248 insertions(+), 181 deletions(-) create mode 100644 db.c diff --git a/Android.mk b/Android.mk index b23b09b..3128778 100644 --- a/Android.mk +++ b/Android.mk @@ -2,7 +2,7 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := su -LOCAL_SRC_FILES := su.c activity.cpp +LOCAL_SRC_FILES := su.c db.c activity.cpp LOCAL_C_INCLUDES += external/sqlite/dist diff --git a/activity.cpp b/activity.cpp index 39b166c..17bb4f2 100644 --- a/activity.cpp +++ b/activity.cpp @@ -1,3 +1,20 @@ +/* +** 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 #include #include @@ -23,7 +40,7 @@ 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 type) +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"); @@ -43,7 +60,7 @@ int send_intent(struct su_initiator *from, struct su_request *to, const char *so if (type == 0) { data.writeString16(String16("com.noshufou.android.su.REQUEST")); /* action */ } else { - data.writeString16(String16("com.noshufou.android.su.NOTIFICATION")); /* action */ + data.writeString16(String16("com.noshufou.android.su.RESULT")); /* action */ } data.writeInt32(NULL_TYPE_ID); /* Uri - data */ data.writeString16(NULL, 0); /* type */ @@ -63,7 +80,7 @@ int send_intent(struct su_initiator *from, struct su_request *to, const char *so int oldPos = data.dataPosition(); data.writeInt32(0x4C444E42); // 'B' 'N' 'D' 'L' { /* writeMapInternal */ - data.writeInt32(4); /* writeMapInternal - size */ + data.writeInt32(6); /* writeMapInternal - size */ data.writeInt32(VAL_STRING); data.writeString16(String16("caller_uid")); @@ -84,6 +101,16 @@ int send_intent(struct su_initiator *from, struct su_request *to, const char *so 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); diff --git a/db.c b/db.c new file mode 100644 index 0000000..c338ee9 --- /dev/null +++ b/db.c @@ -0,0 +1,89 @@ +/* +** Copyright 2010, Adam Shanks (@ChainsDD) +** +** 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 +#include +#include +#include + +#include + +#include "su.h" + +// { int* pint; pint=(int*)data; ++(*pint); } + +sqlite3 *database_init() +{ + sqlite3 *db; + int version, rc, databaseStatus = 0; + char *zErrMsg = 0; + + rc = sqlite3_open_v2(REQUESTOR_DATABASE_PATH, &db, SQLITE_OPEN_READONLY, NULL); + if ( rc ) { + LOGE("Couldn't open database: %s", sqlite3_errmsg(db)); + return NULL; + } + + // Create an automatic busy handler in case the db is locked + sqlite3_busy_timeout(db, 1000); + return db; +} + +int database_check(sqlite3 *db, struct su_initiator *from, struct su_request *to) +{ + char sql[4096]; + char *zErrmsg; + char **result; + int nrow,ncol; + int allow; + struct timeval tv; + + sqlite3_snprintf( + sizeof(sql), sql, + "SELECT _id,name,allow FROM apps WHERE uid=%u AND exec_uid=%u AND exec_cmd='%q';", + (unsigned)from->uid, to->uid, to->command + ); + + if (strlen(sql) >= sizeof(sql)-1) + return DB_DENY; + + int error = sqlite3_get_table(db, sql, &result, &nrow, &ncol, &zErrmsg); + if (error != SQLITE_OK) { + LOGE("Database check failed with error message %s", zErrmsg); + if (error == SQLITE_BUSY) { + LOGE("Specifically, the database is busy"); + } + return DB_DENY; + } + + if (nrow == 0 || ncol != 3) + return DB_INTERACTIVE; + + if (strcmp(result[0], "_id") == 0 && strcmp(result[2], "allow") == 0) { + if (strcmp(result[5], "1") == 0) { + allow = DB_ALLOW; + } else if (strcmp(result[5], "-1") == 0){ + allow = DB_INTERACTIVE; + } else { + allow = DB_DENY; + } + return allow; + } + + sqlite3_free_table(result); + + return DB_INTERACTIVE; +} diff --git a/su.c b/su.c index c498f94..588478e 100644 --- a/su.c +++ b/su.c @@ -1,3 +1,20 @@ +/* +** 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. +*/ + #define LOG_TAG "su" #include @@ -24,18 +41,15 @@ #include +#include "su.h" + extern char* _mktemp(char*); /* mktemp doesn't link right. Don't ask me why. */ -#include "su.h" +extern sqlite3 *database_init(); +extern int database_check(sqlite3*, struct su_initiator*, struct su_request*); -/* Ewwww. I'm way too lazy. */ -static const char socket_path_template[PATH_MAX] = REQUESTOR_CACHE_PATH "/.socketXXXXXX"; -static char socket_path_buf[PATH_MAX]; +/* Not lazy anymore, just need these in too many places */ static char *socket_path = NULL; -static int socket_serv_fd = -1; -static char shell[PATH_MAX]; -static unsigned req_uid = 0; - static sqlite3 *db = NULL; static struct su_initiator su_from = { @@ -130,8 +144,9 @@ static void cleanup_signal(int sig) exit(sig); } -static int socket_create_temp() +static int socket_create_temp(unsigned req_uid) { + static char buf[PATH_MAX]; int fd, err; struct sockaddr_un sun; @@ -145,8 +160,8 @@ static int socket_create_temp() for (;;) { memset(&sun, 0, sizeof(sun)); sun.sun_family = AF_LOCAL; - strcpy(socket_path_buf, socket_path_template); - socket_path = _mktemp(socket_path_buf); + strcpy(buf, SOCKET_PATH_TEMPLATE); + socket_path = _mktemp(buf); snprintf(sun.sun_path, sizeof(sun.sun_path), "%s", socket_path); if (bind(fd, (struct sockaddr*)&sun, sizeof(sun)) < 0) { @@ -207,6 +222,7 @@ static int socket_accept(int serv_fd) static int socket_receive_result(int serv_fd, char *result, ssize_t result_len) { ssize_t len; + char buf[64]; for (;;) { int fd = socket_accept(serv_fd); @@ -219,8 +235,9 @@ static int socket_receive_result(int serv_fd, char *result, ssize_t result_len) return -1; } - if (len > 0) + if (len > 0) { break; + } } result[len] = '\0'; @@ -228,136 +245,23 @@ static int socket_receive_result(int serv_fd, char *result, ssize_t result_len) return 0; } -static sqlite3 *database_init() -{ - sqlite3 *db; - - if (mkdir(REQUESTOR_DATABASES_PATH, 0771) >= 0) { - chown(REQUESTOR_DATABASES_PATH, req_uid, req_uid); - } - - if (sqlite3_open(REQUESTOR_DATABASE_PATH, &db) != SQLITE_OK) { - LOGE("Couldn't open database"); - return NULL; - } - - if (sqlite3_exec(db, - "PRAGMA journal_mode = delete;", - NULL, - NULL, - NULL - ) != SQLITE_OK) { - LOGE("Could not set journal mode"); - sqlite3_close(db); - return NULL; - } - - chmod(REQUESTOR_DATABASE_PATH, 0660); - chown(REQUESTOR_DATABASE_PATH, req_uid, req_uid); - - if (sqlite3_exec(db, - "CREATE TABLE IF NOT EXISTS apps (_id INTEGER, uid INTEGER, package TEXT, name TEXT, exec_uid INTEGER, exec_cmd TEXT, allow INTEGER, PRIMARY KEY (_id), UNIQUE (uid,exec_uid,exec_cmd));", - NULL, - NULL, - NULL - ) != SQLITE_OK) { - LOGE("Couldn't create apps table"); - sqlite3_close(db); - return NULL; - } - - if (sqlite3_exec(db, - "CREATE TABLE IF NOT EXISTS logs (_id INTEGER, app_id INTEGER, date INTEGER, type INTEGER, PRIMARY KEY (_id));", - NULL, - NULL, - NULL - ) != SQLITE_OK) { - LOGE("Couldn't create logs table"); - sqlite3_close(db); - return NULL; - } - - return db; -} - -enum { - DB_INTERACTIVE, - DB_DENY, - DB_ALLOW -}; - -static int database_check(sqlite3 *db, struct su_initiator *from, struct su_request *to) -{ - char sql[4096]; - char *zErrmsg; - char **result; - int nrow,ncol; - int allow; - struct timeval tv; - - sqlite3_snprintf( - sizeof(sql), sql, - "SELECT _id,allow FROM apps WHERE uid=%u AND exec_uid=%u AND exec_cmd='%q';", - (unsigned)from->uid, to->uid, to->command - ); - - if (strlen(sql) >= sizeof(sql)-1) - return DB_DENY; - - if (sqlite3_get_table(db, sql, &result, &nrow, &ncol, &zErrmsg) != SQLITE_OK) { - LOGE("Database check failed with error message %s", zErrmsg); - return DB_DENY; - } - - if (nrow == 0 || ncol != 2) - return DB_INTERACTIVE; - - if (strcmp(result[0], "_id") == 0 && strcmp(result[1], "allow") == 0) { - if (strcmp(result[3], "1") == 0) { - allow = DB_ALLOW; - } else { - allow = DB_DENY; - } - gettimeofday(&tv, NULL); - sqlite3_snprintf( - sizeof(sql), sql, - "INSERT OR IGNORE INTO logs (app_id,date,type) VALUES (%s,(%ld*1000)+(%ld/1000),%s);", - result[2], tv.tv_sec, tv.tv_usec, result[3] - ); - sqlite3_exec(db, sql, NULL, NULL, NULL); - return allow; - } - - sqlite3_free_table(result); - - return DB_INTERACTIVE; -} - -static int check_notifications(sqlite3 *db) +static void usage(void) { - char sql[4096]; - char *zErrmsg; - char **result; - int nrow,ncol; - int notifications; - - sqlite3_snprintf( - sizeof(sql), sql, - "SELECT value FROM prefs WHERE key='notifications';" - ); - - if (sqlite3_get_table(db, sql, &result, &nrow, &ncol, &zErrmsg) != SQLITE_OK) { - LOGE("Notifications check failed with error message %s", zErrmsg); - return 0; - } - - if (nrow == 0 || ncol != 1) - return 0; - - if (strcmp(result[0], "value") == 0 && strcmp(result[1], "1") == 0) - return 1; - - return 0; + printf("Usage: su [options] [LOGIN]\n\n"); + printf("Options:\n"); + printf(" -c, --command COMMAND pass COMMAND to the invoked shell\n"); + printf(" -h, --help display this help message and exit\n"); + printf(" -, -l, --login make the shell a login shell\n"); + // I'll look more into this to figure out what it's about, + // maybe implement it later +// printf(" -m, -p,\n"); +// printf(" --preserve-environment do not reset environment variables, and\n"); +// printf(" keep the same shell\n"); + printf(" -s, --shell SHELL use SHELL instead of the default in passwd\n"); + printf(" -v, --version display version number and exit\n"); + printf(" -V display version code and exit. this is\n"); + printf(" used almost exclusively by Superuser.apk\n"); + exit(EXIT_SUCCESS); } static void deny(void) @@ -365,20 +269,20 @@ static void deny(void) struct su_initiator *from = &su_from; struct su_request *to = &su_to; + send_intent(&su_from, &su_to, "", 0, 1); LOGW("request rejected (%u->%u %s)", from->uid, to->uid, to->command); fprintf(stderr, "%s\n", strerror(EACCES)); - exit(-1); + exit(EXIT_FAILURE); } -static void allow(int notifications) +static void allow(char *shell) { struct su_initiator *from = &su_from; struct su_request *to = &su_to; char *exe = NULL; - if (notifications) - send_intent(&su_from, &su_to, "", 1); - + send_intent(&su_from, &su_to, "", 1, 1); + if (!strcmp(shell, "")) { strcpy(shell , "/system/bin/sh"); } @@ -386,40 +290,48 @@ static void allow(int notifications) setgroups(0, NULL); setresgid(to->uid, to->uid, to->uid); setresuid(to->uid, to->uid, to->uid); - LOGD("%u %s executing %u %s using shell %s : %s", from->uid, from->bin, to->uid, to->command, shell, exe); + LOGD("%u %s executing %u %s using shell %s : %s", from->uid, from->bin, + to->uid, to->command, shell, exe); if (strcmp(to->command, DEFAULT_COMMAND)) { execl(shell, exe, "-c", to->command, (char*)NULL); } else { execl(shell, exe, "-", (char*)NULL); } PLOGE("exec"); - exit(-1); + exit(EXIT_SUCCESS); } int main(int argc, char *argv[]) { struct stat st; - char buf[64], *result; - int i; - int dballow; + static int socket_serv_fd = -1; + char buf[64], shell[PATH_MAX], *result; + int i, dballow; + unsigned req_uid; for (i = 1; i < argc; i++) { - if (!strcmp(argv[i], "-c")) { + if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--command")) { if (++i < argc) { su_to.command = argv[i]; } else { - deny(); + usage(); } - } else if (!strcmp(argv[i], "-s")) { + } else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--shell")) { if (++i < argc) { strcpy(shell, argv[i]); } else { - deny(); + usage(); } - } else if (!strcmp(argv[i], "-v")) { + } else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) { printf("%s\n", VERSION); - exit(-1); - } else if (!strcmp(argv[i], "-")) { + exit(EXIT_SUCCESS); + } else if (!strcmp(argv[i], "-V")) { + printf("%d\n", VERSION_CODE); + exit(EXIT_SUCCESS); + } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { + usage(); + } else if (!strcmp(argv[i], "-") || !strcmp(argv[i], "-l") || + !strcmp(argv[i], "--login")) { ++i; break; } else { @@ -427,7 +339,7 @@ int main(int argc, char *argv[]) } } if (i < argc-1) { - deny(); + usage(); } if (i == argc-1) { struct passwd *pw; @@ -442,7 +354,7 @@ int main(int argc, char *argv[]) from_init(&su_from); if (su_from.uid == AID_ROOT) - allow(0); + allow(shell); if (stat(REQUESTOR_DATA_PATH, &st) < 0) { PLOGE("stat"); @@ -451,7 +363,8 @@ int main(int argc, char *argv[]) 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); + LOGE("Bad uid/gid %d/%d for Superuser Requestor application", + (int)st.st_uid, (int)st.st_gid); deny(); } @@ -465,21 +378,30 @@ int main(int argc, char *argv[]) chown(REQUESTOR_CACHE_PATH, req_uid, req_uid); } + LOGE("sudb - Opening database"); db = database_init(); if (!db) { - deny(); + LOGE("sudb - Could not open database, prompt user"); + // if the database could not be opened, we can assume we need to + // prompt the user + dballow = DB_INTERACTIVE; + } else { + LOGE("sudb - Database opened"); + dballow = database_check(db, &su_from, &su_to); + // Close the database, we're done with it. If it stays open, + // it will cause problems + sqlite3_close(db); + LOGE("sudb - Database closed"); } - dballow = database_check(db, &su_from, &su_to); - int notifications = check_notifications(db); switch (dballow) { - case DB_DENY: deny(); - case DB_ALLOW: allow(notifications); - case DB_INTERACTIVE: break; - default: deny(); + case DB_DENY: LOGE("denying"); deny(); + case DB_ALLOW: LOGE("allowing"); allow(shell); + case DB_INTERACTIVE: LOGE("asking"); break; + default: LOGE("default, denying"); deny(); } - socket_serv_fd = socket_create_temp(); + socket_serv_fd = socket_create_temp(req_uid); if (socket_serv_fd < 0) { deny(); } @@ -490,7 +412,7 @@ int main(int argc, char *argv[]) signal(SIGABRT, cleanup_signal); atexit(cleanup); - if (send_intent(&su_from, &su_to, socket_path, 0) < 0) { + if (send_intent(&su_from, &su_to, socket_path, -1, 0) < 0) { deny(); } @@ -506,7 +428,7 @@ int main(int argc, char *argv[]) if (!strcmp(result, "DENY")) { deny(); } else if (!strcmp(result, "ALLOW")) { - allow(notifications); + allow(shell); } else { LOGE("unknown response from Superuser Requestor: %s", result); deny(); diff --git a/su.h b/su.h index c69a50d..3d450af 100644 --- a/su.h +++ b/su.h @@ -1,18 +1,41 @@ +/* +** 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. +*/ + #ifndef SU_h #define SU_h 1 -#define REQUESTOR_PACKAGE "com.noshufou.android.su" -#define REQUESTOR_CLASS "SuRequest" - -#define REQUESTOR_DATA_PATH "/data/data/" REQUESTOR_PACKAGE +#define REQUESTOR_DATA_PATH "/data/data/com.noshufou.android.su" #define REQUESTOR_CACHE_PATH REQUESTOR_DATA_PATH "/cache" #define REQUESTOR_DATABASES_PATH REQUESTOR_DATA_PATH "/databases" #define REQUESTOR_DATABASE_PATH REQUESTOR_DATABASES_PATH "/permissions.sqlite" +#define APPS_TABLE_DEFINITION "CREATE TABLE IF NOT EXISTS apps (_id INTEGER, uid INTEGER, package TEXT, name TEXT, exec_uid INTEGER, exec_cmd TEXT, allow INTEGER, PRIMARY KEY (_id), UNIQUE (uid,exec_uid,exec_cmd));" +#define LOGS_TABLE_DEFINITION "CREATE TABLE IF NOT EXISTS logs (_id INTEGER, uid INTEGER, name INTEGER, app_id INTEGER, date INTEGER, type INTEGER, PRIMARY KEY (_id));" +#define PREFS_TABLE_DEFINITION "CREATE TABLE IF NOT EXISTS prefs (_id INTEGER, key TEXT, value TEXT, PRIMARY KEY(_id));" + #define DEFAULT_COMMAND "/system/bin/sh" -#define VERSION "2.3.2-cd" +#define SOCKET_PATH_TEMPLATE REQUESTOR_CACHE_PATH "/.socketXXXXXX" + +#define VERSION "3.0l" +#define VERSION_CODE 11 + +#define DATABASE_VERSION 6 struct su_initiator { pid_t pid; @@ -26,7 +49,13 @@ struct su_request { char *command; }; -extern int send_intent(struct su_initiator *from, struct su_request *to, const char *socket_path, int type); +enum { + DB_INTERACTIVE, + DB_DENY, + DB_ALLOW +}; + +extern int send_intent(struct su_initiator *from, struct su_request *to, const char *socket_path, int allow, int type); #if 0 #undef LOGE From b9a7e7b47623de7dd413cef9eb12b8750cd639a2 Mon Sep 17 00:00:00 2001 From: Adam Shanks Date: Sat, 22 Oct 2011 19:41:06 +0100 Subject: [PATCH 4/6] Bring legacy up to date with master --- activity.cpp | 7 ++++++- su.c | 28 ++++++++++++++++------------ su.h | 4 ++-- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/activity.cpp b/activity.cpp index 17bb4f2..f0a131e 100644 --- a/activity.cpp +++ b/activity.cpp @@ -80,13 +80,18 @@ int send_intent(struct su_initiator *from, struct su_request *to, const char *so int oldPos = data.dataPosition(); data.writeInt32(0x4C444E42); // 'B' 'N' 'D' 'L' { /* writeMapInternal */ - data.writeInt32(6); /* writeMapInternal - size */ + 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); diff --git a/su.c b/su.c index 588478e..e529e13 100644 --- a/su.c +++ b/su.c @@ -48,7 +48,7 @@ extern char* _mktemp(char*); /* mktemp doesn't link right. Don't ask me why. */ extern sqlite3 *database_init(); extern int database_check(sqlite3*, struct su_initiator*, struct su_request*); -/* Not lazy anymore, just need these in too many places */ +/* Still lazt, will fix this */ static char *socket_path = NULL; static sqlite3 *db = NULL; @@ -318,7 +318,8 @@ int main(int argc, char *argv[]) } } else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--shell")) { if (++i < argc) { - strcpy(shell, argv[i]); + strncpy(shell, argv[i], sizeof(shell)); + shell[sizeof(shell) - 1] = 0; } else { usage(); } @@ -351,9 +352,11 @@ int main(int argc, char *argv[]) } } - from_init(&su_from); + if (from_init(&su_from) < 0) { + deny(); + } - if (su_from.uid == AID_ROOT) + if (su_from.uid == AID_ROOT || su_from.uid == AID_SHELL) allow(shell); if (stat(REQUESTOR_DATA_PATH, &st) < 0) { @@ -370,14 +373,14 @@ int main(int argc, char *argv[]) req_uid = st.st_uid; - if (from_init(&su_from) < 0) { - deny(); - } - if (mkdir(REQUESTOR_CACHE_PATH, 0771) >= 0) { chown(REQUESTOR_CACHE_PATH, req_uid, req_uid); } + setgroups(0, NULL); + setegid(st.st_gid); + seteuid(st.st_uid); + LOGE("sudb - Opening database"); db = database_init(); if (!db) { @@ -391,14 +394,15 @@ int main(int argc, char *argv[]) // Close the database, we're done with it. If it stays open, // it will cause problems sqlite3_close(db); + db = NULL; LOGE("sudb - Database closed"); } switch (dballow) { - case DB_DENY: LOGE("denying"); deny(); - case DB_ALLOW: LOGE("allowing"); allow(shell); - case DB_INTERACTIVE: LOGE("asking"); break; - default: LOGE("default, denying"); deny(); + case DB_DENY: deny(); + case DB_ALLOW: allow(shell); + case DB_INTERACTIVE: break; + default: deny(); } socket_serv_fd = socket_create_temp(req_uid); diff --git a/su.h b/su.h index 3d450af..8e72a72 100644 --- a/su.h +++ b/su.h @@ -32,8 +32,8 @@ #define SOCKET_PATH_TEMPLATE REQUESTOR_CACHE_PATH "/.socketXXXXXX" -#define VERSION "3.0l" -#define VERSION_CODE 11 +#define VERSION "3.0.1l" +#define VERSION_CODE 12 #define DATABASE_VERSION 6 From 447d6bde3ec0f89a71eadca545228662d5c937af Mon Sep 17 00:00:00 2001 From: Adam Shanks Date: Wed, 14 Dec 2011 20:19:42 +0000 Subject: [PATCH 5/6] bump version --- su.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/su.h b/su.h index 8e72a72..a070531 100644 --- a/su.h +++ b/su.h @@ -32,8 +32,8 @@ #define SOCKET_PATH_TEMPLATE REQUESTOR_CACHE_PATH "/.socketXXXXXX" -#define VERSION "3.0.1l" -#define VERSION_CODE 12 +#define VERSION "3.0.3l" +#define VERSION_CODE 14 #define DATABASE_VERSION 6 From d345f794a375f1e0db4956237a55a1403fe466b2 Mon Sep 17 00:00:00 2001 From: Adam Shanks Date: Sun, 18 Dec 2011 13:25:06 +0000 Subject: [PATCH 6/6] bring legacy up to date with master --- activity.cpp | 4 ++++ db.c | 12 +++++------- su.c | 45 +++++++++++++++++---------------------------- su.h | 8 ++------ 4 files changed, 28 insertions(+), 41 deletions(-) diff --git a/activity.cpp b/activity.cpp index f0a131e..f6d4dc2 100644 --- a/activity.cpp +++ b/activity.cpp @@ -75,6 +75,10 @@ int send_intent(struct su_initiator *from, struct su_request *to, const char *so // 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(); diff --git a/db.c b/db.c index c338ee9..ce4ae72 100644 --- a/db.c +++ b/db.c @@ -28,8 +28,7 @@ sqlite3 *database_init() { sqlite3 *db; - int version, rc, databaseStatus = 0; - char *zErrMsg = 0; + int rc; rc = sqlite3_open_v2(REQUESTOR_DATABASE_PATH, &db, SQLITE_OPEN_READONLY, NULL); if ( rc ) { @@ -48,8 +47,7 @@ int database_check(sqlite3 *db, struct su_initiator *from, struct su_request *to char *zErrmsg; char **result; int nrow,ncol; - int allow; - struct timeval tv; + int allow = DB_INTERACTIVE; sqlite3_snprintf( sizeof(sql), sql, @@ -70,7 +68,7 @@ int database_check(sqlite3 *db, struct su_initiator *from, struct su_request *to } if (nrow == 0 || ncol != 3) - return DB_INTERACTIVE; + goto out; if (strcmp(result[0], "_id") == 0 && strcmp(result[2], "allow") == 0) { if (strcmp(result[5], "1") == 0) { @@ -80,10 +78,10 @@ int database_check(sqlite3 *db, struct su_initiator *from, struct su_request *to } else { allow = DB_DENY; } - return allow; } +out: sqlite3_free_table(result); - return DB_INTERACTIVE; + return allow; } diff --git a/su.c b/su.c index e529e13..b28da67 100644 --- a/su.c +++ b/su.c @@ -71,6 +71,7 @@ static int from_init(struct su_initiator *from) int fd; ssize_t len; int i; + int err; from->uid = getuid(); from->pid = getppid(); @@ -83,9 +84,10 @@ static int from_init(struct su_initiator *from) return -1; } len = read(fd, args, sizeof(args)); + err = errno; close(fd); if (len < 0 || len == sizeof(args)) { - PLOGE("Reading command line"); + PLOGEV("Reading command line", err); return -1; } @@ -144,10 +146,10 @@ static void cleanup_signal(int sig) exit(sig); } -static int socket_create_temp(unsigned req_uid) +static int socket_create_temp(void) { static char buf[PATH_MAX]; - int fd, err; + int fd; struct sockaddr_un sun; @@ -174,18 +176,6 @@ static int socket_create_temp(unsigned req_uid) } } - if (chmod(sun.sun_path, 0600) < 0) { - PLOGE("chmod(socket)"); - unlink(sun.sun_path); - return -1; - } - - if (chown(sun.sun_path, req_uid, req_uid) < 0) { - PLOGE("chown(socket)"); - unlink(sun.sun_path); - return -1; - } - if (listen(fd, 1) < 0) { PLOGE("listen"); return -1; @@ -222,7 +212,6 @@ static int socket_accept(int serv_fd) static int socket_receive_result(int serv_fd, char *result, ssize_t result_len) { ssize_t len; - char buf[64]; for (;;) { int fd = socket_accept(serv_fd); @@ -275,19 +264,19 @@ static void deny(void) exit(EXIT_FAILURE); } -static void allow(char *shell) +static void allow(char *shell, mode_t mask) { struct su_initiator *from = &su_from; struct su_request *to = &su_to; char *exe = NULL; + umask(mask); send_intent(&su_from, &su_to, "", 1, 1); if (!strcmp(shell, "")) { strcpy(shell , "/system/bin/sh"); } exe = strrchr (shell, '/') + 1; - setgroups(0, NULL); setresgid(to->uid, to->uid, to->uid); setresuid(to->uid, to->uid, to->uid); LOGD("%u %s executing %u %s using shell %s : %s", from->uid, from->bin, @@ -307,7 +296,7 @@ int main(int argc, char *argv[]) static int socket_serv_fd = -1; char buf[64], shell[PATH_MAX], *result; int i, dballow; - unsigned req_uid; + mode_t orig_umask; for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--command")) { @@ -356,8 +345,10 @@ int main(int argc, char *argv[]) deny(); } + orig_umask = umask(027); + if (su_from.uid == AID_ROOT || su_from.uid == AID_SHELL) - allow(shell); + allow(shell, orig_umask); if (stat(REQUESTOR_DATA_PATH, &st) < 0) { PLOGE("stat"); @@ -371,10 +362,8 @@ int main(int argc, char *argv[]) deny(); } - req_uid = st.st_uid; - - if (mkdir(REQUESTOR_CACHE_PATH, 0771) >= 0) { - chown(REQUESTOR_CACHE_PATH, req_uid, req_uid); + if (mkdir(REQUESTOR_CACHE_PATH, 0770) >= 0) { + chown(REQUESTOR_CACHE_PATH, st.st_uid, st.st_gid); } setgroups(0, NULL); @@ -400,12 +389,12 @@ int main(int argc, char *argv[]) switch (dballow) { case DB_DENY: deny(); - case DB_ALLOW: allow(shell); + case DB_ALLOW: allow(shell, orig_umask); case DB_INTERACTIVE: break; default: deny(); } - - socket_serv_fd = socket_create_temp(req_uid); + + socket_serv_fd = socket_create_temp(); if (socket_serv_fd < 0) { deny(); } @@ -432,7 +421,7 @@ int main(int argc, char *argv[]) if (!strcmp(result, "DENY")) { deny(); } else if (!strcmp(result, "ALLOW")) { - allow(shell); + allow(shell, orig_umask); } else { LOGE("unknown response from Superuser Requestor: %s", result); deny(); diff --git a/su.h b/su.h index a070531..a32c957 100644 --- a/su.h +++ b/su.h @@ -24,16 +24,12 @@ #define REQUESTOR_DATABASES_PATH REQUESTOR_DATA_PATH "/databases" #define REQUESTOR_DATABASE_PATH REQUESTOR_DATABASES_PATH "/permissions.sqlite" -#define APPS_TABLE_DEFINITION "CREATE TABLE IF NOT EXISTS apps (_id INTEGER, uid INTEGER, package TEXT, name TEXT, exec_uid INTEGER, exec_cmd TEXT, allow INTEGER, PRIMARY KEY (_id), UNIQUE (uid,exec_uid,exec_cmd));" -#define LOGS_TABLE_DEFINITION "CREATE TABLE IF NOT EXISTS logs (_id INTEGER, uid INTEGER, name INTEGER, app_id INTEGER, date INTEGER, type INTEGER, PRIMARY KEY (_id));" -#define PREFS_TABLE_DEFINITION "CREATE TABLE IF NOT EXISTS prefs (_id INTEGER, key TEXT, value TEXT, PRIMARY KEY(_id));" - #define DEFAULT_COMMAND "/system/bin/sh" #define SOCKET_PATH_TEMPLATE REQUESTOR_CACHE_PATH "/.socketXXXXXX" -#define VERSION "3.0.3l" -#define VERSION_CODE 14 +#define VERSION "3.0.3.2l" +#define VERSION_CODE 15 #define DATABASE_VERSION 6