diff --git a/Android.mk b/Android.mk index 4c41aa1..349ef7b 100644 --- a/Android.mk +++ b/Android.mk @@ -34,6 +34,10 @@ ifdef BOARD_RECOVERY_IGNORE_BOOTABLES LOCAL_CFLAGS += -DBOARD_RECOVERY_IGNORE_BOOTABLES endif +ifdef BOARD_HIJACK_RECOVERY_PATH + LOCAL_CFLAGS += -DBOARD_HIJACK_RECOVERY_PATH=\"$(BOARD_HIJACK_RECOVERY_PATH)\" +endif + LOCAL_SRC_FILES += test_roots.c LOCAL_MODULE := recovery @@ -184,6 +188,7 @@ LOCAL_SRC_FILES := killrecovery.sh include $(BUILD_PREBUILT) include $(commands_recovery_local_path)/amend/Android.mk +include $(commands_recovery_local_path)/hijack/Android.mk include $(commands_recovery_local_path)/minui/Android.mk include $(commands_recovery_local_path)/minzip/Android.mk include $(commands_recovery_local_path)/mtdutils/Android.mk diff --git a/hijack/Android.mk b/hijack/Android.mk new file mode 100644 index 0000000..f877f39 --- /dev/null +++ b/hijack/Android.mk @@ -0,0 +1,14 @@ +LOCAL_PATH := $(call my-dir) + +ifdef BOARD_HIJACK_RECOVERY_PATH + +include $(CLEAR_VARS) +LOCAL_SRC_FILES := hijack.c +LOCAL_MODULE := hijack +LOCAL_MODULE_TAGS := eng +LOCAL_STATIC_LIBRARIES := libmtdutils libcutils libc +LOCAL_FORCE_STATIC_EXECUTABLE := true +LOCAL_CFLAGS += -DBOARD_HIJACK_RECOVERY_PATH=\"$(BOARD_HIJACK_RECOVERY_PATH)\" +include $(BUILD_EXECUTABLE) + +endif diff --git a/hijack/hijack.c b/hijack/hijack.c new file mode 100644 index 0000000..231408d --- /dev/null +++ b/hijack/hijack.c @@ -0,0 +1,99 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + + +#define RECOVERY_MODE_FILE "/cache/.recovery_mode" +#define UPDATE_BINARY BOARD_HIJACK_RECOVERY_PATH"/update-binary" +#define UPDATE_PACKAGE BOARD_HIJACK_RECOVERY_PATH"/recovery.zip" +#define BUSYBOX BOARD_HIJACK_RECOVERY_PATH"/busybox" +#define PREPARE_SCRIPT BOARD_HIJACK_RECOVERY_PATH"/prepare.sh" + +// This was pulled from bionic: The default system command always looks +// for shell in /system/bin/sh. This is bad. +#define _PATH_BSHELL BOARD_HIJACK_RECOVERY_PATH"/sh" + +extern char **environ; +int +__system(const char *command) +{ + pid_t pid; + sig_t intsave, quitsave; + sigset_t mask, omask; + int pstat; + char *argp[] = {"sh", "-c", NULL, NULL}; + + if (!command) /* just checking... */ + return(1); + + argp[2] = (char *)command; + + sigemptyset(&mask); + sigaddset(&mask, SIGCHLD); + sigprocmask(SIG_BLOCK, &mask, &omask); + switch (pid = vfork()) { + case -1: /* error */ + sigprocmask(SIG_SETMASK, &omask, NULL); + return(-1); + case 0: /* child */ + sigprocmask(SIG_SETMASK, &omask, NULL); + execve(_PATH_BSHELL, argp, environ); + _exit(127); + } + + intsave = (sig_t) bsd_signal(SIGINT, SIG_IGN); + quitsave = (sig_t) bsd_signal(SIGQUIT, SIG_IGN); + pid = waitpid(pid, (int *)&pstat, 0); + sigprocmask(SIG_SETMASK, &omask, NULL); + (void)bsd_signal(SIGINT, intsave); + (void)bsd_signal(SIGQUIT, quitsave); + return (pid == -1 ? -1 : pstat); +} + +int main(int argc, char** argv) { + char* hijacked_executable = argv[0]; + struct stat info; + + if (NULL != strstr(hijacked_executable, "hijack")) { + // no op + printf("Hijack!\n"); + return 0; + } + + char cmd[PATH_MAX]; + if (0 == stat(RECOVERY_MODE_FILE, &info)) { + remove(RECOVERY_MODE_FILE); + kill(getppid(), SIGKILL); + sprintf(cmd, "%s 2 0 %s", UPDATE_BINARY, UPDATE_PACKAGE); + return __system(cmd); + } + + sprintf(cmd, "%s.bin", hijacked_executable); + int i; + for (i = 1; i < argc; i++) { + strcat(cmd, " '"); + strcat(cmd, argv[i]); + strcat(cmd, "'"); + } + + __system(PREPARE_SCRIPT); + return __system(cmd); +} diff --git a/hijack/prepare.sh b/hijack/prepare.sh new file mode 100644 index 0000000..cfa6322 --- /dev/null +++ b/hijack/prepare.sh @@ -0,0 +1,4 @@ +#!/preinstall/recovery/sh +export PATH=$PATH:/preinstall/recovery +busybox mount -orw,remount / +busybox mkdir -p /res/images