Preface and Reference

syzkaller 是当下最流行的内核白盒模糊测试工具,使用 Go 编写,目前据说已经发现上千个内核漏洞
如同此前的 AFL 一般,当前要做 kernel fuzzing 的 research 就绕不开强大的 syzkaller

先上参考

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/test
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/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; }