diff options
author | Changgyu Choi <changyu.choi@samsung.com> | 2021-08-10 17:14:12 +0900 |
---|---|---|
committer | Changgyu Choi <changyu.choi@samsung.com> | 2021-08-11 18:30:45 +0900 |
commit | 9f8dd0dbbceb293a829f4e6933990cc6069c3ef7 (patch) | |
tree | dad955645f94079852094d9d42633d001101fb6a | |
parent | ac5655de8f5273a74b9afa8e8bb61deaef40d1ba (diff) | |
download | aul-1-9f8dd0dbbceb293a829f4e6933990cc6069c3ef7.tar.gz aul-1-9f8dd0dbbceb293a829f4e6933990cc6069c3ef7.tar.bz2 aul-1-9f8dd0dbbceb293a829f4e6933990cc6069c3ef7.zip |
Change method of checking main symbol
Some binary may need to launch daemons for loading them.
In special case such as mic build, deamons are not launched.
As a result, the parser should not use dlopen().
Change-Id: I102eb220d4ecab2657668a335af95257de981e79
Signed-off-by: Changgyu Choi <changyu.choi@samsung.com>
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | packaging/aul.spec | 1 | ||||
-rw-r--r-- | parser/exec-checker/CMakeLists.txt | 2 | ||||
-rw-r--r-- | parser/exec-checker/inc/exec_checker.hh | 3 | ||||
-rw-r--r-- | parser/exec-checker/src/exec_checker.cc | 75 | ||||
-rw-r--r-- | parser/exec-checker/src/plugin_manager.cc | 6 |
6 files changed, 70 insertions, 18 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index bc0e00a8..52962fa4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,6 +52,7 @@ PKG_CHECK_MODULES(TTRACE_DEPS REQUIRED ttrace) PKG_CHECK_MODULES(UUID_DEPS REQUIRED uuid) PKG_CHECK_MODULES(VCONF_DEPS REQUIRED vconf) PKG_CHECK_MODULES(XDGMIME_DEPS REQUIRED xdgmime) +PKG_CHECK_MODULES(LIBELF_DEPS REQUIRED libelf) ## Target sources AUX_SOURCE_DIRECTORY(src SRCS) diff --git a/packaging/aul.spec b/packaging/aul.spec index 9c510dbd..2144d6fd 100644 --- a/packaging/aul.spec +++ b/packaging/aul.spec @@ -36,6 +36,7 @@ BuildRequires: pkgconfig(uuid) BuildRequires: pkgconfig(libsmack) BuildRequires: pkgconfig(gmock) BuildRequires: pkgconfig(parcel) +BuildRequires: pkgconfig(libelf) %if 0%{?gcov:1} BuildRequires: lcov diff --git a/parser/exec-checker/CMakeLists.txt b/parser/exec-checker/CMakeLists.txt index bb26f1b4..97134e1f 100644 --- a/parser/exec-checker/CMakeLists.txt +++ b/parser/exec-checker/CMakeLists.txt @@ -20,7 +20,7 @@ APPLY_PKG_CONFIG(${TARGET_CHECK_EXEC_PLUGIN_PARSER} PUBLIC LIBXML_DEPS PKGMGR_INFO_DEPS PKGMGR_INSTALLER_DEPS - SQLITE3_DEPS + LIBELF_DEPS ) INSTALL(TARGETS ${TARGET_CHECK_EXEC_PLUGIN_PARSER} diff --git a/parser/exec-checker/inc/exec_checker.hh b/parser/exec-checker/inc/exec_checker.hh index 7857e774..a1c08b86 100644 --- a/parser/exec-checker/inc/exec_checker.hh +++ b/parser/exec-checker/inc/exec_checker.hh @@ -24,7 +24,9 @@ namespace plugin { class ExecChecker { public: explicit ExecChecker(std::string path); + ~ExecChecker() = default; bool IsShared(); + bool CheckMainSymbol(); bool CheckDependencyLibs(); bool IsSameArch(const ExecChecker& exe); @@ -32,6 +34,7 @@ class ExecChecker { std::string path_; int class_bit_ = 0; uint16_t arch_bit_ = 0; + uint16_t type_ = 0; }; } // namespace plugin diff --git a/parser/exec-checker/src/exec_checker.cc b/parser/exec-checker/src/exec_checker.cc index 23278afb..5ef73c55 100644 --- a/parser/exec-checker/src/exec_checker.cc +++ b/parser/exec-checker/src/exec_checker.cc @@ -18,10 +18,14 @@ #include <elf.h> #include <errno.h> #include <fcntl.h> +#include <gelf.h> +#include <libelf.h> +#include <linux/limits.h> #include <string.h> #include <sys/stat.h> #include <sys/wait.h> #include <unistd.h> +#include <uuid/uuid.h> #include <fstream> #include <memory> @@ -66,40 +70,79 @@ ExecChecker::ExecChecker(std::string path) : path_(std::move(path)) { h.c[EI_CLASS] == ELFCLASS32) { class_bit_ = 32; arch_bit_ = h.ehdr32.e_machine; + type_ = h.ehdr32.e_type; } else if (nbyte >= static_cast<int>(sizeof(Elf64_Ehdr)) && h.c[EI_CLASS] == ELFCLASS64) { class_bit_ = 64; arch_bit_ = h.ehdr64.e_machine; + type_ = h.ehdr64.e_type; } - LOGI_STD("class: %dbit, e_machine: %hu", class_bit_, arch_bit_); + LOGI_STD("%s class: %dbit, e_machine: %hu, e_type : %hu", + path_.c_str(), class_bit_, arch_bit_, type_); } bool ExecChecker::IsShared() { - void* handle = dlopen(path_.c_str(), RTLD_LAZY | RTLD_GLOBAL); - if (handle == nullptr) { - LOGE_STD("(%s) is not shared object.", path_.c_str()); + return type_ == ET_DYN; +} + +bool ExecChecker::CheckMainSymbol() { + int fd = open(path_.c_str(), O_RDONLY); + if (fd < 0) { + LOGE_STD("Failed to open file(%s). errno(%d)", path_.c_str(), errno); + return false; + } + + elf_version(EV_CURRENT); + + auto elf_destructor = [fd] (Elf* elf) -> void { + close(fd); + elf_end(elf); + }; + auto elf = std::unique_ptr<Elf, decltype(elf_destructor)> + (elf_begin(fd, ELF_C_READ, nullptr), elf_destructor); + if (elf == nullptr) { + LOGE_STD("Out of memory"); return false; } - auto* main = dlsym(handle, "main"); - if (main == nullptr) - LOGW_STD("Not found main symbol(%s). err(%s)", path_.c_str(), dlerror()); + Elf_Scn* scn = nullptr; + GElf_Shdr shdr; + while ((scn = elf_nextscn(elf.get(), scn)) != nullptr) { + gelf_getshdr(scn, &shdr); + if (shdr.sh_type == SHT_SYMTAB) + break; + } + + Elf_Data* data = elf_getdata(scn, nullptr); + int count = (shdr.sh_entsize == 0 ? 0 : shdr.sh_size / shdr.sh_entsize); + + for (int i = 0; i < count; ++i) { + GElf_Sym sym; + gelf_getsym(data, i, &sym); + char* symbol = elf_strptr(elf.get(), shdr.sh_link, sym.st_name); + if (symbol != nullptr && strcmp("main", symbol) == 0) + return true; + } - dlclose(handle); - return main != nullptr; + LOGW_STD("Not found main symbol(%s)", path_.c_str()); + return false; } bool ExecChecker::CheckDependencyLibs() { std::string root_path = path_.substr(0, path_.find_last_of('/') - 4); - char tmp_format[] = "/tmp/XXXXXX"; - auto* tmp = tmpnam_r(tmp_format); - if (tmp == nullptr) { - LOGE_STD("Failed to make temp file. errno(%d)", errno); - return false; - } + char uuid[37]; + uuid_t u; + uuid_generate(u); + uuid_unparse(u, uuid); + std::string tmp = std::string("/tmp/") + + path_.substr(path_.find_last_of('/') + 1) + "_" + uuid; std::string cmd = "LD_LIBRARY_PATH=" + root_path + "/lib /usr/bin/ldd " + path_ + " > " + tmp; + + if (tmp.size() > PATH_MAX) + tmp = tmp.substr(0, PATH_MAX); + bool pass = true; int ret = WEXITSTATUS(system(cmd.c_str())); if (ret != 0) { @@ -122,7 +165,7 @@ bool ExecChecker::CheckDependencyLibs() { } f.close(); - remove(tmp); + remove(tmp.c_str()); return pass; } diff --git a/parser/exec-checker/src/plugin_manager.cc b/parser/exec-checker/src/plugin_manager.cc index 91e1bdcf..24566dd9 100644 --- a/parser/exec-checker/src/plugin_manager.cc +++ b/parser/exec-checker/src/plugin_manager.cc @@ -118,7 +118,11 @@ int PluginManager::Process() { if (!self_->IsSameArch(checker)) return -1; - checker.IsShared(); + + if (!checker.IsShared()) + LOGW("%s is not shared object", exec); + + checker.CheckMainSymbol(); if (!checker.CheckDependencyLibs()) return -1; } |