public inbox for [email protected]
 help / color / mirror / Atom feed
* [io-uring] WARNING in __put_task_struct
@ 2024-06-07 17:15 chase xd
  2024-06-12  1:18 ` Pavel Begunkov
  0 siblings, 1 reply; 4+ messages in thread
From: chase xd @ 2024-06-07 17:15 UTC (permalink / raw)
  To: axboe, asml.silence, io-uring, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 4573 bytes --]

Dear Linux kernel maintainers,

Syzkaller reports this previously unknown bug on Linux
6.8.0-rc3-00043-ga69d20885494-dirty #4. Seems like the bug was
silently or unintendedly fixed in the latest version.

I found a similar bug report
[here](https://syzkaller.appspot.com/bug?id=ac425cc8dcf667de21cbe25208555a346ab658d0),
but I think this should be a different bug?

```
Syzkaller hit 'WARNING in __put_task_struct' bug.

------------[ cut here ]------------
WARNING: CPU: 2 PID: 10662 at kernel/fork.c:967
__put_task_struct+0x290/0x340 kernel/fork.c:967
Modules linked in:
CPU: 2 PID: 10662 Comm: syz-executor389 Not tainted
6.8.0-rc3-00043-ga69d20885494-dirty #52
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
RIP: 0010:__put_task_struct+0x290/0x340 kernel/fork.c:967
Code: da ff ff 48 8b 3d b0 28 69 0f 4c 89 e6 e8 88 d2 7b 00 e9 45 ff
ff ff be 03 00 00 00 4c 89 e7 e8 46 be c7 02 e9 33 ff ff ff 90 <0f> 0b
90 e9 ac fd ff ff 90 0f 0b 90 e9 e9 fd ff ff 90 0f 0b 90 e9
RSP: 0018:ffffc90017f67b38 EFLAGS: 00010246
RAX: 0000000000000000 RBX: 1ffff92002fecf6f RCX: 1ffff92002fecf36
RDX: 1ffff1100e71a530 RSI: ffffffff8a0bdce0 RDI: ffff8880738d2980
RBP: ffff8880738d2440 R08: 0000000000000000 R09: fffffbfff23d9a15
R10: ffffffff91ecd0af R11: 0000000000000000 R12: ffffffff840b8886
R13: ffff8880738d2468 R14: ffff888024ad7818 R15: ffff8880738d2440
FS:  0000555557445480(0000) GS:ffff8880b9880000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007ff010cdf0b0 CR3: 0000000032094000 CR4: 0000000000750ef0
PKRU: 55555554
Call Trace:
 <TASK>
 put_task_struct include/linux/sched/task.h:138 [inline]
 io_wq_exit_workers io_uring/io-wq.c:1274 [inline]
 io_wq_put_and_exit+0x765/0x8f0 io_uring/io-wq.c:1296
 io_uring_clean_tctx+0x10e/0x190 io_uring/tctx.c:193
 io_uring_cancel_generic+0x643/0x7c0 io_uring/io_uring.c:3395
 io_uring_files_cancel include/linux/io_uring.h:21 [inline]
 do_exit+0x4bf/0x25a0 kernel/exit.c:829
 do_group_exit+0xb4/0x250 kernel/exit.c:1020
 __do_sys_exit_group kernel/exit.c:1031 [inline]
 __se_sys_exit_group kernel/exit.c:1029 [inline]
 __x64_sys_exit_group+0x39/0x40 kernel/exit.c:1029
 do_syscall_x64 arch/x86/entry/common.c:52 [inline]
 do_syscall_64+0xd8/0x270 arch/x86/entry/common.c:83
 entry_SYSCALL_64_after_hwframe+0x6f/0x77
RIP: 0033:0x7ff010c59031
Code: b8 ff ff ff be e7 00 00 00 ba 3c 00 00 00 eb 16 66 0f 1f 84 00
00 00 00 00 89 d0 0f 05 48 3d 00 f0 ff ff 77 1c f4 89 f0 0f 05 <48> 3d
00 f0 ff ff 76 e7 f7 d8 64 41 89 00 eb df 0f 1f 80 00 00 00
RSP: 002b:00007ffd577fbfb8 EFLAGS: 00000246 ORIG_RAX: 00000000000000e7
RAX: ffffffffffffffda RBX: 00007ff010cde1f0 RCX: 00007ff010c59031
RDX: 000000000000003c RSI: 00000000000000e7 RDI: 0000000000000000
RBP: 0000000000000000 R08: ffffffffffffffb8 R09: 000000000000ffff
R10: 0000000000000000 R11: 0000000000000246 R12: 00007ff010cde1f0
R13: 0000000000000000 R14: 00007ff010cdec80 R15: 00007ff010c13500
 </TASK>


