admin 管理员组

文章数量: 1184232

syzkaller

syzkaller

Syzkaller具有丰富的官方文档,其中包括以下几个方面:

使用Syzkaller的介绍:这部分介绍了如何安装和配置Syzkaller,并提供了详细的操作手册。该文档还介绍了如何运行Syzkaller的示例和常用的测试命令。

Syzkaller测试策略:该文档介绍了Syzkaller使用的测试策略,包括随机测试策略、覆盖率优化策略、死锁检测策略等。该文档详细介绍了不同策略的原理和使用方法,并提供了配置样例。

Syzkaller规则系统:Syzkaller的规则系统是生成系统调用序列的重要部分。该文档介绍了规则系统的结构和机制,演示了如何编写自定义规则,以及如何将规则集成到测试过程中。

错误报告和调试:Syzkaller在测试过程中会抓取内核崩溃信息,并生成详细的错误报告。该文档介绍了如何解析错误报告和定位问题。此外,该文档还介绍了Syzkaller内置的调试和分析工具的使用方法。

Syzkaller开发:该文档介绍了Syzkaller源代码结构、API接口、扩展点和开发工具链。该文档还提供了一些常见扩展和案例,如如何增加系统调用支持、如何自定义fuzzer策略等。

所有官方文档均可在Syzkaller GitHub仓库的doc目录下找到,并提供了详细的使用说明。此外,Syzkaller的官方网站还提供了社区支持论坛、Bug报告页面、GitHub Issue等多种支持方式。

本身是个较强大的fuzz工具,使用方法较简单, syz-manager -config my.cfg

但难点是编辑特异性的语法魔板,用于特定模块和系统调用的fuzz。
公开git上已经包含了说明,但感觉比较晦涩,先按字面意思理一下

syscall_descriptions_syntax.md

  • 文本1
    syscall_descriptions_syntax.md
syscallname "(" [arg ["," arg]*] ")" [type] ["(" attribute* ")"]
arg = argname type
argname = identifier
type = typename [ "[" type-options "]" ]
typename = "const" | "intN" | "intptr" | "flags" | "array" | "ptr" |"string" | "strconst" | "filename" | "glob" | "len" |"bytesize" | "bytesizeN" | "bitsize" | "vma" | "proc"
type-options = [type-opt ["," type-opt]]

上来先定义了一套怪异的语法规则,和一般的程序不太一样,光看文字有点不明吧,对照binfmt.txt文本来大致猜测了下。

  • 文本2
    /sys/linux/binfmt.txt
include <uapi/linux/a.out.h>
include <uapi/linux/elf.h>execve(file ptr[in, filename], argv ptr[in, array[ptr[in, string]]], envp ptr[in, array[ptr[in, string]]])
execveat(dirfd fd_dir, file ptr[in, filename], argv ptr[in, array[ptr[in, string]]], envp ptr[in, array[ptr[in, string]]], flags flags[at_flags])write$binfmt_script(fd fd, data ptr[in, binfmt_script], len bytesize[data])
write$binfmt_misc(fd fd, data ptr[in, binfmt_misc], len bytesize[data])
write$binfmt_aout(fd fd, data ptr[in, binfmt_aout], len bytesize[data])
write$binfmt_elf32(fd fd, data ptr[in, binfmt_elf32], len bytesize[data])
write$binfmt_elf64(fd fd, data ptr[in, binfmt_elf64], len bytesize[data])

文本2用来描述fuzz系统调用的原则,file ptr[in, filename] 描述了参数名字文件,属于指针,输入类型,文件名类型

argv ptr[in, array[ptr[in, string]] 描述了指针类型的参数, 指针指向数组指针, 数组指针包含一些字符串。

len bytesize[data]描述 了data的长度。

其他参数类似。

总之参数定义完成后就是变异参数fuzz内核的过程,参数定义还可包含复杂的结构体,可以自行查看sys/linux目录下的各种文档。

syscallname 包含两种形式,一种直接调用,类似execve这种,另一种 write$binfmt_script 对特定数据的系统调用,估计给每个调用起了新的名字。

总之,核心就是给系统调用设置各种参数, argv ptr[in, array[ptr[in, string]]] ,这种。约束了参数后,对系统调用的fuzz就是有针对性的。

常见数据类型

对类型作一些解释,intN标识多少位的整型,还有一些根据名字可以猜到大概。说一些不太明白的。

  • “flags”: a set of values, type-options:
    reference to flags description (see below), underlying int type (e.g. “int32”)

定义的一系列选项,估计是宏定义啥的

  • “glob”: glob pattern to match on the target files, type-options:
    a pattern string in quotes (syntax: )
    (e.g. “/sys/” or “/sys/**/*”),
    类似正则匹配的东西应该

  • “proc”: per process int (see description below), type-options:
    value range start, how many values per process, underlying type
    这个其实有点疑问,但是例子中大部分用法都是这样:

open$proc(file ptr[in, string["/proc/test"]], flags flags[proc_open_flags], mode flags[proc_open_mode]) fd
read$proc(fd fd, buf buffer[out], count len[buf])
write$proc(fd fd, buf buffer[in], count len[buf])
close$proc(fd fd)

类似调用号,不过我感觉应该这两个proc好像代表的意思不太一样,
type signalno int32[0:65]
type net_port proc[20000, 4, int16be]

这里应该是正解,代表了一系列的以4为步长的整形变量。

foo(a const[10], b const[-10])
foo(a const[0xabcd])
foo(a int8['a':'z'])
foo(a const[PATH_MAX])
foo(a ptr[in, array[int8, MY_PATH_MAX]])
define MY_PATH_MAX	PATH_MAX + 2

还有这个,应该都是参数变异的依据。

  • “text”: machine code of the specified type, type-options:
    text type (x86_real, x86_16, x86_32, x86_64, arm64)

使用

编写完文本后就是生成对应的fuzz工具,

$ bin/syz-extract -os linux -arch amd64 -sourcedir /home/fanrong/Computer/kernel/linux-5.1 proc_operation.txt
$ bin/syz-sysgen
$ make clean
$ make all

最后启动fuzz

备注(一些例子收集)

cgroup_freezer_states = "THAWED", "FREEZING", "FROZEN"
openat$cgroup_freezer_state(fd fd_cgroup, file ptr[in, string["freezer.state"]], flags const[O_RDWR], mode const[0]) fd_cgroup_freezer_state
write$cgroup_freezer_state(fd fd_cgroup_freezer_state, buf ptr[in, string[cgroup_freezer_states]], len bytesize[buf])
# devices (.allow, .deny)
cgroup_devices_files = "devices.allow", "devices.deny"# device types: (a)ll, (c)har, (b)lock
cgroup_devices_type = "a", "c", "b"# access: (r)ead, (w)rite, (m)knod, or a combination of them
cgroup_devices_access = "r", "w", "m", "rw", "rm", "wm", "rwm"# TODO: device_major_minor is in form MAJOR:MINOR, where '*' is used for all.
#       It is non-trivial to describe valid MAJOR:MINOR as MAJOR takes values from
#       a wide range while not all such devices might exist in the system.
cgroup_devices_towrite {dev			stringnoz[cgroup_devices_type]device_major_minor	stringnoz[" *:* "]access			string[cgroup_devices_access]
} [packed]openat$cgroup_devices(fd fd_cgroup, file ptr[in, string[cgroup_devices_files]], flags const[O_RDWR], mode const[0]) fd_cgroup_devices
write$cgroup_devices(fd fd_cgroup_devices, buf ptr[in, cgroup_devices_towrite], len bytesize[buf])

本文标签: syzkaller