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 <peter.mitsis@intel.com>
This commit is contained in:
Peter Mitsis 2021-10-01 15:36:27 -04:00 committed by Anas Nashif
parent 7aa874a251
commit da7fbad057

View file

@ -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;