mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-30 18:27:18 +00:00
implement elf dynamic linking check
This commit is contained in:
parent
2922bb9d72
commit
9449c95ad4
1
setup.py
1
setup.py
@ -33,6 +33,7 @@ setup(
|
|||||||
"cerberus",
|
"cerberus",
|
||||||
"inflection",
|
"inflection",
|
||||||
"passlib",
|
"passlib",
|
||||||
|
"pyelftools",
|
||||||
"requests",
|
"requests",
|
||||||
"srcinfo",
|
"srcinfo",
|
||||||
],
|
],
|
||||||
|
95
src/ahriman/models/package_archive.py
Normal file
95
src/ahriman/models/package_archive.py
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2021-2023 ahriman team.
|
||||||
|
#
|
||||||
|
# This file is part of ahriman
|
||||||
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import IO
|
||||||
|
|
||||||
|
from elftools.elf.elffile import ELFFile
|
||||||
|
from elftools.elf.dynamic import DynamicSection
|
||||||
|
from pyalpm import Package # type: ignore[import]
|
||||||
|
|
||||||
|
from ahriman.core.util import walk
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class PackageArchive:
|
||||||
|
"""
|
||||||
|
helper for package archives
|
||||||
|
"""
|
||||||
|
|
||||||
|
package: Package
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_depends_paths(package_base: str, root: Path) -> tuple[set[str], set[Path]]:
|
||||||
|
dependencies = set()
|
||||||
|
roots = set()
|
||||||
|
|
||||||
|
package_dir = root / "build" / package_base / "pkg"
|
||||||
|
for path in walk(package_dir):
|
||||||
|
dependencies.update(PackageArchive.get_dynamic(path))
|
||||||
|
roots.update(path.relative_to(package_dir).parents)
|
||||||
|
|
||||||
|
return dependencies, roots
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_dynamic(binary_path: Path) -> list[str]:
|
||||||
|
with binary_path.open("rb") as binary_file:
|
||||||
|
if not PackageArchive.is_elf(binary_file):
|
||||||
|
return []
|
||||||
|
|
||||||
|
elf_file = ELFFile(binary_file)
|
||||||
|
dynamic_section = next((section for section in elf_file.iter_sections() if isinstance(section, DynamicSection)), None)
|
||||||
|
if dynamic_section is None:
|
||||||
|
return []
|
||||||
|
|
||||||
|
return [tag.needed for tag in dynamic_section.iter_tags() if tag.entry.d_tag == "DT_NEEDED"]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_filesystem(root: Path) -> dict[str, tuple[list[Path], list[Path]]]:
|
||||||
|
result = {}
|
||||||
|
for path in filter(lambda fn: fn.name == "files", walk(root / "var" / "lib" / "pacman" / "local")):
|
||||||
|
package, *_ = path.parent.name.rsplit("-", 2)
|
||||||
|
|
||||||
|
directories = []
|
||||||
|
files = []
|
||||||
|
for entry in path.read_text(encoding="utf8").splitlines():
|
||||||
|
if not entry or entry == "%FILES%":
|
||||||
|
continue # header
|
||||||
|
entry_path = Path(entry)
|
||||||
|
if entry_path.name == "":
|
||||||
|
directories.append(entry_path)
|
||||||
|
else:
|
||||||
|
files.append(entry_path)
|
||||||
|
|
||||||
|
result[package] = (directories, files)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_elf(descriptor: IO[bytes]) -> bool:
|
||||||
|
expected = b"\x7fELF"
|
||||||
|
length = len(expected)
|
||||||
|
|
||||||
|
magic_bytes = descriptor.read(length)
|
||||||
|
descriptor.seek(0) # reset reading position
|
||||||
|
|
||||||
|
return magic_bytes == expected
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user