Skip to content

Commit a88c386

Browse files
committed
Merge tag 'io_uring-6.6-2023-10-06' of git://git.kernel.dk/linux
Pull io_uring fixes from Jens Axboe: - syzbot report on a crash on 32-bit arm with highmem, and went digging to check for potentially similar issues and found one more (me) - Fix a syzbot report with PROVE_LOCKING=y and setting up the ring in a disabled state (me) - Fix for race with CPU hotplut and io-wq init (Jeff) * tag 'io_uring-6.6-2023-10-06' of git://git.kernel.dk/linux: io-wq: fully initialize wqe before calling cpuhp_state_add_instance_nocalls() io_uring: don't allow IORING_SETUP_NO_MMAP rings on highmem pages io_uring: ensure io_lockdep_assert_cq_locked() handles disabled rings io_uring/kbuf: don't allow registered buffer rings on highmem pages
2 parents af95dc6 + 0f8baa3 commit a88c386

File tree

4 files changed

+65
-29
lines changed

4 files changed

+65
-29
lines changed

io_uring/io-wq.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,9 +1151,6 @@ struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data)
11511151
wq = kzalloc(sizeof(struct io_wq), GFP_KERNEL);
11521152
if (!wq)
11531153
return ERR_PTR(-ENOMEM);
1154-
ret = cpuhp_state_add_instance_nocalls(io_wq_online, &wq->cpuhp_node);
1155-
if (ret)
1156-
goto err_wq;
11571154

11581155
refcount_inc(&data->hash->refs);
11591156
wq->hash = data->hash;
@@ -1186,13 +1183,14 @@ struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data)
11861183
wq->task = get_task_struct(data->task);
11871184
atomic_set(&wq->worker_refs, 1);
11881185
init_completion(&wq->worker_done);
1186+
ret = cpuhp_state_add_instance_nocalls(io_wq_online, &wq->cpuhp_node);
1187+
if (ret)
1188+
goto err;
1189+
11891190
return wq;
11901191
err:
11911192
io_wq_put_hash(data->hash);
1192-
cpuhp_state_remove_instance_nocalls(io_wq_online, &wq->cpuhp_node);
1193-
11941193
free_cpumask_var(wq->cpu_mask);
1195-
err_wq:
11961194
kfree(wq);
11971195
return ERR_PTR(ret);
11981196
}

io_uring/io_uring.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2686,7 +2686,7 @@ static void *__io_uaddr_map(struct page ***pages, unsigned short *npages,
26862686
{
26872687
struct page **page_array;
26882688
unsigned int nr_pages;
2689-
int ret;
2689+
int ret, i;
26902690

26912691
*npages = 0;
26922692

@@ -2716,6 +2716,20 @@ static void *__io_uaddr_map(struct page ***pages, unsigned short *npages,
27162716
*/
27172717
if (page_array[0] != page_array[ret - 1])
27182718
goto err;
2719+
2720+
/*
2721+
* Can't support mapping user allocated ring memory on 32-bit archs
2722+
* where it could potentially reside in highmem. Just fail those with
2723+
* -EINVAL, just like we did on kernels that didn't support this
2724+
* feature.
2725+
*/
2726+
for (i = 0; i < nr_pages; i++) {
2727+
if (PageHighMem(page_array[i])) {
2728+
ret = -EINVAL;
2729+
goto err;
2730+
}
2731+
}
2732+
27192733
*pages = page_array;
27202734
*npages = nr_pages;
27212735
return page_to_virt(page_array[0]);

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
{

io_uring/kbuf.c

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -477,14 +477,25 @@ static int io_pin_pbuf_ring(struct io_uring_buf_reg *reg,
477477
{
478478
struct io_uring_buf_ring *br;
479479
struct page **pages;
480-
int nr_pages;
480+
int i, nr_pages;
481481

482482
pages = io_pin_pages(reg->ring_addr,
483483
flex_array_size(br, bufs, reg->ring_entries),
484484
&nr_pages);
485485
if (IS_ERR(pages))
486486
return PTR_ERR(pages);
487487

488+
/*
489+
* Apparently some 32-bit boxes (ARM) will return highmem pages,
490+
* which then need to be mapped. We could support that, but it'd
491+
* complicate the code and slowdown the common cases quite a bit.
492+
* So just error out, returning -EINVAL just like we did on kernels
493+
* that didn't support mapped buffer rings.
494+
*/
495+
for (i = 0; i < nr_pages; i++)
496+
if (PageHighMem(pages[i]))
497+
goto error_unpin;
498+
488499
br = page_address(pages[0]);
489500
#ifdef SHM_COLOUR
490501
/*
@@ -496,20 +507,20 @@ static int io_pin_pbuf_ring(struct io_uring_buf_reg *reg,
496507
* should use IOU_PBUF_RING_MMAP instead, and liburing will handle
497508
* this transparently.
498509
*/
499-
if ((reg->ring_addr | (unsigned long) br) & (SHM_COLOUR - 1)) {
500-
int i;
501-
502-
for (i = 0; i < nr_pages; i++)
503-
unpin_user_page(pages[i]);
504-
return -EINVAL;
505-
}
510+
if ((reg->ring_addr | (unsigned long) br) & (SHM_COLOUR - 1))
511+
goto error_unpin;
506512
#endif
507513
bl->buf_pages = pages;
508514
bl->buf_nr_pages = nr_pages;
509515
bl->buf_ring = br;
510516
bl->is_mapped = 1;
511517
bl->is_mmap = 0;
512518
return 0;
519+
error_unpin:
520+
for (i = 0; i < nr_pages; i++)
521+
unpin_user_page(pages[i]);
522+
kvfree(pages);
523+
return -EINVAL;
513524
}
514525

515526
static int io_alloc_pbuf_ring(struct io_uring_buf_reg *reg,

0 commit comments

Comments
 (0)