Skip to content

Commit 1658633

Browse files
committed
io_uring: ensure io_lockdep_assert_cq_locked() handles disabled rings
io_lockdep_assert_cq_locked() checks that locking is correctly done when a CQE is posted. If the ring is setup in a disabled state with IORING_SETUP_R_DISABLED, then ctx->submitter_task isn't assigned until the ring is later enabled. We generally don't post CQEs in this state, as no SQEs can be submitted. However it is possible to generate a CQE if tagged resources are being updated. If this happens and PROVE_LOCKING is enabled, then the locking check helper will dereference ctx->submitter_task, which hasn't been set yet. Fixup io_lockdep_assert_cq_locked() to handle this case correctly. While at it, convert it to a static inline as well, so that generated line offsets will actually reflect which condition failed, rather than just the line offset for io_lockdep_assert_cq_locked() itself. Reported-and-tested-by: syzbot+efc45d4e7ba6ab4ef1eb@syzkaller.appspotmail.com Fixes: f26cc95 ("io_uring: lockdep annotate CQ locking") Cc: stable@vger.kernel.org Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent f8024f1 commit 1658633

File tree

1 file changed

+27
-14
lines changed

1 file changed

+27
-14
lines changed

io_uring/io_uring.h

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -86,20 +86,33 @@ bool __io_alloc_req_refill(struct io_ring_ctx *ctx);
8686
bool io_match_task_safe(struct io_kiocb *head, struct task_struct *task,
8787
bool cancel_all);
8888

89-
#define io_lockdep_assert_cq_locked(ctx) \
90-
do { \
91-
lockdep_assert(in_task()); \
92-
\
93-
if (ctx->flags & IORING_SETUP_IOPOLL) { \
94-
lockdep_assert_held(&ctx->uring_lock); \
95-
} else if (!ctx->task_complete) { \
96-
lockdep_assert_held(&ctx->completion_lock); \
97-
} else if (ctx->submitter_task->flags & PF_EXITING) { \
98-
lockdep_assert(current_work()); \
99-
} else { \
100-
lockdep_assert(current == ctx->submitter_task); \
101-
} \
102-
} while (0)
89+
#if defined(CONFIG_PROVE_LOCKING)
90+
static inline void io_lockdep_assert_cq_locked(struct io_ring_ctx *ctx)
91+
{
92+
lockdep_assert(in_task());
93+
94+
if (ctx->flags & IORING_SETUP_IOPOLL) {
95+
lockdep_assert_held(&ctx->uring_lock);
96+
} else if (!ctx->task_complete) {
97+
lockdep_assert_held(&ctx->completion_lock);
98+
} else if (ctx->submitter_task) {
99+
/*
100+
* ->submitter_task may be NULL and we can still post a CQE,
101+
* if the ring has been setup with IORING_SETUP_R_DISABLED.
102+
* Not from an SQE, as those cannot be submitted, but via
103+
* updating tagged resources.
104+
*/
105+
if (ctx->submitter_task->flags & PF_EXITING)
106+
lockdep_assert(current_work());
107+
else
108+
lockdep_assert(current == ctx->submitter_task);
109+
}
110+
}
111+
#else
112+
static inline void io_lockdep_assert_cq_locked(struct io_ring_ctx *ctx)
113+
{
114+
}
115+
#endif
103116

104117
static inline void io_req_task_work_add(struct io_kiocb *req)
105118
{

0 commit comments

Comments
 (0)