Messages in this thread | ![/](/images/icornerl.gif) | | From | Sam Sun <> | Date | Tue, 9 Apr 2024 22:02:49 +0800 | Subject | [Linux kernel bug] WARNING in ax25_dev_device_down |
| |
Dear developers and maintainers,
We encountered a kernel warning in function ax25_dev_device_down during testing using our modified syzkaller. It is tested against the latest upstream linux (6.9-rc3). C repro and kernel config are attached to this email. Kernel log is listed below. ``` WARNING: CPU: 0 PID: 8121 at lib/ref_tracker.c:255 ref_tracker_free+0x610/0x830 lib/ref_tracker.c:255 Modules linked in: CPU: 0 PID: 8121 Comm: syz-executor329 Not tainted 6.7.0-rc7 #2 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 RIP: 0010:ref_tracker_free+0x610/0x830 lib/ref_tracker.c:255 Code: 00 00 44 8b 73 18 31 ff 44 89 f6 e8 7a 58 fe fc 45 85 f6 0f 85 a7 00 00 00 e8 4c 5c fe fc 4c 89 ee 48 89 ef e8 11 0a e5 05 90 <0f> 0b 90 41 bd ea ff ff ff e9 51 fd ff ff e8 2d 5c fe fc 4c 8d 75 RSP: 0018:ffffc900029bf8b8 EFLAGS: 00010286 RAX: 0000000080000000 RBX: ffff888106185480 RCX: 0000000000000000 RDX: 0000000000000001 RSI: 0000000000000001 RDI: 0000000000000001 RBP: ffff8881136c85b8 R08: 0000000000000001 R09: fffffbfff23e8bd1 R10: 0000000000000001 R11: 0000000000000001 R12: 1ffff92000537f19 R13: 0000000000000292 R14: 00000000067a01d1 R15: ffff888106185498 FS: 0000555556e663c0(0000) GS:ffff888063a00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fc148041ba8 CR3: 0000000016374000 CR4: 0000000000750ef0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 PKRU: 55555554 Call Trace: <TASK> netdev_tracker_free include/linux/netdevice.h:4127 [inline] netdev_put include/linux/netdevice.h:4144 [inline] netdev_put include/linux/netdevice.h:4140 [inline] ax25_dev_device_down+0x2bc/0x420 net/ax25/ax25_dev.c:140 ax25_device_event+0x4bc/0x650 net/ax25/af_ax25.c:148 notifier_call_chain+0xb6/0x3d0 kernel/notifier.c:93 call_netdevice_notifiers_info+0xbe/0x140 net/core/dev.c:1967 call_netdevice_notifiers_extack net/core/dev.c:2005 [inline] call_netdevice_notifiers net/core/dev.c:2019 [inline] __dev_notify_flags+0x1f5/0x2e0 net/core/dev.c:8649 dev_change_flags+0x11b/0x170 net/core/dev.c:8685 change_flags net/core/net-sysfs.c:371 [inline] netdev_store net/core/net-sysfs.c:100 [inline] flags_store+0x1ba/0x240 net/core/net-sysfs.c:377 dev_attr_store+0x54/0x80 drivers/base/core.c:2366 sysfs_kf_write+0x114/0x170 fs/sysfs/file.c:136 kernfs_fop_write_iter+0x337/0x500 fs/kernfs/file.c:334 call_write_iter include/linux/fs.h:2020 [inline] new_sync_write fs/read_write.c:491 [inline] vfs_write+0x96a/0xd80 fs/read_write.c:584 ksys_write+0x122/0x250 fs/read_write.c:637 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0x40/0x110 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x63/0x6b RIP: 0033:0x7f80fd95f697 Code: ff ff f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b7 0f 1f 00 f3 0f 1e fa 64 8b 04 25 18 00 00 00 85 c0 75 10 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 51 c3 48 83 ec 28 48 89 54 24 18 48 89 74 24 RSP: 002b:00007ffed044c0b8 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 RAX: ffffffffffffffda RBX: 0000000000000006 RCX: 00007f80fd95f697 RDX: 0000000000000004 RSI: 00007ffed044c8d0 RDI: 0000000000000007 RBP: 0000000000000007 R08: 000000000000000f R09: 0074656e2d74736f R10: 0000000000000000 R11: 0000000000000246 R12: 00007ffed044c8d0 R13: 00007ffed044c4d0 R14: 00007f80fd9dd4f0 R15: 0000000000000001 </TASK> ``` If you have any questions, please contact us. Reported by: Yue Sun <samsun1006219@gmail.com> Reported by: xingwei lee <xrivendell7@gmail.com>
Best Regards, Yue [unhandled content-type:application/octet-stream]// autogenerated by syzkaller (https://github.com/google/syzkaller)
#define _GNU_SOURCE
#include <dirent.h> #include <endian.h> #include <errno.h> #include <fcntl.h> #include <signal.h> #include <stdarg.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/prctl.h> #include <sys/stat.h> #include <sys/syscall.h> #include <sys/types.h> #include <sys/wait.h> #include <time.h> #include <unistd.h>
static void sleep_ms(uint64_t ms) { usleep(ms * 1000); }
static uint64_t current_time_ms(void) { struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts)) exit(1); return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; }
static bool write_file(const char* file, const char* what, ...) { char buf[1024]; va_list args; va_start(args, what); vsnprintf(buf, sizeof(buf), what, args); va_end(args); buf[sizeof(buf) - 1] = 0; int len = strlen(buf); int fd = open(file, O_WRONLY | O_CLOEXEC); if (fd == -1) return false; if (write(fd, buf, len) != len) { int err = errno; close(fd); errno = err; return false; } close(fd); return true; }
const int kInitNetNsFd = 201;
static long syz_mod_dev(volatile long a0, volatile long a1, volatile long a2, volatile long a3, volatile long a4, volatile long a5) { int fd, sysfd; char buf[1024], sysbuf[1024], input[1024]; char* hash; char dev_num; dev_num = '\0'; strncpy(buf, (char*)a0, sizeof(buf) - 1); buf[sizeof(buf) - 1] = 0; while ((hash = strchr(buf, '#'))) { *hash = '0' + (char)(a1 % 10); a1 /= 10; if (dev_num == '\0') dev_num = *hash; } fd = open(buf, a2, 0); strncpy(sysbuf, (char*)a3, sizeof(sysbuf) - 1); sysbuf[sizeof(sysbuf) - 1] = 0; if ((hash = strchr(sysbuf, '#'))) { *hash = dev_num; while ((hash = strchr(sysbuf, '#'))) { *hash = '0' + (char)(a1 % 10); a1 /= 10; } } sysfd = open(sysbuf, O_RDWR, 0); strncpy(input, (char*)a4, sizeof(input) - 1); input[sizeof(input) - 1] = 0; hash = strchr(input, '\0'); sysfd = write(sysfd, input, hash - input + 1); return fd; }
static long syz_init_net_socket(volatile long domain, volatile long type, volatile long proto) { return syscall(__NR_socket, domain, type, proto); }
static void kill_and_wait(int pid, int* status) { kill(-pid, SIGKILL); kill(pid, SIGKILL); for (int i = 0; i < 100; i++) { if (waitpid(-1, status, WNOHANG | __WALL) == pid) return; usleep(1000); } DIR* dir = opendir("/sys/fs/fuse/connections"); if (dir) { for (;;) { struct dirent* ent = readdir(dir); if (!ent) break; if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) continue; char abort[300]; snprintf(abort, sizeof(abort), "/sys/fs/fuse/connections/%s/abort", ent->d_name); int fd = open(abort, O_WRONLY); if (fd == -1) { continue; } if (write(fd, abort, 1) < 0) { } close(fd); } closedir(dir); } else { } while (waitpid(-1, status, __WALL) != pid) { } }
static void setup_test() { prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); setpgrp(); write_file("/proc/self/oom_score_adj", "1000"); }
static void execute_one(void);
#define WAIT_FLAGS __WALL
static void loop(void) { int iter = 0; for (;; iter++) { int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { setup_test(); execute_one(); exit(0); } int status = 0; uint64_t start = current_time_ms(); for (;;) { if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) break; sleep_ms(1); if (current_time_ms() - start < 5000) continue; kill_and_wait(pid, &status); break; } } }
uint64_t r[1] = {0xffffffffffffffff};
void execute_one(void) { intptr_t res = 0; memcpy((void*)0x20000040, "/dev/vhost-net\000", 15); memcpy((void*)0x20000080, "/sys/devices/virtual/net/bpq0/flags\000", 36); memcpy((void*)0x200000c0, "1\000", 2); syz_mod_dev(/*dev=*/0x20000040, /*id=*/6, /*flags=*/0x100000, /*file=*/0x20000080, /*buf=*/0x200000c0, /*fd=*/-1); res = -1; res = syz_init_net_socket(/*domain=*/3, /*type=SOCK_SEQPACKET*/ 5, /*proto=*/0); if (res != -1) r[0] = res; *(uint16_t*)0x20000100 = 3; *(uint8_t*)0x20000102 = 0x98; *(uint8_t*)0x20000103 = 0x92; *(uint8_t*)0x20000104 = 0x9c; *(uint8_t*)0x20000105 = 0xaa; *(uint8_t*)0x20000106 = 0xb0; *(uint8_t*)0x20000107 = 0x40; *(uint8_t*)0x20000108 = 2; *(uint32_t*)0x2000010c = 0; *(uint8_t*)0x20000110 = 0x40; *(uint8_t*)0x20000111 = 0x40; *(uint8_t*)0x20000112 = 0x40; *(uint8_t*)0x20000113 = 0x40; *(uint8_t*)0x20000114 = 0x40; *(uint8_t*)0x20000115 = 0x40; *(uint8_t*)0x20000116 = 0; *(uint8_t*)0x20000117 = 0x40; *(uint8_t*)0x20000118 = 0x40; *(uint8_t*)0x20000119 = 0x40; *(uint8_t*)0x2000011a = 0x40; *(uint8_t*)0x2000011b = 0x40; *(uint8_t*)0x2000011c = 0x40; *(uint8_t*)0x2000011d = 0; *(uint8_t*)0x2000011e = 0x98; *(uint8_t*)0x2000011f = 0x92; *(uint8_t*)0x20000120 = 0x9c; *(uint8_t*)0x20000121 = 0xaa; *(uint8_t*)0x20000122 = 0xb0; *(uint8_t*)0x20000123 = 0x40; *(uint8_t*)0x20000124 = 2; *(uint8_t*)0x20000125 = 0xcc; *(uint8_t*)0x20000126 = 0xcc; *(uint8_t*)0x20000127 = 0xcc; *(uint8_t*)0x20000128 = 0xcc; *(uint8_t*)0x20000129 = 0xcc; *(uint8_t*)0x2000012a = 0xcc; *(uint8_t*)0x2000012b = 2; *(uint8_t*)0x2000012c = 0x98; *(uint8_t*)0x2000012d = 0x92; *(uint8_t*)0x2000012e = 0x9c; *(uint8_t*)0x2000012f = 0xaa; *(uint8_t*)0x20000130 = 0xb0; *(uint8_t*)0x20000131 = 0x40; *(uint8_t*)0x20000132 = 2; *(uint8_t*)0x20000133 = 0x40; *(uint8_t*)0x20000134 = 0x40; *(uint8_t*)0x20000135 = 0x40; *(uint8_t*)0x20000136 = 0x40; *(uint8_t*)0x20000137 = 0x40; *(uint8_t*)0x20000138 = 0x40; *(uint8_t*)0x20000139 = 0; *(uint8_t*)0x2000013a = 0x98; *(uint8_t*)0x2000013b = 0x92; *(uint8_t*)0x2000013c = 0x9c; *(uint8_t*)0x2000013d = 0xaa; *(uint8_t*)0x2000013e = 0xb0; *(uint8_t*)0x2000013f = 0x40; *(uint8_t*)0x20000140 = 2; *(uint8_t*)0x20000141 = 0x98; *(uint8_t*)0x20000142 = 0x92; *(uint8_t*)0x20000143 = 0x9c; *(uint8_t*)0x20000144 = 0xaa; *(uint8_t*)0x20000145 = 0xb0; *(uint8_t*)0x20000146 = 0x40; *(uint8_t*)0x20000147 = 2; syscall(__NR_bind, /*fd=*/r[0], /*addr=*/0x20000100ul, /*addrlen=*/0x48ul); memcpy((void*)0x20000040, "/dev/vhost-net\000", 15); memcpy((void*)0x20000080, "/sys/devices/virtual/net/bpq0/flags\000", 36); memcpy((void*)0x20000000, "100\000", 4); syz_mod_dev(/*dev=*/0x20000040, /*id=*/6, /*flags=*/0x100000, /*file=*/0x20000080, /*buf=*/0x20000000, /*fd=*/-1); } int main(void) { syscall(__NR_mmap, /*addr=*/0x1ffff000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/-1, /*offset=*/0ul); syscall(__NR_mmap, /*addr=*/0x20000000ul, /*len=*/0x1000000ul, /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/ 7ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/-1, /*offset=*/0ul); syscall(__NR_mmap, /*addr=*/0x21000000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/-1, /*offset=*/0ul); loop(); return 0; }
| ![\](/images/icornerr.gif) |