diff options
author | Manuel Bentele | 2020-10-23 15:18:01 +0200 |
---|---|---|
committer | Manuel Bentele | 2020-10-23 15:18:01 +0200 |
commit | dbb41ce2b7f309d394054a6bd1e33afd578798a5 (patch) | |
tree | 6a31092063d9f2fb5ac5720ec6759040e793c3d5 /src/kernel/tests/lib/tst_buffers.c | |
parent | Set Linux kernel version to unknown if it is not detectable (diff) | |
download | xloop-dbb41ce2b7f309d394054a6bd1e33afd578798a5.tar.gz xloop-dbb41ce2b7f309d394054a6bd1e33afd578798a5.tar.xz xloop-dbb41ce2b7f309d394054a6bd1e33afd578798a5.zip |
Move the source code of all xloop components to the common 'src' directory
Diffstat (limited to 'src/kernel/tests/lib/tst_buffers.c')
-rw-r--r-- | src/kernel/tests/lib/tst_buffers.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/src/kernel/tests/lib/tst_buffers.c b/src/kernel/tests/lib/tst_buffers.c new file mode 100644 index 0000000..b8b597a --- /dev/null +++ b/src/kernel/tests/lib/tst_buffers.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2019 Cyril Hrubis <chrubis@suse.cz> + */ + +#include <sys/mman.h> +#include <stdlib.h> +#define TST_NO_DEFAULT_MAIN +#include "tst_test.h" + +struct map { + void *addr; + size_t size; + size_t buf_shift; + struct map *next; +}; + +static struct map *maps; + +static void setup_canary(struct map *map) +{ + size_t i; + char *buf = map->addr; + + for (i = 0; i < map->buf_shift/2; i++) { + char c = random(); + buf[map->buf_shift - i - 1] = c; + buf[i] = c; + } +} + +static void check_canary(struct map *map) +{ + size_t i; + char *buf = map->addr; + + for (i = 0; i < map->buf_shift/2; i++) { + if (buf[map->buf_shift - i - 1] != buf[i]) { + tst_res(TWARN, + "pid %i: buffer modified address %p[%zi]", + getpid(), (char*)map->addr + map->buf_shift, -i-1); + } + } +} + +void *tst_alloc(size_t size) +{ + size_t page_size = getpagesize(); + unsigned int pages = (size / page_size) + !!(size % page_size) + 1; + void *ret; + struct map *map = SAFE_MALLOC(sizeof(struct map)); + static int print_msg = 1; + + if (print_msg) { + tst_res(TINFO, "Test is using guarded buffers"); + print_msg = 0; + } + + ret = SAFE_MMAP(NULL, page_size * pages, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + + mprotect(ret + (pages-1) * page_size, page_size, PROT_NONE); + + map->addr = ret; + map->size = pages * page_size; + map->next = maps; + maps = map; + + if (size % page_size) + map->buf_shift = page_size - (size % page_size); + else + map->buf_shift = 0; + + setup_canary(map); + + return ret + map->buf_shift; +} + +static int count_iovec(int *sizes) +{ + int ret = 0; + + while (sizes[ret++] != -1); + + return ret - 1; +} + +struct iovec *tst_iovec_alloc(int sizes[]) +{ + int i, cnt = count_iovec(sizes); + struct iovec *iovec; + + if (cnt <= 0) + return NULL; + + iovec = tst_alloc(sizeof(struct iovec) * cnt); + + for (i = 0; i < cnt; i++) { + if (sizes[i]) { + iovec[i].iov_base = tst_alloc(sizes[i]); + iovec[i].iov_len = sizes[i]; + } else { + iovec[i].iov_base = NULL; + iovec[i].iov_base = 0; + } + } + + return iovec; +} + +void tst_buffers_alloc(struct tst_buffers bufs[]) +{ + unsigned int i; + + for (i = 0; bufs[i].ptr; i++) { + if (bufs[i].size) + *((void**)bufs[i].ptr) = tst_alloc(bufs[i].size); + else + *((void**)bufs[i].ptr) = tst_iovec_alloc(bufs[i].iov_sizes); + } +} + +char *tst_strdup(const char *str) +{ + size_t len = strlen(str); + char *ret = tst_alloc(len + 1); + return strcpy(ret, str); +} + +void tst_free_all(void) +{ + struct map *i = maps; + + while (i) { + struct map *j = i; + check_canary(i); + SAFE_MUNMAP(i->addr, i->size); + i = i->next; + free(j); + } + + maps = NULL; +} |