Skip to content

[WIP] Updating Debian Package, Part II - Installation Paths #1564

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
28 changes: 23 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,28 @@ RUN apt-get -qq update && \
COPY --from=panda /tmp/base_dep.txt /tmp
COPY --from=panda /tmp/build_dep.txt /tmp

# NOTE: If you use the panda debian package, you still need to manually curl
# the libosi and libcapstone-dev package as seen in the main Dockerfile/install_ubuntu.sh

# 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/

# 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 +45,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
58 changes: 51 additions & 7 deletions panda/debian/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,35 +25,79 @@ 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

# Check if HTTP_PROXY and HTTPS_PROXY are set, if not set them to blank
HTTP_PROXY="${HTTP_PROXY:-}"
HTTPS_PROXY="${HTTPS_PROXY:-}"

# 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 HTTP_PROXY="${HTTP_PROXY}" \
--build-arg HTTPS_PROXY="${HTTPS_PROXY}" \
--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 arbitrarily change the generated wheel file name
docker run --rm \
-v $(pwd):/out \
-e HTTP_PROXY="${HTTP_PROXY}" \
-e HTTPS_PROXY="${HTTPS_PROXY}" \
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 HTTP_PROXY="${HTTP_PROXY}" \
--build-arg HTTPS_PROXY="${HTTPS_PROXY}" \
--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 HTTP_PROXY="${HTTP_PROXY}" \
--build-arg HTTPS_PROXY="${HTTPS_PROXY}" \
--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
37 changes: 34 additions & 3 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,12 +42,25 @@ 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};

const char * panda_system_paths[] = {
"/usr/bin/panda-system-aarch64",
"/usr/bin/panda-system-arm",
"/usr/bin/panda-system-i386",
"/usr/bin/panda-system-mips",
"/usr/bin/panda-system-mips64",
"/usr/bin/panda-system-mips64el",
"/usr/bin/panda-system-mipsel",
"/usr/bin/panda-system-ppc",
"/usr/bin/panda-system-x86_64",
NULL
};

#if 0
###########################################################
WARNING: This is all gloriously thread-unsafe!!!
Expand Down Expand Up @@ -153,6 +169,14 @@ static bool load_libpanda(void) {
g_free((char *)panda_lib);
}

INSTALL_BIN_DIR = "/usr/local/bin/";
for (int i = 0; panda_system_paths[i] != NULL; i++) {
if (access(panda_system_paths[i], F_OK) != -1) {
INSTALL_BIN_DIR = "/usr/bin";
break;
}
}

// 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 @@ -347,7 +371,14 @@ char* resolve_file_from_plugin_directory(const char* file_name_fmt, const char*
return plugin_path;
}
g_free(plugin_path);


INSTALL_PLUGIN_DIR = "/usr/local/lib/panda/";
for (int i = 0; panda_system_paths[i] != NULL; i++) {
if (access(panda_system_paths[i], F_OK) != -1) {
INSTALL_PLUGIN_DIR = "/usr/lib/panda";
break;
}
}

// Third, check relative to the standard install location.
plugin_path = attempt_normalize_path(
Expand Down
Loading