Syzkaller reproducer:
# {Threaded:false Repeat:true 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:true Repro:false Trace:false LegacyOptions:{Collide:false
Fault:false FaultCall:0 FaultNth:0}}
r0 = syz_io_uring_setup(0x6e47, &(0x7f0000000000)={0x0, 0x8847, 0x80,
0x4000003, 0x3d6}, &(0x7f0000000080)=<r1=>0x0,
&(0x7f00000000c0)=<r2=>0x0)
open(&(0x7f0000000100)='./file0\x00', 0x2041, 0x8)
r3 = open$dir(&(0x7f0000000140)='./file0\x00', 0x680400, 0x104)
r4 = socket(0x28, 0x80000, 0x89)
epoll_create1(0x80000)
eventfd2(0x802, 0x80800)
syz_io_uring_submit(r1, r2,
&(0x7f0000000340)=@IORING_OP_SEND_ZC={0x2f, 0x1c, 0x1, @sock=r4,
&(0x7f0000000240)=@tipc=@name={0x1e, 0x2, 0x1, {{0x41, 0x4}, 0x3}},
&(0x7f00000002c0)=""/82, 0x52, 0x200, 0x1, 0x101, 0x0, {0x100}})
io_uring_enter(r0, 0x1, 0x1, 0x11, &(0x7f0000000380), 0x8)
syz_io_uring_complete(r1, &(0x7f0000000400))
io_uring_register$IORING_REGISTER_ENABLE_RINGS(r0, 0xc, 0x0, 0x0)
syz_io_uring_submit(r1, r2,
&(0x7f0000000180)=@IORING_OP_ASYNC_CANCEL={0xe, 0x1, 0x0, 0x0, 0x0,
0x1, 0x0, 0x4, 0x1})
syz_io_uring_submit(r1, r2, 0x0)
syz_io_uring_submit(r1, r2,
&(0x7f0000000680)=@IORING_OP_UNLINKAT={0x24, 0x50, 0x0, @fd_dir=r3,
0x0, &(0x7f0000000500)='./file0\x00'})
io_uring_enter(r0, 0x3, 0x3, 0xb, 0x0, 0x0)
syz_io_uring_complete(r1, 0x0)
```

crepro is in the attachment.

Best Regards
Xdchase

[-- Attachment #2: repro.c --]
[-- Type: application/octet-stream, Size: 17553 bytes --]

// autogenerated by syzkaller (https://github.com/google/syzkaller)

#define _GNU_SOURCE

#include <dirent.h>
#include <endian.h>
#include <errno.h>
#include <fcntl.h>
#include <setjmp.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.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>

#ifndef __NR_io_uring_enter
#define __NR_io_uring_enter 426
#endif
#ifndef __NR_io_uring_register
#define __NR_io_uring_register 427
#endif
#ifndef __NR_io_uring_setup
#define __NR_io_uring_setup 425
#endif

static __thread int clone_ongoing;
static __thread int skip_segv;
static __thread jmp_buf segv_env;

static void segv_handler(int sig, siginfo_t* info, void* ctx)
{
  if (__atomic_load_n(&clone_ongoing, __ATOMIC_RELAXED) != 0) {
    exit(sig);
  }
  uintptr_t addr = (uintptr_t)info->si_addr;
  const uintptr_t prog_start = 1 << 20;
  const uintptr_t prog_end = 100 << 20;
  int skip = __atomic_load_n(&skip_segv, __ATOMIC_RELAXED) != 0;
  int valid = addr < prog_start || addr > prog_end;
  if (skip && valid) {
    _longjmp(segv_env, 1);
  }
  exit(sig);
}

static void install_segv_handler(void)
{
  struct sigaction sa;
  memset(&sa, 0, sizeof(sa));
  sa.sa_handler = SIG_IGN;
  syscall(SYS_rt_sigaction, 0x20, &sa, NULL, 8);
  syscall(SYS_rt_sigaction, 0x21, &sa, NULL, 8);
  memset(&sa, 0, sizeof(sa));
  sa.sa_sigaction = segv_handler;
  sa.sa_flags = SA_NODEFER | SA_SIGINFO;
  sigaction(SIGSEGV, &sa, NULL);
  sigaction(SIGBUS, &sa, NULL);
}

#define NONFAILING(...)                                                        \
  ({                                                                           \
    int ok = 1;                                                                \
    __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST);                       \
    if (_setjmp(segv_env) == 0) {                                              \
      __VA_ARGS__;                                                             \
    } else                                                                     \
      ok = 0;                                                                  \
    __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST);                       \
    ok;                                                                        \
  })

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

#define SIZEOF_IO_URING_SQE 64
#define SIZEOF_IO_URING_CQE 16
#define SQ_HEAD_OFFSET 0
#define SQ_TAIL_OFFSET 64
#define SQ_RING_MASK_OFFSET 256
#define SQ_RING_ENTRIES_OFFSET 264
#define SQ_FLAGS_OFFSET 276
#define SQ_DROPPED_OFFSET 272
#define CQ_HEAD_OFFSET 128
#define CQ_TAIL_OFFSET 192
#define CQ_RING_MASK_OFFSET 260
#define CQ_RING_ENTRIES_OFFSET 268
#define CQ_RING_OVERFLOW_OFFSET 284
#define CQ_FLAGS_OFFSET 280
#define CQ_CQES_OFFSET 320

// From linux/io_uring.h
struct io_uring_cqe {
  uint64_t user_data;
  uint32_t res;
  uint32_t flags;
};

/* This is x86 specific */
#define read_barrier() __asm__ __volatile__("" ::: "memory")
#define write_barrier() __asm__ __volatile__("" ::: "memory")

struct io_sqring_offsets {
  uint32_t head;
  uint32_t tail;
  uint32_t ring_mask;
  uint32_t ring_entries;
  uint32_t flags;
  uint32_t dropped;
  uint32_t array;
  uint32_t resv1;
  uint64_t resv2;
};

struct io_cqring_offsets {
  uint32_t head;
  uint32_t tail;
  uint32_t ring_mask;
  uint32_t ring_entries;
  uint32_t overflow;
  uint32_t cqes;
  uint64_t resv[2];
};

struct io_uring_params {
  uint32_t sq_entries;
  uint32_t cq_entries;
  uint32_t flags;
  uint32_t sq_thread_cpu;
  uint32_t sq_thread_idle;
  uint32_t features;
  uint32_t resv[4];
  struct io_sqring_offsets sq_off;
  struct io_cqring_offsets cq_off;
};

#define IORING_OFF_SQ_RING 0
#define IORING_OFF_SQES 0x10000000ULL
#define IORING_SETUP_SQE128 (1U << 10)
#define IORING_SETUP_CQE32 (1U << 11)
#define IORING_SETUP_NO_SQARRAY (1U << 16)

static struct io_uring_params* io_uring_p;

static long syz_io_uring_complete(volatile long a0, volatile long a1)
{
  // syzlang: syz_io_uring_complete(ring_ptr ring_ptr)
  // C:       syz_io_uring_complete(char* ring_ptr)
  // It is not checked if the ring is empty
  // Cast to original
  long ring_ptr = a0;
  int* result_fd = (int*)a1;
  // result_fd = (int*)mmap(0, sizeof(int) * (io_uring_p->cq_entries), PROT_READ
  // | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); result_fd_cnt = (int*)mmap(0,
  // sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
  int cnt = 0;
  // head read once
  unsigned cq_head_raw = *(unsigned*)(io_uring_p->cq_off.head + ring_ptr);
  unsigned cq_ring_mask = *(unsigned*)(io_uring_p->cq_off.ring_mask + ring_ptr);
  do {

    read_barrier();
    // tail
    unsigned cq_tail_raw = *(unsigned*)(io_uring_p->cq_off.tail + ring_ptr);
    if (cq_head_raw == cq_tail_raw) {
      break;
    }
    // head != tail, retrieve cq from head
    unsigned cq_head = cq_head_raw & cq_ring_mask;
    struct io_uring_cqe* cqe;
    if ((io_uring_p->flags & IORING_SETUP_CQE32) == 0)
      cqe = (struct io_uring_cqe*)(io_uring_p->cq_off.cqes + ring_ptr +
                                   SIZEOF_IO_URING_CQE * cq_head);
    else
      cqe = (struct io_uring_cqe*)(io_uring_p->cq_off.cqes + ring_ptr +
                                   SIZEOF_IO_URING_CQE * 2 * cq_head);
    // In the descriptions (sys/linux/io_uring.txt), openat and openat2 are
    // passed with a unique range of sqe.user_data (0x12345 and 0x23456) to
    // identify the operations which produces an fd instance. Check
    // cqe.user_data, which should be the same as sqe.user_data for that
    // operation. If it falls in that unique range, return cqe.res as fd.
    // Otherwise, just return an invalid fd.
    if (cqe->user_data == 0x12345 || cqe->user_data == 0x23456)
      result_fd[cnt++] = cqe->res;
    cq_head_raw += 1;
  } while (1);
  *(unsigned*)(io_uring_p->cq_off.head + ring_ptr) = cq_head_raw;
  write_barrier();
  if (cnt == 0) {
    return -1;
  }
  return 0;
}

// Wrapper for io_uring_setup and the subsequent mmap calls that map the ring
// and the sqes
static long syz_io_uring_setup(volatile long a0, volatile long a1,
                               volatile long a2, volatile long a3)
{
  // syzlang: syz_io_uring_setup(entries int32[1:IORING_MAX_ENTRIES], params
  // ptr[inout, io_uring_params], ring_ptr ptr[out, ring_ptr], sqes_ptr ptr[out,
  // sqes_ptr]) fd_io_uring C:       syz_io_uring_setup(uint32_t entries, struct
  // io_uring_params* params, void** ring_ptr_out, void** sqes_ptr_out) //
  // returns uint32_t fd_io_uring Cast to original
  uint32_t entries = (uint32_t)a0;
  struct io_uring_params* setup_params = (struct io_uring_params*)a1;
  void** ring_ptr_out = (void**)a2;
  void** sqes_ptr_out = (void**)a3;
  // Temporarily disable IORING_SETUP_CQE32 and IORING_SETUP_SQE128 that may
  // change SIZEOF_IO_URING_CQE and SIZEOF_IO_URING_SQE. Tracking bug:
  // https://github.com/google/syzkaller/issues/4531.
  setup_params->flags &= ~(IORING_SETUP_CQE32 | IORING_SETUP_SQE128);
  uint32_t fd_io_uring = syscall(__NR_io_uring_setup, entries, setup_params);
  io_uring_p = setup_params;
  // Compute the ring sizes
  uint32_t sq_ring_sz =
      setup_params->sq_off.array + setup_params->sq_entries * sizeof(uint32_t);
  uint32_t cq_ring_sz = setup_params->cq_off.cqes +
                        setup_params->cq_entries * SIZEOF_IO_URING_CQE;
  // Asssumed IORING_FEAT_SINGLE_MMAP, which is always the case with the current
  // implementation The implication is that the sq_ring_ptr and the cq_ring_ptr
  // are the same but the difference is in the offsets to access the fields of
  // these rings.
  uint32_t ring_sz = sq_ring_sz > cq_ring_sz ? sq_ring_sz : cq_ring_sz;
  *ring_ptr_out =
      mmap(0, ring_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE,
           fd_io_uring, IORING_OFF_SQ_RING);
  uint32_t sqes_sz = setup_params->sq_entries * SIZEOF_IO_URING_SQE;
  *sqes_ptr_out = mmap(0, sqes_sz, PROT_READ | PROT_WRITE,
                       MAP_SHARED | MAP_POPULATE, fd_io_uring, IORING_OFF_SQES);
  return fd_io_uring;
}

static long syz_io_uring_submit(volatile long a0, volatile long a1,
                                volatile long a2)
{
  // syzlang: syz_io_uring_submit(ring_ptr ring_ptr, sqes_ptr sqes_ptr,
  // sqe ptr[in, io_uring_sqe]) C:       syz_io_uring_submit(char* ring_ptr,
  // io_uring_sqe* sqes_ptr,    io_uring_sqe* sqe) It is not checked if the ring
  // is full Cast to original
  long ring_ptr = a0; // This will be exposed to offsets in bytes
  char* sqes_ptr = (char*)a1;
  char* sqe = (char*)a2;
  unsigned sq_tail_raw = *(unsigned*)(io_uring_p->sq_off.tail + ring_ptr);
  unsigned sq_ring_mask = *(unsigned*)(io_uring_p->sq_off.ring_mask + ring_ptr);
  unsigned sq_tail = sq_tail_raw & sq_ring_mask;
  // write to current sq tail sqe
  void* sqe_dest;
  if ((io_uring_p->flags & IORING_SETUP_SQE128) == 0)
    sqe_dest = (void*)(sqes_ptr + SIZEOF_IO_URING_SQE * sq_tail);
  else {
    sqe_dest = (void*)(sqes_ptr + SIZEOF_IO_URING_SQE * sq_tail * 2);
  }

  // Write the sqe entry to its destination in sqes
  memcpy(sqe_dest, sqe, SIZEOF_IO_URING_SQE);
  // Advance the tail. Tail is a free-flowing integer and relies on natural
  // wrapping. Ensure that the kernel will never see a tail update without the
  // preceeding SQE stores being done.
  __atomic_store_n((unsigned*)(io_uring_p->sq_off.tail + ring_ptr),
                   sq_tail_raw + 1, __ATOMIC_RELEASE);
  // update sq array
  if ((io_uring_p->flags & IORING_SETUP_NO_SQARRAY) == 0)
    __atomic_store_n((unsigned*)(io_uring_p->sq_off.array + ring_ptr) + sq_tail,
                     sq_tail, __ATOMIC_RELEASE);
  // Now the application is free to call io_uring_enter() to submit the sqe
  return 0;
}

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[5] = {0x0, 0x0, 0x0, 0xffffffffffffff9c, 0x0};

void execute_one(void)
{
  intptr_t res = 0;
  NONFAILING(*(uint32_t*)0x20000004 = 0x8847);
  NONFAILING(*(uint32_t*)0x20000008 = 0x80);
  NONFAILING(*(uint32_t*)0x2000000c = 0x4000003);
  NONFAILING(*(uint32_t*)0x20000010 = 0x3d6);
  NONFAILING(*(uint32_t*)0x20000018 = 0);
  NONFAILING(memset((void*)0x2000001c, 0, 12));
  res = -1;
  NONFAILING(res = syz_io_uring_setup(/*entries=*/0x6e47, /*params=*/0x20000000,
                                      /*ring_ptr=*/0x20000080,
                                      /*sqes_ptr=*/0x200000c0));
  if (res != -1) {
    r[0] = res;
    NONFAILING(r[1] = *(uint64_t*)0x20000080);
    NONFAILING(r[2] = *(uint64_t*)0x200000c0);
  }
  NONFAILING(memcpy((void*)0x20000100, "./file0\000", 8));
  syscall(__NR_open, /*file=*/0x20000100ul,
          /*flags=O_CREAT|FASYNC|O_WRONLY*/ 0x2041ul, /*mode=S_IXGRP*/ 8ul);
  NONFAILING(memcpy((void*)0x20000140, "./file0\000", 8));
  res = syscall(__NR_open, /*file=*/0x20000140ul,
                /*flags=__O_TMPFILE|O_PATH|O_CLOEXEC|O_APPEND*/ 0x680400ul,
                /*mode=S_IROTH|S_IRUSR*/ 0x104ul);
  if (res != -1)
    r[3] = res;
  res = syscall(__NR_socket, /*domain=AF_VSOCK*/ 0x28ul,
                /*type=SOCK_CLOEXEC*/ 0x80000ul, /*proto=*/0x89);
  if (res != -1)
    r[4] = res;
  syscall(__NR_epoll_create1, /*flags=EPOLL_CLOEXEC*/ 0x80000ul);
  syscall(__NR_eventfd2, /*initval=*/0x802,
          /*flags=EFD_NONBLOCK|EFD_CLOEXEC*/ 0x80800ul);
  NONFAILING(*(uint8_t*)0x20000340 = 0x2f);
  NONFAILING(*(uint8_t*)0x20000341 = 0x1c);
  NONFAILING(*(uint16_t*)0x20000342 = 1);
  NONFAILING(*(uint32_t*)0x20000344 = r[4]);
  NONFAILING(*(uint64_t*)0x20000348 = 0x20000240);
  NONFAILING(*(uint16_t*)0x20000240 = 0x1e);
  NONFAILING(*(uint8_t*)0x20000242 = 2);
  NONFAILING(*(uint8_t*)0x20000243 = 1);
  NONFAILING(*(uint32_t*)0x20000244 = 0x41);
  NONFAILING(*(uint32_t*)0x20000248 = 4);
  NONFAILING(*(uint32_t*)0x2000024c = 3);
  NONFAILING(*(uint64_t*)0x20000350 = 0x200002c0);
  NONFAILING(*(uint32_t*)0x20000358 = 0x52);
  NONFAILING(*(uint32_t*)0x2000035c = 0x200);
  NONFAILING(*(uint64_t*)0x20000360 = 1);
  NONFAILING(*(uint16_t*)0x20000368 = 0x101);
  NONFAILING(*(uint16_t*)0x2000036a = 0);
  NONFAILING(*(uint16_t*)0x2000036c = 0x100);
  NONFAILING(*(uint16_t*)0x2000036e = 0);
  NONFAILING(memset((void*)0x20000370, 0, 16));
  NONFAILING(syz_io_uring_submit(/*ring_ptr=*/r[1], /*sqes_ptr=*/r[2],
                                 /*sqe=*/0x20000340));
  NONFAILING(*(uint64_t*)0x20000380 = 0);
  syscall(__NR_io_uring_enter, /*fd=*/r[0], /*to_submit=*/1, /*min_complete=*/1,
          /*flags=IORING_ENTER_REGISTERED_RING|IORING_ENTER_GETEVENTS*/ 0x11ul,
          /*sigmask=*/0x20000380ul, /*size=*/8ul);
  NONFAILING(
      syz_io_uring_complete(/*ring_ptr=*/r[1], /*result_fd=*/0x20000400));
  syscall(__NR_io_uring_register, /*fd=*/r[0], /*opcode=*/0xcul, /*arg=*/0ul,
          /*nr_args=*/0ul);
  NONFAILING(*(uint8_t*)0x20000180 = 0xe);
  NONFAILING(*(uint8_t*)0x20000181 = 1);
  NONFAILING(*(uint16_t*)0x20000182 = 0);
  NONFAILING(*(uint32_t*)0x20000184 = 0);
  NONFAILING(*(uint64_t*)0x20000188 = 0);
  NONFAILING(*(uint64_t*)0x20000190 = 1);
  NONFAILING(*(uint32_t*)0x20000198 = 0);
  NONFAILING(*(uint32_t*)0x2000019c = 4);
  NONFAILING(*(uint64_t*)0x200001a0 = 1);
  NONFAILING(*(uint16_t*)0x200001a8 = 0);
  NONFAILING(*(uint16_t*)0x200001aa = 0);
  NONFAILING(memset((void*)0x200001ac, 0, 4));
  NONFAILING(memset((void*)0x200001b0, 0, 16));
  NONFAILING(syz_io_uring_submit(/*ring_ptr=*/r[1], /*sqes_ptr=*/r[2],
                                 /*sqe=*/0x20000180));
  NONFAILING(
      syz_io_uring_submit(/*ring_ptr=*/r[1], /*sqes_ptr=*/r[2], /*sqe=*/0));
  NONFAILING(*(uint8_t*)0x20000680 = 0x24);
  NONFAILING(*(uint8_t*)0x20000681 = 0x50);
  NONFAILING(*(uint16_t*)0x20000682 = 0);
  NONFAILING(*(uint32_t*)0x20000684 = r[3]);
  NONFAILING(*(uint64_t*)0x20000688 = 0);
  NONFAILING(*(uint64_t*)0x20000690 = 0x20000500);
  NONFAILING(memcpy((void*)0x20000500, "./file0\000", 8));
  NONFAILING(*(uint32_t*)0x20000698 = 0);
  NONFAILING(*(uint32_t*)0x2000069c = 0);
  NONFAILING(*(uint64_t*)0x200006a0 = 0);
  NONFAILING(*(uint16_t*)0x200006a8 = 0);
  NONFAILING(*(uint16_t*)0x200006aa = 0);
  NONFAILING(memset((void*)0x200006ac, 0, 4));
  NONFAILING(memset((void*)0x200006b0, 0, 16));
  NONFAILING(syz_io_uring_submit(/*ring_ptr=*/r[1], /*sqes_ptr=*/r[2],
                                 /*sqe=*/0x20000680));
  syscall(
      __NR_io_uring_enter, /*fd=*/r[0], /*to_submit=*/3, /*min_complete=*/3,
      /*flags=IORING_ENTER_EXT_ARG|IORING_ENTER_SQ_WAKEUP|IORING_ENTER_GETEVENTS*/
      0xbul, /*sigmask=*/0ul, /*size=*/0ul);
  NONFAILING(syz_io_uring_complete(/*ring_ptr=*/r[1], /*result_fd=*/0));
}
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);
  install_segv_handler();
  loop();
  return 0;
}

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [io-uring] WARNING in __put_task_struct
  2024-06-07 17:15 [io-uring] WARNING in __put_task_struct chase xd
@ 2024-06-12  1:18 ` Pavel Begunkov
  2024-06-12  6:59   ` chase xd
  0 siblings, 1 reply; 4+ messages in thread
From: Pavel Begunkov @ 2024-06-12  1:18 UTC (permalink / raw)
  To: chase xd, axboe, io-uring, linux-kernel

On 6/7/24 18:15, chase xd wrote:
> Dear Linux kernel maintainers,
> 
> Syzkaller reports this previously unknown bug on Linux
> 6.8.0-rc3-00043-ga69d20885494-dirty #4. Seems like the bug was
> silently or unintendedly fixed in the latest version.

I can't reproduce it neither with upstream nor a69d20885494,
it's likely some funkiness of that branch, and sounds like
you already tested newer kernels with no success. You can
also try it with a stable kernel to see if you can hit it.

-- 
Pavel Begunkov

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [io-uring] WARNING in __put_task_struct
  2024-06-12  1:18 ` Pavel Begunkov
