Change method of checking main symbol 23/262423/11
authorChanggyu Choi <changyu.choi@samsung.com>
Tue, 10 Aug 2021 08:14:12 +0000 (17:14 +0900)
committerChanggyu Choi <changyu.choi@samsung.com>
Wed, 11 Aug 2021 09:30:45 +0000 (18:30 +0900)
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>
CMakeLists.txt
packaging/aul.spec
parser/exec-checker/CMakeLists.txt
parser/exec-checker/inc/exec_checker.hh
parser/exec-checker/src/exec_checker.cc
parser/exec-checker/src/plugin_manager.cc

index bc0e00a..52962fa 100644 (file)
@@ -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)
index 9c510db..2144d6f 100644 (file)
@@ -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
index bb26f1b..97134e1 100644 (file)
@@ -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}
index 7857e77..a1c08b8 100644 (file)
@@ -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
index 23278af..5ef73c5 100644 (file)
 #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;
 }
 
index 91e1bdc..24566dd 100644 (file)
@@ -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;
   }