diff options
Diffstat (limited to 'updater/install.cpp')
-rw-r--r-- | updater/install.cpp | 159 |
1 files changed, 78 insertions, 81 deletions
diff --git a/updater/install.cpp b/updater/install.cpp index b09086964..413e147a1 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -34,6 +34,9 @@ #include <linux/xattr.h> #include <inttypes.h> +#include <memory> +#include <vector> + #include <android-base/parseint.h> #include <android-base/strings.h> #include <android-base/stringprintf.h> @@ -44,10 +47,11 @@ #include "cutils/misc.h" #include "cutils/properties.h" #include "edify/expr.h" -#include "mincrypt/sha.h" +#include "openssl/sha.h" #include "minzip/DirUtil.h" #include "mtdutils/mounts.h" #include "mtdutils/mtdutils.h" +#include "otafault/ota_io.h" #include "updater.h" #include "install.h" #include "tune2fs.h" @@ -91,10 +95,10 @@ void uiPrintf(State* state, const char* format, ...) { // Take a sha-1 digest and return it as a newly-allocated hex string. char* PrintSha1(const uint8_t* digest) { - char* buffer = reinterpret_cast<char*>(malloc(SHA_DIGEST_SIZE*2 + 1)); + char* buffer = reinterpret_cast<char*>(malloc(SHA_DIGEST_LENGTH*2 + 1)); const char* alphabet = "0123456789abcdef"; size_t i; - for (i = 0; i < SHA_DIGEST_SIZE; ++i) { + for (i = 0; i < SHA_DIGEST_LENGTH; ++i) { buffer[i*2] = alphabet[(digest[i] >> 4) & 0xf]; buffer[i*2+1] = alphabet[digest[i] & 0xf]; } @@ -439,8 +443,7 @@ Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) { for (int i = 0; i < argc; ++i) { paths[i] = Evaluate(state, argv[i]); if (paths[i] == NULL) { - int j; - for (j = 0; j < i; ++i) { + for (int j = 0; j < i; ++j) { free(paths[j]); } free(paths); @@ -555,18 +558,18 @@ Value* PackageExtractFileFn(const char* name, State* state, } { - int fd = TEMP_FAILURE_RETRY(open(dest_path, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, + int fd = TEMP_FAILURE_RETRY(ota_open(dest_path, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, S_IRUSR | S_IWUSR)); if (fd == -1) { printf("%s: can't open %s for write: %s\n", name, dest_path, strerror(errno)); goto done2; } success = mzExtractZipEntryToFile(za, entry, fd); - if (fsync(fd) == -1) { + if (ota_fsync(fd) == -1) { printf("fsync of \"%s\" failed: %s\n", dest_path, strerror(errno)); success = false; } - if (close(fd) == -1) { + if (ota_close(fd) == -1) { printf("close of \"%s\" failed: %s\n", dest_path, strerror(errno)); success = false; } @@ -581,13 +584,13 @@ Value* PackageExtractFileFn(const char* name, State* state, // as the result. char* zip_path; + if (ReadArgs(state, argv, 1, &zip_path) < 0) return NULL; + Value* v = reinterpret_cast<Value*>(malloc(sizeof(Value))); v->type = VAL_BLOB; v->size = -1; v->data = NULL; - if (ReadArgs(state, argv, 1, &zip_path) < 0) return NULL; - ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip; const ZipEntry* entry = mzFindZipEntry(za, zip_path); if (entry == NULL) { @@ -993,21 +996,21 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) { } FILE* f; - f = fopen(filename, "rb"); + f = ota_fopen(filename, "rb"); if (f == NULL) { ErrorAbort(state, "%s: failed to open %s: %s", name, filename, strerror(errno)); goto done; } - if (fread(buffer, 1, st.st_size, f) != static_cast<size_t>(st.st_size)) { + if (ota_fread(buffer, 1, st.st_size, f) != static_cast<size_t>(st.st_size)) { ErrorAbort(state, "%s: failed to read %lld bytes from %s", name, (long long)st.st_size+1, filename); - fclose(f); + ota_fclose(f); goto done; } buffer[st.st_size] = '\0'; - fclose(f); + ota_fclose(f); char* line; line = strtok(buffer, "\n"); @@ -1102,7 +1105,7 @@ Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) { if (contents->type == VAL_STRING) { // we're given a filename as the contents char* filename = contents->data; - FILE* f = fopen(filename, "rb"); + FILE* f = ota_fopen(filename, "rb"); if (f == NULL) { printf("%s: can't open %s: %s\n", name, filename, strerror(errno)); result = strdup(""); @@ -1112,12 +1115,12 @@ Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) { success = true; char* buffer = reinterpret_cast<char*>(malloc(BUFSIZ)); int read; - while (success && (read = fread(buffer, 1, BUFSIZ, f)) > 0) { + while (success && (read = ota_fread(buffer, 1, BUFSIZ, f)) > 0) { int wrote = mtd_write_data(ctx, buffer, read); success = success && (wrote == read); } free(buffer); - fclose(f); + ota_fclose(f); } else { // we're given a blob as the contents ssize_t wrote = mtd_write_data(ctx, contents->data, contents->size); @@ -1193,44 +1196,40 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) { } int patchcount = (argc-4) / 2; - Value** patches = ReadValueVarArgs(state, argc-4, argv+4); + std::unique_ptr<Value*, decltype(&free)> arg_values(ReadValueVarArgs(state, argc-4, argv+4), + free); + if (!arg_values) { + return nullptr; + } + std::vector<std::unique_ptr<Value, decltype(&FreeValue)>> patch_shas; + std::vector<std::unique_ptr<Value, decltype(&FreeValue)>> patches; + // Protect values by unique_ptrs first to get rid of memory leak. + for (int i = 0; i < patchcount * 2; i += 2) { + patch_shas.emplace_back(arg_values.get()[i], FreeValue); + patches.emplace_back(arg_values.get()[i+1], FreeValue); + } - int i; - for (i = 0; i < patchcount; ++i) { - if (patches[i*2]->type != VAL_STRING) { + for (int i = 0; i < patchcount; ++i) { + if (patch_shas[i]->type != VAL_STRING) { ErrorAbort(state, "%s(): sha-1 #%d is not string", name, i); - break; + return nullptr; } - if (patches[i*2+1]->type != VAL_BLOB) { + if (patches[i]->type != VAL_BLOB) { ErrorAbort(state, "%s(): patch #%d is not blob", name, i); - break; - } - } - if (i != patchcount) { - for (i = 0; i < patchcount*2; ++i) { - FreeValue(patches[i]); + return nullptr; } - free(patches); - return NULL; } - char** patch_sha_str = reinterpret_cast<char**>(malloc(patchcount * sizeof(char*))); - for (i = 0; i < patchcount; ++i) { - patch_sha_str[i] = patches[i*2]->data; - patches[i*2]->data = NULL; - FreeValue(patches[i*2]); - patches[i] = patches[i*2+1]; + std::vector<char*> patch_sha_str; + std::vector<Value*> patch_ptrs; + for (int i = 0; i < patchcount; ++i) { + patch_sha_str.push_back(patch_shas[i]->data); + patch_ptrs.push_back(patches[i].get()); } int result = applypatch(source_filename, target_filename, target_sha1, target_size, - patchcount, patch_sha_str, patches, NULL); - - for (i = 0; i < patchcount; ++i) { - FreeValue(patches[i]); - } - free(patch_sha_str); - free(patches); + patchcount, patch_sha_str.data(), patch_ptrs.data(), NULL); return StringValue(strdup(result == 0 ? "t" : "")); } @@ -1349,24 +1348,27 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) { return ErrorAbort(state, "%s() expects at least 1 arg", name); } - Value** args = ReadValueVarArgs(state, argc, argv); - if (args == NULL) { - return NULL; + std::unique_ptr<Value*, decltype(&free)> arg_values(ReadValueVarArgs(state, argc, argv), free); + if (arg_values == nullptr) { + return nullptr; + } + std::vector<std::unique_ptr<Value, decltype(&FreeValue)>> args; + for (int i = 0; i < argc; ++i) { + args.emplace_back(arg_values.get()[i], FreeValue); } if (args[0]->size < 0) { return StringValue(strdup("")); } - uint8_t digest[SHA_DIGEST_SIZE]; - SHA_hash(args[0]->data, args[0]->size, digest); - FreeValue(args[0]); + uint8_t digest[SHA_DIGEST_LENGTH]; + SHA1(reinterpret_cast<uint8_t*>(args[0]->data), args[0]->size, digest); if (argc == 1) { return StringValue(PrintSha1(digest)); } int i; - uint8_t* arg_digest = reinterpret_cast<uint8_t*>(malloc(SHA_DIGEST_SIZE)); + uint8_t arg_digest[SHA_DIGEST_LENGTH]; for (i = 1; i < argc; ++i) { if (args[i]->type != VAL_STRING) { printf("%s(): arg %d is not a string; skipping", @@ -1375,22 +1377,16 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) { // Warn about bad args and skip them. printf("%s(): error parsing \"%s\" as sha-1; skipping", name, args[i]->data); - } else if (memcmp(digest, arg_digest, SHA_DIGEST_SIZE) == 0) { + } else if (memcmp(digest, arg_digest, SHA_DIGEST_LENGTH) == 0) { break; } - FreeValue(args[i]); } if (i >= argc) { // Didn't match any of the hex strings; return false. return StringValue(strdup("")); } - // Found a match; free all the remaining arguments and return the - // matched one. - int j; - for (j = i+1; j < argc; ++j) { - FreeValue(args[j]); - } - return args[i]; + // Found a match. + return args[i].release(); } // Read a local file and return its contents (the Value* returned @@ -1402,21 +1398,22 @@ Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) { char* filename; if (ReadArgs(state, argv, 1, &filename) < 0) return NULL; - Value* v = reinterpret_cast<Value*>(malloc(sizeof(Value))); + Value* v = static_cast<Value*>(malloc(sizeof(Value))); + if (v == nullptr) { + return nullptr; + } v->type = VAL_BLOB; + v->size = -1; + v->data = nullptr; FileContents fc; if (LoadFileContents(filename, &fc) != 0) { - free(filename); - v->size = -1; - v->data = NULL; - free(fc.data); - return v; + v->data = static_cast<char*>(malloc(fc.data.size())); + if (v->data != nullptr) { + memcpy(v->data, fc.data.data(), fc.data.size()); + v->size = fc.data.size(); + } } - - v->size = fc.size; - v->data = (char*)fc.data; - free(filename); return v; } @@ -1443,10 +1440,10 @@ Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) { // zero out the 'command' field of the bootloader message. memset(buffer, 0, sizeof(((struct bootloader_message*)0)->command)); - FILE* f = fopen(filename, "r+b"); + FILE* f = ota_fopen(filename, "r+b"); fseek(f, offsetof(struct bootloader_message, command), SEEK_SET); - fwrite(buffer, sizeof(((struct bootloader_message*)0)->command), 1, f); - fclose(f); + ota_fwrite(buffer, sizeof(((struct bootloader_message*)0)->command), 1, f); + ota_fclose(f); free(filename); strcpy(buffer, "reboot,"); @@ -1485,7 +1482,7 @@ Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) { // bootloader message that the main recovery uses to save its // arguments in case of the device restarting midway through // package installation. - FILE* f = fopen(filename, "r+b"); + FILE* f = ota_fopen(filename, "r+b"); fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET); int to_write = strlen(stagestr)+1; int max_size = sizeof(((struct bootloader_message*)0)->stage); @@ -1493,8 +1490,8 @@ Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) { to_write = max_size; stagestr[max_size-1] = 0; } - fwrite(stagestr, to_write, 1, f); - fclose(f); + ota_fwrite(stagestr, to_write, 1, f); + ota_fclose(f); free(stagestr); return StringValue(filename); @@ -1511,10 +1508,10 @@ Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) { if (ReadArgs(state, argv, 1, &filename) < 0) return NULL; char buffer[sizeof(((struct bootloader_message*)0)->stage)]; - FILE* f = fopen(filename, "rb"); + FILE* f = ota_fopen(filename, "rb"); fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET); - fread(buffer, sizeof(buffer), 1, f); - fclose(f); + ota_fread(buffer, sizeof(buffer), 1, f); + ota_fclose(f); buffer[sizeof(buffer)-1] = '\0'; return StringValue(strdup(buffer)); @@ -1531,13 +1528,13 @@ Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) size_t len; android::base::ParseUint(len_str, &len); - int fd = open(filename, O_WRONLY, 0644); + int fd = ota_open(filename, O_WRONLY, 0644); int success = wipe_block_device(fd, len); free(filename); free(len_str); - close(fd); + ota_close(fd); return StringValue(strdup(success ? "t" : "")); } |