summaryrefslogtreecommitdiff
path: root/cmds/installd/dexopt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cmds/installd/dexopt.cpp')
-rw-r--r--cmds/installd/dexopt.cpp120
1 files changed, 101 insertions, 19 deletions
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 6f7ab6b52f..6a7d84580d 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -41,6 +41,7 @@
#include <system/thread_defs.h>
#include "dexopt.h"
+#include "globals.h"
#include "installd_deps.h"
#include "otapreopt_utils.h"
#include "utils.h"
@@ -156,7 +157,7 @@ static int split_count(const char *str)
int count = 0;
char buf[kPropertyValueMax];
- strncpy(buf, str, sizeof(buf));
+ strlcpy(buf, str, sizeof(buf));
char *pBuf = buf;
while(strtok_r(pBuf, " ", &ctx) != NULL) {
@@ -333,7 +334,8 @@ static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vd
bool have_dex2oat_compiler_filter_flag = false;
if (skip_compilation) {
- strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=extract");
+ strlcpy(dex2oat_compiler_filter_arg, "--compiler-filter=extract",
+ sizeof(dex2oat_compiler_filter_arg));
have_dex2oat_compiler_filter_flag = true;
have_dex2oat_relocation_skip_flag = true;
} else if (compiler_filter != nullptr) {
@@ -955,14 +957,6 @@ static std::string create_vdex_filename(const std::string& oat_path) {
return replace_file_extension(oat_path, ".vdex");
}
-static bool add_extension_to_file_name(char* file_name, const char* extension) {
- if (strlen(file_name) + strlen(extension) + 1 > PKG_PATH_MAX) {
- return false;
- }
- strcat(file_name, extension);
- return true;
-}
-
static int open_output_file(const char* file_name, bool recreate, int permissions) {
int flags = O_RDWR | O_CREAT;
if (recreate) {
@@ -1198,21 +1192,16 @@ unique_fd maybe_open_dexopt_swap_file(const char* out_oat_path) {
if (!ShouldUseSwapFileForDexopt()) {
return invalid_unique_fd();
}
- // Make sure there really is enough space.
- char swap_file_name[PKG_PATH_MAX];
- strcpy(swap_file_name, out_oat_path);
- if (!add_extension_to_file_name(swap_file_name, ".swap")) {
- return invalid_unique_fd();
- }
+ auto swap_file_name = std::string(out_oat_path) + ".swap";
unique_fd swap_fd(open_output_file(
- swap_file_name, /*recreate*/true, /*permissions*/0600));
+ swap_file_name.c_str(), /*recreate*/true, /*permissions*/0600));
if (swap_fd.get() < 0) {
// Could not create swap file. Optimistically go on and hope that we can compile
// without it.
- ALOGE("installd could not create '%s' for swap during dexopt\n", swap_file_name);
+ ALOGE("installd could not create '%s' for swap during dexopt\n", swap_file_name.c_str());
} else {
// Immediately unlink. We don't really want to hit flash.
- if (unlink(swap_file_name) < 0) {
+ if (unlink(swap_file_name.c_str()) < 0) {
PLOG(ERROR) << "Couldn't unlink swap file " << swap_file_name;
}
}
@@ -2040,5 +2029,98 @@ bool delete_odex(const char* apk_path, const char* instruction_set, const char*
return return_value_oat && return_value_art && return_value_vdex;
}
+static bool is_absolute_path(const std::string& path) {
+ if (path.find('/') != 0 || path.find("..") != std::string::npos) {
+ LOG(ERROR) << "Invalid absolute path " << path;
+ return false;
+ } else {
+ return true;
+ }
+}
+
+static bool is_valid_instruction_set(const std::string& instruction_set) {
+ // TODO: add explicit whitelisting of instruction sets
+ if (instruction_set.find('/') != std::string::npos) {
+ LOG(ERROR) << "Invalid instruction set " << instruction_set;
+ return false;
+ } else {
+ return true;
+ }
+}
+
+bool calculate_oat_file_path_default(char path[PKG_PATH_MAX], const char *oat_dir,
+ const char *apk_path, const char *instruction_set) {
+ std::string oat_dir_ = oat_dir;
+ std::string apk_path_ = apk_path;
+ std::string instruction_set_ = instruction_set;
+
+ if (!is_absolute_path(oat_dir_)) return false;
+ if (!is_absolute_path(apk_path_)) return false;
+ if (!is_valid_instruction_set(instruction_set_)) return false;
+
+ std::string::size_type end = apk_path_.rfind('.');
+ std::string::size_type start = apk_path_.rfind('/', end);
+ if (end == std::string::npos || start == std::string::npos) {
+ LOG(ERROR) << "Invalid apk_path " << apk_path_;
+ return false;
+ }
+
+ std::string res_ = oat_dir_ + '/' + instruction_set + '/'
+ + apk_path_.substr(start + 1, end - start - 1) + ".odex";
+ const char* res = res_.c_str();
+ if (strlen(res) >= PKG_PATH_MAX) {
+ LOG(ERROR) << "Result too large";
+ return false;
+ } else {
+ strlcpy(path, res, PKG_PATH_MAX);
+ return true;
+ }
+}
+
+bool calculate_odex_file_path_default(char path[PKG_PATH_MAX], const char *apk_path,
+ const char *instruction_set) {
+ std::string apk_path_ = apk_path;
+ std::string instruction_set_ = instruction_set;
+
+ if (!is_absolute_path(apk_path_)) return false;
+ if (!is_valid_instruction_set(instruction_set_)) return false;
+
+ std::string::size_type end = apk_path_.rfind('.');
+ std::string::size_type start = apk_path_.rfind('/', end);
+ if (end == std::string::npos || start == std::string::npos) {
+ LOG(ERROR) << "Invalid apk_path " << apk_path_;
+ return false;
+ }
+
+ std::string oat_dir = apk_path_.substr(0, start + 1) + "oat";
+ return calculate_oat_file_path_default(path, oat_dir.c_str(), apk_path, instruction_set);
+}
+
+bool create_cache_path_default(char path[PKG_PATH_MAX], const char *src,
+ const char *instruction_set) {
+ std::string src_ = src;
+ std::string instruction_set_ = instruction_set;
+
+ if (!is_absolute_path(src_)) return false;
+ if (!is_valid_instruction_set(instruction_set_)) return false;
+
+ for (auto it = src_.begin() + 1; it < src_.end(); ++it) {
+ if (*it == '/') {
+ *it = '@';
+ }
+ }
+
+ std::string res_ = android_data_dir + DALVIK_CACHE + '/' + instruction_set_ + src_
+ + DALVIK_CACHE_POSTFIX;
+ const char* res = res_.c_str();
+ if (strlen(res) >= PKG_PATH_MAX) {
+ LOG(ERROR) << "Result too large";
+ return false;
+ } else {
+ strlcpy(path, res, PKG_PATH_MAX);
+ return true;
+ }
+}
+
} // namespace installd
} // namespace android