Browse Source

kernel: pipe: runtime error checking

Add runtime error checking to k_pipe_cleanup and k_pipe_get and remove
asserts.
Adapted test which was expecting a fault to handle errors instead.

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
pull/22056/head
Anas Nashif 6 years ago
parent
commit
361a84d07f
  1. 5
      include/kernel.h
  2. 26
      kernel/pipes.c
  3. 14
      tests/kernel/pipe/pipe/src/test_pipe.c

5
include/kernel.h

@ -4155,9 +4155,11 @@ void k_pipe_init(struct k_pipe *pipe, unsigned char *buffer, size_t size); @@ -4155,9 +4155,11 @@ void k_pipe_init(struct k_pipe *pipe, unsigned char *buffer, size_t size);
* if the buffer wasn't dynamically allocated.
*
* @param pipe Address of the pipe.
* @retval 0 on success
* @retval -EAGAIN nothing to cleanup
* @req K-PIPE-002
*/
void k_pipe_cleanup(struct k_pipe *pipe);
int k_pipe_cleanup(struct k_pipe *pipe);
/**
* @brief Initialize a pipe and allocate a buffer for it
@ -4216,6 +4218,7 @@ __syscall int k_pipe_put(struct k_pipe *pipe, void *data, @@ -4216,6 +4218,7 @@ __syscall int k_pipe_put(struct k_pipe *pipe, void *data,
* and K_FOREVER.
*
* @retval 0 At least @a min_xfer bytes of data were read.
* @retval -EINVAL invalid parameters supplied
* @retval -EIO Returned without waiting; zero data bytes were read.
* @retval -EAGAIN Waiting period timed out; between zero and @a min_xfer
* minus one data bytes were read.

26
kernel/pipes.c

@ -20,8 +20,8 @@ @@ -20,8 +20,8 @@
#include <sys/dlist.h>
#include <init.h>
#include <syscall_handler.h>
#include <sys/__assert.h>
#include <kernel_internal.h>
#include <sys/check.h>
struct k_pipe_desc {
unsigned char *buffer; /* Position in src/dest buffer */
@ -174,16 +174,19 @@ static inline int z_vrfy_k_pipe_alloc_init(struct k_pipe *pipe, size_t size) @@ -174,16 +174,19 @@ static inline int z_vrfy_k_pipe_alloc_init(struct k_pipe *pipe, size_t size)
#include <syscalls/k_pipe_alloc_init_mrsh.c>
#endif
void k_pipe_cleanup(struct k_pipe *pipe)
int k_pipe_cleanup(struct k_pipe *pipe)
{
__ASSERT_NO_MSG(!z_waitq_head(&pipe->wait_q.readers));
__ASSERT_NO_MSG(!z_waitq_head(&pipe->wait_q.writers));
CHECKIF(z_waitq_head(&pipe->wait_q.readers) != NULL ||
z_waitq_head(&pipe->wait_q.writers) != NULL) {
return -EAGAIN;
}
if ((pipe->flags & K_PIPE_FLAG_ALLOC) != 0) {
k_free(pipe->buffer);
pipe->buffer = NULL;
pipe->flags &= ~K_PIPE_FLAG_ALLOC;
}
return 0;
}
/**
@ -438,6 +441,10 @@ int z_pipe_put_internal(struct k_pipe *pipe, struct k_pipe_async *async_desc, @@ -438,6 +441,10 @@ int z_pipe_put_internal(struct k_pipe *pipe, struct k_pipe_async *async_desc,
ARG_UNUSED(async_desc);
#endif
CHECKIF((min_xfer > bytes_to_write) || bytes_written == NULL) {
return -EINVAL;
}
k_spinlock_key_t key = k_spin_lock(&pipe->lock);
/*
@ -577,8 +584,9 @@ int z_impl_k_pipe_get(struct k_pipe *pipe, void *data, size_t bytes_to_read, @@ -577,8 +584,9 @@ int z_impl_k_pipe_get(struct k_pipe *pipe, void *data, size_t bytes_to_read,
size_t num_bytes_read = 0;
size_t bytes_copied;
__ASSERT(min_xfer <= bytes_to_read, "");
__ASSERT(bytes_read != NULL, "");
CHECKIF((min_xfer > bytes_to_read) || bytes_read == NULL) {
return -EINVAL;
}
k_spinlock_key_t key = k_spin_lock(&pipe->lock);
@ -586,7 +594,6 @@ int z_impl_k_pipe_get(struct k_pipe *pipe, void *data, size_t bytes_to_read, @@ -586,7 +594,6 @@ int z_impl_k_pipe_get(struct k_pipe *pipe, void *data, size_t bytes_to_read,
* Create a list of "working readers" into which the data will be
* directly copied.
*/
if (!pipe_xfer_prepare(&xfer_list, &writer, &pipe->wait_q.writers,
pipe->bytes_used, bytes_to_read,
min_xfer, timeout)) {
@ -718,7 +725,6 @@ int z_vrfy_k_pipe_get(struct k_pipe *pipe, void *data, size_t bytes_to_read, @@ -718,7 +725,6 @@ int z_vrfy_k_pipe_get(struct k_pipe *pipe, void *data, size_t bytes_to_read,
Z_OOPS(Z_SYSCALL_OBJ(pipe, K_OBJ_PIPE));
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(bytes_read, sizeof(*bytes_read)));
Z_OOPS(Z_SYSCALL_MEMORY_WRITE((void *)data, bytes_to_read));
Z_OOPS(Z_SYSCALL_VERIFY(min_xfer <= bytes_to_read));
return z_impl_k_pipe_get((struct k_pipe *)pipe, (void *)data,
bytes_to_read, bytes_read, min_xfer,
@ -730,9 +736,6 @@ int z_vrfy_k_pipe_get(struct k_pipe *pipe, void *data, size_t bytes_to_read, @@ -730,9 +736,6 @@ int z_vrfy_k_pipe_get(struct k_pipe *pipe, void *data, size_t bytes_to_read,
int z_impl_k_pipe_put(struct k_pipe *pipe, void *data, size_t bytes_to_write,
size_t *bytes_written, size_t min_xfer, s32_t timeout)
{
__ASSERT(min_xfer <= bytes_to_write, "");
__ASSERT(bytes_written != NULL, "");
return z_pipe_put_internal(pipe, NULL, data,
bytes_to_write, bytes_written,
min_xfer, timeout);
@ -745,7 +748,6 @@ int z_vrfy_k_pipe_put(struct k_pipe *pipe, void *data, size_t bytes_to_write, @@ -745,7 +748,6 @@ int z_vrfy_k_pipe_put(struct k_pipe *pipe, void *data, size_t bytes_to_write,
Z_OOPS(Z_SYSCALL_OBJ(pipe, K_OBJ_PIPE));
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(bytes_written, sizeof(*bytes_written)));
Z_OOPS(Z_SYSCALL_MEMORY_READ((void *)data, bytes_to_write));
Z_OOPS(Z_SYSCALL_VERIFY(min_xfer <= bytes_to_write));
return z_impl_k_pipe_put((struct k_pipe *)pipe, (void *)data,
bytes_to_write, bytes_written, min_xfer,

14
tests/kernel/pipe/pipe/src/test_pipe.c

@ -813,22 +813,16 @@ void test_pipe_get_timeout(void) @@ -813,22 +813,16 @@ void test_pipe_get_timeout(void)
* @ingroup kernel_pipe_tests
* @see k_pipe_get()
*/
#ifdef CONFIG_USERSPACE
/* userspace invalid size */
void test_pipe_get_invalid_size(void)
{
size_t read;
int ret;
valid_fault = true;
k_pipe_get(&test_pipe, &rx_buffer,
ret = k_pipe_get(&test_pipe, &rx_buffer,
0, &read,
1, TIMEOUT_200MSEC);
zassert_unreachable("fault didn't occur for min_xfer <= bytes_to_read");
zassert_equal(ret, -EINVAL,
"fault didn't occur for min_xfer <= bytes_to_read");
}
#else
void test_pipe_get_invalid_size(void)
{
ztest_test_skip();
}
#endif

Loading…
Cancel
Save