From 402b12ec0feda5bec4db64c18d015977c54ba561 Mon Sep 17 00:00:00 2001 From: zhangzhang Date: Mon, 17 Aug 2026 10:40:26 +0800 Subject: [PATCH] openssl fuzzing --- .../lpi4a/lipi4a-oss-fuzz-openssl.yaml | 62 +++++ .../qemu/qemu-oss-fuzz-openssl.yaml | 80 +++++++ .../sg2042/sg2042-oss-fuzz-openssl.yaml | 74 ++++++ .../k1-bpif3-oss-fuzz-openssl.yaml | 72 ++++++ .../oss-fuzz-openssl/openssl_fuzzing.sh | 219 ++++++++++++++++++ .../oss-fuzz-openssl/openssl_fuzzing.yaml | 21 ++ 6 files changed, 528 insertions(+) create mode 100644 lava-job-template/lpi4a/lipi4a-oss-fuzz-openssl.yaml create mode 100644 lava-job-template/qemu/qemu-oss-fuzz-openssl.yaml create mode 100644 lava-job-template/sg2042/sg2042-oss-fuzz-openssl.yaml create mode 100644 lava-job-template/spacemit-k1-bananapi-f3/k1-bpif3-oss-fuzz-openssl.yaml create mode 100644 lava-testcases/security-test/oss-fuzz-openssl/openssl_fuzzing.sh create mode 100644 lava-testcases/security-test/oss-fuzz-openssl/openssl_fuzzing.yaml diff --git a/lava-job-template/lpi4a/lipi4a-oss-fuzz-openssl.yaml b/lava-job-template/lpi4a/lipi4a-oss-fuzz-openssl.yaml new file mode 100644 index 0000000..32f53e0 --- /dev/null +++ b/lava-job-template/lpi4a/lipi4a-oss-fuzz-openssl.yaml @@ -0,0 +1,62 @@ +device_type: lpi4a +job_name: ${job_name} +timeouts: + job: + minutes: 10250 + action: + minutes: 10249 + actions: + power-off: + seconds: 60 +priority: medium +visibility: public +metadata: + # please change these fields when modifying this job for your own tests. + format: Lava-Test Test Definition 1.0 + name: lpi4a-test + description: "test for lpi4a" + version: "1.0" +# ACTION_BLOCK +actions: +# DEPLOY_BLOCK +- deploy: + timeout: + minutes: 120 + to: tftp + dtb: + url: ${dtb_url} + kernel: + url: ${kernel_image_url} + type: image + nfsrootfs: + url: ${rootfs_image_url} + compression: gz +# BOOT_BLOCK +- boot: + timeout: + minutes: 20 + method: u-boot + commands: nfs + soft_reboot: + - root + - openEuler + - reboot + - The system will reboot now! + prompts: ["root@riscv64", "login:", "Password:"] + auto_login: + login_prompt: "(.*)riscv64 login:(.*)" + username: root + password_prompt: "Password:" + password: openEuler12#$ +# TEST_BLOCK +- test: + timeout: + minutes: 10109 + definitions: + - repository: ${testcase_repo} + from: git + name: ${testitem_name} + path: ${testcase_path} + parameters: + FUZZTIME: ${FUZZTIME} #fuzzing测试时间,单位为s + MAILBOX: ${MAILBOX} #crash.zip文件发送的邮件地址 \ No newline at end of file diff --git a/lava-job-template/qemu/qemu-oss-fuzz-openssl.yaml b/lava-job-template/qemu/qemu-oss-fuzz-openssl.yaml new file mode 100644 index 0000000..abebe0d --- /dev/null +++ b/lava-job-template/qemu/qemu-oss-fuzz-openssl.yaml @@ -0,0 +1,80 @@ +# Your first LAVA JOB definition for an riscv_64 QEMU +device_type: qemu +job_name: ${job_name} +timeouts: + job: + minutes: 10150 + action: + minutes: 10140 + connection: + minutes: 10 +priority: medium +visibility: public +# context allows specific values to be overridden or included +context: + # tell the qemu template which architecture is being tested + # the template uses that to ensure that qemu-system-riscv64 is executed. + arch: riscv64 + machine: virt + guestfs_interface: virtio + extra_options: + - -machine virt + - -nographic + - -smp 8 + - -m 8G + - -device virtio-blk-device,drive=hd0 + - -device virtio-blk-device,drive=hd1 + - -append "root=/dev/vda rw console=ttyS0 selinux=0" + - -device virtio-net-device,netdev=usernet + - -netdev user,id=usernet,hostfwd=tcp::10001-:22 +metadata: + # please change these fields when modifying this job for your own tests. + format: Lava-Test Test Definition 1.0 + name: qemu-riscv64-test + description: "test for riscv64 qemu" + version: "1.0" +# ACTION_BLOCK +actions: +# DEPLOY_BLOCK +- deploy: + timeout: + minutes: 20 + to: tmpfs + images: + kernel: + image_arg: -kernel {kernel} + url: ${kernel_image_url} + rootfs: + image_arg: -drive file={rootfs},format=raw,id=hd0,if=none + url: ${rootfs_image_url} + compression: zstd + data_disk: + image_arg: -drive file={data_disk},format=raw,id=hd1,if=none + url: ${data_disk_url} + compression: zstd + +# BOOT_BLOCK +- boot: + timeout: + minutes: 20 + method: qemu + media: tmpfs + prompts: ["root@riscv64"] + auto_login: + login_prompt: "riscv64 login:" + username: root + password_prompt: "Password:" + password: openEuler12#$ + +# TEST_BLOCK +- test: + timeout: + minutes: 10010 + definitions: + - from: git + name: ${testitem_name} + path: ${testcase_path} + repository: ${testcase_repo} + parameters: + FUZZTIME: ${FUZZTIME} #fuzzing测试时间,单位为s + MAILBOX: ${MAILBOX} #crash.zip文件发送的邮件地址 \ No newline at end of file diff --git a/lava-job-template/sg2042/sg2042-oss-fuzz-openssl.yaml b/lava-job-template/sg2042/sg2042-oss-fuzz-openssl.yaml new file mode 100644 index 0000000..122346c --- /dev/null +++ b/lava-job-template/sg2042/sg2042-oss-fuzz-openssl.yaml @@ -0,0 +1,74 @@ +device_type: sg2042 +job_name: ${job_name} +timeouts: + job: + minutes: 10300 + action: + minutes: 10299 + actions: + power-off: + seconds: 60 +priority: medium +visibility: public +metadata: + # please change these fields when modifying this job for your own tests. + format: Lava-Test Test Definition 1.0 + name: sg2042-test + description: "test for sg2042" + version: "1.0" +# ACTION_BLOCK +actions: +- command: + name: pre_os_command + timeout: + minutes: 20 +# DEPLOY_BLOCK +- deploy: + timeout: + minutes: 120 + to: tftp + kernel: + url: ${kernel_image_url} + type: image + ramdisk: + url: ${ramdisk_url} + install_overlay: False + install_modules: False + dtb: + url: ${dtb_url} + persistent_nfs: + address: "{FILE_SERVER_IP}:/var/lib/lava/dispatcher/tmp/sg2042_rootfs" +- command: + name: pxelinux_generate + timeout: + minutes: 20 +# BOOT_BLOCK +- boot: + timeout: + minutes: 30 + method: u-boot + commands: + - "dhclient -ipv6=false eth0" + - "pxeboot -file tftp://{SERVER_IP}/pxelinux.cfg -server {SERVER_IP}" + soft_reboot: + - root + - openEuler + - reboot + - The system will reboot now! + prompts: ["root@riscv64", "login:", "Password:"] + auto_login: + login_prompt: "(.*)riscv64 login:(.*)" + username: root + password_prompt: "Password:" + password: openEuler12#$ +- test: + timeout: + minutes: 10109 + definitions: + - repository: ${testcase_repo} + from: git + name: ${testitem_name} + path: ${testcase_path} + parameters: + FUZZTIME: ${FUZZTIME} #fuzzing测试时间,单位为s + MAILBOX: ${MAILBOX} #crash.zip文件发送的邮件地址 \ No newline at end of file diff --git a/lava-job-template/spacemit-k1-bananapi-f3/k1-bpif3-oss-fuzz-openssl.yaml b/lava-job-template/spacemit-k1-bananapi-f3/k1-bpif3-oss-fuzz-openssl.yaml new file mode 100644 index 0000000..12ac6bc --- /dev/null +++ b/lava-job-template/spacemit-k1-bananapi-f3/k1-bpif3-oss-fuzz-openssl.yaml @@ -0,0 +1,72 @@ +device_type: spacemit-k1-bananapi-f3 +job_name: ${job_name} +timeouts: + job: + minutes: 10300 + action: + minutes: 10299 + actions: + power-off: + seconds: 60 +priority: medium +visibility: public +metadata: + # please change these fields when modifying this job for your own tests. + format: Lava-Test Test Definition 1.0 + name: k1-bananapi-f3-test + description: "test for k1-bananapi-f3" + version: "1.0" +# ACTION_BLOCK +actions: +- command: + name: pre_os_command + timeout: + minutes: 20 +# DEPLOY_BLOCK +- deploy: + timeout: + minutes: 120 + to: tftp + dtb: + url: ${dtb_url} + kernel: + url: ${kernel_image_url} + type: image + ramdisk: + url: ${ramdisk_url} + install_overlay: False + install_modules: False + persistent_nfs: + address: "{FILE_SERVER_IP}:{NFSROOTFS_PATH}" +- command: + name: pxelinux_generate + timeout: + minutes: 20 +# BOOT_BLOCK +- boot: + timeout: + minutes: 30 + method: minimal + soft_reboot: + - root + - openEuler + - reboot + - The system will reboot now! + prompts: ["root@riscv64", "login:", "Password:"] + auto_login: + login_prompt: "(.*)riscv64 login:(.*)" + username: root + password_prompt: "Password:" + password: openEuler12#$ +# TEST_BLOCK +- test: + timeout: + minutes: 10109 + definitions: + - repository: ${testcase_repo} + from: git + name: ${testitem_name} + path: ${testcase_path} + parameters: + FUZZTIME: ${FUZZTIME} #fuzzing测试时间,单位为s + MAILBOX: ${MAILBOX} #crash.zip文件发送的邮件地址 \ No newline at end of file diff --git a/lava-testcases/security-test/oss-fuzz-openssl/openssl_fuzzing.sh b/lava-testcases/security-test/oss-fuzz-openssl/openssl_fuzzing.sh new file mode 100644 index 0000000..0ee0c67 --- /dev/null +++ b/lava-testcases/security-test/oss-fuzz-openssl/openssl_fuzzing.sh @@ -0,0 +1,219 @@ +#!/bin/bash +set -x + +OUTPUT="$(pwd)/output" +mkdir -p "$OUTPUT" +RESULT_FILE="${OUTPUT}/result.txt" +WORKSPACE=$(pwd) + +FUZZTIME="${1}" +MAILBOX="${2}" + +# 加载数据盘 +load_disk(){ + DISK=/dev/vdb + PART=${DISK}1 + MNT=/build + + # 1. 分区并格式化 + parted -s $DISK mklabel gpt + parted -s $DISK mkpart primary ext4 0% 100% + mkfs.ext4 -F $PART + + # 2. 挂载并写入fstab(重启生效) + mkdir -p $MNT + UUID=$(blkid -s UUID -o value $PART) + echo "UUID=$UUID $MNT ext4 defaults,noatime 0 2" >> /etc/fstab + mount -a + + # 3. 验证 + df -h $MNT +} + + +#测试环境准备 +env_prep(){ + cd /root/ + + dnf makecache + dnf -y install rpm-build docker-engine git + + #开启docker experimental功能 + touch /etc/docker/daemon.json + mkdir -p /build/docker #设置docker存放路径 + cat > /etc/docker/daemon.json << 'EOF' +{ + "experimental": true, + "data-root":"/build/docker" +} +EOF + systemctl restart docker + docker info | grep -i 'experimental' + + #设置rpm打包环境 + dnf -y install rpmdevtools + rpmdev-setuptree #自动在用户家目录生成一个rpmbuild的文件夹, + + #下载oss-fuzz仓库并进行rv环境兼容 + git clone https://github.com/google/oss-fuzz.git + #1.infra/constants.py文件ARCHITECTURES增加riscv64架构兼容 + sed -i "s/ARCHITECTURES = \['i386', 'x86_64', 'aarch64'\]/ARCHITECTURES = ['i386', 'x86_64', 'aarch64', 'riscv64']/" oss-fuzz/infra/constants.py + #2.infra/helper.py文件platform 增加riscv64架构兼容 + old="platform = 'linux/arm64' if architecture == 'aarch64' else 'linux/amd64'" + new="platform = 'linux/arm64' if architecture == 'aarch64' else 'linux/riscv64' if architecture == 'riscv64' else 'linux/amd64'" + sed -i "s|$old|$new|g" oss-fuzz/infra/helper.py +} + +#测试数据准备 +data_prep(){ + #根据openEuler系统版本下载对应的的openssl源码,并将安装了补丁的源码文件放到oss-fuzz框架openssl目录下 + #source /etc/os-release + #BRANCH="${NAME}-${VERSION_ID}-$(echo "$VERSION" | sed 's/.*(\(.*\))/\1/')" + #git clone --branch $BRANCH https://atomgit.com/src-openeuler/openssl + VER=$(rpm -q openssl --qf '%{VERSION}') + REL=$(rpm -q openssl --qf '%{RELEASE}') + echo "${VER}-${REL}" + + dnf download --source openssl-${VER}-${REL} + mkdir openssl && cd openssl + rpm2cpio /root/openssl-*.src.rpm | cpio -idmv + + cp -r ./* /root/rpmbuild/SOURCES + cd /root/rpmbuild/SOURCES + dnf builddep openssl.spec -y #下载编译依赖 + rpmbuild -bp openssl.spec + cd /root/rpmbuild/BUILD + cp -r openssl-*/ /root/oss-fuzz/projects/openssl +} + +#执行测试 +fuzz_test(){ + cd /root/oss-fuzz + #下载适用于rv环境的基础镜像 + docker pull zhangzhang1/oss-fuzz-base-image:latest + docker pull zhangzhang1/oss-fuzz-base-clang:latest + docker pull zhangzhang1/oss-fuzz-base-builder:latest + docker pull zhangzhang1/oss-fuzz-base-runner:latest + docker pull zhangzhang1/oss-fuzz-base-runner-debug:latest + + docker tag zhangzhang1/oss-fuzz-base-image gcr.io/oss-fuzz-base/base-image + docker tag zhangzhang1/oss-fuzz-base-clang gcr.io/oss-fuzz-base/base-clang + docker tag zhangzhang1/oss-fuzz-base-builder gcr.io/oss-fuzz-base/base-builder + docker tag zhangzhang1/oss-fuzz-base-runner gcr.io/oss-fuzz-base/base-runner + docker tag zhangzhang1/oss-fuzz-base-runner-debug gcr.io/oss-fuzz-base/base-runner-debug + + + #设置oss-fuzz中openssl项目Dockerfile,同时调整build.sh文件 + PROJECT_PATH="projects/openssl" + cp projects/openssl/Dockerfile projects/openssl/Dockerfile.bak + # 获取系统中openssl软件包版本 + OPENSSL_DIR=$(basename projects/openssl/openssl-*) + BRANCH=$(echo "$OPENSSL_DIR" | sed 's/openssl-\([0-9]*\)\.\([0-9]*\).*/\1.\2/') + VERSION=$(echo "$OPENSSL_DIR" | sed 's/openssl-\([0-9]*\)\.\([0-9]*\).*/\1\2/') + OPENSSL_TARGET=openssl$VERSION + cat > projects/openssl/Dockerfile << 'EOF' +FROM gcr.io/oss-fuzz-base/base-builder +RUN apt-get update && apt-get install -y make +RUN git clone --depth 1 --branch openssl-BRANCH https://atomgit.com/openssl/openssl.git OPENSSL_TARGET +COPY OPENSSL_DIR $SRC/OPENSSL_TARGET +RUN cd $SRC/OPENSSL_TARGET/ && git submodule update --init fuzz/corpora +WORKDIR openssl +COPY build.sh *.options replay_build.sh run_tests.sh $SRC/ +ENV AFL_SKIP_OSSFUZZ=1 +ENV AFL_LLVM_MODE_WORKAROUND=0 +EOF + sed -i "s|BRANCH|$BRANCH|g" projects/openssl/Dockerfile + sed -i "s|OPENSSL_DIR|$OPENSSL_DIR|g" projects/openssl/Dockerfile + sed -i "s|OPENSSL_TARGET|$OPENSSL_TARGET|g" projects/openssl/Dockerfile + + BUILDSH='projects/openssl/build.sh' + sed -i '/^cd \$SRC\/openssl\//,$ d' $BUILDSH + echo ' +# In introspector, indexer builds and when capturing replay builds, only build +# the master branch +if [[ "$SANITIZER" == introspector || -n "${INDEXER_BUILD:-}" || -n "${CAPTURE_REPLAY_SCRIPT:-}" ]]; then + exit 0 +fi +' >> $BUILDSH + + if [ $VERSION = '30' ]; then + echo ' +cd $SRC/openssl$VERSION/ +build_fuzzers "_$VERSION" "" "engines" +' >> $BUILDSH + else + echo ' +cd $SRC/openssl$VERSION/ +build_fuzzers "_$VERSION" "no-apps no-docs" "engines" +' >> $BUILDSH + fi + + sed -i "s|\$VERSION|$VERSION|g" $BUILDSH + + # 构建fuzz target + python3 infra/helper.py build_fuzzers --architecture riscv64 --sanitizer undefined openssl + + # 执行fuzz + target=$(basename -a build/out/openssl/*30) + for targ in $target; do + python3 infra/helper.py run_fuzzer --architecture riscv64 --sanitizer undefined openssl $targ -- -max_total_time=$FUZZTIME -timeout=60 + done + +} + +#通过邮件发送附件 +send_main(){ + local crash_zip="$1" #crash压缩文件 + dnf install -y postfix mutt + postconf -e "message_size_limit = 52428800" + systemctl reload postfix + echo "fuzzing crashes" | mutt -s "openssl fuzzing" -a $crash_zip -- $MAILBOX + tail -100 /var/log/maillog | grep -i "$MAILBOX" +} + +#输出测试结果 +data_to_lava(){ + # openssl fuzzing:全部通过输出openssl-fuzzing pass,否则输出 fuzz-target + fail + # 返回测试路径 + cd $WORKSPACE + OUTPUTDIR=$(find /root/oss-fuzz/build/out/openssl -maxdepth 1 -type d -name '*address_out') + FAIL=0 + CRASHDIR='' + for dir in $OUTPUTDIR; do + if [ -n "$(ls -A "$dir" 2>/dev/null)" ]; then + FAIL=1 + #记录有crashes的目录 + CRASHDIR="${CRASHDIR:+$CRASHDIR }$dir" + fi + done + if [ $FAIL = 0 ];then + echo 'openssl-fuzzing pass' >> $RESULT_FILE + else + echo 'openssl-fuzzing fail' >> $RESULT_FILE + fi + # + if [ -z "$CRASHDIR" ]; then + echo "模糊测试完成,无crash" + else + echo "模糊测试完成," + zip -r openssl-crash.zip $CRASHDIR + send_main openssl-crash.zip + fi + + +} + +#qemu环境加载数据盘 +if [ "$(systemd-detect-virt)" = "qemu" ]; then + load_disk +fi +# 测试环境准备 +env_prep +# 测试数据准备 +data_prep +#执行fuzz测试 +fuzz_test +#输出测试结果 +data_to_lava + + diff --git a/lava-testcases/security-test/oss-fuzz-openssl/openssl_fuzzing.yaml b/lava-testcases/security-test/oss-fuzz-openssl/openssl_fuzzing.yaml new file mode 100644 index 0000000..8af183a --- /dev/null +++ b/lava-testcases/security-test/oss-fuzz-openssl/openssl_fuzzing.yaml @@ -0,0 +1,21 @@ +metadata: + name: openssl_fuzzing + format: "Lava-Test Test Definition 1.0" + description: "Run fio on RISC-V device" + maintainer: + - zhangju@iscas.ac.cn + os: + - openEuler-riscv64 + scope: + - security + devices: + - qemu + - lpi4a + - sg2042 + - spacemit-k1-bananapi-f3 +run: + steps: + - cd lava-testcases/security-test/oss-fuzz-openssl + - bash openssl_fuzzing.sh "${FUZZTIME}" "${MAILBOX}" + - chmod +x ../../utils/send-to-lava.sh + - ../../utils/send-to-lava.sh ./output/result.txt