mirror of
https://github.com/xemu-project/xemu.git
synced 2026-07-11 01:24:41 +02:00
aio-posix: fix fdmon-io_uring.c timeout stack variable lifetime
io_uring_prep_timeout() stashes a pointer to the timespec struct rather than copying its fields. That means the struct must live until after the SQE has been submitted by io_uring_enter(2). add_timeout_sqe() violates this constraint because the SQE is not submitted within the function. Inline add_timeout_sqe() into fdmon_io_uring_wait() so that the struct lives at least as long as io_uring_enter(2). This fixes random hangs (bogus timeout values) when the kernel loads undefined timespec struct values from userspace after the original struct on the stack has been destroyed. Reported-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Message-ID: <20251104022933.618123-3-stefanha@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
committed by
Kevin Wolf
parent
dbf70f0a03
commit
c31a445749
+12
-15
@@ -188,20 +188,6 @@ static void add_poll_remove_sqe(AioContext *ctx, AioHandler *node)
|
||||
io_uring_sqe_set_data(sqe, NULL);
|
||||
}
|
||||
|
||||
/* Add a timeout that self-cancels when another cqe becomes ready */
|
||||
static void add_timeout_sqe(AioContext *ctx, int64_t ns)
|
||||
{
|
||||
struct io_uring_sqe *sqe;
|
||||
struct __kernel_timespec ts = {
|
||||
.tv_sec = ns / NANOSECONDS_PER_SECOND,
|
||||
.tv_nsec = ns % NANOSECONDS_PER_SECOND,
|
||||
};
|
||||
|
||||
sqe = get_sqe(ctx);
|
||||
io_uring_prep_timeout(sqe, &ts, 1, 0);
|
||||
io_uring_sqe_set_data(sqe, NULL);
|
||||
}
|
||||
|
||||
/* Add sqes from ctx->submit_list for submission */
|
||||
static void fill_sq_ring(AioContext *ctx)
|
||||
{
|
||||
@@ -291,13 +277,24 @@ static int process_cq_ring(AioContext *ctx, AioHandlerList *ready_list)
|
||||
static int fdmon_io_uring_wait(AioContext *ctx, AioHandlerList *ready_list,
|
||||
int64_t timeout)
|
||||
{
|
||||
struct __kernel_timespec ts;
|
||||
unsigned wait_nr = 1; /* block until at least one cqe is ready */
|
||||
int ret;
|
||||
|
||||
if (timeout == 0) {
|
||||
wait_nr = 0; /* non-blocking */
|
||||
} else if (timeout > 0) {
|
||||
add_timeout_sqe(ctx, timeout);
|
||||
/* Add a timeout that self-cancels when another cqe becomes ready */
|
||||
struct io_uring_sqe *sqe;
|
||||
|
||||
ts = (struct __kernel_timespec){
|
||||
.tv_sec = timeout / NANOSECONDS_PER_SECOND,
|
||||
.tv_nsec = timeout % NANOSECONDS_PER_SECOND,
|
||||
};
|
||||
|
||||
sqe = get_sqe(ctx);
|
||||
io_uring_prep_timeout(sqe, &ts, 1, 0);
|
||||
io_uring_sqe_set_data(sqe, NULL);
|
||||
}
|
||||
|
||||
fill_sq_ring(ctx);
|
||||
|
||||
Reference in New Issue
Block a user