From da7fbad057013a8d9a280d96afe81a0cf409b7a6 Mon Sep 17 00:00:00 2001 From: Peter Mitsis Date: Fri, 1 Oct 2021 15:36:27 -0400 Subject: [PATCH] kernel: pipes: fix race condition Fixes a race condition in the k_pipe_cleanup() routine by adding a spinlock. Additionally, internal counters are now reset after freeing the buffer as the pipe has now become a bufferless pipe. Signed-off-by: Peter Mitsis --- kernel/pipes.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/kernel/pipes.c b/kernel/pipes.c index 40edec93736..83d1e6f8bf6 100644 --- a/kernel/pipes.c +++ b/kernel/pipes.c @@ -82,8 +82,12 @@ int k_pipe_cleanup(struct k_pipe *pipe) { SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_pipe, cleanup, pipe); + k_spinlock_key_t key = k_spin_lock(&pipe->lock); + CHECKIF(z_waitq_head(&pipe->wait_q.readers) != NULL || z_waitq_head(&pipe->wait_q.writers) != NULL) { + k_spin_unlock(&pipe->lock, key); + SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_pipe, cleanup, pipe, -EAGAIN); return -EAGAIN; @@ -92,9 +96,21 @@ int k_pipe_cleanup(struct k_pipe *pipe) if ((pipe->flags & K_PIPE_FLAG_ALLOC) != 0U) { k_free(pipe->buffer); pipe->buffer = NULL; + + /* + * Freeing the buffer changes the pipe into a bufferless + * pipe. Reset the pipe's counters to prevent malfunction. + */ + + pipe->size = 0; + pipe->bytes_used = 0; + pipe->read_index = 0; + pipe->write_index = 0; pipe->flags &= ~K_PIPE_FLAG_ALLOC; } + k_spin_unlock(&pipe->lock, key); + SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_pipe, cleanup, pipe, 0); return 0;