From 3be241af8b705754078926f561b7f5f75129c58d Mon Sep 17 00:00:00 2001 From: AndrewQuijano Date: Tue, 10 Dec 2024 21:06:59 -0500 Subject: [PATCH] Updating Debian packaging to more appropiately match proper Debian Packaging standards --- .github/workflows/publish_docker.yml | 2 +- panda/debian/Dockerfile | 34 +++++++++++++++++++++++---- panda/debian/control | 12 +++++++--- panda/debian/setup.sh | 30 +++++++++++++++++------ panda/debian/triggers | 2 ++ panda/plugins/osi_linux/osi_linux.cpp | 7 ++++++ panda/python/core/pandare/panda.py | 3 +++ panda/python/core/pandare/utils.py | 10 +++++--- panda/src/callbacks.c | 24 +++++++++++++++++-- 9 files changed, 103 insertions(+), 21 deletions(-) create mode 100644 panda/debian/triggers diff --git a/.github/workflows/publish_docker.yml b/.github/workflows/publish_docker.yml index 25db2724909..b5ed42f700c 100644 --- a/.github/workflows/publish_docker.yml +++ b/.github/workflows/publish_docker.yml @@ -46,7 +46,7 @@ jobs: - name: Build package working-directory: panda/debian - run: ./setup.sh Ubuntu ${{ matrix.ubuntu_version }} + run: ./setup.sh Ubuntu ${{ matrix.ubuntu_version }} ${{ needs.create_release.outputs.v-version }} - name: Upload wheel and debian packages to release uses: softprops/action-gh-release@v2 diff --git a/panda/debian/Dockerfile b/panda/debian/Dockerfile index 8d45e844161..7ce91618b51 100644 --- a/panda/debian/Dockerfile +++ b/panda/debian/Dockerfile @@ -1,7 +1,9 @@ +ARG PACKAGE_VERSION="" + # First run the main Dockerfile to build the base image and name it panda. Then we run here # to generate a debian package -FROM debian:buster-slim +FROM debian:bookworm-slim # Install necessary tools for packaging RUN apt-get -qq update && \ @@ -12,15 +14,34 @@ RUN apt-get -qq update && \ COPY --from=panda /tmp/base_dep.txt /tmp COPY --from=panda /tmp/build_dep.txt /tmp +# Copy libcapstone and libosi shared object files from panda +RUN mkdir -p /package-root/usr/lib/x86_64-linux-gnu/ +COPY --from=panda /lib/libcapstone.so* /package-root/usr/lib/x86_64-linux-gnu/ +COPY --from=panda /lib/libosi.so /lib/libiohal.so /lib/liboffset.so /package-root/usr/lib/ + # Set up /package-root with files from panda we'll package -COPY --from=panda /usr/local/bin/panda* /usr/local/bin/libpanda* /usr/local/bin/qemu-img /package-root/usr/local/bin/ -COPY --from=panda /usr/local/etc/panda /package-root/usr/local/etc/panda -COPY --from=panda /usr/local/lib/panda /package-root/usr/local/lib/panda -COPY --from=panda /usr/local/share/panda /package-root/usr/local/share/panda +COPY --from=panda /usr/local/bin/panda* /usr/local/bin/libpanda* /usr/local/bin/qemu-img /package-root/usr/bin/ +COPY --from=panda /usr/local/etc/panda /package-root/etc/panda/ +COPY --from=panda /usr/local/lib/panda /package-root/usr/lib/panda/ +COPY --from=panda /usr/local/share/panda /package-root/usr/share/panda/ + +# Copy documentation over, we should have a better Changelog if we go for official release? +# COPY ./LICENSE /package-root/usr/share/doc/panda +# COPY ./README.md /package-root/usr/share/doc/panda # Create DEBIAN directory and control file COPY control /package-root/DEBIAN/control +# Generate MD5 checksums for all files and save to DEBIAN/md5sums +RUN cd /package-root && \ + find . -type f ! -path './DEBIAN/*' -exec md5sum {} + | sed 's| \./| |' > /package-root/DEBIAN/md5sums + +# Update control file with the correct version, and place installed size +ARG PACKAGE_VERSION +RUN INSTALLED_SIZE=$(du -sk /package-root | cut -f1) && \ + sed -i "s/^Installed-Size:.*/Installed-Size: ${INSTALLED_SIZE}/" /package-root/DEBIAN/control +RUN sed -i "s/^Version:.*/Version: ${PACKAGE_VERSION}/" /package-root/DEBIAN/control + # Update control file with dependencies # Build time. We only select dependencies that are not commented out or blank RUN dependencies=$(grep '^[a-zA-Z]' /tmp/build_dep.txt | tr '\n' ',' | sed 's/,,\+/,/g'| sed 's/,$//') && \ @@ -30,6 +51,9 @@ RUN dependencies=$(grep '^[a-zA-Z]' /tmp/build_dep.txt | tr '\n' ',' | sed 's/,, RUN dependencies=$(grep '^[a-zA-Z]' /tmp/base_dep.txt | tr '\n' ',' | sed 's/,,\+/,/g' | sed 's/,$//') && \ sed -i "s/DEPENDS_LIST/Depends: ipxe-qemu,${dependencies}/" /package-root/DEBIAN/control +# Add triggers script to run ldconfig after installation +COPY triggers /package-root/DEBIAN/triggers + # Build the package RUN fakeroot dpkg-deb --build /package-root /pandare.deb diff --git a/panda/debian/control b/panda/debian/control index c5457a4457d..00d02c5baff 100644 --- a/panda/debian/control +++ b/panda/debian/control @@ -1,9 +1,15 @@ Package: pandare -Version: 3.1.0 -Architecture: all +Source: MIT +Version: +Architecture: amd64 BUILD_DEPENDS_LIST DEPENDS_LIST -Maintainer: Andrew Fasano +Maintainer: Luke Craig +Installed-Size: +Section: devel +Priority: optional +Multi-Arch: same +Homepage: https://panda.re/ Description: dynamic analysis platform Platform for Architecture Neutral Dynamic Analysis (PANDA) is a processor emulator designed to support analyses of guest code. PANDA supports record- diff --git a/panda/debian/setup.sh b/panda/debian/setup.sh index b28dc85c7e2..6fbf26ce7c5 100755 --- a/panda/debian/setup.sh +++ b/panda/debian/setup.sh @@ -25,17 +25,33 @@ if [[ $# -eq 1 ]]; then echo " To build a package for current Ubuntu version:" echo " $0" echo " To build a package for a specific OS/version (only Ubuntu supported for now):" - echo " $0 " + echo " $0 " exit 1 fi if [[ $# -eq 2 ]]; then version=$2 - else version=$(lsb_release -r | awk '{print $2}') fi +if [[ $# -eq 3 ]]; then + tag_version=$3 +else + tag_version='v3.1.0' +fi + +# Remove leading 'v' if present, e. g. v1.5.1 -> 1.5.1 +if [[ "$tag_version" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + tag_version=${tag_version:1} +fi + +# Check if the version follows the format X.Y.Z, e. g. 1.5.1 or 1.9.1 +if [[ ! "$tag_version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "ERROR: Version must be in the format X.Y.Z, provided tag version: $tag_version" + exit 1 +fi + # Check if the given version is supported if [[ ! -f "../dependencies/ubuntu_${version}_base.txt" ]]; then echo "ERROR: Ubuntu ${version} is not supported, no dependencies file found" @@ -43,17 +59,17 @@ if [[ ! -f "../dependencies/ubuntu_${version}_base.txt" ]]; then fi # Build the installer to generate the wheel file -DOCKER_BUILDKIT=1 docker build --target installer -t panda --build-arg BASE_IMAGE="ubuntu:${version}" ../.. +DOCKER_BUILDKIT=1 docker build --target installer -t panda_installer --build-arg BASE_IMAGE="ubuntu:${version}" ../.. # Copy wheel file out of container to host -# this also preserves wheel name, which is important as pip install WILL fail if you arbitarily change the generated wheel file name -docker run --rm -v $(pwd):/out panda bash -c "cp /panda/panda/python/core/dist/*.whl /out" +# This also preserves wheel name, which is important as pip install WILL fail if you arbitarily change the generated wheel file name +docker run --rm -v $(pwd):/out panda_installer bash -c "cp /panda/panda/python/core/dist/*.whl /out" # Finish building main panda container for the target ubuntu version -DOCKER_BUILDKIT=1 docker build --target panda -t panda --build-arg BASE_IMAGE="ubuntu:${version}" ../.. +DOCKER_BUILDKIT=1 docker build --cache-from panda_installer --target panda -t panda --build-arg BASE_IMAGE="ubuntu:${version}" ../.. # Now build the packager container from that -docker build -t packager . +DOCKER_BUILDKIT=1 docker build --cache-from panda -t packager --build-arg PACKAGE_VERSION="${tag_version}" . # Copy deb file out of container to host docker run --rm -v $(pwd):/out packager bash -c "cp /pandare.deb /out" diff --git a/panda/debian/triggers b/panda/debian/triggers new file mode 100644 index 00000000000..cd1ae26a175 --- /dev/null +++ b/panda/debian/triggers @@ -0,0 +1,2 @@ +# Trigger ldconfig after install +activate-noawait ldconfig \ No newline at end of file diff --git a/panda/plugins/osi_linux/osi_linux.cpp b/panda/plugins/osi_linux/osi_linux.cpp index d6cfc3ead23..b36aec97c19 100644 --- a/panda/plugins/osi_linux/osi_linux.cpp +++ b/panda/plugins/osi_linux/osi_linux.cpp @@ -1241,6 +1241,13 @@ bool init_plugin(void *self) { if (kconf_file != NULL) g_free(kconf_file); const char* panda_dir = g_getenv("PANDA_DIR"); kconf_file = g_strdup_printf("%s%s", panda_dir, KERNEL_CONF); + LOG_INFO("Looking for kconf_file attempt %u: %s", 3, kconf_file); + kconffile_canon = realpath(kconf_file, NULL); + } + if (kconffile_canon == NULL) { // from /etc/panda/osi_linux (Debian package) + if (kconf_file != NULL) g_free(kconf_file); + kconf_file = g_build_filename("/etc", "panda", "osi_linux", "kernelinfo.conf", NULL); + LOG_INFO("Looking for kconf_file attempt %u: %s", 4, kconf_file); kconffile_canon = realpath(kconf_file, NULL); } diff --git a/panda/python/core/pandare/panda.py b/panda/python/core/pandare/panda.py index 01307a3029c..d659c827807 100644 --- a/panda/python/core/pandare/panda.py +++ b/panda/python/core/pandare/panda.py @@ -270,6 +270,9 @@ def get_plugin_path(self): if build_dir == "/usr/local/bin/": # Installed - use /usr/local/lib/panda/plugins self.plugin_path = f"/usr/local/lib/panda/{self.arch_name}" + elif build_dir == "/usr/bin/": + # Installed - use /usr/lib/panda/plugins + self.plugin_path = f"/usr/lib/panda/{self.arch_name}" elif isdir(rel_dir): self.plugin_path = rel_dir else: diff --git a/panda/python/core/pandare/utils.py b/panda/python/core/pandare/utils.py index d7af0c4bfe5..a76c69aee78 100644 --- a/panda/python/core/pandare/utils.py +++ b/panda/python/core/pandare/utils.py @@ -180,6 +180,7 @@ def _find_build_dir(arch_name, find_executable=False): Internal function to return the build directory for the specified architecture ''' + debian_build = "/usr/bin/" system_build = "/usr/local/bin/" python_package = pjoin(*[dirname(__file__), "data"]) local_build = realpath(pjoin(dirname(__file__), "../../../../build")) @@ -190,9 +191,12 @@ def _find_build_dir(arch_name, find_executable=False): f"libpanda-{arch_name}.so" # system path could have panda-system-X or libpanda-X.so. Others would have an arch_name - softmmu directory - pot_paths = [system_build, - pjoin(python_package, arch_dir), - pjoin(local_build, arch_dir)] + pot_paths = [ + system_build, + debian_build, + pjoin(python_package, arch_dir), + pjoin(local_build, arch_dir) + ] if find_executable and 'PATH' in environ: # If we're looking for the panda executable, also search the user's path diff --git a/panda/src/callbacks.c b/panda/src/callbacks.c index 81078650304..365927fc60c 100644 --- a/panda/src/callbacks.c +++ b/panda/src/callbacks.c @@ -12,6 +12,9 @@ * See the COPYING file in the top-level directory. * PANDAENDCOMMENT */ +#include +#include +#include #include #include #include @@ -39,8 +42,8 @@ PANDAENDCOMMENT */ #define LIBRARY_NAME "/libpanda-" TARGET_NAME ".so" #define PLUGIN_DIR "/" TARGET_NAME "-softmmu/panda/plugins/" -#define INSTALL_PLUGIN_DIR "/usr/local/lib/panda/" -#define INSTALL_BIN_DIR "/usr/local/bin/" // libpanda-arch.so and panda-system-arch in here +const char* INSTALL_PLUGIN_DIR; +const char* INSTALL_BIN_DIR; // libpanda-arch.so and panda-system-arch in here const gchar *panda_bool_true_strings[] = {"y", "yes", "true", "1", NULL}; const gchar *panda_bool_false_strings[] = {"n", "no", "false", "0", NULL}; @@ -153,6 +156,14 @@ static bool load_libpanda(void) { g_free((char *)panda_lib); } + if (access("/usr/bin/libpanda-i386.so", F_OK) != -1) { + // File exists + INSTALL_BIN_DIR = "/usr/bin"; + } else { + // File does not exist + INSTALL_BIN_DIR = "/usr/local/bin/"; + } + // Try standard install location panda_lib = g_strdup_printf("%s%s", INSTALL_BIN_DIR, LIBRARY_NAME); if (g_file_test(panda_lib, G_FILE_TEST_EXISTS)) { @@ -349,6 +360,15 @@ char* resolve_file_from_plugin_directory(const char* file_name_fmt, const char* g_free(plugin_path); + if (access("/usr/bin/libpanda-i386.so", F_OK) != -1) { + // File exists + INSTALL_PLUGIN_DIR = "/usr/lib/panda"; + } else { + // File does not exist + INSTALL_PLUGIN_DIR = "/usr/local/lib/panda/"; + } + + // Third, check relative to the standard install location. plugin_path = attempt_normalize_path( g_strdup_printf("%s/%s/%s", INSTALL_PLUGIN_DIR,