Skip to content
Radon10043Public

About

SyzPilot is a state-guided agentic syscall specification synthesizer

Resources

Stars

10 stars

Watchers

0 watching

Forks

Repository files navigation

SyzPilot

SyzPilot is a state-guided agentic syscall specification synthesizer, designed for syzlang.

This document explains how to use SyzPilot to synthesize syscall specifications and run fuzzing for the Linux kernel. SyzPilot also supports FreeBSD, OpenBSD, NetBSD, and Android. The synthesized specs can also be used to fuzz gVisor and Starnix.

Note

The documentation is still being improved, and some content may contain typos. We are doing our best to review and fix them :)

Please replace the following variables according to your environment:

  • $SYZPILOT: directory for saving the SyzPilot source code.
  • $KERNSRC: directory for saving the kernel source code.
  • $IMAGE: directory for saving the vm image used for fuzzing.

Build the Docker image

We recommend running SyzPilot with Docker. You can build the Docker image with the following commands:

wget -O Dockerfile https://raw.githubusercontent.com/Radon10043/SyzPilot/main/docker/Dockerfile
docker build -t syzpilot:latest --network host -f ./Dockerfile .

Start a container and enter it:

docker run \
    -d \
    -v ./vol:/vol \
    --cpus 20 \
    --network host \
    --privileged \
    --name syzpilot-test \
    syzpilot:latest tail -f /dev/null
docker exec -it syzpilot-test bash

We recommend downloading fuzzers, kernels, images, and other artifacts to the mounted /vol directory for persistent storage :)

Build and run SyzPilot

This section explains how to set up and use SyzPilot for syscall spec synthesis. All commands below are executed inside the container.

If you do not want to re-synthesize specs, you can reuse our synthesized specs, which are also used in our evaluation.

Download SyzPilot

Download SyzPilot together with its syzkaller submodule:

export SYZPILOT=/vol/SyzPilot
git clone --recurse-submodules https://github.com/Radon10043/SyzPilot $SYZPILOT
# if you forgot to clone with --recurse-submodules, run `git submodule update --init --recursive` under $SYZPILOT

Patch syzkaller to support additional constant extraction. SyzPilot validates synthesized specs with the syz-extract built from this syzkaller checkout, so apply the patches before building SyzPilot:

