def inspect_file(self, path): file_info = {"path": path, "is_file": True} mtime = os.path.getmtime(path) # don't inspect files if they haven't been modified since last update if path in self.cache: file_info = self.cache[path] if mtime == file_info["mtime"]: return file_info file_info["mtime"] = mtime if is_elf(path): file_info["is_elf"] = True if is_elf_executable(path): file_info["is_bin"] = True else: file_info["is_lib"] = True try: patchelf = PatchElf() patchelf.logger.level = logging.WARNING patchelf.log_stderr = False file_info["pt_needed"] = patchelf.get_needed(path) # an exception is raised if the elf has no PT_INTERP section file_info["pt_interp"] = patchelf.get_interpreter(path) except PatchElfError: pass if os.access(path, os.X_OK): file_info["is_exec"] = True return file_info
def _resolve_bin_interpreters(self): patch_elf = PatchElf() patch_elf.log_stderr = False interpreter_paths = set() for bin in self.runtime_bins: try: interpreter = patch_elf.get_interpreter(bin) if not interpreter.startswith("/tmp"): interpreter_paths.add(interpreter) except PatchElfError: pass return interpreter_paths
def __init__(self, app_dir, app_dir_cache): super().__init__(app_dir, app_dir_cache) self.priority = 100 self.patch_elf = PatchElf() self.patch_elf.logger.level = logging.WARNING self.interpreters = {}
def get_dependants_of(self, lib_name): dependants = set() for root, dirs, files in os.walk(self.app_dir): if "opt/libc" in root: continue for file in files: abs_path = os.path.join(root, file) try: if has_magic_bytes(abs_path): patch_elf = PatchElf() patch_elf.log_stdout = False patch_elf.log_stderr = False patch_elf.log_command = False needs = patch_elf.get_needed(abs_path) if lib_name in needs: dependants.add( os.path.relpath(abs_path, self.app_dir)) except FileNotFoundError: pass except PatchElfError: pass return dependants
def get_bundle_needed_libs(self): libs_needed = set() bundle_libs = set() for root, dirs, files in os.walk(self.app_dir): if "opt/libc" in root: continue for file in files: bundle_libs.add(file) abs_path = os.path.join(root, file) try: if has_magic_bytes(abs_path): patch_elf = PatchElf() patch_elf.log_stdout = False patch_elf.log_stderr = False patch_elf.log_command = False libs_needed.update(patch_elf.get_needed(abs_path)) except FileNotFoundError: pass except PatchElfError: pass bundle_needed = libs_needed - bundle_libs return bundle_needed
def _set_interpreter(self, file, uuid): original_interpreter = self.app_dir_cache.cache[file]["pt_interp"] if original_interpreter.startswith("/tmp/appimage-"): # skip, the binary has been patched already return try: patchelf_command = PatchElf() patchelf_command.log_stderr = False patchelf_command.log_stdout = False apprun_interpreter = self._gen_interpreter_link_path( original_interpreter, uuid) if original_interpreter and original_interpreter != apprun_interpreter: # only include interpreters from standard paths if original_interpreter.startswith("/lib"): self.interpreters[ original_interpreter] = apprun_interpreter logging.info("Replacing PT_INTERP on: %s" % os.path.relpath(file, self.app_dir)) logging.debug('\t"%s" => "%s"' % (original_interpreter, apprun_interpreter)) patchelf_command.set_interpreter(file, apprun_interpreter) self.app_dir_cache.cache[file][ "pt_interp"] = apprun_interpreter except PatchElfError: pass