Preface and Reference
syzkaller 是当下最流行的内核白盒模糊测试工具,使用 Go 编写,目前据说已经发现上千个内核漏洞
如同此前的 AFL 一般,当前要做 kernel fuzzing 的 research 就绕不开强大的 syzkaller
先上参考
- syzkaller/docs at master
- 官方文档写得很不错,值得称赞
- syzkaller 环境搭建 | Kiprey's Blog
Install Go and Compile syzkaller
syzkaller 依赖于 go1.19 或以上的工具链,首先安装 Go
apt 里的 Go 版本太老(1.15),建议官网下载手动安装,也可以使用 snap 安装
sudo snap install go --classic
安装完运行go version
检查是否成功安装正确版本
然后拉取 syzkaller 并编译
git clone https://github.com/google/syzkaller.git
cd syzkaller
make all
编译出的二进制文件存放在/bin
目录下
Compile Linux kernel and Boot with QEMU
首先安装编译依赖
sudo apt install make gcc flex bison libncurses-dev libelf-dev libssl-dev
拉取 Linux 源码
git clone https://github.com/torvalds/linux.git
配置默认编译选项
cd linux
make defconfig
然后手动修改部分选项
遇到要修改的XXX is not set
建议直接在上面改,如果保留这行可能在后面更新配置文件时会出现非预期的结果
# Coverage collection.
CONFIG_KCOV=y
# Debug info for symbolization.
CONFIG_DEBUG_INFO_DWARF4=y
# Memory bug detector
CONFIG_KASAN=y
CONFIG_KASAN_INLINE=y
# Required for Debian Stretch and later
CONFIG_CONFIGFS_FS=y
CONFIG_SECURITYFS=y
此外如果后面遇到网络服务启动失败和 ssh 连接问题可以再加上网络相关配置
CONFIG_VIRTIO_NET=y
CONFIG_E1000=y
CONFIG_E1000E=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="net.ifnames=0"
更新编译选项并编译完整内核
make olddefconfig
make -j`nproc`
编译出的内核镜像 bzImage 在/arch/x86/boot
目录下
然后安装基本根文件系统构造工具 debootstrap
sudo apt install debootstrap
构建一个 Debian Bullseye Linux 镜像
mkdir $IMAGE
cd $IMAGE/
wget https://raw.githubusercontent.com/google/syzkaller/master/tools/create-image.sh -O create-image.sh
chmod +x create-image.sh
./create-image.sh
构建完目录下会多出几个文件,包括镜像文件、ssh 的 RSA 公钥私钥等
安装 QEMU
sudo apt install qemu-system-x86
然后用 QEMU 启动镜像看看是否正常
touch boot.sh
chmod +x boot.sh
boot.sh
内容如下,记得修改相关路径
qemu-system-x86_64 \
-m 2G \
-smp 2 \
-kernel /path/to/linux/arch/x86/boot/bzImage \
-append "console=ttyS0 root=/dev/sda earlyprintk=serial net.ifnames=0" \
-drive file=/path/to/linux/image/bullseye.img,format=raw \
-net user,host=10.0.2.10,hostfwd=tcp:127.0.0.1:10021-:22 \
-net nic,model=e1000 \
-enable-kvm \
-nographic \
-pidfile vm.pid \
2>&1 | tee vm.log
./boot.sh
如果正常出现syzkaller login
且可以无密码登录 root 证明这部分正常
忘记截图了,借用一下 Kiprey 师傅的图
然后测试下 sshd 是否正常
在另一个 terminal 窗口里尝试连接 QEMU 里的 kernel
ssh -i /path/to/bullseye.id_rsa -p 10021 -o "StrictHostKeyChecking no" root@localhost
确认无异常就poweroff
关闭 kernel
First taste of kernel fuzzing
随便建一个 workspace,然后创建配置文件mycfg.cfg
,内容如下,同样记得修改相关路径
{
"target": "linux/amd64",
"http": "127.0.0.1:56741",
"workdir": "/path/to/workspace",
"kernel_obj": "/path/to/linux",
"image": "/path/to/linux/image/stretch.img",
"sshkey": "/path/to/linux/image/stretch.id_rsa",
"syzkaller": "/path/to/syzkaller",
"procs": 8,
"type": "qemu",
"vm": {
"count": 4,
"kernel": "/path/to/linux/arch/x86/boot/bzImage",
"cpu": 2,
"mem": 2048
}
}
回到 syzkaller 项目目录下
syzkaller,启动!😠🤚📟
./bin/syz-manager -config=/path/to/mycfg.cfg
如果遇到神必错误failed to create instance: can't ssh into the instance
而且加调试参数-debug
启动发现有个网络服务飘红(忘具体名字了),可以回到前面编译 kernel 那里加上网络相关的配置重新编译,并在mycfg.cfg
添加"cmdline": "net.ifnames=0"
如下
{
"target": "linux/amd64",
"http": "127.0.0.1:56741",
"workdir": "/path/to/workspace",
"kernel_obj": "/path/to/linux",
"image": "/path/to/linux/image/stretch.img",
"sshkey": "/path/to/linux/image/stretch.id_rsa",
"syzkaller": "/path/to/syzkaller",
"procs": 8,
"type": "qemu",
"vm": {
"count": 4,
"kernel": "/path/to/linux/arch/x86/boot/bzImage",
"cmdline": "net.ifnames=0",
"cpu": 2,
"mem": 2048
}
}
最终效果如下,包括 shell 和 web 端(127.0.0.1:56741)
不知道为啥截图绿绿的,似乎是因为 Ubuntu 自带的截图对半透明窗口不太友好,将就着看吧
就这样裸跑了将近一天(中途神必电源管理把系统挂起了,也许时间更短),没想到还真跑出点东西来
一共跑出六个 crash,其中除了第一个其他似乎都不是 kernel bug
每个文件夹下大都包含这些文件
- description:crash 描述,也许是 KASAN,也有可能是一些其他的错误信息
- log:一些看不太懂的日志信息
- machineInfo:QEMU 机器信息
- report:crash 的详细信息,包含 backtrace、寄存器信息、物理页信息、各种 info 和 syzkaller 生成的 poc
来看看唯一有用的第一个 crash 的部分 report
==================================================================
BUG: KASAN: stack-out-of-bounds in profile_pc+0x124/0x130 arch/x86/kernel/time.c:42
Read of size 8 at addr ffff8880019dfde8 by task syz-executor.0/23512
CPU: 1 PID: 23512 Comm: syz-executor.0 Not tainted 6.5.0-rc1 #3
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
Call Trace:
<IRQ>
__dump_stack lib/dump_stack.c:88 [inline]
dump_stack_lvl+0x50/0x70 lib/dump_stack.c:106
print_address_description mm/kasan/report.c:364 [inline]
print_report+0xcc/0x620 mm/kasan/report.c:475
kasan_report+0xb0/0xe0 mm/kasan/report.c:588
profile_pc+0x124/0x130 arch/x86/kernel/time.c:42
profile_tick+0x93/0xd0 kernel/profile.c:339
tick_sched_timer+0xcc/0x100 kernel/time/tick-sched.c:1492
__run_hrtimer kernel/time/hrtimer.c:1688 [inline]
__hrtimer_run_queues+0x335/0x780 kernel/time/hrtimer.c:1752
hrtimer_interrupt+0x2cd/0x6e0 kernel/time/hrtimer.c:1814
local_apic_timer_interrupt arch/x86/kernel/apic/apic.c:1098 [inline]
__sysvec_apic_timer_interrupt+0xcc/0x2f0 arch/x86/kernel/apic/apic.c:1115
sysvec_apic_timer_interrupt+0x69/0x90 arch/x86/kernel/apic/apic.c:1109
</IRQ>
<TASK>
asm_sysvec_apic_timer_interrupt+0x1a/0x20 arch/x86/include/asm/idtentry.h:645
RIP: 0010:arch_atomic_try_cmpxchg arch/x86/include/asm/atomic.h:115 [inline]
RIP: 0010:raw_atomic_try_cmpxchg_acquire include/linux/atomic/atomic-arch-fallback.h:2155 [inline]
RIP: 0010:atomic_try_cmpxchg_acquire include/linux/atomic/atomic-instrumented.h:1296 [inline]
RIP: 0010:queued_spin_lock include/asm-generic/qspinlock.h:111 [inline]
RIP: 0010:do_raw_spin_lock include/linux/spinlock.h:187 [inline]
RIP: 0010:__raw_spin_lock include/linux/spinlock_api_smp.h:134 [inline]
RIP: 0010:_raw_spin_lock+0x8e/0xe0 kernel/locking/spinlock.c:154
Code: c7 44 24 20 00 00 00 00 e8 ef f1 98 fd be 04 00 00 00 48 8d 7c 24 20 e8 e0 f1 98 fd ba 01 00 00 00 8b 44 24 20 f0 0f b1 55 00 <75> 2d 48 b8 00 00 00 00 00 fc ff df 48 c7 04 03 00 00 00 00 48 8b
RSP: 0018:ffff8880019dfde8 EFLAGS: 00000246
RAX: 0000000000000000 RBX: 1ffff1100033bfbd RCX: ffffffff8b13d980
RDX: 0000000000000001 RSI: 0000000000000004 RDI: ffff8880019dfe08
RBP: ffff88800ed1c248 R08: 0000000000000001 R09: ffffed100033bfc1
R10: 0000000000000003 R11: 0000000000030001 R12: 0000000000000041
R13: ffffffff8c089660 R14: ffff88800ed1c1c2 R15: ffff88800ed1c248
spin_lock include/linux/spinlock.h:351 [inline]
do_inode_permission fs/namei.c:464 [inline]
inode_permission fs/namei.c:528 [inline]
inode_permission+0x455/0x510 fs/namei.c:503
path_permission include/linux/fs.h:2526 [inline]
__do_sys_chdir fs/open.c:555 [inline]
__se_sys_chdir fs/open.c:545 [inline]
__x64_sys_chdir+0x10b/0x230 fs/open.c:545
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x3c/0x90 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x6e/0xd8
RIP: 0033:0x7f66807c1c5b
Code: 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa b8 50 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007ffc610ef618 EFLAGS: 00000246 ORIG_RAX: 0000000000000050
RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f66807c1c5b
RDX: 00005555569c9740 RSI: 0000000000000000 RDI: 00007ffc610ef6b0
RBP: 0000000000000000 R08: 0000000000000000 R09: 00005555569c9480
R10: 00005555569c9750 R11: 0000000000000246 R12: 0000000000000001
R13: 0000000000000000 R14: 0000000000000001 R15: 0000000000000000
</TASK>
The buggy address belongs to stack of task syz-executor.0/23512
and is located at offset 0 in frame:
_raw_spin_lock+0x0/0xe0 include/asm-generic/qrwlock.h:87
This frame has 1 object:
[32, 36) 'val'
The buggy address belongs to the physical page:
page:000000002b42e617 refcount:0 mapcount:0 mapping:0000000000000000 index:0x2 pfn:0x19df
flags: 0x100000000000000(node=0|zone=1)
page_type: 0xffffffff()
raw: 0100000000000000 0000000000000000 ffffffff00060101 0000000000000000
raw: 0000000000000002 0000000000000000 00000000ffffffff 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff8880019dfc80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ffff8880019dfd00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>ffff8880019dfd80: 00 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1
^
ffff8880019dfe00: f1 04 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00
ffff8880019dfe80: 00 00 00 00 00 f1 f1 f1 f1 00 00 f3 f3 00 00 00
==================================================================
···
----------------
Code disassembly (best guess):
0: c7 44 24 20 00 00 00 movl $0x0,0x20(%rsp)
7: 00
8: e8 ef f1 98 fd call 0xfd98f1fc
d: be 04 00 00 00 mov $0x4,%esi
12: 48 8d 7c 24 20 lea 0x20(%rsp),%rdi
17: e8 e0 f1 98 fd call 0xfd98f1fc
1c: ba 01 00 00 00 mov $0x1,%edx
21: 8b 44 24 20 mov 0x20(%rsp),%eax
25: f0 0f b1 55 00 lock cmpxchg %edx,0x0(%rbp)
* 2a: 75 2d jne 0x59 <-- trapping instruction
2c: 48 b8 00 00 00 00 00 movabs $0xdffffc0000000000,%rax
33: fc ff df
36: 48 c7 04 03 00 00 00 movq $0x0,(%rbx,%rax,1)
3d: 00
3e: 48 rex.W
3f: 8b .byte 0x8b
可以看到最后 syzkaller 还会根据 crash 拟合出一个 poc
实际上,每当 syzkaller 跑出一个 crash 都会将手上的所有机器停下来专注去分析复现这个 crash
搜了一下发现这个 bug 上年已经被人 report 过了,也是 syzkaller 跑出来的,不过人家还有似乎是 syzkaller 生成的 C reproduce
Fuzzing kernel driver
这里将一个简单的带 kernel heap overflow 的 driver 编译进 kernel 看看能不能 fuzz 出来
因为一时半会还不懂 kernel programming,这里全部参考了 Kiprey 师傅的文章,如果有没写到的细节可以去看看
首先是我们的 test drivertest.c
,位置在/linux/drivers/char
#include <linux/init.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#define MY_DEV_NAME "test"
#define DEBUG_FLAG "PROC_DEV"
static ssize_t proc_read (struct file *proc_file, char __user *proc_user, size_t n, loff_t *loff);
static ssize_t proc_write (struct file *proc_file, const char __user *proc_user, size_t n, loff_t *loff);
static int proc_open (struct inode *proc_inode, struct file *proc_file);
static struct proc_ops a = {
.proc_open = proc_open,
.proc_read = proc_read,
.proc_write = proc_write,
};
static int __init mod_init(void)
{
struct proc_dir_entry *test_entry;
const struct proc_ops *proc_fops = &a;
printk(DEBUG_FLAG":proc init start!\n");
test_entry = proc_create(MY_DEV_NAME, S_IRUGO|S_IWUGO, NULL, proc_fops);
if(!test_entry)
printk(DEBUG_FLAG":there is somethings wrong!\n");
printk(DEBUG_FLAG":proc init over!\n");
return 0;
}
static ssize_t proc_read (struct file *proc_file, char __user *proc_user, size_t n, loff_t *loff)
{
printk(DEBUG_FLAG":finish copy_from_use,the string of newbuf is");
return 0;
}
static ssize_t proc_write (struct file *proc_file, const char __user *proc_user, size_t n, loff_t *loff)
{
char *c = kmalloc(n + 512, GFP_KERNEL);
size_t size = copy_from_user(c, proc_user, n + 4096);
printk(DEBUG_FLAG":into write %ld!\n", size);
return 0;
}
int proc_open (struct inode *proc_inode, struct file *proc_file)
{
printk(DEBUG_FLAG":into open!\n");
return 0;
}
module_init(mod_init);
然后在这个目录下的 Makefile 里加上并回到 kernel 根目录重新 make
obj-y += test.o
QEMU 启动一下可以看到/proc
目录下已经装载了 test
确认完记得 poweroff
在syzkaller/sys/linux
创建一个对应于这个漏洞驱动的处理规则 test.txt
include <linux/fs.h>
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_open_flags = O_RDONLY, O_WRONLY, O_RDWR, O_APPEND, FASYNC, O_CLOEXEC, O_CREAT, O_DIRECT, O_DIRECTORY, O_EXCL, O_LARGEFILE, O_NOATIME, O_NOCTTY, O_NOFOLLOW, O_NONBLOCK, O_PATH, O_SYNC, O_TRUNC, __O_TMPFILE
proc_open_mode = S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP, S_IROTH, S_IWOTH, S_IXOTH
在 syzkaller 项目根目录下执行以下命令以创建对应的 .const 文件
bin/syz-extract -os linux -sourcedir "/path/to/linux" -arch amd64 test.txt
然后重新构建 syzkaller
./bin/syz-sysgen
make all
- 关于编写处理规则、.const 文件和重新构建 syzkaller 这几步我其实不太明白为什么要这么做,之后了解下整个工作流程和读读源码看看是否能解惑
最后修改一下 mycfg.cfg,加上系统调用规则
"enable_syscalls": [
"open$proc",
"read$proc",
"write$proc",
"close$proc"
],
syzkaller,启动!😠🤚📟
./bin/syz-manager -config my.cfg -vv 10
很快就能把这洞跑出来,不过 reproduce 要等一段时间
这次能生成一个 C reproduce
这次生成了很多中间 report 文件
先来看看 description
slab 是 Linux kernel 的堆管理器
KASAN: slab-out-of-bounds Write in proc_write
生成的 C reproduce 如下
Syzkaller hit 'KASAN: slab-out-of-bounds Write in proc_write' bug.
audit: type=1400 audit(1689065732.902:6): avc: denied { execmem } for pid=218 comm="syz-executor552" scontext=system_u:system_r:kernel_t:s0 tcontext=system_u:system_r:kernel_t:s0 tclass=process permissive=1
PROC_DEV:into open!
==================================================================
BUG: KASAN: slab-out-of-bounds in instrument_copy_from_user_before include/linux/instrumented.h:129 [inline]
BUG: KASAN: slab-out-of-bounds in _copy_from_user+0x47/0xc0 lib/usercopy.c:22
Write of size 4096 at addr ffff888004414800 by task syz-executor552/218
CPU: 1 PID: 218 Comm: syz-executor552 Not tainted 6.5.0-rc1-dirty #4
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:88 [inline]
dump_stack_lvl+0x50/0x70 lib/dump_stack.c:106
print_address_description mm/kasan/report.c:364 [inline]
print_report+0xcc/0x620 mm/kasan/report.c:475
kasan_report+0xb0/0xe0 mm/kasan/report.c:588
check_region_inline mm/kasan/generic.c:181 [inline]
kasan_check_range+0x39/0x1c0 mm/kasan/generic.c:187
instrument_copy_from_user_before include/linux/instrumented.h:129 [inline]
_copy_from_user+0x47/0xc0 lib/usercopy.c:22
copy_from_user include/linux/uaccess.h:183 [inline]
proc_write+0x4b/0x80 drivers/char/test.c:45
pde_write fs/proc/inode.c:340 [inline]
proc_reg_write+0x1f4/0x2c0 fs/proc/inode.c:352
vfs_write+0x25f/0xb60 fs/read_write.c:582
ksys_write+0x104/0x210 fs/read_write.c:637
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x3c/0x90 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x6e/0xd8
RIP: 0033:0x7f849901cf8d
Code: 28 c3 e8 46 1e 00 00 66 0f 1f 44 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007ffe718b2e28 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 00007ffe718b3028 RCX: 00007f849901cf8d
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000003
RBP: 0000000000000001 R08: 0000000000000000 R09: 00007ffe718b3028
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000001
R13: 00007ffe718b3018 R14: 00007f849909a530 R15: 0000000000000001
</TASK>
Allocated by task 218:
kasan_save_stack+0x22/0x50 mm/kasan/common.c:45
kasan_set_track+0x25/0x30 mm/kasan/common.c:52
____kasan_kmalloc mm/kasan/common.c:374 [inline]
__kasan_kmalloc+0x7f/0x90 mm/kasan/common.c:383
kasan_kmalloc include/linux/kasan.h:196 [inline]
__do_kmalloc_node mm/slab_common.c:985 [inline]
__kmalloc+0x5a/0x140 mm/slab_common.c:998
kmalloc include/linux/slab.h:586 [inline]
proc_write+0x2c/0x80 drivers/char/test.c:43
pde_write fs/proc/inode.c:340 [inline]
proc_reg_write+0x1f4/0x2c0 fs/proc/inode.c:352
vfs_write+0x25f/0xb60 fs/read_write.c:582
ksys_write+0x104/0x210 fs/read_write.c:637
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x3c/0x90 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x6e/0xd8
Last potentially related work creation:
kasan_save_stack+0x22/0x50 mm/kasan/common.c:45
__kasan_record_aux_stack+0x94/0xa0 mm/kasan/generic.c:492
insert_work+0x46/0x300 kernel/workqueue.c:1553
__queue_work+0x57c/0xdd0 kernel/workqueue.c:1714
queue_work_on+0x6c/0x80 kernel/workqueue.c:1744
ops_exit_list+0xad/0x160 net/core/net_namespace.c:170
cleanup_net+0x41d/0x8e0 net/core/net_namespace.c:614
process_one_work+0x872/0x1290 kernel/workqueue.c:2597
worker_thread+0x5a0/0x1170 kernel/workqueue.c:2748
kthread+0x2c7/0x3c0 kernel/kthread.c:389
ret_from_fork+0x29/0x50 arch/x86/entry/entry_64.S:308
The buggy address belongs to the object at ffff888004414800
which belongs to the cache kmalloc-512 of size 512
The buggy address is located 0 bytes inside of
allocated 512-byte region [ffff888004414800, ffff888004414a00)
The buggy address belongs to the physical page:
page:000000005ae7563e refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x4414
head:000000005ae7563e order:2 entire_mapcount:0 nr_pages_mapped:0 pincount:0
flags: 0x100000000010200(slab|head|node=0|zone=1)
page_type: 0xffffffff()
raw: 0100000000010200 ffff888001041c80 dead000000000100 dead000000000122
raw: 0000000000000000 0000000080100010 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff888004414900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ffff888004414980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>ffff888004414a00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
^
ffff888004414a80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff888004414b00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
==================================================================
PROC_DEV:into write 4096!
Syzkaller reproducer:
# {Threaded:false Repeat:false RepeatTimes:0 Procs:1 Slowdown:1 Sandbox: SandboxArg:0 Leak:false NetInjection:false NetDevices:false NetReset:false Cgroups:false BinfmtMisc:false CloseFDs:false KCSAN:false DevlinkPCI:false NicVF:false USB:false VhciInjection:false Wifi:false IEEE802154:false Sysctl:false Swap:false UseTmpDir:false HandleSegv:false Repro:false Trace:false LegacyOptions:{Collide:false Fault:false FaultCall:0 FaultNth:0}}
r0 = open$proc(&(0x7f0000000200), 0x2, 0x0)
write$proc(r0, 0x0, 0x0)
C reproducer:
// autogenerated by syzkaller (https://github.com/google/syzkaller)
#define _GNU_SOURCE
#include <endian.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
uint64_t r[1] = {0xffffffffffffffff};
int main(void)
{
syscall(__NR_mmap, /*addr=*/0x1ffff000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=*/0x32ul, /*fd=*/-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x20000000ul, /*len=*/0x1000000ul, /*prot=*/7ul, /*flags=*/0x32ul, /*fd=*/-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x21000000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=*/0x32ul, /*fd=*/-1, /*offset=*/0ul);
intptr_t res = 0;
memcpy((void*)0x20000200, "/proc/testSyzkaller hit 'KASAN: slab-out-of-bounds Write in proc_write' bug.
audit: type=1400 audit(1689065732.902:6): avc: denied { execmem } for pid=218 comm="syz-executor552" scontext=system_u:system_r:kernel_t:s0 tcontext=system_u:system_r:kernel_t:s0 tclass=process permissive=1
PROC_DEV:into open!
==================================================================
BUG: KASAN: slab-out-of-bounds in instrument_copy_from_user_before include/linux/instrumented.h:129 [inline]
BUG: KASAN: slab-out-of-bounds in _copy_from_user+0x47/0xc0 lib/usercopy.c:22
Write of size 4096 at addr ffff888004414800 by task syz-executor552/218
CPU: 1 PID: 218 Comm: syz-executor552 Not tainted 6.5.0-rc1-dirty #4
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:88 [inline]
dump_stack_lvl+0x50/0x70 lib/dump_stack.c:106
print_address_description mm/kasan/report.c:364 [inline]
print_report+0xcc/0x620 mm/kasan/report.c:475
kasan_report+0xb0/0xe0 mm/kasan/report.c:588
check_region_inline mm/kasan/generic.c:181 [inline]
kasan_check_range+0x39/0x1c0 mm/kasan/generic.c:187
instrument_copy_from_user_before include/linux/instrumented.h:129 [inline]
_copy_from_user+0x47/0xc0 lib/usercopy.c:22
copy_from_user include/linux/uaccess.h:183 [inline]
proc_write+0x4b/0x80 drivers/char/test.c:45
pde_write fs/proc/inode.c:340 [inline]
proc_reg_write+0x1f4/0x2c0 fs/proc/inode.c:352
vfs_write+0x25f/0xb60 fs/read_write.c:582
ksys_write+0x104/0x210 fs/read_write.c:637
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x3c/0x90 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x6e/0xd8
RIP: 0033:0x7f849901cf8d
Code: 28 c3 e8 46 1e 00 00 66 0f 1f 44 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007ffe718b2e28 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 00007ffe718b3028 RCX: 00007f849901cf8d
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000003
RBP: 0000000000000001 R08: 0000000000000000 R09: 00007ffe718b3028
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000001
R13: 00007ffe718b3018 R14: 00007f849909a530 R15: 0000000000000001
</TASK>
Allocated by task 218:
kasan_save_stack+0x22/0x50 mm/kasan/common.c:45
kasan_set_track+0x25/0x30 mm/kasan/common.c:52
____kasan_kmalloc mm/kasan/common.c:374 [inline]
__kasan_kmalloc+0x7f/0x90 mm/kasan/common.c:383
kasan_kmalloc include/linux/kasan.h:196 [inline]
__do_kmalloc_node mm/slab_common.c:985 [inline]
__kmalloc+0x5a/0x140 mm/slab_common.c:998
kmalloc include/linux/slab.h:586 [inline]
proc_write+0x2c/0x80 drivers/char/test.c:43
pde_write fs/proc/inode.c:340 [inline]
proc_reg_write+0x1f4/0x2c0 fs/proc/inode.c:352
vfs_write+0x25f/0xb60 fs/read_write.c:582
ksys_write+0x104/0x210 fs/read_write.c:637
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x3c/0x90 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x6e/0xd8
Last potentially related work creation:
kasan_save_stack+0x22/0x50 mm/kasan/common.c:45
__kasan_record_aux_stack+0x94/0xa0 mm/kasan/generic.c:492
insert_work+0x46/0x300 kernel/workqueue.c:1553
__queue_work+0x57c/0xdd0 kernel/workqueue.c:1714
queue_work_on+0x6c/0x80 kernel/workqueue.c:1744
ops_exit_list+0xad/0x160 net/core/net_namespace.c:170
cleanup_net+0x41d/0x8e0 net/core/net_namespace.c:614
process_one_work+0x872/0x1290 kernel/workqueue.c:2597
worker_thread+0x5a0/0x1170 kernel/workqueue.c:2748
kthread+0x2c7/0x3c0 kernel/kthread.c:389
ret_from_fork+0x29/0x50 arch/x86/entry/entry_64.S:308
The buggy address belongs to the object at ffff888004414800
which belongs to the cache kmalloc-512 of size 512
The buggy address is located 0 bytes inside of
allocated 512-byte region [ffff888004414800, ffff888004414a00)
The buggy address belongs to the physical page:
page:000000005ae7563e refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x4414
head:000000005ae7563e order:2 entire_mapcount:0 nr_pages_mapped:0 pincount:0
flags: 0x100000000010200(slab|head|node=0|zone=1)
page_type: 0xffffffff()
raw: 0100000000010200 ffff888001041c80 dead000000000100 dead000000000122
raw: 0000000000000000 0000000080100010 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff888004414900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ffff888004414980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>ffff888004414a00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
^
ffff888004414a80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff888004414b00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
==================================================================
PROC_DEV:into write 4096!
Syzkaller reproducer:
# {Threaded:false Repeat:false RepeatTimes:0 Procs:1 Slowdown:1 Sandbox: SandboxArg:0 Leak:false NetInjection:false NetDevices:false NetReset:false Cgroups:false BinfmtMisc:false CloseFDs:false KCSAN:false DevlinkPCI:false NicVF:false USB:false VhciInjection:false Wifi:false IEEE802154:false Sysctl:false Swap:false UseTmpDir:false HandleSegv:false Repro:false Trace:false LegacyOptions:{Collide:false Fault:false FaultCall:0 FaultNth:0}}
r0 = open$proc(&(0x7f0000000200), 0x2, 0x0)
write$proc(r0, 0x0, 0x0)
C reproducer:
// autogenerated by syzkaller (https://github.com/google/syzkaller)
#define _GNU_SOURCE
#include <endian.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
uint64_t r[1] = {0xffffffffffffffff};
int main(void)
{
syscall(__NR_mmap, /*addr=*/0x1ffff000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=*/0x32ul, /*fd=*/-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x20000000ul, /*len=*/0x1000000ul, /*prot=*/7ul, /*flags=*/0x32ul, /*fd=*/-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x21000000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=*/0x32ul, /*fd=*/-1, /*offset=*/0ul);
intptr_t res = 0;
memcpy((void*)0x20000200, "/proc/test\000", 11);
res = syscall(__NR_open, /*file=*/0x20000200ul, /*flags=*/2ul, /*mode=*/0ul);
if (res != -1)
r[0] = res;
syscall(__NR_write, /*fd=*/r[0], /*buf=*/0ul, /*count=*/0ul);
return 0;
}
0", 11);
res = syscall(__NR_open, /*file=*/0x20000200ul, /*flags=*/2ul, /*mode=*/0ul);
if (res != -1)
r[0] = res;
syscall(__NR_write, /*fd=*/r[0], /*buf=*/0ul, /*count=*/0ul);
return 0;
}
Comments NOTHING