diff options
Diffstat (limited to 'minelf/Retouch.c')
-rw-r--r-- | minelf/Retouch.c | 210 |
1 files changed, 0 insertions, 210 deletions
diff --git a/minelf/Retouch.c b/minelf/Retouch.c index 33809cd6d..d75eec1e8 100644 --- a/minelf/Retouch.c +++ b/minelf/Retouch.c @@ -194,213 +194,3 @@ int retouch_mask_data(uint8_t *binary_object, if (retouch_offset != NULL) *retouch_offset = offset_candidate; return RETOUCH_DATA_MATCHED; } - -// On success, _override is set to the offset that was actually applied. -// This implies that once we randomize to an offset we stick with it. -// This in turn is necessary in order to guarantee recovery after crash. -bool retouch_one_library(const char *binary_name, - const char *binary_sha1, - int32_t retouch_offset, - int32_t *retouch_offset_override) { - bool success = true; - int result; - - FileContents file; - file.data = NULL; - - char binary_name_atomic[strlen(binary_name)+10]; - strcpy(binary_name_atomic, binary_name); - strcat(binary_name_atomic, ".atomic"); - - // We need a path that exists for calling statfs() later. - // - // Assume that binary_name (eg "/system/app/Foo.apk") is located - // on the same filesystem as its top-level directory ("/system"). - char target_fs[strlen(binary_name)+1]; - char* slash = strchr(binary_name+1, '/'); - if (slash != NULL) { - int count = slash - binary_name; - strncpy(target_fs, binary_name, count); - target_fs[count] = '\0'; - } else { - strcpy(target_fs, binary_name); - } - - result = LoadFileContents(binary_name, &file, RETOUCH_DONT_MASK); - - if (result == 0) { - // Figure out the *apparent* offset to which this file has been - // retouched. If it looks good, we will skip processing (we might - // have crashed and during this recovery pass we don't want to - // overwrite a valuable saved file in /cache---which would happen - // if we blindly retouch everything again). NOTE: This implies - // that we might have to override the supplied retouch offset. We - // can do the override only once though: everything should match - // afterward. - - int32_t inferred_offset; - int retouch_probe_result = retouch_mask_data(file.data, - file.size, - NULL, - &inferred_offset); - - if (retouch_probe_result == RETOUCH_DATA_MATCHED) { - if ((retouch_offset == inferred_offset) || - ((retouch_offset != 0 && inferred_offset != 0) && - (retouch_offset_override != NULL))) { - // This file is OK already and we are allowed to override. - // Let's just return the offset override value. It is critical - // to skip regardless of override: a broken file might need - // recovery down the list and we should not mess up the saved - // copy by doing unnecessary retouching. - // - // NOTE: If retouching was already started with a different - // value, we will not be allowed to override. This happens - // if on the retouch list there is a patched binary (which is - // masked in apply_patch()) before there is a non-patched - // binary. - if (retouch_offset_override != NULL) - *retouch_offset_override = inferred_offset; - success = true; - goto out; - } else { - // Retouch to zero (mask the retouching), to make sure that - // the SHA-1 check will pass below. - int32_t zero = 0; - retouch_mask_data(file.data, file.size, &zero, NULL); - SHA(file.data, file.size, file.sha1); - } - } - - if (retouch_probe_result == RETOUCH_DATA_NOTAPPLICABLE) { - // In the case of not retouchable, fake it. We do not want - // to do the normal processing and overwrite the backup file: - // we might be recovering! - // - // We return a zero override, which tells the caller that we - // simply skipped the file. - if (retouch_offset_override != NULL) - *retouch_offset_override = 0; - success = true; - goto out; - } - - // If we get here, either there was a mismatch in the offset, or - // the file has not been processed yet. Continue with normal - // processing. - } - - if (result != 0 || FindMatchingPatch(file.sha1, &binary_sha1, 1) < 0) { - free(file.data); - printf("Attempting to recover source from '%s' ...\n", - CACHE_TEMP_SOURCE); - result = LoadFileContents(CACHE_TEMP_SOURCE, &file, RETOUCH_DO_MASK); - if (result != 0 || FindMatchingPatch(file.sha1, &binary_sha1, 1) < 0) { - printf(" failed.\n"); - success = false; - goto out; - } - printf(" succeeded.\n"); - } - - // Retouch in-memory before worrying about backing up the original. - // - // Recovery steps will be oblivious to the actual retouch offset used, - // so might as well write out the already-retouched copy. Then, in the - // usual case, we will just swap the file locally, with no more writes - // needed. In the no-free-space case, we will then write the same to the - // original location. - - result = retouch_mask_data(file.data, file.size, &retouch_offset, NULL); - if (result != RETOUCH_DATA_MATCHED) { - success = false; - goto out; - } - if (retouch_offset_override != NULL) - *retouch_offset_override = retouch_offset; - - // How much free space do we need? - bool enough_space = false; - size_t free_space = FreeSpaceForFile(target_fs); - // 50% margin when estimating the space needed. - enough_space = (free_space > (file.size * 3 / 2)); - - // The experts say we have to allow for a retry of the - // whole process to avoid filesystem weirdness. - int retry = 1; - bool made_copy = false; - do { - // First figure out where to store a copy of the original. - // Ideally leave the original itself intact until the - // atomic swap. If no room on the same partition, fall back - // to the cache partition and remove the original. - - if (!enough_space) { - printf("Target is %ldB; free space is %ldB: not enough.\n", - (long)file.size, (long)free_space); - - retry = 0; - if (MakeFreeSpaceOnCache(file.size) < 0) { - printf("Not enough free space on '/cache'.\n"); - success = false; - goto out; - } - if (SaveFileContents(CACHE_TEMP_SOURCE, file) < 0) { - printf("Failed to back up source file.\n"); - success = false; - goto out; - } - made_copy = true; - unlink(binary_name); - - size_t free_space = FreeSpaceForFile(target_fs); - printf("(now %ld bytes free for target)\n", (long)free_space); - } - - result = SaveFileContents(binary_name_atomic, file); - if (result != 0) { - // Maybe the filesystem was optimistic: retry. - enough_space = false; - unlink(binary_name_atomic); - printf("Saving the retouched contents failed; retrying.\n"); - continue; - } - - // Succeeded; no need to retry. - break; - } while (retry-- > 0); - - // Give the .atomic file the same owner, group, and mode of the - // original source file. - if (chmod(binary_name_atomic, file.st.st_mode) != 0) { - printf("chmod of \"%s\" failed: %s\n", - binary_name_atomic, strerror(errno)); - success = false; - goto out; - } - if (chown(binary_name_atomic, file.st.st_uid, file.st.st_gid) != 0) { - printf("chown of \"%s\" failed: %s\n", - binary_name_atomic, - strerror(errno)); - success = false; - goto out; - } - - // Finally, rename the .atomic file to replace the target file. - if (rename(binary_name_atomic, binary_name) != 0) { - printf("rename of .atomic to \"%s\" failed: %s\n", - binary_name, strerror(errno)); - success = false; - goto out; - } - - // If this run created a copy, and we're here, we can delete it. - if (made_copy) unlink(CACHE_TEMP_SOURCE); - - out: - // clean up - free(file.data); - unlink(binary_name_atomic); - - return success; -} |