Marco Elver b16ef427ad io_uring: fix data race to avoid potential NULL-deref
Commit ba5ef6dc8a82 ("io_uring: fortify tctx/io_wq cleanup") introduced
setting tctx->io_wq to NULL a bit earlier. This has caused KCSAN to
detect a data race between accesses to tctx->io_wq:

  write to 0xffff88811d8df330 of 8 bytes by task 3709 on cpu 1:
   io_uring_clean_tctx                  fs/io_uring.c:9042 [inline]
   __io_uring_cancel                    fs/io_uring.c:9136
   io_uring_files_cancel                include/linux/io_uring.h:16 [inline]
   do_exit                              kernel/exit.c:781
   do_group_exit                        kernel/exit.c:923
   get_signal                           kernel/signal.c:2835
   arch_do_signal_or_restart            arch/x86/kernel/signal.c:789
   handle_signal_work                   kernel/entry/common.c:147 [inline]
   exit_to_user_mode_loop               kernel/entry/common.c:171 [inline]
   ...
  read to 0xffff88811d8df330 of 8 bytes by task 6412 on cpu 0:
   io_uring_try_cancel_iowq             fs/io_uring.c:8911 [inline]
   io_uring_try_cancel_requests         fs/io_uring.c:8933
   io_ring_exit_work                    fs/io_uring.c:8736
   process_one_work                     kernel/workqueue.c:2276
   ...

With the config used, KCSAN only reports data races with value changes:
this implies that in the case here we also know that tctx->io_wq was
non-NULL. Therefore, depending on interleaving, we may end up with:

              [CPU 0]                 |        [CPU 1]
  io_uring_try_cancel_iowq()          | io_uring_clean_tctx()
    if (!tctx->io_wq) // false        |   ...
    ...                               |   tctx->io_wq = NULL
    io_wq_cancel_cb(tctx->io_wq, ...) |   ...
      -> NULL-deref                   |

Note: It is likely that thus far we've gotten lucky and the compiler
optimizes the double-read into a single read into a register -- but this
is never guaranteed, and can easily change with a different config!

Fix the data race by restoring the previous behaviour, where both
setting io_wq to NULL and put of the wq are _serialized_ after
concurrent io_uring_try_cancel_iowq() via acquisition of the uring_lock
and removal of the node in io_uring_del_task_file().

Fixes: ba5ef6dc8a82 ("io_uring: fortify tctx/io_wq cleanup")
Suggested-by: Pavel Begunkov <asml.silence@gmail.com>
Reported-by: syzbot+bf2b3d0435b9b728946c@syzkaller.appspotmail.com
Signed-off-by: Marco Elver <elver@google.com>
Cc: Jens Axboe <axboe@kernel.dk>
Link: https://lore.kernel.org/r/20210527092547.2656514-1-elver@google.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2021-05-27 07:44:49 -06:00
..
2021-01-24 14:27:20 +01:00
2021-02-23 13:39:45 -08:00
2021-04-27 13:27:39 -07:00
2021-01-24 14:27:20 +01:00
2021-01-24 14:27:20 +01:00
2021-04-12 15:04:29 +02:00
2021-04-12 15:04:29 +02:00
2021-04-10 03:20:19 +08:00
\n
2021-04-29 11:06:13 -07:00
\n
2021-04-29 11:06:13 -07:00
2021-04-27 13:08:12 -07:00
2021-02-23 13:39:45 -08:00
2021-04-29 10:33:35 -07:00
2021-01-24 14:27:20 +01:00
2021-04-12 15:04:29 +02:00
2021-01-24 14:27:20 +01:00
2021-04-27 12:27:23 -07:00
2021-02-23 13:39:45 -08:00
2021-04-12 15:04:29 +02:00
2021-02-23 13:39:45 -08:00
2021-01-24 14:27:20 +01:00
2021-04-26 23:23:41 +01:00
2021-04-27 13:42:11 -07:00
2021-04-12 15:04:30 +02:00
2021-01-24 14:27:20 +01:00
2021-04-27 10:03:12 -07:00
2021-04-27 18:09:44 -07:00
2021-02-24 13:38:26 -08:00
\n
2021-04-29 10:51:29 -07:00
2021-01-24 14:27:20 +01:00
2021-02-23 13:39:45 -08:00
2021-01-24 14:27:20 +01:00
2020-09-10 14:03:31 -07:00
2021-04-29 10:43:51 -07:00
\n
2021-04-29 11:06:13 -07:00
2021-01-24 14:27:20 +01:00
2021-01-24 14:27:20 +01:00
2021-04-28 14:39:37 -07:00
2021-02-24 13:38:26 -08:00
2021-02-24 13:38:26 -08:00
2021-02-23 13:39:45 -08:00
2021-01-24 14:27:19 +01:00
2021-04-27 12:49:42 -07:00
2021-02-23 13:39:45 -08:00
2021-04-12 15:04:23 +02:00
2021-03-23 11:20:25 +01:00
2021-04-26 13:24:39 -07:00
2021-04-27 12:49:42 -07:00
2021-02-23 13:39:45 -08:00
2021-02-24 13:38:26 -08:00
2021-01-24 14:27:20 +01:00
2021-01-24 14:27:19 +01:00
2021-01-21 14:06:00 -07:00
2021-02-21 11:02:48 -08:00
2021-01-24 14:27:20 +01:00
2021-02-13 17:17:53 +01:00
2021-01-24 14:27:18 +01:00