199 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (C) 2020 ARM Limited3 4#define _GNU_SOURCE5 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_SIZE21#define OVERFLOW MT_GRANULE_SIZE22 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 */ 027};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 else80 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}199