cd $SYZPILOT/syzkaller
git apply -3 ../patch/syzkaller/*
git reset .

Build SyzPilot

SyzPilot can be built with the following commands:

cd $SYZPILOT
make

Analyze kernel

SyzPilot needs to analyze the kernel and construct the corresponding knowledge base. Here, we use Linux v6.18 as an example:

export KERNSRC=/vol/linux/v6.18
git clone --depth 1 -b v6.18 https://github.com/torvalds/linux $KERNSRC
cp $SYZPILOT/configs/kernel/linux.config $KERNSRC/.config
cd $KERNSRC
make CC="ccache clang" olddefconfig modules_prepare all -j16
python3 scripts/clang-tools/gen_compile_commands.py

Analyze the kernel compile commands and construct the knowledge base:

cd $SYZPILOT
./bin/analyzer -i $KERNSRC/compile_commands.json -o data/database/linux.db -j 16 > logs/analyze.log 2>&1

Flags of analyzer:

  • -i: path to compile_commands.json
  • -o: path to the output database (default: ./data/kernel.db)
  • -j: number of parallel jobs (default: 1)

Synthesize specs in an agentic manner

Setup the .env file:

cd $SYZPILOT
echo "OPENAI_BASE_URL=[YOUR_BASE_URL]" > .env
echo "OPENAI_API_KEY=[YOUR_API_KEY]" >> .env

Prepare a reference file for spec synthesis. Here, we use dvb_frontend_fops from the Linux DVB subsystem as an example:

cd $SYZPILOT
mkdir .workdir
echo "variable,dvb_frontend_fops" > .workdir/ref.txt

Manually enumerating all syscall related elements is tedious. You can use SyzPilot's minitask tool to automatically filter related elements and list the syscalls whose specs need to be synthesized.

Synthesize syscall specs:

cd $SYZPILOT
./bin/generator \
    -db=./data/database/linux.db \
    -outdir=./.workdir \
    -kernel=$KERNSRC \
    -os=linux \
    -model=gemini-3-flash-preview \
    -ref=./.workdir/ref.txt \
    -jobs=4 > logs/generate.log 2>&1

The synthesized specs are saved under ./.workdir/specs.

Caution

Watch the costs during synthesis!

Flags of generator:

  • required:
    • -model: model to query, e.g. gemini-3-flash-preview
    • -db: path to the kernel knowledge database produced in the Analyze kernel section
    • -outdir: output path for specs synthesized by SyzPilot
    • -kernel: path to the kernel used for spec validation
    • -os: target OS type. Currently supported values are linux, freebsd, openbsd, netbsd, and android.
    • -ref: path to the file containing reference global variables or functions for spec synthesis.
  • optional:
    • -env: path to the .env file (default: $PWD/.env)
    • -extract-bin: path to syz-extract (default: $PWD/bin/syz-extract)
    • -check-bin: path to syz-check (default: $PWD/bin/syz-check)
    • -sysdir: path to a directory such as syzkaller/sys. SyzPilot reuses specs under -sysdir to avoid duplicate synthesis of common flags, syscalls, and similar elements. (default: $PWD/syzkaller/sys)
    • -resume: whether to resume previous progress (default: true)
    • -max-fix: maximum number of attempts to fix a generated spec (default: 5)
    • -max-retry: maximum number of outline-generate-fix attempts. -1 means unlimited retries. (default: 5)
    • -jobs: number of parallel jobs (default: 1)
    • -otl-system-prompt: path to outline prompt file(s). Use commas to separate multiple files. (default: $PWD/data/prompts/outline/instruction.md,$PWD/data/prompts/outline/example_media.md,$PWD/data/prompts/outline/example_ppp.md)
    • -gen-system-prompt: path to generation prompt file(s). Use commas to separate multiple files. (default: $PWD/data/prompts/generate/instruction.md,$PWD/data/prompts/generate/example_media.md,$PWD/data/prompts/generate/example_ppp.md)
    • -fix-system-prompt: path to fix prompt file(s). Use commas to separate multiple files. (default: $PWD/data/prompts/fix/instruction.md,$PWD/data/prompts/fix/example_v4l2.md)

Refactor synthesized specs

Refactor synthesized specs by adding a unique suffix to each element to avoid conflicts:

cd $SYZPILOT
./bin/refactor -indir=./.workdir/specs -outdir=./.workdir/refactored

(Optional) Add meta arches["amd64"] to limit the scope of the specs:

sed -i '1i meta arches["amd64"]' .workdir/refactored/*.txt

TODO: Currently, the variable or function name is added as a suffix to each spec element, e.g. ioctl$ABC -> ioctl$ABC_dvb_frontend_fops. However, this refactoring can be inconvenient for subsystem fuzzing since we have to list the full names of all synthesized syscalls to distinguish them from syzkaller's existing syscalls. We are considering a more suitable refactoring method.

Integrate synthesized specs into syzkaller

Note

During integration, some errors in the synthesized specs may need to be fixed manually. This typically involves adjusting the order of include files and removing unused elements. SyzPilot provides several utility tools to help fix these errors.

Integrate the specs with syzkaller, extract constants, and build syzkaller:

cd $SYZPILOT/syzkaller
cp ../.workdir/refactored/* sys/linux
make bin/syz-extract
ls sys/linux/gen#*.txt | xargs -n 1 basename | xargs ./bin/syz-extract -build -sourcedir=$KERNSRC -os=linux -arch=amd64
make generate
make all -j16

Fuzzing with synthesized specs

Create a Debian Bullseye image for fuzzing:

export IMAGE=/vol/images/Debian
mkdir -p $IMAGE && cd $IMAGE
cp $SYZPILOT/scripts/linux/create-image.sh .
chmod +x ./create-image.sh
./create-image.sh

Start fuzzing with the synthesized specifications:

cd $SYZPILOT
cat <<__EOF__ > .workdir/fuzz.cfg
{
	"target": "linux/amd64",
	"http": "127.0.0.1:56741",
	".workdir": "$SYZPILOT/.workdir",
	"kernel_obj": "$KERNSRC",
	"image": "$IMAGE/bullseye.img",
	"sshkey": "$IMAGE/bullseye.id_rsa",
	"syzkaller": "$SYZPILOT/syzkaller",
	"procs": 8,
	"type": "qemu",
	"reproduce": false,
	"vm": {
		"count": 4,
		"kernel": "$KERNSRC/arch/x86/boot/bzImage",
		"cpu": 8,
		"mem": 2048
	}
}
__EOF__

./syzkaller/bin/syz-manager -config=./.workdir/fuzz.cfg

Utility tools

minitask

minitask selects global variables associated with syscalls by using string matching, then lists all syscalls that require specifications. It helps avoid the tedious process of manually enumerating syscall related elements and prevents duplicate spec synthesis for the same syscall. You can directly run generator based on the output of minitask for optimal efficiency.

Build:

make minitask   # it will also be built via `make all`

Set up the .env file if you have not already done so:

echo "OPENAI_BASE_URL=[YOUR_BASE_URL]" > .env
echo "OPENAI_API_KEY=[YOUR_API_KEY]" >> .env

Run minitask to select all syscall related elements and enumerate all unique syscalls that require spec synthesis:

cd $SYZPILOT
./bin/minitask \
    -db=./data/database/linux.db \
    -os=linux \
    -outdir=./.workdir/minitask \
    -model=gemini-3-flash-preview > logs/minitask.log 2>&1

Extract references:

./scripts/reflist.sh ./.workdir/minitask > ./.workdir/minitask/ref.txt

Then run generator with -outdir=./.workdir/minitask -ref=./.workdir/minitask/ref.txt to reuse the results of minitask.

rmunused

Remove unused elements in place:

$SYZPILOT/bin/rmunused -indir=$SYZPILOT/syzkaller/sys/linux

Reuse synthesized specs

Specifications used in our evaluation are saved under $SYZPILOT/patch/specs-*. Feel free to reuse them to avoid duplicate synthesis. Remember to apply the syzkaller patches first (see Download SyzPilot); they also enable syzkaller to fuzz the OpenBSD kernel on Linux.

specs-kern stores specs for full kernel fuzzing:

cd $SYZPILOT/syzkaller
git apply ../patch/specs-kern/*

specs-subsys stores specs for subsystem fuzzing. We re-synthesize specs for subsystems that already have specs:

cd $SYZPILOT/syzkaller
git apply ../patch/specs-subsys/*

specs-ablation stores specs synthesized by the variants used in our ablation study.

Reproduce evaluation

Please follow setup-env.md to set up the evaluation environment. You can then reproduce our evaluation using the Docker Compose files.

Re-synthesize subsystem specs

Please see subsystem.md for instructions on re-synthesizing specs for a subsystem that already has specs.

Trophies

Note

We will update the trophies as soon as new specs synthesized by SyzPilot are merged into the syzkaller repository or related issues are assigned CVEs.

Merged specifications

Linux bugs

Bugs related to our generated specifications and reported by syzbot:

FreeBSD bugs

Test cases generated by SyzPilot have been incorporated into FreeBSD's test suite:

OpenBSD bugs

NetBSD bugs

Citation

If you find SyzPilot helpful, please cite it. Thanks.

@inproceedings{Zhang2027SyzPilot,
  title     = {{SyzPilot}: State-Guided Agentic Syscall Specification Synthesis for Enhancing Kernel Fuzzing},
  author    = {Zhang, Jiaming and Sun, Chang-ai and Liu, Huai and Cui, Zhanqi},
  booktitle = {Proceedings of the Network and Distributed System Security Symposium},
  year      = {2027},
  note      = {{Just Accepted}}
}

Links

Intermediate data, including LLM query records and fuzzing results (~30 GB): Google Drive.

Acknowledgement

Thanks Shifan Liu (USTB), Huiwen Yang (NUAA), and Xiaoyang Han (NJU) for their support and suggestions throughout the work.

About

SyzPilot is a state-guided agentic syscall specification synthesizer

Resources

Stars

10 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages