Update dockerfile (#3020)

* Fix just

* Update dockerfile

* Changes to test all architectures for qemu-user fuzzers

* Update version of QEMU

* Fix qemu on aarch64

* Fix qemu on i386

---------

Co-authored-by: Your Name <you@example.com>
This commit is contained in:
WorksButNotTested 2025-02-24 15:13:34 +00:00 committed by GitHub
parent e5ba51aae4
commit 7121defff9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 132 additions and 59 deletions

View File

@ -364,7 +364,7 @@ jobs:
shell: bash
run: RUN_ON_CI=1 LLVM_CONFIG=llvm-config-${{env.MAIN_LLVM_VERSION}} ./scripts/test_fuzzer.sh ${{ matrix.fuzzer }}
fuzzers-qemu:
fuzzers-qemu-user:
needs:
- changes
if: ${{ needs.changes.outputs.qemu == 'true' }}
@ -376,7 +376,31 @@ jobs:
- ./fuzzers/binary_only/qemu_cmin
- ./fuzzers/binary_only/qemu_coverage
- ./fuzzers/binary_only/qemu_launcher
arch:
- aarch64
- arm
- i386
- ppc
- x86_64
runs-on: [ self-hosted, qemu ]
container: registry.gitlab.com/qemu-project/qemu/qemu/ubuntu2204:latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/workflows/qemu-fuzzer-tester-prepare
- name: Build and run example QEMU fuzzers (Linux)
if: runner.os == 'Linux'
shell: bash
run: ARCH=${{ matrix.arch }} RUN_ON_CI=1 LLVM_CONFIG=llvm-config-${{env.MAIN_LLVM_VERSION}} ./scripts/test_fuzzer.sh ${{ matrix.fuzzer }}
fuzzers-qemu-system:
needs:
- changes
if: ${{ needs.changes.outputs.qemu == 'true' }}
strategy:
matrix:
os: [ubuntu-24.04]
fuzzer:
# Full-system
- ./fuzzers/full_system/qemu_baremetal
- ./fuzzers/full_system/qemu_linux_kernel

View File

@ -1,17 +1,21 @@
# syntax=docker/dockerfile:1.2
FROM rust:1.76.0 AS libafl
FROM rust:1.85.0 AS libafl
LABEL "maintainer"="afl++ team <afl@aflplus.plus>"
LABEL "about"="LibAFL Docker image"
# Install cargo-binstall to download the sccache build
# Install cargo-binstall
RUN curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
# install sccache to cache subsequent builds of dependencies
RUN cargo binstall --no-confirm sccache
# We now use just to build things rather than cargo-make
RUN cargo binstall --no-confirm just
# Nexttest allows us to run tests which panic in an environment where we can't unwind
RUN cargo binstall --no-confirm cargo-nextest
# Cargo fuzz is useful for fuzz testing our implementations
RUN cargo binstall -y cargo-fuzz
# Taplo allows us to format toml files
RUN cargo binstall -y taplo-cli
ENV HOME=/root
ENV SCCACHE_CACHE_SIZE="1G"
ENV SCCACHE_DIR=$HOME/.cache/sccache
ENV RUSTC_WRAPPER="/usr/local/cargo/bin/sccache"
ENV IS_DOCKER="1"
RUN sh -c 'echo set encoding=utf-8 > /root/.vimrc' \
echo "export PS1='"'[LibAFL \h] \w$(__git_ps1) \$ '"'" >> ~/.bashrc && \
@ -21,14 +25,71 @@ RUN sh -c 'echo set encoding=utf-8 > /root/.vimrc' \
RUN rustup default nightly
RUN rustup component add rustfmt clippy
RUN rustup target add armv7-unknown-linux-gnueabi
RUN rustup target add aarch64-unknown-linux-gnu
RUN rustup target add i686-unknown-linux-gnu
RUN rustup target add powerpc-unknown-linux-gnu
# Install clang 18, common build tools
ENV LLVM_VERSION=18
RUN apt update && apt install -y build-essential gdb git wget python3-venv ninja-build lsb-release software-properties-common gnupg cmake
RUN dpkg --add-architecture i386
RUN apt-get update && \
apt-get install -y \
build-essential \
cmake \
curl \
g++-aarch64-linux-gnu \
g++-arm-linux-gnueabi \
g++-i686-linux-gnu \
g++-mipsel-linux-gnu \
g++-powerpc-linux-gnu \
gcc-aarch64-linux-gnu \
gcc-arm-linux-gnueabi \
gcc-i686-linux-gnu \
gcc-mipsel-linux-gnu \
gcc-powerpc-linux-gnu \
gdb \
gdb-multiarch \
git \
gnupg \
libc6-dev:i386 \
libclang-dev \
libgcc-12-dev:i386 \
libglib2.0-dev \
lsb-release \
ninja-build \
python3 \
python3-pip \
python3-venv \
software-properties-common \
wget
RUN set -ex &&\
wget https://apt.llvm.org/llvm.sh &&\
chmod +x llvm.sh &&\
./llvm.sh ${LLVM_VERSION}
RUN git config --global core.pager cat
# Install a modern version of QEMU
WORKDIR /root
ENV QEMU_VER=9.2.1
RUN wget https://download.qemu.org/qemu-${QEMU_VER}.tar.xz
RUN tar xvJf qemu-${QEMU_VER}.tar.xz
WORKDIR /root/qemu-${QEMU_VER}
RUN ./configure --target-list="\
arm-linux-user,\
aarch64-linux-user,\
i386-linux-user,\
ppc-linux-user,\
mips-linux-user,\
arm-softmmu,\
aarch64-softmmu,\
i386-softmmu,\
ppc-softmmu,\
mips-softmmu"
RUN make -j
RUN make install
# Copy a dummy.rs and Cargo.toml first, so that dependencies are cached
WORKDIR /libafl

View File

@ -1,3 +1,3 @@
CROSS_CC="x86_64-linux-gnu-gcc"
CROSS_CXX="x86_64-linux-gnu-g++"
CROSS_CFLAGS="-m32"
CROSS_CC="i686-linux-gnu-gcc"
CROSS_CXX="i686-linux-gnu-g++"
CROSS_CFLAGS="-m32"

View File

@ -1,3 +1,3 @@
CROSS_CC="powerpc-linux-gnu-gcc"
CROSS_CXX="powerpc-linux-gnu-gcc"
CROSS_CFLAGS=""
CROSS_CXX="powerpc-linux-gnu-g++"
CROSS_CFLAGS=""

View File

@ -1,6 +1,7 @@
import "libafl-cc.just"
OPTIMIZATIONS := env("OPTIMIZATIONS", "yes")
ARCH := env("ARCH", "x86_64")
OPTIMIZATIONS := env("OPTIMIZATIONS", if ARCH == "ppc" { "no" } else { "yes" })
LIBPNG_ROOT := DEPS_DIR / "libpng-1.6.37"
LIBPNG_BUILD := TARGET_DIR / "build-png"

View File

@ -3,7 +3,7 @@ import "libafl-qemu.just"
# Useful rules to build libpng for multiple architecture.
ARCH := env("ARCH", "x86_64")
OPTIMIZATIONS := env("OPTIMIZATIONS", "yes")
OPTIMIZATIONS := env("OPTIMIZATIONS", if ARCH == "ppc" { "no" } else { "yes" })
DEPS_DIR := TARGET_DIR / "deps"
@ -81,4 +81,4 @@ libpng: arch_dir zlib libpng_wget
--enable-hardware-optimizations={{ OPTIMIZATIONS }} \
--host={{ ARCH }}
make -j -C {{ TARGET_DIR }}/build-png/
make -j -C {{ TARGET_DIR }}/build-png/

View File

@ -117,7 +117,7 @@ impl crate::ArchExtras for crate::CPU {
7 => self.read_reg(Regs::X7),
_ => {
const SIZE: usize = size_of::<GuestReg>();
let stack_ptr: GuestAddr = self.read_reg(Regs::Rsp)?;
let stack_ptr: GuestAddr = self.read_reg(Regs::Sp)?;
/*
* Stack is full and descending. SP points to return address, arguments
* are in reverse order above that. 8th argument is at SP + 8.

View File

@ -67,7 +67,7 @@ impl crate::ArchExtras for crate::CPU {
fn read_return_address(&self) -> Result<GuestReg, QemuRWError> {
let stack_ptr: GuestReg = self.read_reg(Regs::Esp)?;
let mut ret_addr = [0; size_of::<GuestReg>()];
unsafe { self.read_mem(stack_ptr, &mut ret_addr) };
self.read_mem(stack_ptr, &mut ret_addr)?;
Ok(GuestReg::from_le_bytes(ret_addr).into())
}
@ -78,7 +78,7 @@ impl crate::ArchExtras for crate::CPU {
let stack_ptr: GuestReg = self.read_reg(Regs::Esp)?;
let val: GuestReg = val.into();
let ret_addr = val.to_le_bytes();
unsafe { self.write_mem(stack_ptr, &ret_addr) };
self.write_mem(stack_ptr, &ret_addr)?;
Ok(())
}
@ -89,23 +89,17 @@ impl crate::ArchExtras for crate::CPU {
) -> Result<GuestReg, QemuRWError> {
QemuRWError::check_conv(QemuRWErrorKind::Read, CallingConvention::Cdecl, conv)?;
match idx {
_ => {
const SIZE: usize = size_of::<GuestReg>();
let stack_ptr: GuestAddr = self.read_reg(Regs::Sp)?;
/*
* Stack is full and descending. SP points to return address, arguments
* are in reverse order above that.
*/
const SIZE: usize = size_of::<GuestReg>();
let stack_ptr: GuestAddr = self.read_reg(Regs::Sp)?;
/*
* Stack is full and descending. SP points to return address, arguments
* are in reverse order above that.
*/
let offset = (SIZE as GuestAddr) * (GuestAddr::from(idx) + 1);
let mut val = [0u8; SIZE];
unsafe {
self.read_mem(stack_ptr + offset, &mut val);
}
Ok(GuestReg::from_le_bytes(val).into())
}
}
let offset = (SIZE as GuestAddr) * (GuestAddr::from(idx) + 1);
let mut val = [0u8; SIZE];
self.read_mem(stack_ptr + offset, &mut val)?;
Ok(GuestReg::from_le_bytes(val).into())
}
fn write_function_argument_with_cc<T>(
@ -119,24 +113,17 @@ impl crate::ArchExtras for crate::CPU {
{
QemuRWError::check_conv(QemuRWErrorKind::Write, CallingConvention::Cdecl, conv)?;
match idx {
_ => {
let val: GuestReg = val.into();
let stack_ptr: GuestAddr = self.read_reg(Regs::Sp)?;
/*
* Stack is full and descending. SP points to return address, arguments
* are in reverse order above that.
*/
let size: GuestAddr = size_of::<GuestReg>() as GuestAddr;
let offset = size * (GuestAddr::from(idx) + 1);
let val: GuestReg = val.into();
let stack_ptr: GuestAddr = self.read_reg(Regs::Sp)?;
/*
* Stack is full and descending. SP points to return address, arguments
* are in reverse order above that.
*/
let size: GuestAddr = size_of::<GuestReg>() as GuestAddr;
let offset = size * (GuestAddr::from(idx) + 1);
let arg = val.to_le_bytes();
unsafe {
self.write_mem(stack_ptr + offset, &arg);
}
Ok(())
}
r => Err(QemuRWError::new_argument_error(QemuRWErrorKind::Write, r)),
}
let arg = val.to_le_bytes();
self.write_mem(stack_ptr + offset, &arg)?;
Ok(())
}
}

View File

@ -3,8 +3,8 @@ import "../../just/libafl.just"
DEMO_TARGET := "powerpc-unknown-linux-gnu"
HOST_TARGET := "x86_64-unknown-linux-gnu"
DEMO_DIR := {{TARGET_DIR}}/{{DEMO_TARGET}}/"debug"
TARGET_DIR := {{TARGET_DIR}}/{{HOST_TARGET}}/"debug"
DEMO_DIR := TARGET_DIR/DEMO_TARGET/PROFILE_DIR
HOST_DIR := TARGET_DIR/HOST_TARGET/PROFILE_DIR
FUZZER_NAME := ""
clean:
@ -17,15 +17,15 @@ demo: format
cargo build -p gdb_demo --profile {{PROFILE}} --target powerpc-unknown-linux-gnu
run_demo: demo
cargo run -p gdb_demo --target powerpc-unknown-linux-gnu
cargo run -p gdb_demo --profile {{PROFILE}} --target powerpc-unknown-linux-gnu
build: format
cargo build -p gdb_qemu --profile {{PROFILE}}
run: demo
cargo run -p gdb_qemu --profile {{PROFILE}} -- -p 1234 -L trace -- qemu-ppc -L /usr/powerpc-linux-gnu -g 1234 {{DEMO_DIR}}/gdb_demo
cargo run -p gdb_qemu --profile {{PROFILE}} -- -p 1234 -L trace qemu-ppc -- -L /usr/powerpc-linux-gnu -g 1234 {{DEMO_DIR}}/gdb_demo
gdb:
gdb-multiarch -ex "set architecture powerpc:MPC8XX" -ex "set pagination off" -ex "set confirm off" -ex "file {{DEMO_DIR}}/gdb_demo" -ex "target remote | {{TARGET_DIR}}/gdb_qemu -p 1234 -L trace qemu-ppc -- -L /usr/powerpc-linux-gnu -g 1234 {{DEMO_DIR}}/gdb_demo"
gdb-multiarch -ex "set architecture powerpc:MPC8XX" -ex "set pagination off" -ex "set confirm off" -ex "file {{DEMO_DIR}}/gdb_demo" -ex "target remote | {{HOST_DIR}}/gdb_qemu -p 1234 -L trace qemu-ppc -- -L /usr/powerpc-linux-gnu -g 1234 {{DEMO_DIR}}/gdb_demo"
all: demo build