diff options
Diffstat (limited to 'twrp-functions.cpp')
-rw-r--r-- | twrp-functions.cpp | 327 |
1 files changed, 265 insertions, 62 deletions
diff --git a/twrp-functions.cpp b/twrp-functions.cpp index 85ce7274a..3e06f8770 100644 --- a/twrp-functions.cpp +++ b/twrp-functions.cpp @@ -48,10 +48,10 @@ int TWFunc::Exec_Cmd(string cmd, string &result) { } /* Checks md5 for a path - Return values: - -1 : MD5 does not exist - 0 : Failed - 1 : Success */ + Return values: + -1 : MD5 does not exist + 0 : Failed + 1 : Success */ int TWFunc::Check_MD5(string File) { int ret; string Command, DirPath, MD5_File, Sline, Filename, MD5_File_Filename, OK; @@ -86,7 +86,7 @@ int TWFunc::Check_MD5(string File) { ret = -1; } - return ret; + return ret; } // Returns "file.name" from a full /path/to/file.name @@ -288,30 +288,30 @@ static const char *TEMPORARY_INSTALL_FILE = "/tmp/last_install"; // close a file, log an error if the error indicator is set void TWFunc::check_and_fclose(FILE *fp, const char *name) { - fflush(fp); - if (ferror(fp)) LOGE("Error in %s\n(%s)\n", name, strerror(errno)); - fclose(fp); + fflush(fp); + if (ferror(fp)) LOGE("Error in %s\n(%s)\n", name, strerror(errno)); + fclose(fp); } void TWFunc::copy_log_file(const char* source, const char* destination, int append) { - FILE *log = fopen_path(destination, append ? "a" : "w"); - if (log == NULL) { - LOGE("Can't open %s\n", destination); - } else { - FILE *tmplog = fopen(source, "r"); - if (tmplog != NULL) { - if (append) { - fseek(tmplog, tmplog_offset, SEEK_SET); // Since last write - } - char buf[4096]; - while (fgets(buf, sizeof(buf), tmplog)) fputs(buf, log); - if (append) { - tmplog_offset = ftell(tmplog); - } - check_and_fclose(tmplog, source); - } - check_and_fclose(log, destination); - } + FILE *log = fopen_path(destination, append ? "a" : "w"); + if (log == NULL) { + LOGE("Can't open %s\n", destination); + } else { + FILE *tmplog = fopen(source, "r"); + if (tmplog != NULL) { + if (append) { + fseek(tmplog, tmplog_offset, SEEK_SET); // Since last write + } + char buf[4096]; + while (fgets(buf, sizeof(buf), tmplog)) fputs(buf, log); + if (append) { + tmplog_offset = ftell(tmplog); + } + check_and_fclose(tmplog, source); + } + check_and_fclose(log, destination); + } } // clear the recovery command and prepare to boot a (hopefully working) system, @@ -323,10 +323,10 @@ void TWFunc::twfinish_recovery(const char *send_intent) { if (send_intent != NULL) { FILE *fp = fopen_path(INTENT_FILE, "w"); if (fp == NULL) { - LOGE("Can't open %s\n", INTENT_FILE); + LOGE("Can't open %s\n", INTENT_FILE); } else { - fputs(send_intent, fp); - check_and_fclose(fp, INTENT_FILE); + fputs(send_intent, fp); + check_and_fclose(fp, INTENT_FILE); } } @@ -346,7 +346,7 @@ void TWFunc::twfinish_recovery(const char *send_intent) { // Remove the command file, so recovery won't repeat indefinitely. if (!PartitionManager.Mount_By_Path("/system", true) || (unlink(COMMAND_FILE) && errno != ENOENT)) { - LOGW("Can't unlink %s\n", COMMAND_FILE); + LOGW("Can't unlink %s\n", COMMAND_FILE); } PartitionManager.UnMount_By_Path("/cache", true); @@ -357,34 +357,34 @@ void TWFunc::twfinish_recovery(const char *send_intent) { int TWFunc::tw_reboot(RebootCommand command) { // Always force a sync before we reboot - sync(); + sync(); - switch (command) - { - case rb_current: - case rb_system: - twfinish_recovery("s"); + switch (command) + { + case rb_current: + case rb_system: + twfinish_recovery("s"); sync(); check_and_run_script("/sbin/rebootsystem.sh", "reboot system"); - return reboot(RB_AUTOBOOT); - case rb_recovery: + return reboot(RB_AUTOBOOT); + case rb_recovery: check_and_run_script("/sbin/rebootrecovery.sh", "reboot recovery"); - return __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, (void*) "recovery"); - case rb_bootloader: + return __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, (void*) "recovery"); + case rb_bootloader: check_and_run_script("/sbin/rebootbootloader.sh", "reboot bootloader"); - return __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, (void*) "bootloader"); - case rb_poweroff: + return __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, (void*) "bootloader"); + case rb_poweroff: check_and_run_script("/sbin/poweroff.sh", "power off"); android_reboot(ANDROID_RB_POWEROFF, 0, 0); - return reboot(RB_POWER_OFF); - case rb_download: + return reboot(RB_POWER_OFF); + case rb_download: check_and_run_script("/sbin/rebootdownload.sh", "reboot download"); return __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, (void*) "download"); return 1; - default: - return -1; - } - return -1; + default: + return -1; + } + return -1; } void TWFunc::check_and_run_script(const char* script_file, const char* display_name) @@ -503,21 +503,224 @@ int TWFunc::write_file(string fn, string& line) { timespec TWFunc::timespec_diff(timespec& start, timespec& end) { - timespec temp; - if ((end.tv_nsec-start.tv_nsec)<0) { - temp.tv_sec = end.tv_sec-start.tv_sec-1; - temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; - } else { - temp.tv_sec = end.tv_sec-start.tv_sec; - temp.tv_nsec = end.tv_nsec-start.tv_nsec; - } - return temp; + timespec temp; + if ((end.tv_nsec-start.tv_nsec)<0) { + temp.tv_sec = end.tv_sec-start.tv_sec-1; + temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; + } else { + temp.tv_sec = end.tv_sec-start.tv_sec; + temp.tv_nsec = end.tv_nsec-start.tv_nsec; + } + return temp; } int TWFunc::drop_caches(void) { - string file = "/proc/sys/vm/drop_caches"; - string value = "3"; - if (write_file(file, value) != 0) - return -1; - return 0; + string file = "/proc/sys/vm/drop_caches"; + string value = "3"; + if (write_file(file, value) != 0) + return -1; + return 0; +} + +int TWFunc::Check_su_Perms(void) { + struct stat st; + int ret = 0; + + if (!PartitionManager.Mount_By_Path("/system", false)) + return 0; + + // Check to ensure that perms are 6755 for all 3 file locations + if (stat("/system/bin/su", &st) == 0) { + if ((st.st_mode & (S_ISUID | S_ISGID | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) != (S_ISUID | S_ISGID | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) || st.st_uid != 0 || st.st_gid != 0) { + ret = 1; + } + } + if (stat("/system/xbin/su", &st) == 0) { + if ((st.st_mode & (S_ISUID | S_ISGID | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) != (S_ISUID | S_ISGID | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) || st.st_uid != 0 || st.st_gid != 0) { + ret += 2; + } + } + if (stat("/system/bin/.ext/.su", &st) == 0) { + if ((st.st_mode & (S_ISUID | S_ISGID | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) != (S_ISUID | S_ISGID | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) || st.st_uid != 0 || st.st_gid != 0) { + ret += 4; + } + } + return ret; +} + +bool TWFunc::Fix_su_Perms(void) { + if (!PartitionManager.Mount_By_Path("/system", true)) + return false; + + string file = "/system/bin/su"; + if (TWFunc::Path_Exists(file)) { + if (chown(file.c_str(), 0, 0) != 0) { + LOGE("Failed to chown '%s'\n", file.c_str()); + return false; + } + if (tw_chmod(file, "6755") != 0) { + LOGE("Failed to chmod '%s'\n", file.c_str()); + return false; + } + } + file = "/system/xbin/su"; + if (TWFunc::Path_Exists(file)) { + if (chown(file.c_str(), 0, 0) != 0) { + LOGE("Failed to chown '%s'\n", file.c_str()); + return false; + } + if (tw_chmod(file, "6755") != 0) { + LOGE("Failed to chmod '%s'\n", file.c_str()); + return false; + } + } + file = "/system/bin/.ext/.su"; + if (TWFunc::Path_Exists(file)) { + if (chown(file.c_str(), 0, 0) != 0) { + LOGE("Failed to chown '%s'\n", file.c_str()); + return false; + } + if (tw_chmod(file, "6755") != 0) { + LOGE("Failed to chmod '%s'\n", file.c_str()); + return false; + } + } + file = "/system/app/Superuser.apk"; + if (TWFunc::Path_Exists(file)) { + if (chown(file.c_str(), 0, 0) != 0) { + LOGE("Failed to chown '%s'\n", file.c_str()); + return false; + } + if (tw_chmod(file, "0644") != 0) { + LOGE("Failed to chmod '%s'\n", file.c_str()); + return false; + } + } + sync(); + if (!PartitionManager.UnMount_By_Path("/system", true)) + return false; + return true; +} + +int TWFunc::tw_chmod(string fn, string mode) { + long mask = 0; + + for ( std::string::size_type n = 0; n < mode.length(); ++n) { + if (n == 0) { + if (mode[n] == '0') + continue; + if (mode[n] == '1') + mask |= S_ISVTX; + if (mode[n] == '2') + mask |= S_ISGID; + if (mode[n] == '4') + mask |= S_ISUID; + if (mode[n] == '5') { + mask |= S_ISVTX; + mask |= S_ISUID; + } + if (mode[n] == '6') { + mask |= S_ISGID; + mask |= S_ISUID; + } + if (mode[n] == '7') { + mask |= S_ISVTX; + mask |= S_ISGID; + mask |= S_ISUID; + } + } + else if (n == 1) { + if (mode[n] == '7') { + mask |= S_IRWXU; + } + if (mode[n] == '6') { + mask |= S_IRUSR; + mask |= S_IWUSR; + } + if (mode[n] == '5') { + mask |= S_IRUSR; + mask |= S_IXUSR; + } + if (mode[n] == '4') + mask |= S_IRUSR; + if (mode[n] == '3') { + mask |= S_IWUSR; + mask |= S_IRUSR; + } + if (mode[n] == '2') + mask |= S_IWUSR; + if (mode[n] == '1') + mask |= S_IXUSR; + } + else if (n == 2) { + if (mode[n] == '7') { + mask |= S_IRWXG; + } + if (mode[n] == '6') { + mask |= S_IRGRP; + mask |= S_IWGRP; + } + if (mode[n] == '5') { + mask |= S_IRGRP; + mask |= S_IXGRP; + } + if (mode[n] == '4') + mask |= S_IRGRP; + if (mode[n] == '3') { + mask |= S_IWGRP; + mask |= S_IXGRP; + } + if (mode[n] == '2') + mask |= S_IWGRP; + if (mode[n] == '1') + mask |= S_IXGRP; + } + else if (n == 3) { + if (mode[n] == '7') { + mask |= S_IRWXO; + } + if (mode[n] == '6') { + mask |= S_IROTH; + mask |= S_IWOTH; + } + if (mode[n] == '5') { + mask |= S_IROTH; + mask |= S_IXOTH; + } + if (mode[n] == '4') + mask |= S_IROTH; + if (mode[n] == '3') { + mask |= S_IWOTH; + mask |= S_IXOTH; + } + if (mode[n] == '2') + mask |= S_IWOTH; + if (mode[n] == '1') + mask |= S_IXOTH; + } + } + + if (chmod(fn.c_str(), mask) != 0) { + LOGE("Unable to chmod '%s' %l\n", fn.c_str(), mask); + return -1; + } + + return 0; +} + +bool TWFunc::Install_SuperSU(void) { + if (!PartitionManager.Mount_By_Path("/system", true)) + return false; + + if (copy_file("/res/supersu/su", "/system/xbin/su", 0755) != 0) { + LOGE("Failed to copy su binary to /system/bin\n"); + return false; + } + if (copy_file("/res/supersu/Superuser.apk", "/system/app/Superuser.apk", 0644) != 0) { + LOGE("Failed to copy Superuser app to /system/app\n"); + return false; + } + if (!Fix_su_Perms()) + return false; + return true; } |