@ 2024-06-12  6:59   ` chase xd
  2024-06-12 13:54     ` Pavel Begunkov
  0 siblings, 1 reply; 4+ messages in thread
From: chase xd @ 2024-06-12  6:59 UTC (permalink / raw)
  To: Pavel Begunkov, Jens Axboe, io-uring, linux-kernel

Repro hit the bug with a low probability, so maybe you need to try
more times on the branch I reported. Also, this bug still exists in
branch 6.10.0-rc1-00004-gff802a9f35cf-dirty #7.

Pavel Begunkov <[email protected]> 于2024年6月12日周三 03:17写道:
>
> On 6/7/24 18:15, chase xd wrote:
> > Dear Linux kernel maintainers,
> >
> > Syzkaller reports this previously unknown bug on Linux
> > 6.8.0-rc3-00043-ga69d20885494-dirty #4. Seems like the bug was
> > silently or unintendedly fixed in the latest version.
>
> I can't reproduce it neither with upstream nor a69d20885494,
> it's likely some funkiness of that branch, and sounds like
> you already tested newer kernels with no success. You can
> also try it with a stable kernel to see if you can hit it.
>
> --
> Pavel Begunkov

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [io-uring] WARNING in __put_task_struct
  2024-06-12  6:59   ` chase xd
@ 2024-06-12 13:54     ` Pavel Begunkov
  0 siblings, 0 replies; 4+ messages in thread
