From 3d83727571bf41c846bf24b601a1b993c8b87664 Mon Sep 17 00:00:00 2001 From: Vadim Kazakov Date: Tue, 14 Jul 2026 13:10:38 +0300 Subject: [PATCH 01/10] feat: launch opensuse in separate container with kvm --- Makefile | 1 + docker/compose.yml | 19 +++++++++++++++++-- docker/open-suse.dockerfile | 3 --- docker/vm-suse.dockerfile | 19 +++++++++++++++++++ scripts/opensuse/start-vm.sh | 20 ++++++++++++++++++++ scripts/opensuse/suse-compose.sh | 4 +--- 6 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 docker/vm-suse.dockerfile create mode 100755 scripts/opensuse/start-vm.sh diff --git a/Makefile b/Makefile index f49d789b..5880725b 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ DOCKER_PREFIX := ${LIB_NAME} DOCKER_TAG := ${DOCKER_PREFIX}-yocto-builder DOCKER_SUSE_TAG := ${DOCKER_PREFIX}-open-suse-env DOCKER_PYTHON_TAG := ${DOCKER_PREFIX}-analyzer +DOCKER_SUSE_VM_TAG := ${DOCKER_PREFIX}-suse-vm DOCKER_BUILD_VOLUME := ${DOCKER_PREFIX}-yocto-build DOCKER_DOWNLOADS_VOLUME := ${DOCKER_PREFIX}-yocto-downloads DOCKER_SSTATE_VOLUME := ${DOCKER_PREFIX}-yocto-sstate diff --git a/docker/compose.yml b/docker/compose.yml index a7f1a374..2c0d72a0 100644 --- a/docker/compose.yml +++ b/docker/compose.yml @@ -51,13 +51,28 @@ services: environment: S_USER: ${S_USER} PASSWORD: ${PASSWORD} - VM_RAM: ${QEMU_VM_RAM} - CPUS: ${CPUS} + networks: + - yocto-network + + imgtests-suse-vm: + build: + dockerfile: docker/vm-suse.dockerfile + args: + USER: ${USER} + image: ${DOCKER_SUSE_VM_TAG} + privileged: true + devices: + - /dev/kvm + volumes: + - ${DOCKER_OPENSUSE_VOLUME}:${SUSE_DIR} + environment: SSH_QEMU_PORT: ${SSH_TO_QEMU_PORT} SSH_SUSE_PORT: ${SSH_SUSE_PORT_156} SUSE_NE_PORT: ${SUSE_156_NE_PORT} DEFAULT_NE_PORT: ${DEFAULT_NE_PORT} IPERF3_PORT: ${IPERF3_PORT} + VM_RAM: ${QEMU_VM_RAM} + CPUS: ${CPUS} ports: - ${SSH_SUSE_PORT_156}:${SSH_SUSE_PORT_156} networks: diff --git a/docker/open-suse.dockerfile b/docker/open-suse.dockerfile index 189d9519..ac93fdac 100644 --- a/docker/open-suse.dockerfile +++ b/docker/open-suse.dockerfile @@ -7,9 +7,6 @@ ENV DEBIAN_FRONTEND=noninteractive \ RUN apt-get update && \ apt-get install -y --no-install-recommends \ - qemu-system \ - qemu-utils \ - qemu-user-static \ cloud-init \ cloud-image-utils \ wget \ diff --git a/docker/vm-suse.dockerfile b/docker/vm-suse.dockerfile new file mode 100644 index 00000000..d6843278 --- /dev/null +++ b/docker/vm-suse.dockerfile @@ -0,0 +1,19 @@ +FROM ubuntu:24.04 + +ARG USER + +ENV DEBIAN_FRONTEND=noninteractive \ + SUSE_DIR=/home/${USER}/suse + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + qemu-system \ + qemu-utils \ + qemu-user-static + +WORKDIR ${SUSE_DIR} + +COPY scripts/opensuse/start-vm.sh /start-vm.sh +RUN chmod +x /start-vm.sh + +ENTRYPOINT ["/start-vm.sh"] diff --git a/scripts/opensuse/start-vm.sh b/scripts/opensuse/start-vm.sh new file mode 100755 index 00000000..5e942a22 --- /dev/null +++ b/scripts/opensuse/start-vm.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +set -e + +cd "${SUSE_DIR}" + +echo "Waiting for OpenSUSE image to be ready..." +while true; do + for img in open-suse-*.ready.qcow2; do + [ -f "$img" ] && IMAGE="$img" && break 2 + done + sleep 10 +done + +exec qemu-system-x86_64 -enable-kvm -m "${VM_RAM}" -smp "${CPUS}" -nographic \ + -monitor tcp:0.0.0.0:4444,server,nowait \ + -drive file="$IMAGE",index=0,media=disk \ + -cdrom cloud-init.iso \ + -net user,hostfwd=tcp::"${SSH_SUSE_PORT}"-:"${SSH_QEMU_PORT}",hostfwd=tcp::"${SUSE_NE_PORT}"-:"${DEFAULT_NE_PORT}",hostfwd=tcp:0.0.0.0:"${IPERF3_PORT}"-:"${IPERF3_PORT}",hostfwd=udp:0.0.0.0:"${IPERF3_PORT}"-:"${IPERF3_PORT}" \ + -net nic diff --git a/scripts/opensuse/suse-compose.sh b/scripts/opensuse/suse-compose.sh index 60959d06..9e3d2877 100755 --- a/scripts/opensuse/suse-compose.sh +++ b/scripts/opensuse/suse-compose.sh @@ -4,6 +4,4 @@ set -e ./scripts/download_images.py "$1" ./scripts/cloud-setup.sh "${S_USER}" "${PASSWORD}" -CPUS=4 -qemu-system-x86_64 -m "${VM_RAM}" -smp "${CPUS}" -nographic -monitor tcp:0.0.0.0:4444,server,nowait -drive file=open-suse-"$1".ready.qcow2,index=0,media=disk \ - -cdrom cloud-init.iso -net user,hostfwd=tcp::"${SSH_SUSE_PORT}"-:"${SSH_QEMU_PORT}",hostfwd=tcp::"${SUSE_NE_PORT}"-:"${DEFAULT_NE_PORT}",hostfwd=tcp:0.0.0.0:"${IPERF3_PORT}"-:"${IPERF3_PORT}",hostfwd=udp:0.0.0.0:"${IPERF3_PORT}"-:"${IPERF3_PORT}" -net nic +echo "Image is ready. VM will be started by imgtests-suse-vm container." From d711fa4c6ca770bc899b7bbd31cf5bf628c41073 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B8=D0=B2=D0=BE=D0=B5=D0=B2=20=D0=9D=D0=B8=D0=BA?= =?UTF-8?q?=D0=B8=D1=82=D0=B0?= Date: Fri, 17 Jul 2026 16:00:39 +0300 Subject: [PATCH 02/10] feat: add kvm support for poky via separate container --- Makefile | 1 + docker/compose.yml | 32 ++++++++++++++++++++++++++- docker/image_builder.dockerfile | 6 ++++-- docker/vm-yocto.dockerfile | 38 +++++++++++++++++++++++++++++++++ scripts/cmd_yocto.sh | 4 ---- scripts/start-vm-yocto.sh | 10 +++++++++ 6 files changed, 84 insertions(+), 7 deletions(-) create mode 100644 docker/vm-yocto.dockerfile create mode 100755 scripts/start-vm-yocto.sh diff --git a/Makefile b/Makefile index 5880725b..5c5fe521 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ DOCKER_PREFIX := ${LIB_NAME} DOCKER_TAG := ${DOCKER_PREFIX}-yocto-builder DOCKER_SUSE_TAG := ${DOCKER_PREFIX}-open-suse-env DOCKER_PYTHON_TAG := ${DOCKER_PREFIX}-analyzer +DOCKER_YOCTO_VM_TAG := ${DOCKER_PREFIX}-yocto-vm DOCKER_SUSE_VM_TAG := ${DOCKER_PREFIX}-suse-vm DOCKER_BUILD_VOLUME := ${DOCKER_PREFIX}-yocto-build DOCKER_DOWNLOADS_VOLUME := ${DOCKER_PREFIX}-yocto-downloads diff --git a/docker/compose.yml b/docker/compose.yml index 2c0d72a0..9f5e06f8 100644 --- a/docker/compose.yml +++ b/docker/compose.yml @@ -23,7 +23,34 @@ services: BUILD_DIR: ${BUILD_DIR} POKY_DIR: ${POKY_DIR} OS_IMAGE: ${OS_IMAGE} - VM_RAM: ${QEMU_VM_RAM} + USER: ${USER} + GROUP: ${GROUP} + + imgtests-yocto-vm: + build: + dockerfile: docker/vm-yocto.dockerfile + args: + USER: ${USER} + GROUP: ${GROUP} + PASSWORD: ${PASSWORD} + POKY_DIR: ${POKY_DIR} + image: ${DOCKER_YOCTO_VM_TAG} + privileged: true + devices: + - /dev/kvm + volumes: + - ${DOCKER_BUILD_VOLUME}:${BUILD_DIR} + - ${DOCKER_DOWNLOADS_VOLUME}:${POKY_DIR}/downloads + - ${DOCKER_SSTATE_VOLUME}:${POKY_DIR}/sstate-cache + - ${HOST_CONF_PATH}/local.conf:${BUILD_DIR}/conf/local.conf + - ${HOST_CONF_PATH}/packages.conf:${BUILD_DIR}/conf/packages.conf + - ${HOST_CONF_PATH}/added_packages.conf:${BUILD_DIR}/conf/added_packages.conf + - ${HOST_LAYERS_PATH}/meta-image-tests:${POKY_DIR}/meta-image-tests + - ${HOST_SCRIPTS_PATH}/add-layers.sh:${POKY_DIR}/add-layers.sh + environment: + BUILD_DIR: ${BUILD_DIR} + POKY_DIR: ${POKY_DIR} + OS_IMAGE: ${OS_IMAGE} CPUS: ${CPUS} USER: ${USER} GROUP: ${GROUP} @@ -37,6 +64,9 @@ services: networks: yocto-network: ipv4_address: ${YOCTO_ADDRESS} + depends_on: + imgtests-yocto: + condition: service_completed_successfully imgtests-suse-156: build: diff --git a/docker/image_builder.dockerfile b/docker/image_builder.dockerfile index e4df2346..dee15e62 100644 --- a/docker/image_builder.dockerfile +++ b/docker/image_builder.dockerfile @@ -30,12 +30,14 @@ RUN groupadd -g 510 ${GROUP} && \ echo "${USER}:${PASSWORD}" | chpasswd USER ${USER} + RUN mkdir --parents ${POKY_DIR} && \ git clone --depth 1 -b walnascar --recurse-submodules https://git.yoctoproject.org/poky ${POKY_DIR} + WORKDIR ${POKY_DIR} COPY --chown=${USER}:${GROUP} layers ${POKY_DIR} -COPY --chown=${USER}:${GROUP} scripts/entrypoint.sh ${POKY_DIR}/ -COPY --chown=${USER}:${GROUP} scripts/cmd_yocto.sh ${POKY_DIR}/ +COPY --chown=${USER}:${GROUP} scripts/entrypoint.sh ${POKY_DIR} +COPY --chown=${USER}:${GROUP} scripts/cmd_yocto.sh ${POKY_DIR} ENTRYPOINT ["/home/user/poky/entrypoint.sh"] diff --git a/docker/vm-yocto.dockerfile b/docker/vm-yocto.dockerfile new file mode 100644 index 00000000..5fd0be70 --- /dev/null +++ b/docker/vm-yocto.dockerfile @@ -0,0 +1,38 @@ +FROM ubuntu:22.04 + +ARG USER +ARG GROUP +ARG PASSWORD +ARG POKY_DIR + +ENV DEBIAN_FRONTEND=noninteractive \ + LANG=en_US.UTF-8 + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + sudo wget git locales chrpath cpio diffstat gawk \ + zstd liblz4-tool python3 python3-pip tar gcc make \ + bzip2 file g++ patch python3-pexpect python3-git \ + python3-jinja2 python3-subunit screen \ + libtirpc-dev libtirpc3 pkg-config \ + qemu qemu-system-x86 qemu-utils \ + openssh-server && \ + rm -rf /var/lib/apt/lists/* && \ + locale-gen en_US.UTF-8 + +RUN groupadd -g 510 ${GROUP} && \ + groupadd -g 993 kvm && \ + useradd -rm -d /home/${USER} -s /bin/bash -g ${GROUP} -u 1010 -G sudo,kvm ${USER} && \ + echo "${USER} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/${USER} && \ + echo "${USER}:${PASSWORD}" | chpasswd + +USER ${USER} + +RUN git clone --depth 1 -b walnascar --recurse-submodules https://git.yoctoproject.org/poky ${POKY_DIR} + +WORKDIR ${POKY_DIR} + +COPY --chown=${USER}:${GROUP} layers ${POKY_DIR} +COPY --chown=${USER}:${GROUP} scripts/start-vm-yocto.sh ${POKY_DIR} + +ENTRYPOINT ["/home/user/poky/start-vm-yocto.sh"] diff --git a/scripts/cmd_yocto.sh b/scripts/cmd_yocto.sh index 970e2dff..767e454c 100755 --- a/scripts/cmd_yocto.sh +++ b/scripts/cmd_yocto.sh @@ -5,7 +5,3 @@ set -e cd "${POKY_DIR}" ./add-layers.sh bitbake "${OS_IMAGE}" -ROOTFS_IMAGE="${POKY_DIR}/build/tmp/deploy/images/qemux86-64/${OS_IMAGE}-qemux86-64.rootfs.ext4.qcow2" - -QB_SLIRP_OPT="-netdev user,id=net0,hostfwd=tcp::8080-:80,hostfwd=tcp::${SSH_QEMU_PORT}-:${SSH_TO_QEMU_PORT},hostfwd=tcp::${YOCTO_NE_PORT}-:${DEFAULT_NE_PORT},hostfwd=tcp:0.0.0.0:${IPERF3_PORT}-:${IPERF3_PORT},hostfwd=udp:0.0.0.0:${IPERF3_PORT}-:${IPERF3_PORT}" \ - runqemu qemux86-64 slirp nographic "${ROOTFS_IMAGE}" qemuparams="-monitor tcp:0.0.0.0:4444,server,nowait -smp ${CPUS}" diff --git a/scripts/start-vm-yocto.sh b/scripts/start-vm-yocto.sh new file mode 100755 index 00000000..bf15b3b0 --- /dev/null +++ b/scripts/start-vm-yocto.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +rm -rf /home/user/poky/meta-openjdk-temurin/recipes-java/helloworld-java + +source "/home/user/poky/oe-init-build-env" "/home/user/poky/build" + +ROOTFS_IMAGE="${POKY_DIR}/build/tmp/deploy/images/qemux86-64/${OS_IMAGE}-qemux86-64.rootfs.ext4.qcow2" + +QB_SLIRP_OPT="-netdev user,id=net0,hostfwd=tcp::8080-:80,hostfwd=tcp::${SSH_QEMU_PORT}-:${SSH_TO_QEMU_PORT},hostfwd=tcp::${YOCTO_NE_PORT}-:${DEFAULT_NE_PORT},hostfwd=tcp:0.0.0.0:${IPERF3_PORT}-:${IPERF3_PORT},hostfwd=udp:0.0.0.0:${IPERF3_PORT}-:${IPERF3_PORT}" \ + runqemu qemux86-64 kvm slirp nographic "${ROOTFS_IMAGE}" qemuparams="-monitor tcp:0.0.0.0:4444,server,nowait -smp ${CPUS}" From e4379031ac71805fdd4ee8b5854d6c147e7b9ebb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B8=D0=B2=D0=BE=D0=B5=D0=B2=20=D0=9D=D0=B8=D0=BA?= =?UTF-8?q?=D0=B8=D1=82=D0=B0?= Date: Fri, 17 Jul 2026 16:05:58 +0300 Subject: [PATCH 03/10] fix: shellcheck warning --- scripts/start-vm-yocto.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/start-vm-yocto.sh b/scripts/start-vm-yocto.sh index bf15b3b0..cd649b92 100755 --- a/scripts/start-vm-yocto.sh +++ b/scripts/start-vm-yocto.sh @@ -2,6 +2,7 @@ rm -rf /home/user/poky/meta-openjdk-temurin/recipes-java/helloworld-java +# shellcheck disable=SC1091 source "/home/user/poky/oe-init-build-env" "/home/user/poky/build" ROOTFS_IMAGE="${POKY_DIR}/build/tmp/deploy/images/qemux86-64/${OS_IMAGE}-qemux86-64.rootfs.ext4.qcow2" From 17e81b36fe85fa0a011a2bf2175bd077ccc099ec Mon Sep 17 00:00:00 2001 From: Vadim Kazakov Date: Tue, 11 Aug 2026 16:08:32 +0300 Subject: [PATCH 04/10] docs: add info about fault injection examples to documentation --- docs/methodology/failure_emulation.md | 15 +++++++++++++++ docs/utilities/benchmarking/general/chaosblade.md | 7 +++++++ 2 files changed, 22 insertions(+) diff --git a/docs/methodology/failure_emulation.md b/docs/methodology/failure_emulation.md index 7bcb6d4c..e20dc9eb 100644 --- a/docs/methodology/failure_emulation.md +++ b/docs/methodology/failure_emulation.md @@ -11,6 +11,15 @@ * Проводить различные манипуляции с сетевыми пакетами, в т.ч. вызывать потерю пакетов, дублировать их, повреждать, блокировать; * Делать порт недоступным; * Вносить изменения в работу DNS. + * Пример создания сетевой задержки 100 мс на интерфейсе `eth0` (реализован в `scripts/fault-injection/chaosblade_vm.sh`): + ``` + # Создать эксперимент: задержка 100 мс, автоматическое завершение через 30 с + sudo blade create network delay --time 100 --interface eth0 --timeout 30 + + # Проверить статус и, при необходимости, завершить вручную + sudo blade status + sudo blade destroy + ``` - [tc](https://man7.org/linux/man-pages/man8/tc.8.html) - утилита для управления трафиком. Для эмуляции сетевых сбоев используется `tc netem`. Как и `chaosblade` позволяет создавать задержки, потери, дубликации, неправильный порядок пакетов. Пример: добавление задержки 100 мс: ```sudo tc qdisc add dev eth0 root netem delay 100ms``` ### Диски и файловые системы @@ -32,6 +41,9 @@ + ```# krfctl -p 100``` - установить вероятность ошибки равной 1% + ```# krfctl -P io``` - для указания группы системных вызовов, которые должны завершаться с ошибкой (в данном случае, все, связанные с вводом/выводом) + ```$ krfexec [args]``` - для запуска программы через `krfexec` + + Пример использования `krf` реализован в `scripts/fault-injection/krf_vm.sh` + - [epbfault](https://github.com/trailofbits/ebpfault) - утилита для внедрения ошибок в системные вызовы, работающая на основе eBPF. Удобна в использовании, так как позволяет задать в конфигурационном файле системные вызовы, в которых будет симулироваться ошибка, вощвращаемое значение и вероятность возврата этого значения. Пример конфигурационного файла: ``` { @@ -68,6 +80,9 @@ Использование: ```ebpfault --config /path/to/config.json --exec /path/to/program arg1 arg2``` + + Пример использования `ebpfault` реализован в `scripts/fault-injection/ebpfault_vm.sh` + - Аналогично `ebpfault` можно писать свои тесты с использованием `kprobes` и `bpf`. Для этого подходит функция `bpf_override_return()`, позволяющая перезаписывать код возврата функций. Кроме того, некоторые рассмотренные инструменты, можно использовать и для других целей. Так, chaosblade можно также использовать для эмуляции сбоев файловой подсистемы, процессора, дисков. diff --git a/docs/utilities/benchmarking/general/chaosblade.md b/docs/utilities/benchmarking/general/chaosblade.md index f842a49f..107623fd 100644 --- a/docs/utilities/benchmarking/general/chaosblade.md +++ b/docs/utilities/benchmarking/general/chaosblade.md @@ -282,3 +282,10 @@ blade status --type create --flag-filter "timeout=10" ] } ``` + +6. Создать эксперимент с сетевой задержкой. Например, 100 мс на интерфейсе `eth0` с автоматическим завершением через 30 секунд: +``` +blade create network delay --time 100 --interface eth0 --timeout 30 +``` + +Задержку можно комбинировать с другими параметрами: `--offset` (jitter в мс), `--destination-ip`, `--exclude-ip`. Получение статуса и завершение эксперимента выполняются командами `blade status ` и `blade destroy `. Реализация примера есть в скриптах `scripts/fault-injection/chaosblade.sh` и `scripts/fault-injection/chaosblade_vm.sh`. From a12bbae7b0d2e26deb0aff0433515adbb9939585 Mon Sep 17 00:00:00 2001 From: Vadim Kazakov Date: Wed, 5 Aug 2026 13:36:53 +0300 Subject: [PATCH 05/10] feat: add fault injection scripts to launch in vm --- docs/methodology/failure_emulation.md | 2 +- .../linux/linux-yocto/fault-injection.cfg | 1 + scripts/fault-injection/ebpfault_vm.sh | 67 ++++++++++ scripts/fault-injection/krf_vm.sh | 121 ++++++++++++++++++ 4 files changed, 190 insertions(+), 1 deletion(-) create mode 100755 scripts/fault-injection/ebpfault_vm.sh create mode 100755 scripts/fault-injection/krf_vm.sh diff --git a/docs/methodology/failure_emulation.md b/docs/methodology/failure_emulation.md index e20dc9eb..f10664ab 100644 --- a/docs/methodology/failure_emulation.md +++ b/docs/methodology/failure_emulation.md @@ -11,7 +11,7 @@ * Проводить различные манипуляции с сетевыми пакетами, в т.ч. вызывать потерю пакетов, дублировать их, повреждать, блокировать; * Делать порт недоступным; * Вносить изменения в работу DNS. - * Пример создания сетевой задержки 100 мс на интерфейсе `eth0` (реализован в `scripts/fault-injection/chaosblade_vm.sh`): + * Пример создания сетевой задержки 100 мс на интерфейсе `eth0`: ``` # Создать эксперимент: задержка 100 мс, автоматическое завершение через 30 с sudo blade create network delay --time 100 --interface eth0 --timeout 30 diff --git a/layers/meta-image-tests/recipes-kernel/linux/linux-yocto/fault-injection.cfg b/layers/meta-image-tests/recipes-kernel/linux/linux-yocto/fault-injection.cfg index 2c2602a3..722145fd 100644 --- a/layers/meta-image-tests/recipes-kernel/linux/linux-yocto/fault-injection.cfg +++ b/layers/meta-image-tests/recipes-kernel/linux/linux-yocto/fault-injection.cfg @@ -5,3 +5,4 @@ CONFIG_FAIL_PAGE_ALLOC=y CONFIG_FAIL_MAKE_REQUEST=y CONFIG_FAIL_IO_TIMEOUT=y CONFIG_FAIL_FUTEX=y +CONFIG_BPF_KPROBE_OVERRIDE=y diff --git a/scripts/fault-injection/ebpfault_vm.sh b/scripts/fault-injection/ebpfault_vm.sh new file mode 100755 index 00000000..43b7b4b9 --- /dev/null +++ b/scripts/fault-injection/ebpfault_vm.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +set -euo pipefail + +DIR="${EBPFAULT_DIR:-/opt/ebpfault}" +VER="${EBPFAULT_VER:-1.1.2}" +SYSCALL="${EBPFAULT_SYSCALL:-fchmodat}" +ERRNO="${EBPFAULT_ERRNO:-ENOENT}" +PROB="${EBPFAULT_PROB:-50}" +ARGS="${EBPFAULT_ARGS:-/bin/chmod 0755 /tmp/ebpfault_marker}" + +install_ebpf() { + if [[ -x "$DIR/bin/ebpfault" ]]; then + echo "[INFO] ebpfault already installed in ${DIR}" + return + fi + echo "[INFO] Installing ebpfault v${VER}..." + url="https://github.com/trailofbits/ebpfault/releases/download/v${VER}/ebpfault-${VER}-1.x86_64.tar.gz" + tmp=$(mktemp -d) + trap 'rm -rf "$tmp"' EXIT + wget -q -O "$tmp/ebpfault.tar.gz" "$url" || curl -fsSL -o "$tmp/ebpfault.tar.gz" "$url" + tar -xzf "$tmp/ebpfault.tar.gz" -C "$tmp" + sudo mkdir -p "$DIR" + sudo chown "$(id -u):$(id -g)" "$DIR" + cp -r "$tmp"/ebpfault-"${VER}"-1.x86_64/. "$DIR"/ + chmod +x "$DIR/bin/ebpfault" +} + +kprobe_supported() { + { zcat /proc/config.gz 2>/dev/null || cat "/boot/config-$(uname -r)" 2>/dev/null; } | grep -q '^CONFIG_BPF_KPROBE_OVERRIDE=y' +} + +gen_config() { + echo "[INFO] Writing ebpfault config (${SYSCALL} -> -${ERRNO}, ${PROB}%)..." + cat > "$DIR/config.json" </dev/null 2>&1 || true + sudo "$KRF_DIR/src/krfctl/krfctl" -C >/dev/null 2>&1 || true + if (( LOADED )); then + sudo rmmod krfx >/dev/null 2>&1 || true + fi +} +trap cleanup EXIT + +missing() { + for tool in gcc make ruby; do + command -v "$tool" >/dev/null 2>&1 || echo "$tool" + done + ls /lib/modules/*/build >/dev/null 2>&1 || echo "kernel headers" +} + +install_deps() { + sudo zypper -n install --no-recommends gcc make libelf-devel ruby git-core kernel-default-devel +} + +build_krf() { + if [[ -x "$KRF_DIR/src/krfctl/krfctl" ]]; then + echo "[INFO] krf already built in ${KRF_DIR}" + return + fi + echo "[INFO] Cloning and building krf in ${KRF_DIR}..." + if [[ ! -d "$KRF_DIR" ]]; then + sudo git clone --depth 1 https://github.com/trailofbits/krf "$KRF_DIR" + sudo chown -R "$(id -u):$(id -g)" "$KRF_DIR" + fi + headers="/lib/modules/$(uname -r)/build" + if [[ ! -d "$headers" ]]; then + headers=$(ls -d /lib/modules/*/build 2>/dev/null | head -1) + fi + if [[ -z "$headers" || ! -d "$headers" ]]; then + echo "no kernel headers found" + exit 1 + fi + kver=$(basename "$(dirname "$headers")") + echo "building against kernel headers: ${kver}" + mkdir -p /tmp/krf-fakebin + cat > /tmp/krf-fakebin/uname <<'INNER' +#!/bin/bash +if [[ "$1" == "-r" ]]; then echo "__KVER__"; else /bin/uname "$@"; fi +INNER + sed -i "s/__KVER__/${kver}/" /tmp/krf-fakebin/uname + chmod +x /tmp/krf-fakebin/uname + export PATH="/tmp/krf-fakebin:$PATH" + make -C "$KRF_DIR/src/module/linux" codegen + make -C "$headers" M="$KRF_DIR/src/module/linux" modules + make PLATFORM=linux -C "$KRF_DIR/src/krfexec" + make PLATFORM=linux -C "$KRF_DIR/src/krfctl" + make PLATFORM=linux -C "$KRF_DIR/src/krfmesg" +} + +load_module() { + if lsmod | grep -q '^krfx'; then + echo "[INFO] krfx module already loaded" + return + fi + echo "[INFO] Loading krfx.ko (force; built against non-running kernel headers)..." + sudo insmod -f "$KRF_DIR/src/module/linux/krfx.ko" + LOADED=1 +} + +configure_krf() { + echo "[INFO] Configuring krf (syscalls='${SYSCALLS}', prob=${PROB})..." + krfctl="$KRF_DIR/src/krfctl/krfctl" + sudo "$krfctl" -F "$SYSCALLS" + sudo "$krfctl" -T personality=28 + sudo "$krfctl" -p "$PROB" + if [[ -n "$PROFILE" ]]; then + sudo "$krfctl" -P "$PROFILE" + fi + echo 1 | sudo tee /proc/krf/log_faults >/dev/null +} + +run_target() { + echo "[INFO] Running '${TARGET_CMD}' through krfexec..." + set +e + "$KRF_DIR/src/krfexec/krfexec" $TARGET_CMD + echo "exit_code=$?" + set -e +} + +show_logs() { + sudo dmesg | grep -i "faulting" | tail -n 20 +} + +main() { + local missing_list + missing_list=$(missing) + echo "[INFO] Missing prerequisites: ${missing_list:-none}" + if [[ -n "$missing_list" ]]; then + install_deps + missing_list=$(missing) + if [[ -n "$missing_list" ]]; then + echo "[ERROR] Still missing prerequisites: $missing_list" + exit 1 + fi + fi + + build_krf + load_module + configure_krf + run_target + show_logs + echo "[INFO] Done!" +} +main "$@" From f00257e4a7a35e213ced55485a7a0a45c1230769 Mon Sep 17 00:00:00 2001 From: Artanias <43622365+Artanias@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:32:47 +0300 Subject: [PATCH 06/10] refactor: removes unnecessary changes for this PR. --- docker/image_builder.dockerfile | 6 ++---- docker/open-suse.dockerfile | 3 +++ docker/vm-suse.dockerfile | 19 ----------------- docker/vm-yocto.dockerfile | 38 --------------------------------- scripts/opensuse/start-vm.sh | 20 ----------------- scripts/start-vm-yocto.sh | 11 ---------- 6 files changed, 5 insertions(+), 92 deletions(-) delete mode 100644 docker/vm-suse.dockerfile delete mode 100644 docker/vm-yocto.dockerfile delete mode 100755 scripts/opensuse/start-vm.sh delete mode 100755 scripts/start-vm-yocto.sh diff --git a/docker/image_builder.dockerfile b/docker/image_builder.dockerfile index dee15e62..e4df2346 100644 --- a/docker/image_builder.dockerfile +++ b/docker/image_builder.dockerfile @@ -30,14 +30,12 @@ RUN groupadd -g 510 ${GROUP} && \ echo "${USER}:${PASSWORD}" | chpasswd USER ${USER} - RUN mkdir --parents ${POKY_DIR} && \ git clone --depth 1 -b walnascar --recurse-submodules https://git.yoctoproject.org/poky ${POKY_DIR} - WORKDIR ${POKY_DIR} COPY --chown=${USER}:${GROUP} layers ${POKY_DIR} -COPY --chown=${USER}:${GROUP} scripts/entrypoint.sh ${POKY_DIR} -COPY --chown=${USER}:${GROUP} scripts/cmd_yocto.sh ${POKY_DIR} +COPY --chown=${USER}:${GROUP} scripts/entrypoint.sh ${POKY_DIR}/ +COPY --chown=${USER}:${GROUP} scripts/cmd_yocto.sh ${POKY_DIR}/ ENTRYPOINT ["/home/user/poky/entrypoint.sh"] diff --git a/docker/open-suse.dockerfile b/docker/open-suse.dockerfile index ac93fdac..189d9519 100644 --- a/docker/open-suse.dockerfile +++ b/docker/open-suse.dockerfile @@ -7,6 +7,9 @@ ENV DEBIAN_FRONTEND=noninteractive \ RUN apt-get update && \ apt-get install -y --no-install-recommends \ + qemu-system \ + qemu-utils \ + qemu-user-static \ cloud-init \ cloud-image-utils \ wget \ diff --git a/docker/vm-suse.dockerfile b/docker/vm-suse.dockerfile deleted file mode 100644 index d6843278..00000000 --- a/docker/vm-suse.dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -FROM ubuntu:24.04 - -ARG USER - -ENV DEBIAN_FRONTEND=noninteractive \ - SUSE_DIR=/home/${USER}/suse - -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - qemu-system \ - qemu-utils \ - qemu-user-static - -WORKDIR ${SUSE_DIR} - -COPY scripts/opensuse/start-vm.sh /start-vm.sh -RUN chmod +x /start-vm.sh - -ENTRYPOINT ["/start-vm.sh"] diff --git a/docker/vm-yocto.dockerfile b/docker/vm-yocto.dockerfile deleted file mode 100644 index 5fd0be70..00000000 --- a/docker/vm-yocto.dockerfile +++ /dev/null @@ -1,38 +0,0 @@ -FROM ubuntu:22.04 - -ARG USER -ARG GROUP -ARG PASSWORD -ARG POKY_DIR - -ENV DEBIAN_FRONTEND=noninteractive \ - LANG=en_US.UTF-8 - -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - sudo wget git locales chrpath cpio diffstat gawk \ - zstd liblz4-tool python3 python3-pip tar gcc make \ - bzip2 file g++ patch python3-pexpect python3-git \ - python3-jinja2 python3-subunit screen \ - libtirpc-dev libtirpc3 pkg-config \ - qemu qemu-system-x86 qemu-utils \ - openssh-server && \ - rm -rf /var/lib/apt/lists/* && \ - locale-gen en_US.UTF-8 - -RUN groupadd -g 510 ${GROUP} && \ - groupadd -g 993 kvm && \ - useradd -rm -d /home/${USER} -s /bin/bash -g ${GROUP} -u 1010 -G sudo,kvm ${USER} && \ - echo "${USER} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/${USER} && \ - echo "${USER}:${PASSWORD}" | chpasswd - -USER ${USER} - -RUN git clone --depth 1 -b walnascar --recurse-submodules https://git.yoctoproject.org/poky ${POKY_DIR} - -WORKDIR ${POKY_DIR} - -COPY --chown=${USER}:${GROUP} layers ${POKY_DIR} -COPY --chown=${USER}:${GROUP} scripts/start-vm-yocto.sh ${POKY_DIR} - -ENTRYPOINT ["/home/user/poky/start-vm-yocto.sh"] diff --git a/scripts/opensuse/start-vm.sh b/scripts/opensuse/start-vm.sh deleted file mode 100755 index 5e942a22..00000000 --- a/scripts/opensuse/start-vm.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -set -e - -cd "${SUSE_DIR}" - -echo "Waiting for OpenSUSE image to be ready..." -while true; do - for img in open-suse-*.ready.qcow2; do - [ -f "$img" ] && IMAGE="$img" && break 2 - done - sleep 10 -done - -exec qemu-system-x86_64 -enable-kvm -m "${VM_RAM}" -smp "${CPUS}" -nographic \ - -monitor tcp:0.0.0.0:4444,server,nowait \ - -drive file="$IMAGE",index=0,media=disk \ - -cdrom cloud-init.iso \ - -net user,hostfwd=tcp::"${SSH_SUSE_PORT}"-:"${SSH_QEMU_PORT}",hostfwd=tcp::"${SUSE_NE_PORT}"-:"${DEFAULT_NE_PORT}",hostfwd=tcp:0.0.0.0:"${IPERF3_PORT}"-:"${IPERF3_PORT}",hostfwd=udp:0.0.0.0:"${IPERF3_PORT}"-:"${IPERF3_PORT}" \ - -net nic diff --git a/scripts/start-vm-yocto.sh b/scripts/start-vm-yocto.sh deleted file mode 100755 index cd649b92..00000000 --- a/scripts/start-vm-yocto.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -rm -rf /home/user/poky/meta-openjdk-temurin/recipes-java/helloworld-java - -# shellcheck disable=SC1091 -source "/home/user/poky/oe-init-build-env" "/home/user/poky/build" - -ROOTFS_IMAGE="${POKY_DIR}/build/tmp/deploy/images/qemux86-64/${OS_IMAGE}-qemux86-64.rootfs.ext4.qcow2" - -QB_SLIRP_OPT="-netdev user,id=net0,hostfwd=tcp::8080-:80,hostfwd=tcp::${SSH_QEMU_PORT}-:${SSH_TO_QEMU_PORT},hostfwd=tcp::${YOCTO_NE_PORT}-:${DEFAULT_NE_PORT},hostfwd=tcp:0.0.0.0:${IPERF3_PORT}-:${IPERF3_PORT},hostfwd=udp:0.0.0.0:${IPERF3_PORT}-:${IPERF3_PORT}" \ - runqemu qemux86-64 kvm slirp nographic "${ROOTFS_IMAGE}" qemuparams="-monitor tcp:0.0.0.0:4444,server,nowait -smp ${CPUS}" From 42db2efaba45d20f2bad63edb8edf06937361904 Mon Sep 17 00:00:00 2001 From: Artanias <43622365+Artanias@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:36:34 +0300 Subject: [PATCH 07/10] refactor: adds necessary changes for this PR back. --- scripts/cmd_yocto.sh | 4 ++++ scripts/opensuse/suse-compose.sh | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/scripts/cmd_yocto.sh b/scripts/cmd_yocto.sh index 767e454c..970e2dff 100755 --- a/scripts/cmd_yocto.sh +++ b/scripts/cmd_yocto.sh @@ -5,3 +5,7 @@ set -e cd "${POKY_DIR}" ./add-layers.sh bitbake "${OS_IMAGE}" +ROOTFS_IMAGE="${POKY_DIR}/build/tmp/deploy/images/qemux86-64/${OS_IMAGE}-qemux86-64.rootfs.ext4.qcow2" + +QB_SLIRP_OPT="-netdev user,id=net0,hostfwd=tcp::8080-:80,hostfwd=tcp::${SSH_QEMU_PORT}-:${SSH_TO_QEMU_PORT},hostfwd=tcp::${YOCTO_NE_PORT}-:${DEFAULT_NE_PORT},hostfwd=tcp:0.0.0.0:${IPERF3_PORT}-:${IPERF3_PORT},hostfwd=udp:0.0.0.0:${IPERF3_PORT}-:${IPERF3_PORT}" \ + runqemu qemux86-64 slirp nographic "${ROOTFS_IMAGE}" qemuparams="-monitor tcp:0.0.0.0:4444,server,nowait -smp ${CPUS}" diff --git a/scripts/opensuse/suse-compose.sh b/scripts/opensuse/suse-compose.sh index 9e3d2877..60959d06 100755 --- a/scripts/opensuse/suse-compose.sh +++ b/scripts/opensuse/suse-compose.sh @@ -4,4 +4,6 @@ set -e ./scripts/download_images.py "$1" ./scripts/cloud-setup.sh "${S_USER}" "${PASSWORD}" -echo "Image is ready. VM will be started by imgtests-suse-vm container." +CPUS=4 +qemu-system-x86_64 -m "${VM_RAM}" -smp "${CPUS}" -nographic -monitor tcp:0.0.0.0:4444,server,nowait -drive file=open-suse-"$1".ready.qcow2,index=0,media=disk \ + -cdrom cloud-init.iso -net user,hostfwd=tcp::"${SSH_SUSE_PORT}"-:"${SSH_QEMU_PORT}",hostfwd=tcp::"${SUSE_NE_PORT}"-:"${DEFAULT_NE_PORT}",hostfwd=tcp:0.0.0.0:"${IPERF3_PORT}"-:"${IPERF3_PORT}",hostfwd=udp:0.0.0.0:"${IPERF3_PORT}"-:"${IPERF3_PORT}" -net nic From 9e12bf8cccf094d8812950c7f201eac7a4bf9d64 Mon Sep 17 00:00:00 2001 From: Artanias <43622365+Artanias@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:51:03 +0300 Subject: [PATCH 08/10] refactor: adds necessary changes in the compose.yml for this PR back. --- Makefile | 2 -- docker/compose.yml | 51 +++------------------------------------------- 2 files changed, 3 insertions(+), 50 deletions(-) diff --git a/Makefile b/Makefile index 51181ebc..68dabf97 100644 --- a/Makefile +++ b/Makefile @@ -6,8 +6,6 @@ DOCKER_PREFIX := ${LIB_NAME} DOCKER_TAG := ${DOCKER_PREFIX}-yocto-builder DOCKER_SUSE_TAG := ${DOCKER_PREFIX}-open-suse-env DOCKER_PYTHON_TAG := ${DOCKER_PREFIX}-analyzer -DOCKER_YOCTO_VM_TAG := ${DOCKER_PREFIX}-yocto-vm -DOCKER_SUSE_VM_TAG := ${DOCKER_PREFIX}-suse-vm DOCKER_BUILD_VOLUME := ${DOCKER_PREFIX}-yocto-build DOCKER_DOWNLOADS_VOLUME := ${DOCKER_PREFIX}-yocto-downloads DOCKER_SSTATE_VOLUME := ${DOCKER_PREFIX}-yocto-sstate diff --git a/docker/compose.yml b/docker/compose.yml index 0c53ef2d..376be5b5 100644 --- a/docker/compose.yml +++ b/docker/compose.yml @@ -23,34 +23,7 @@ services: BUILD_DIR: ${BUILD_DIR} POKY_DIR: ${POKY_DIR} OS_IMAGE: ${OS_IMAGE} - USER: ${USER} - GROUP: ${GROUP} - - imgtests-yocto-vm: - build: - dockerfile: docker/vm-yocto.dockerfile - args: - USER: ${USER} - GROUP: ${GROUP} - PASSWORD: ${PASSWORD} - POKY_DIR: ${POKY_DIR} - image: ${DOCKER_YOCTO_VM_TAG} - privileged: true - devices: - - /dev/kvm - volumes: - - ${DOCKER_BUILD_VOLUME}:${BUILD_DIR} - - ${DOCKER_DOWNLOADS_VOLUME}:${POKY_DIR}/downloads - - ${DOCKER_SSTATE_VOLUME}:${POKY_DIR}/sstate-cache - - ${HOST_CONF_PATH}/local.conf:${BUILD_DIR}/conf/local.conf - - ${HOST_CONF_PATH}/packages.conf:${BUILD_DIR}/conf/packages.conf - - ${HOST_CONF_PATH}/added_packages.conf:${BUILD_DIR}/conf/added_packages.conf - - ${HOST_LAYERS_PATH}/meta-image-tests:${POKY_DIR}/meta-image-tests - - ${HOST_SCRIPTS_PATH}/add-layers.sh:${POKY_DIR}/add-layers.sh - environment: - BUILD_DIR: ${BUILD_DIR} - POKY_DIR: ${POKY_DIR} - OS_IMAGE: ${OS_IMAGE} + VM_RAM: ${QEMU_VM_RAM} CPUS: ${CPUS} USER: ${USER} GROUP: ${GROUP} @@ -64,9 +37,6 @@ services: networks: yocto-network: ipv4_address: ${YOCTO_ADDRESS} - depends_on: - imgtests-yocto: - condition: service_completed_successfully imgtests-suse-156: build: @@ -81,28 +51,13 @@ services: environment: S_USER: ${S_USER} PASSWORD: ${PASSWORD} - networks: - - yocto-network - - imgtests-suse-vm: - build: - dockerfile: docker/vm-suse.dockerfile - args: - USER: ${USER} - image: ${DOCKER_SUSE_VM_TAG} - privileged: true - devices: - - /dev/kvm - volumes: - - ${DOCKER_OPENSUSE_VOLUME}:${SUSE_DIR} - environment: + VM_RAM: ${QEMU_VM_RAM} + CPUS: ${CPUS} SSH_QEMU_PORT: ${SSH_TO_QEMU_PORT} SSH_SUSE_PORT: ${SSH_SUSE_PORT_156} SUSE_NE_PORT: ${SUSE_156_NE_PORT} DEFAULT_NE_PORT: ${DEFAULT_NE_PORT} IPERF3_PORT: ${IPERF3_PORT} - VM_RAM: ${QEMU_VM_RAM} - CPUS: ${CPUS} ports: - ${SSH_SUSE_PORT_156}:${SSH_SUSE_PORT_156} networks: From f09a2846485d65ad9b62bbb41b284f3381306f2f Mon Sep 17 00:00:00 2001 From: Artanias <43622365+Artanias@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:54:06 +0300 Subject: [PATCH 09/10] docs: updates chaosblade.md. --- docs/utilities/benchmarking/general/chaosblade.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/utilities/benchmarking/general/chaosblade.md b/docs/utilities/benchmarking/general/chaosblade.md index 107623fd..c4f6045f 100644 --- a/docs/utilities/benchmarking/general/chaosblade.md +++ b/docs/utilities/benchmarking/general/chaosblade.md @@ -288,4 +288,4 @@ blade status --type create --flag-filter "timeout=10" blade create network delay --time 100 --interface eth0 --timeout 30 ``` -Задержку можно комбинировать с другими параметрами: `--offset` (jitter в мс), `--destination-ip`, `--exclude-ip`. Получение статуса и завершение эксперимента выполняются командами `blade status ` и `blade destroy `. Реализация примера есть в скриптах `scripts/fault-injection/chaosblade.sh` и `scripts/fault-injection/chaosblade_vm.sh`. +Задержку можно комбинировать с другими параметрами: `--offset` (jitter в мс), `--destination-ip`, `--exclude-ip`. Получение статуса и завершение эксперимента выполняются командами `blade status ` и `blade destroy `. Реализация примера есть в скрипте `scripts/fault-injection/chaosblade_vm.sh`. From 3bb2b2055ed1f35f7da2a5380a4fd23ed322bec8 Mon Sep 17 00:00:00 2001 From: Artanias <43622365+Artanias@users.noreply.github.com> Date: Sun, 16 Aug 2026 20:04:29 +0300 Subject: [PATCH 10/10] fix: pre-commit issues. --- scripts/fault-injection/ebpfault_vm.sh | 2 +- scripts/fault-injection/krf_vm.sh | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/fault-injection/ebpfault_vm.sh b/scripts/fault-injection/ebpfault_vm.sh index 43b7b4b9..5c92e0e9 100755 --- a/scripts/fault-injection/ebpfault_vm.sh +++ b/scripts/fault-injection/ebpfault_vm.sh @@ -46,7 +46,7 @@ run_exp() { set +e touch /tmp/ebpfault_marker chmod 0644 /tmp/ebpfault_marker - "$DIR/bin/ebpfault" --config "$DIR/config.json" --exec $ARGS + "$DIR/bin/ebpfault" --config "$DIR/config.json" --exec "$ARGS" echo "exit_code=$?" set -e } diff --git a/scripts/fault-injection/krf_vm.sh b/scripts/fault-injection/krf_vm.sh index 99dd0876..31efa00e 100755 --- a/scripts/fault-injection/krf_vm.sh +++ b/scripts/fault-injection/krf_vm.sh @@ -41,6 +41,7 @@ build_krf() { fi headers="/lib/modules/$(uname -r)/build" if [[ ! -d "$headers" ]]; then + # shellcheck disable=SC2012 headers=$(ls -d /lib/modules/*/build 2>/dev/null | head -1) fi if [[ -z "$headers" || ! -d "$headers" ]]; then @@ -89,7 +90,7 @@ configure_krf() { run_target() { echo "[INFO] Running '${TARGET_CMD}' through krfexec..." set +e - "$KRF_DIR/src/krfexec/krfexec" $TARGET_CMD + "$KRF_DIR/src/krfexec/krfexec" "$TARGET_CMD" echo "exit_code=$?" set -e }