userspace/su: implement basic features (#62)

This commit is contained in:
Scirese
2023-01-14 22:42:45 +08:00
committed by GitHub
parent 0b86cd69fc
commit 8274f6a1ff
3 changed files with 118 additions and 4 deletions

View File

@@ -3,5 +3,9 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS) include $(CLEAR_VARS)
LOCAL_MODULE := su LOCAL_MODULE := su
LOCAL_SRC_FILES := su.c LOCAL_SRC_FILES := su.c
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_MODULE := simple_su
LOCAL_SRC_FILES := simple_su.c
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)

View File

@@ -0,0 +1,10 @@
#include <unistd.h>
#include <stdlib.h>
#include <sys/prctl.h>
int main(){
int32_t result = 0;
prctl(0xdeadbeef, 0, 0, 0, &result);
system("/system/bin/sh");
return 0;
}

View File

@@ -1,10 +1,110 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include <sys/prctl.h> #include <sys/prctl.h>
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; int32_t result = 0;
prctl(0xdeadbeef, 0, 0, 0, &result); prctl(0xDEADBEEF, cmd, arg1, arg2, & result);
system("/system/bin/sh"); 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; return 0;
} }