cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

check_child_memory.c (6761B)


      1// SPDX-License-Identifier: GPL-2.0
      2// Copyright (C) 2020 ARM Limited
      3
      4#define _GNU_SOURCE
      5
      6#include <errno.h>
      7#include <signal.h>
      8#include <stdio.h>
      9#include <stdlib.h>
     10#include <string.h>
     11#include <ucontext.h>
     12#include <sys/wait.h>
     13
     14#include "kselftest.h"
     15#include "mte_common_util.h"
     16#include "mte_def.h"
     17
     18#define BUFFER_SIZE		(5 * MT_GRANULE_SIZE)
     19#define RUNS			(MT_TAG_COUNT)
     20#define UNDERFLOW		MT_GRANULE_SIZE
     21#define OVERFLOW		MT_GRANULE_SIZE
     22
     23static size_t page_size;
     24static int sizes[] = {
     25	1, 537, 989, 1269, MT_GRANULE_SIZE - 1, MT_GRANULE_SIZE,
     26	/* page size - 1*/ 0, /* page_size */ 0, /* page size + 1 */ 0
     27};
     28
     29static int check_child_tag_inheritance(char *ptr, int size, int mode)
     30{
     31	int i, parent_tag, child_tag, fault, child_status;
     32	pid_t child;
     33
     34	parent_tag = MT_FETCH_TAG((uintptr_t)ptr);
     35	fault = 0;
     36
     37	child = fork();
     38	if (child == -1) {
     39		ksft_print_msg("FAIL: child process creation\n");
     40		return KSFT_FAIL;
     41	} else if (child == 0) {
     42		mte_initialize_current_context(mode, (uintptr_t)ptr, size);
     43		/* Do copy on write */
     44		memset(ptr, '1', size);
     45		mte_wait_after_trig();
     46		if (cur_mte_cxt.fault_valid == true) {
     47			fault = 1;
     48			goto check_child_tag_inheritance_err;
     49		}
     50		for (i = 0 ; i < size ; i += MT_GRANULE_SIZE) {
     51			child_tag = MT_FETCH_TAG((uintptr_t)(mte_get_tag_address(ptr + i)));
     52			if (parent_tag != child_tag) {
     53				ksft_print_msg("FAIL: child mte tag mismatch\n");
     54				fault = 1;
     55				goto check_child_tag_inheritance_err;
     56			}
     57		}
     58		mte_initialize_current_context(mode, (uintptr_t)ptr, -UNDERFLOW);
     59		memset(ptr - UNDERFLOW, '2', UNDERFLOW);
     60		mte_wait_after_trig();
     61		if (cur_mte_cxt.fault_valid == false) {
     62			fault = 1;
     63			goto check_child_tag_inheritance_err;
     64		}
     65		mte_initialize_current_context(mode, (uintptr_t)ptr, size + OVERFLOW);
     66		memset(ptr + size, '3', OVERFLOW);
     67		mte_wait_after_trig();
     68		if (cur_mte_cxt.fault_valid == false) {
     69			fault = 1;
     70			goto check_child_tag_inheritance_err;
     71		}
     72check_child_tag_inheritance_err:
     73		_exit(fault);
     74	}
     75	/* Wait for child process to terminate */
     76	wait(&child_status);
     77	if (WIFEXITED(child_status))
     78		fault = WEXITSTATUS(child_status);
     79	else
     80		fault = 1;
     81	return (fault) ? KSFT_FAIL : KSFT_PASS;
     82}
     83
     84static int check_child_memory_mapping(int mem_type, int mode, int mapping)
     85{
     86	char *ptr;
     87	int run, result;
     88	int item = ARRAY_SIZE(sizes);
     89
     90	item = ARRAY_SIZE(sizes);
     91	mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);
     92	for (run = 0; run < item; run++) {
     93		ptr = (char *)mte_allocate_memory_tag_range(sizes[run], mem_type, mapping,
     94							    UNDERFLOW, OVERFLOW);
     95		if (check_allocated_memory_range(ptr, sizes[run], mem_type,
     96						 UNDERFLOW, OVERFLOW) != KSFT_PASS)
     97			return KSFT_FAIL;
     98		result = check_child_tag_inheritance(ptr, sizes[run], mode);
     99		mte_free_memory_tag_range((void *)ptr, sizes[run], mem_type, UNDERFLOW, OVERFLOW);
    100		if (result == KSFT_FAIL)
    101			return result;
    102	}
    103	return KSFT_PASS;
    104}
    105
    106static int check_child_file_mapping(int mem_type, int mode, int mapping)
    107{
    108	char *ptr, *map_ptr;
    109	int run, fd, map_size, result = KSFT_PASS;
    110	int total = ARRAY_SIZE(sizes);
    111
    112	mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);
    113	for (run = 0; run < total; run++) {
    114		fd = create_temp_file();
    115		if (fd == -1)
    116			return KSFT_FAIL;
    117
    118		map_size = sizes[run] + OVERFLOW + UNDERFLOW;
    119		map_ptr = (char *)mte_allocate_file_memory(map_size, mem_type, mapping, false, fd);
    120		if (check_allocated_memory(map_ptr, map_size, mem_type, false) != KSFT_PASS) {
    121			close(fd);
    122			return KSFT_FAIL;
    123		}
    124		ptr = map_ptr + UNDERFLOW;
    125		mte_initialize_current_context(mode, (uintptr_t)ptr, sizes[run]);
    126		/* Only mte enabled memory will allow tag insertion */
    127		ptr = mte_insert_tags((void *)ptr, sizes[run]);
    128		if (!ptr || cur_mte_cxt.fault_valid == true) {
    129			ksft_print_msg("FAIL: Insert tags on file based memory\n");
    130			munmap((void *)map_ptr, map_size);
    131			close(fd);
    132			return KSFT_FAIL;
    133		}
    134		result = check_child_tag_inheritance(ptr, sizes[run], mode);
    135		mte_clear_tags((void *)ptr, sizes[run]);
    136		munmap((void *)map_ptr, map_size);
    137		close(fd);
    138		if (result != KSFT_PASS)
    139			return KSFT_FAIL;
    140	}
    141	return KSFT_PASS;
    142}
    143
    144int main(int argc, char *argv[])
    145{
    146	int err;
    147	int item = ARRAY_SIZE(sizes);
    148
    149	page_size = getpagesize();
    150	if (!page_size) {
    151		ksft_print_msg("ERR: Unable to get page size\n");
    152		return KSFT_FAIL;
    153	}
    154	sizes[item - 3] = page_size - 1;
    155	sizes[item - 2] = page_size;
    156	sizes[item - 1] = page_size + 1;
    157
    158	err = mte_default_setup();
    159	if (err)
    160		return err;
    161
    162	/* Register SIGSEGV handler */
    163	mte_register_signal(SIGSEGV, mte_default_handler);
    164	mte_register_signal(SIGBUS, mte_default_handler);
    165
    166	/* Set test plan */
    167	ksft_set_plan(12);
    168
    169	evaluate_test(check_child_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE),
    170		"Check child anonymous memory with private mapping, precise mode and mmap memory\n");
    171	evaluate_test(check_child_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_SHARED),
    172		"Check child anonymous memory with shared mapping, precise mode and mmap memory\n");
    173	evaluate_test(check_child_memory_mapping(USE_MMAP, MTE_ASYNC_ERR, MAP_PRIVATE),
    174		"Check child anonymous memory with private mapping, imprecise mode and mmap memory\n");
    175	evaluate_test(check_child_memory_mapping(USE_MMAP, MTE_ASYNC_ERR, MAP_SHARED),
    176		"Check child anonymous memory with shared mapping, imprecise mode and mmap memory\n");
    177	evaluate_test(check_child_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_PRIVATE),
    178		"Check child anonymous memory with private mapping, precise mode and mmap/mprotect memory\n");
    179	evaluate_test(check_child_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_SHARED),
    180		"Check child anonymous memory with shared mapping, precise mode and mmap/mprotect memory\n");
    181
    182	evaluate_test(check_child_file_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE),
    183		"Check child file memory with private mapping, precise mode and mmap memory\n");
    184	evaluate_test(check_child_file_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_SHARED),
    185		"Check child file memory with shared mapping, precise mode and mmap memory\n");
    186	evaluate_test(check_child_memory_mapping(USE_MMAP, MTE_ASYNC_ERR, MAP_PRIVATE),
    187		"Check child file memory with private mapping, imprecise mode and mmap memory\n");
    188	evaluate_test(check_child_memory_mapping(USE_MMAP, MTE_ASYNC_ERR, MAP_SHARED),
    189		"Check child file memory with shared mapping, imprecise mode and mmap memory\n");
    190	evaluate_test(check_child_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_PRIVATE),
    191		"Check child file memory with private mapping, precise mode and mmap/mprotect memory\n");
    192	evaluate_test(check_child_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_SHARED),
    193		"Check child file memory with shared mapping, precise mode and mmap/mprotect memory\n");
    194
    195	mte_restore_setup();
    196	ksft_print_cnts();
    197	return ksft_get_fail_cnt() == 0 ? KSFT_PASS : KSFT_FAIL;
    198}