From: Pavel Begunkov @ 2024-06-12 13:54 UTC (permalink / raw)
  To: chase xd, Jens Axboe, io-uring, linux-kernel

On 6/12/24 07:59, chase xd wrote:
> Repro hit the bug with a low probability, so maybe you need to try
> more times on the branch I reported. Also, this bug still exists in
> branch 6.10.0-rc1-00004-gff802a9f35cf-dirty #7.

Yeah, unreliable, just hit something with some version,
will try to repro with 6.10 and see what's going on


> Pavel Begunkov <[email protected]> 于2024年6月12日周三 03:17写道:
>>
>> On 6/7/24 18:15, chase xd wrote:
>>> Dear Linux kernel maintainers,
>>>
>>> Syzkaller reports this previously unknown bug on Linux
>>> 6.8.0-rc3-00043-ga69d20885494-dirty #4. Seems like the bug was
>>> silently or unintendedly fixed in the latest version.
>>
>> I can't reproduce it neither with upstream nor a69d20885494,
>> it's likely some funkiness of that branch, and sounds like
>> you already tested newer kernels with no success. You can
>> also try it with a stable kernel to see if you can hit it.

-- 
Pavel Begunkov

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2024-06-12 13:54 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-06-07 17:15 [io-uring] WARNING in __put_task_struct chase xd
2024-06-12  1:18 ` Pavel Begunkov
2024-06-12  6:59   ` chase xd
2024-06-12 13:54     ` Pavel Begunkov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox