From 40f3c605aa76f50eec48e1f443f8448496de10ab Mon Sep 17 00:00:00 2001 From: AndrewQuijano Date: Thu, 28 Nov 2024 13:28:56 -0500 Subject: [PATCH] Creating Debian Package for capstone v5 --- .github/workflows/build_release.yml | 52 ++++++++++++++-------- packages/deb/.gitignore | 2 + packages/deb/Dockerfile | 69 +++++++++++++++++++++++++++++ packages/deb/check_capstone.sh | 50 +++++++++++++++++++++ packages/deb/control | 25 +++++++++++ packages/deb/setup.sh | 57 ++++++++++++++++++++++++ packages/deb/triggers | 2 + 7 files changed, 238 insertions(+), 19 deletions(-) create mode 100644 packages/deb/.gitignore create mode 100644 packages/deb/Dockerfile create mode 100644 packages/deb/check_capstone.sh create mode 100644 packages/deb/control create mode 100644 packages/deb/setup.sh create mode 100644 packages/deb/triggers diff --git a/.github/workflows/build_release.yml b/.github/workflows/build_release.yml index 5859fabf27..01b1a57403 100644 --- a/.github/workflows/build_release.yml +++ b/.github/workflows/build_release.yml @@ -11,10 +11,33 @@ jobs: name: build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true + - name: Make setup.sh and check_capstone.sh are executable + run: | + chmod +x ./packages/deb/setup.sh + chmod +x ./packages/deb/check_capstone.sh + + - name: Build Debian Package + working-directory: ./packages/deb + run: ./setup.sh ${{ github.event.release.tag_name }} + + - name: Run sanity checks on the Debian package + working-directory: ./packages/deb + run: | + ./check_capstone.sh ./libcapstone-dev_${{ github.event.release.tag_name }}_amd64.deb + + - name: Upload debian package to release + uses: softprops/action-gh-release@v2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.event.release.tag_name }} + files: | + ./packages/deb/*.deb + - name: archive id: archive run: | @@ -27,24 +50,15 @@ jobs: TARBALL=$PKGNAME.tar.xz tar cJf $TARBALL $PKGNAME sha256sum $TARBALL > $SHASUM - echo "::set-output name=tarball::$TARBALL" - echo "::set-output name=shasum::$SHASUM" - - name: upload tarball - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ github.event.release.upload_url }} - asset_path: ./${{ steps.archive.outputs.tarball }} - asset_name: ${{ steps.archive.outputs.tarball }} - asset_content_type: application/gzip - - - name: upload shasum - uses: actions/upload-release-asset@v1 + echo "tarball=$TARBALL" >> $GITHUB_OUTPUT + echo "shasum=$SHASUM" >> $GITHUB_OUTPUT + + - name: Upload tarball and shasum to release + uses: softprops/action-gh-release@v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - upload_url: ${{ github.event.release.upload_url }} - asset_path: ./${{ steps.archive.outputs.shasum }} - asset_name: ${{ steps.archive.outputs.shasum }} - asset_content_type: text/plain + tag_name: ${{ github.event.release.tag_name }} + files: | + ${{ steps.archive.outputs.tarball }} + ${{ steps.archive.outputs.shasum }} diff --git a/packages/deb/.gitignore b/packages/deb/.gitignore new file mode 100644 index 0000000000..c636824af1 --- /dev/null +++ b/packages/deb/.gitignore @@ -0,0 +1,2 @@ +*.deb +*.txt \ No newline at end of file diff --git a/packages/deb/Dockerfile b/packages/deb/Dockerfile new file mode 100644 index 0000000000..f55f55ad96 --- /dev/null +++ b/packages/deb/Dockerfile @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: MIT +# Copyright (C) 2024 Andrew Quijano +# Contact: andrewquijano92@gmail.com +ARG VERSION="" + +# Run in the root of the repo +# docker build -f ./packages/deb/Dockerfile -t packager . +FROM debian:bookworm-slim + +# Install necessary tools for packaging +RUN apt-get -qq update && \ + DEBIAN_FRONTEND=noninteractive apt-get -qq install -y \ + fakeroot dpkg-dev dos2unix cmake + +# Copy project files into the container +RUN mkdir /capstone +COPY . /capstone +WORKDIR /capstone/ + +# Using cmake, see BUILDING.md file +# For debug build change "Release" to "Debug" +ARG VERSION +RUN cmake -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=1 -DPROJECT_VERSION=${VERSION} -DCMAKE_INSTALL_PREFIX=/usr +RUN cmake --build build + +# List files before cmake install +# RUN find / -type f > /before-install.txt + +# Make directories as needed +RUN mkdir -p /package-root/usr/include/capstone/ +RUN mkdir -p /package-root/usr/lib/pkgconfig/ +RUN mkdir -p /package-root/usr/bin/ +RUN mkdir -p /package-root/usr/share/doc/libcapstone-dev + +# Run cmake install +RUN cmake --install build --prefix /package-root/usr/ + +# List files after cmake install +# RUN find / -type f > /after-install.txt + +# Create DEBIAN directory and control file +COPY ./packages/deb/control /package-root/DEBIAN/control + +# Copy documentation over +COPY ./ChangeLog /package-root/usr/share/doc/libcapstone-dev +COPY ./CREDITS.TXT /package-root/usr/share/doc/libcapstone-dev +COPY ./HACK.TXT /package-root/usr/share/doc/libcapstone-dev +COPY ./LICENSE.TXT /package-root/usr/share/doc/libcapstone-dev +COPY ./README.md /package-root/usr/share/doc/libcapstone-dev +COPY ./SPONSORS.TXT /package-root/usr/share/doc/libcapstone-dev + +# 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 information +ARG 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: ${VERSION}/" /package-root/DEBIAN/control + +# Add triggers script to run ldconfig after installation +COPY ./packages/deb/triggers /package-root/DEBIAN/triggers + +# Build the package +RUN fakeroot dpkg-deb --build /package-root /libcapstone-dev_${VERSION}_amd64.deb + +# The user can now extract the .deb file from the container with something like +# docker run --rm -v $(pwd):/out packager bash -c "cp /libcapstone-dev.deb /out" diff --git a/packages/deb/check_capstone.sh b/packages/deb/check_capstone.sh new file mode 100644 index 0000000000..deb791b4d4 --- /dev/null +++ b/packages/deb/check_capstone.sh @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: MIT +# Copyright (C) 2024 Andrew Quijano +# Contact: andrewquijano92@gmail.com + +#!/bin/bash +set -eu + +# Usage: ./check_capstone_pc.sh + +DEB_FILE=$1 + +# Check if the deb file exists +if [[ ! -f "$DEB_FILE" ]]; then + echo "Debian package file not found!" + exit 1 +fi + +# Create a temporary directory to extract the deb file +TEMP_DIR=$(mktemp -d) + +# Extract the deb file +dpkg-deb -x "$DEB_FILE" "$TEMP_DIR" + +# Check if the capstone.pc file exists +CAPSTONE_PC="$TEMP_DIR/usr/lib/x86_64-linux-gnu/pkgconfig/capstone.pc" +if [[ ! -f "$CAPSTONE_PC" ]]; then + echo "capstone.pc file not found in the package!" + rm -rf "$TEMP_DIR" + exit 1 +fi + +# Check if libcapstone.a is included in the package +LIBCAPSTONE_A="$TEMP_DIR/usr/lib/x86_64-linux-gnu/libcapstone.a" +if [[ ! -f "$LIBCAPSTONE_A" ]]; then + echo "libcapstone.a not found in the package!" + rm -rf "$TEMP_DIR" + exit 1 +fi + +# Check if libcapstone.so is included in the package +LIBCAPSTONE_SO="$TEMP_DIR/usr/lib/x86_64-linux-gnu/libcapstone.so" +if [[ ! -f "$LIBCAPSTONE_SO" ]]; then + echo "libcapstone.so not found in the package!" + rm -rf "$TEMP_DIR" + exit 1 +fi + +echo "libcapstone-dev.deb file is correct." +rm -rf "$TEMP_DIR" +exit 0 diff --git a/packages/deb/control b/packages/deb/control new file mode 100644 index 0000000000..1c9cee3ea6 --- /dev/null +++ b/packages/deb/control @@ -0,0 +1,25 @@ +Package: libcapstone-dev +Source: capstone +Version: +Architecture: amd64 +Maintainer: Rot127 +Original-Maintainer: Debian Security Tools +Installed-Size: +Depends: libc6 (>= 2.2.5) +Section: libdevel +Priority: optional +Multi-Arch: same +Homepage: https://www.capstone-engine.org/ +Description: lightweight multi-architecture disassembly framework - devel files + Capstone is a lightweight multi-platform, multi-architecture disassembly + framework. These are the development headers and libraries. + Features: + - Support hardware architectures: AArch64, ARM, Alpha, BPF, EVM, HPPA, LongArch, M680X, M68K, MOS65XX, Mips, PowerPC, RISCV, SH, Sparc, SystemZ, TMS320C64x, TriCore, WASM, x86, XCore. + - Clean/simple/lightweight/intuitive architecture-neutral API. + - Provide details on disassembled instructions (called "decomposer" by some + others). + - Provide some semantics of the disassembled instruction, such as list of + implicit registers read & written. + - Thread-safe by design. + - Special support for embedding into firmware or OS kernel. + - Distributed under the open source BSD license. diff --git a/packages/deb/setup.sh b/packages/deb/setup.sh new file mode 100644 index 0000000000..6c7f71bb45 --- /dev/null +++ b/packages/deb/setup.sh @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: MIT +# Copyright (C) 2024 Andrew Quijano +# Contact: andrewquijano92@gmail.com + +# !/bin/bash +set -eu + +# Function to get the current Ubuntu version +get_os_version() { + lsb_release -i -s 2>/dev/null +} + +# Check if the script is running in the ./packages/deb folder +if [[ $(basename "$PWD") != "deb" ]]; then + echo "ERROR: Script must be run from the ./deb directory" + exit 1 +fi + +OS_VERSION=$(get_os_version) +if [[ "$OS_VERSION" != "Ubuntu" && "$OS_VERSION" != "Debian" ]]; then + echo "ERROR: OS is not Ubuntu or Debian and unsupported" + exit 1 +fi + +# Get the version number as an input +# Check if version argument is provided +if [[ $# -ne 1 ]]; then + echo "ERROR: Version argument is required" + exit 1 +fi + +# Get the version number as an input +version=$1 + +# Remove leading 'v' if present, e. g. v1.5.1 -> 1.5.1 +if [[ "$version" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + version=${version:1} +fi + +# Check if the version follows the format for Debian Packages +if [[ ! "$version" =~ ^[0-9]+(.[0-9]+)*(-[A-Za-z0-9]+)?$ ]]; then + echo "ERROR: Version must be in a valid Debian package format" + exit 1 +fi + +# Now build the packager container from that +pushd ../../ +docker build -f ./packages/deb/Dockerfile -t packager --build-arg VERSION="${version}" . +popd + +# Copy deb file out of container to host +docker run --rm -v $(pwd):/out packager bash -c "cp /*.deb /out" + +# Check which files existed before and after 'make install' was executed. +# docker run --rm -v $(pwd):/out packager bash -c "cp /before-install.txt /out" +# docker run --rm -v $(pwd):/out packager bash -c "cp /after-install.txt /out" +# diff before-install.txt after-install.txt diff --git a/packages/deb/triggers b/packages/deb/triggers new file mode 100644 index 0000000000..eafa63be77 --- /dev/null +++ b/packages/deb/triggers @@ -0,0 +1,2 @@ +# Trigger ldconfig after install +activate-noawait ldconfig