Skip to content

Commit

Permalink
Updating Debian packaging to more appropiately match proper Debian Pa…
Browse files Browse the repository at this point in the history
…ckaging standards
  • Loading branch information
AndrewQuijano committed Dec 12, 2024
1 parent cc88392 commit 3be241a
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/publish_docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
34 changes: 29 additions & 5 deletions panda/debian/Dockerfile
Original file line number Diff line number Diff line change
@@ -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 && \
Expand All @@ -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/,$//') && \
Expand All @@ -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

Expand Down
12 changes: 9 additions & 3 deletions panda/debian/control
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
Package: pandare
Version: 3.1.0
Architecture: all
Source: MIT
Version: <version-placeholder>
Architecture: amd64
BUILD_DEPENDS_LIST
DEPENDS_LIST
Maintainer: Andrew Fasano <fasano@mit.edu>
Maintainer: Luke Craig <luke.craig@mit.edu>
Installed-Size: <size-in-kb>
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-
Expand Down
30 changes: 23 additions & 7 deletions panda/debian/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,35 +25,51 @@ 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 <OS> <version>"
echo " $0 <OS> <ubuntu-version> <tag-version>"
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"
exit 1
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"
Expand Down
2 changes: 2 additions & 0 deletions panda/debian/triggers
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Trigger ldconfig after install
activate-noawait ldconfig
7 changes: 7 additions & 0 deletions panda/plugins/osi_linux/osi_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
3 changes: 3 additions & 0 deletions panda/python/core/pandare/panda.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
10 changes: 7 additions & 3 deletions panda/python/core/pandare/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
Expand All @@ -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
Expand Down
24 changes: 22 additions & 2 deletions panda/src/callbacks.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
* See the COPYING file in the top-level directory.
*
PANDAENDCOMMENT */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <string.h>
#include <dlfcn.h>
Expand Down Expand Up @@ -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};
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit 3be241a

Please sign in to comment.