diff --git a/kernel-src/include/ringbuffer.h b/kernel-src/include/ringbuffer.h index 9164f8d5..dd1c577f 100644 --- a/kernel-src/include/ringbuffer.h +++ b/kernel-src/include/ringbuffer.h @@ -19,11 +19,13 @@ int ringbuffer_init(ringbuffer_t *ringbuffer, size_t size); void ringbuffer_destroy(ringbuffer_t *ringbuffer); // reads count bytes from ring buffer into buffer +// can accept a buffer in userspace // returns -1 if it was unable to read (due to EFAULT when copying a user page) // otherwise returns the number of bytes read size_t ringbuffer_read(ringbuffer_t* ringbuffer, void *buffer, size_t count); // writes count bytes from buffer into ring buffer +// can accept a buffer in userspace // returns -1 if it was unable to write (due to EFAULT when copying a user page) // otherwise returns the number of bytes read size_t ringbuffer_write(ringbuffer_t* ringbuffer, void *buffer, size_t count); @@ -33,6 +35,7 @@ size_t ringbuffer_write(ringbuffer_t* ringbuffer, void *buffer, size_t count); size_t ringbuffer_truncate(ringbuffer_t *ringbuffer, size_t count); // same as ringbuffer_read, but accepts an offset and does not update the read pointer +// can accept a buffer in userspace // returns -1 if it was unable to read (due to EFAULT when copying a user page) // otherwise returns the number of bytes read size_t ringbuffer_peek(ringbuffer_t *ringbuffer, void *buffer, uintmax_t offset, size_t count); diff --git a/kernel-src/lib/ringbuffer.c b/kernel-src/lib/ringbuffer.c index c81e1bfc..6f730df7 100644 --- a/kernel-src/lib/ringbuffer.c +++ b/kernel-src/lib/ringbuffer.c @@ -3,6 +3,7 @@ #include #include #include +#include int ringbuffer_init(ringbuffer_t *ringbuffer, size_t size) { ringbuffer->data = vmm_map(NULL, ROUND_UP(size, PAGE_SIZE), VMM_FLAGS_ALLOCATE, ARCH_MMU_FLAGS_WRITE | ARCH_MMU_FLAGS_READ | ARCH_MMU_FLAGS_NOEXEC, NULL); @@ -32,12 +33,14 @@ size_t ringbuffer_read(ringbuffer_t *ringbuffer, void *buffer, size_t count) { size_t firstpassremaining = ringbuffer->size - firstpassoffset; size_t firstpasscount = min(count, firstpassremaining); - memcpy(buffer, (void *)((uintptr_t)ringbuffer->data + firstpassoffset), firstpasscount); + if (USERCOPY_POSSIBLY_FROM_USER(buffer, (void *)((uintptr_t)ringbuffer->data + firstpassoffset), firstpasscount)) + return -1; if (firstpasscount == count) goto leave; - memcpy((void *)((uintptr_t)buffer + firstpasscount), ringbuffer->data, count - firstpasscount); + if (USERCOPY_POSSIBLY_FROM_USER((void *)((uintptr_t)buffer + firstpasscount), ringbuffer->data, count - firstpasscount)) + return -1; leave: ringbuffer->read += count; @@ -58,12 +61,14 @@ size_t ringbuffer_peek(ringbuffer_t *ringbuffer, void *buffer, uintmax_t offset, size_t firstpassremaining = ringbuffer->size - firstpassoffset; size_t firstpasscount = min(count, firstpassremaining); - memcpy(buffer, (void *)((uintptr_t)ringbuffer->data + firstpassoffset), firstpasscount); + if (USERCOPY_POSSIBLY_TO_USER(buffer, (void *)((uintptr_t)ringbuffer->data + firstpassoffset), firstpasscount)) + return -1; if (firstpasscount == count) return count; - memcpy((void *)((uintptr_t)buffer + firstpasscount), ringbuffer->data, count - firstpasscount); + if (USERCOPY_POSSIBLY_TO_USER((void *)((uintptr_t)buffer + firstpasscount), ringbuffer->data, count - firstpasscount)) + return -1; return count; } @@ -75,12 +80,14 @@ size_t ringbuffer_write(ringbuffer_t *ringbuffer, void *buffer, size_t count) { size_t firstpassremaining = ringbuffer->size - firstpassoffset; size_t firstpasscount = min(count, firstpassremaining); - memcpy((void *)((uintptr_t)ringbuffer->data + firstpassoffset), buffer, firstpasscount); + if (USERCOPY_POSSIBLY_FROM_USER((void *)((uintptr_t)ringbuffer->data + firstpassoffset), buffer, firstpasscount)) + return -1; - if (firstpasscount == count) + if (firstpasscount == count) goto leave; - memcpy(ringbuffer->data, (void *)((uintptr_t)buffer + firstpasscount), count - firstpasscount); + if (USERCOPY_POSSIBLY_FROM_USER(ringbuffer->data, (void *)((uintptr_t)buffer + firstpasscount), count - firstpasscount)) + return -1; leave: ringbuffer->write += count;