diff options
author | Jens Axboe <axboe@kernel.dk> | 2019-04-17 09:25:32 -0600 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2019-04-17 09:42:23 -0600 |
commit | 76b61ebf1bd17d3a31c3bf2d8236b9bd50d0f9a8 (patch) | |
tree | c2216573054fa22dab7e9c5672ba60a3ae28fbb1 /src | |
parent | 26993e98723e1f2d9be94b53068ead1e4a9a849d (diff) |
Add io_uring_cqe_seen()
There's a failure case where an application gets a cqe entry, but
the kernel can then overwrite it before the application is done
reading it. This can happen since the io_uring_{get,wait}_completion()
interface both returns a CQE pointer AND increments the ring index.
If the kernel reuses this entry before the applications is done reading
it, the contents may be corrupted.
Remove the CQ head increment from the CQE retrieval, and put it into
a separate helper, io_uring_cqe_seen(). The application must call this
helper when it got a new CQE entry through one of the above calls, and
it's now done reading it.
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'src')
-rw-r--r-- | src/liburing.h | 20 | ||||
-rw-r--r-- | src/queue.c | 9 |
2 files changed, 20 insertions, 9 deletions
diff --git a/src/liburing.h b/src/liburing.h index a544fa5..158239a 100644 --- a/src/liburing.h +++ b/src/liburing.h @@ -6,6 +6,7 @@ #include <inttypes.h> #include "compat.h" #include "io_uring.h" +#include "barrier.h" /* * Library interface to io_uring @@ -68,6 +69,25 @@ extern int io_uring_submit(struct io_uring *ring); extern struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring); /* + * Must be called after io_uring_{get,wait}_completion() after the cqe has + * been processed by the application. + */ +static inline void io_uring_cqe_seen(struct io_uring *ring, + struct io_uring_cqe *cqe) +{ + if (cqe) { + struct io_uring_cq *cq = &ring->cq; + + (*cq->khead)++; + /* + * Ensure that the kernel sees our new head, the kernel has + * the matching read barrier. + */ + write_barrier(); + } +} + +/* * Command prep helpers */ static inline void io_uring_sqe_set_data(struct io_uring_sqe *sqe, void *data) diff --git a/src/queue.c b/src/queue.c index 6767790..72b3af2 100644 --- a/src/queue.c +++ b/src/queue.c @@ -41,15 +41,6 @@ static int __io_uring_get_completion(struct io_uring *ring, return -errno; } while (1); - if (*cqe_ptr) { - *cq->khead = head + 1; - /* - * Ensure that the kernel sees our new head, the kernel has - * the matching read barrier. - */ - write_barrier(); - } - return 0; } |