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>
This commit is contained in:
Anas Nashif 2019-06-16 08:22:08 -04:00
commit 361a84d07f
3 changed files with 22 additions and 23 deletions

View file

@ -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. * if the buffer wasn't dynamically allocated.
* *
* @param pipe Address of the pipe. * @param pipe Address of the pipe.
* @retval 0 on success
* @retval -EAGAIN nothing to cleanup
* @req K-PIPE-002 * @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 * @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,
* and K_FOREVER. * and K_FOREVER.
* *
* @retval 0 At least @a min_xfer bytes of data were read. * @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 -EIO Returned without waiting; zero data bytes were read.
* @retval -EAGAIN Waiting period timed out; between zero and @a min_xfer * @retval -EAGAIN Waiting period timed out; between zero and @a min_xfer
* minus one data bytes were read. * minus one data bytes were read.

View file

@ -20,8 +20,8 @@
#include <sys/dlist.h> #include <sys/dlist.h>
#include <init.h> #include <init.h>
#include <syscall_handler.h> #include <syscall_handler.h>
#include <sys/__assert.h>
#include <kernel_internal.h> #include <kernel_internal.h>
#include <sys/check.h>
struct k_pipe_desc { struct k_pipe_desc {
unsigned char *buffer; /* Position in src/dest buffer */ 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)
#include <syscalls/k_pipe_alloc_init_mrsh.c> #include <syscalls/k_pipe_alloc_init_mrsh.c>
#endif #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)); CHECKIF(z_waitq_head(&pipe->wait_q.readers) != NULL ||
__ASSERT_NO_MSG(!z_waitq_head(&pipe->wait_q.writers)); z_waitq_head(&pipe->wait_q.writers) != NULL) {
return -EAGAIN;
}
if ((pipe->flags & K_PIPE_FLAG_ALLOC) != 0) { if ((pipe->flags & K_PIPE_FLAG_ALLOC) != 0) {
k_free(pipe->buffer); k_free(pipe->buffer);
pipe->buffer = NULL; pipe->buffer = NULL;
pipe->flags &= ~K_PIPE_FLAG_ALLOC; 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,
ARG_UNUSED(async_desc); ARG_UNUSED(async_desc);
#endif #endif
CHECKIF((min_xfer > bytes_to_write) || bytes_written == NULL) {
return -EINVAL;
}
k_spinlock_key_t key = k_spin_lock(&pipe->lock); 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,
size_t num_bytes_read = 0; size_t num_bytes_read = 0;
size_t bytes_copied; size_t bytes_copied;
__ASSERT(min_xfer <= bytes_to_read, ""); CHECKIF((min_xfer > bytes_to_read) || bytes_read == NULL) {
__ASSERT(bytes_read != NULL, ""); return -EINVAL;
}
k_spinlock_key_t key = k_spin_lock(&pipe->lock); 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,
* Create a list of "working readers" into which the data will be * Create a list of "working readers" into which the data will be
* directly copied. * directly copied.
*/ */
if (!pipe_xfer_prepare(&xfer_list, &writer, &pipe->wait_q.writers, if (!pipe_xfer_prepare(&xfer_list, &writer, &pipe->wait_q.writers,
pipe->bytes_used, bytes_to_read, pipe->bytes_used, bytes_to_read,
min_xfer, timeout)) { min_xfer, timeout)) {
@ -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_OBJ(pipe, K_OBJ_PIPE));
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(bytes_read, sizeof(*bytes_read))); 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_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, return z_impl_k_pipe_get((struct k_pipe *)pipe, (void *)data,
bytes_to_read, bytes_read, min_xfer, 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,
int z_impl_k_pipe_put(struct k_pipe *pipe, void *data, size_t bytes_to_write, 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) 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, return z_pipe_put_internal(pipe, NULL, data,
bytes_to_write, bytes_written, bytes_to_write, bytes_written,
min_xfer, timeout); min_xfer, timeout);
@ -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_OBJ(pipe, K_OBJ_PIPE));
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(bytes_written, sizeof(*bytes_written))); 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_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, return z_impl_k_pipe_put((struct k_pipe *)pipe, (void *)data,
bytes_to_write, bytes_written, min_xfer, bytes_to_write, bytes_written, min_xfer,

View file

@ -813,22 +813,16 @@ void test_pipe_get_timeout(void)
* @ingroup kernel_pipe_tests * @ingroup kernel_pipe_tests
* @see k_pipe_get() * @see k_pipe_get()
*/ */
#ifdef CONFIG_USERSPACE
/* userspace invalid size */
void test_pipe_get_invalid_size(void) void test_pipe_get_invalid_size(void)
{ {
size_t read; size_t read;
int ret;
valid_fault = true; valid_fault = true;
k_pipe_get(&test_pipe, &rx_buffer, ret = k_pipe_get(&test_pipe, &rx_buffer,
0, &read, 0, &read,
1, TIMEOUT_200MSEC); 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