diff --git a/userspace/su/jni/Android.mk b/userspace/su/jni/Android.mk index 5391ce7f..fcc47e76 100644 --- a/userspace/su/jni/Android.mk +++ b/userspace/su/jni/Android.mk @@ -3,5 +3,9 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := su LOCAL_SRC_FILES := su.c - +include $(BUILD_EXECUTABLE) + +include $(CLEAR_VARS) +LOCAL_MODULE := simple_su +LOCAL_SRC_FILES := simple_su.c include $(BUILD_EXECUTABLE) diff --git a/userspace/su/jni/simple_su.c b/userspace/su/jni/simple_su.c new file mode 100644 index 00000000..695c1cce --- /dev/null +++ b/userspace/su/jni/simple_su.c @@ -0,0 +1,10 @@ +#include +#include +#include + +int main(){ + int32_t result = 0; + prctl(0xdeadbeef, 0, 0, 0, &result); + system("/system/bin/sh"); + return 0; +} diff --git a/userspace/su/jni/su.c b/userspace/su/jni/su.c index 695c1cce..38b5b5e8 100644 --- a/userspace/su/jni/su.c +++ b/userspace/su/jni/su.c @@ -1,10 +1,110 @@ +#include +#include #include #include +#include #include -int main(){ +#define CMD_GRANT_ROOT 0 +#define CMD_GET_VERSION 2 + +static void help(int status) { + + printf("KernelSU\n" + "Usage: su [options] [argument...]\n\n" + "Options: \n" + "-c Pass command to invoked shell\n" + "-v Print version code and exit\n" + "-h Display this message and exit\n" + ); + exit(status); + +} + +static bool ksuctl(int cmd, void * arg1, void * arg2) { + int32_t result = 0; - prctl(0xdeadbeef, 0, 0, 0, &result); - system("/system/bin/sh"); + prctl(0xDEADBEEF, cmd, arg1, arg2, & result); + return result == 0xDEADBEEF; + +} + +void elevate() { + + // Talk to Daemon in Kernel Space + bool status = ksuctl(CMD_GRANT_ROOT, 0, NULL); + + if (!status) { + fprintf(stderr, "Permission denied\n"); + exit(EXIT_FAILURE); + } + +} + +int getver() { + + elevate(); + + int32_t version = -1; + ksuctl(CMD_GET_VERSION, & version, NULL); + + return version; +} + +void su_shell(char * envp[]) { + + char * shell = getenv("SHELL"); + int status; + + elevate(); + + if (shell) { + status = execve(shell, NULL, envp); + } else { + status = execve("/system/bin/sh", NULL, envp); + } + + exit(status); +} + +void su_command(char * command[], int len) { + + elevate(); + int status; + + if (len == 1) { + status = system(command[0]); + } else { + status = execvp(command[0], command); + } + exit(status); +} + +int main(int argc, char * argv[], char * envp[]) { + + if (argc == 1) { + su_shell(envp); + } + + int opt; + + while ((opt = getopt(argc, argv, "vch")) != -1) { + switch (opt) { + case 'v': { + int version = getver(); + printf("%d:KernelSU\n", version); + exit(EXIT_SUCCESS); + } + case 'c': + if (argc < 3) { + fprintf(stderr, "ERROR: -c requires an argument\n\n"); + help(EXIT_FAILURE); + } + su_command(argv + 2, argc - 2); + case 'h': + default: + help(EXIT_SUCCESS); + } + } return 0; }