@@ -21,9 +21,16 @@ static char *buf3;
static void do_test(unsigned int n)
{
- int pid = SAFE_FORK();
+ int pid;
int status;
+ if (n == 6) {
+ buf1[-1] = 0;
+ buf3[-1] = 0;
+ tst_res(TPASS, "Buffers dirtied!");
+ }
+
+ pid = SAFE_FORK();
if (!pid) {
switch (n) {
case 0:
@@ -44,6 +51,10 @@ static void do_test(unsigned int n)
case 5:
buf3[BUF3_LEN] = 0;
break;
+ case 6:
+ buf1[-2] = 0;
+ buf3[-2] = 0;
+ break;
}
exit(0);
@@ -51,6 +62,9 @@ static void do_test(unsigned int n)
SAFE_WAITPID(pid, &status, 0);
+ if (n == 6)
+ return;
+
if (n < 3) {
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
tst_res(TPASS, "Exitted normally");
@@ -69,7 +83,7 @@ static void do_test(unsigned int n)
static struct tst_test test = {
.forks_child = 1,
.test = do_test,
- .tcnt = 6,
+ .tcnt = 7,
.bufs = (struct tst_buffers []) {
{&buf1, .size = BUF1_LEN},
{&buf2, .size = BUF2_LEN},
@@ -11,11 +11,38 @@
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();
@@ -40,9 +67,13 @@ void *tst_alloc(size_t size)
maps = map;
if (size % page_size)
- ret += page_size - (size % page_size);
+ map->buf_shift = page_size - (size % page_size);
+ else
+ map->buf_shift = 0;
+
+ setup_canary(map);
- return ret;
+ return ret + map->buf_shift;
}
static int count_iovec(int *sizes)
@@ -102,6 +133,7 @@ void tst_free_all(void)
while (i) {
struct map *j = i;
+ check_canary(i);
SAFE_MUNMAP(i->addr, i->size);
i = i->next;
free(j);
@@ -390,6 +390,9 @@ pid_t safe_fork(const char *filename, unsigned int lineno)
if (pid < 0)
tst_brk_(filename, lineno, TBROK | TERRNO, "fork() failed");
+ if (!pid)
+ atexit(tst_free_all);
+
return pid;
}
In a case that the buffer size is not a multiple of a page size there is unused space before the start of the buffer. Let's fill that with center mirrored random bytes and check that the buffer wasn't modified before we unmap it. The tst_free_all() function is also set to be executed atexit() in the safe_fork() function for all child processes, which guaratees that canaries are checked in child processes as well. Signed-off-by: Cyril Hrubis <chrubis@suse.cz> --- lib/newlib_tests/test_guarded_buf.c | 18 +++++++++++++-- lib/tst_buffers.c | 36 +++++++++++++++++++++++++++-- lib/tst_test.c | 3 +++ 3 files changed, 53 insertions(+), 4 deletions(-)