266 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (C) 2020 ARM Limited3 4#define _GNU_SOURCE5 6#include <errno.h>7#include <fcntl.h>8#include <signal.h>9#include <stdio.h>10#include <stdlib.h>11#include <string.h>12#include <ucontext.h>13#include <sys/mman.h>14#include <sys/stat.h>15#include <sys/types.h>16 17#include "kselftest.h"18#include "mte_common_util.h"19#include "mte_def.h"20 21#define RUNS (MT_TAG_COUNT)22#define UNDERFLOW MT_GRANULE_SIZE23#define OVERFLOW MT_GRANULE_SIZE24#define TAG_CHECK_ON 025#define TAG_CHECK_OFF 126 27static size_t page_size;28static int sizes[] = {29 1, 537, 989, 1269, MT_GRANULE_SIZE - 1, MT_GRANULE_SIZE,30 /* page size - 1*/ 0, /* page_size */ 0, /* page size + 1 */ 031};32 33static int check_mte_memory(char *ptr, int size, int mode, int tag_check)34{35 mte_initialize_current_context(mode, (uintptr_t)ptr, size);36 memset(ptr, '1', size);37 mte_wait_after_trig();38 if (cur_mte_cxt.fault_valid == true)39 return KSFT_FAIL;40 41 mte_initialize_current_context(mode, (uintptr_t)ptr, -UNDERFLOW);42 memset(ptr - UNDERFLOW, '2', UNDERFLOW);43 mte_wait_after_trig();44 if (cur_mte_cxt.fault_valid == false && tag_check == TAG_CHECK_ON)45 return KSFT_FAIL;46 if (cur_mte_cxt.fault_valid == true && tag_check == TAG_CHECK_OFF)47 return KSFT_FAIL;48 49 mte_initialize_current_context(mode, (uintptr_t)ptr, size + OVERFLOW);50 memset(ptr + size, '3', OVERFLOW);51 mte_wait_after_trig();52 if (cur_mte_cxt.fault_valid == false && tag_check == TAG_CHECK_ON)53 return KSFT_FAIL;54 if (cur_mte_cxt.fault_valid == true && tag_check == TAG_CHECK_OFF)55 return KSFT_FAIL;56 57 return KSFT_PASS;58}59 60static int check_anonymous_memory_mapping(int mem_type, int mode, int mapping, int tag_check)61{62 char *ptr, *map_ptr;63 int run, result, map_size;64 int item = ARRAY_SIZE(sizes);65 66 mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);67 for (run = 0; run < item; run++) {68 map_size = sizes[run] + OVERFLOW + UNDERFLOW;69 map_ptr = (char *)mte_allocate_memory(map_size, mem_type, mapping, false);70 if (check_allocated_memory(map_ptr, map_size, mem_type, false) != KSFT_PASS)71 return KSFT_FAIL;72 73 ptr = map_ptr + UNDERFLOW;74 mte_initialize_current_context(mode, (uintptr_t)ptr, sizes[run]);75 /* Only mte enabled memory will allow tag insertion */76 ptr = mte_insert_tags((void *)ptr, sizes[run]);77 if (!ptr || cur_mte_cxt.fault_valid == true) {78 ksft_print_msg("FAIL: Insert tags on anonymous mmap memory\n");79 munmap((void *)map_ptr, map_size);80 return KSFT_FAIL;81 }82 result = check_mte_memory(ptr, sizes[run], mode, tag_check);83 mte_clear_tags((void *)ptr, sizes[run]);84 mte_free_memory((void *)map_ptr, map_size, mem_type, false);85 if (result == KSFT_FAIL)86 return KSFT_FAIL;87 }88 return KSFT_PASS;89}90 91static int check_file_memory_mapping(int mem_type, int mode, int mapping, int tag_check)92{93 char *ptr, *map_ptr;94 int run, fd, map_size;95 int total = ARRAY_SIZE(sizes);96 int result = KSFT_PASS;97 98 mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);99 for (run = 0; run < total; run++) {100 fd = create_temp_file();101 if (fd == -1)102 return KSFT_FAIL;103 104 map_size = sizes[run] + UNDERFLOW + OVERFLOW;105 map_ptr = (char *)mte_allocate_file_memory(map_size, mem_type, mapping, false, fd);106 if (check_allocated_memory(map_ptr, map_size, mem_type, false) != KSFT_PASS) {107 close(fd);108 return KSFT_FAIL;109 }110 ptr = map_ptr + UNDERFLOW;111 mte_initialize_current_context(mode, (uintptr_t)ptr, sizes[run]);112 /* Only mte enabled memory will allow tag insertion */113 ptr = mte_insert_tags((void *)ptr, sizes[run]);114 if (!ptr || cur_mte_cxt.fault_valid == true) {115 ksft_print_msg("FAIL: Insert tags on file based memory\n");116 munmap((void *)map_ptr, map_size);117 close(fd);118 return KSFT_FAIL;119 }120 result = check_mte_memory(ptr, sizes[run], mode, tag_check);121 mte_clear_tags((void *)ptr, sizes[run]);122 munmap((void *)map_ptr, map_size);123 close(fd);124 if (result == KSFT_FAIL)125 break;126 }127 return result;128}129 130static int check_clear_prot_mte_flag(int mem_type, int mode, int mapping)131{132 char *ptr, *map_ptr;133 int run, prot_flag, result, fd, map_size;134 int total = ARRAY_SIZE(sizes);135 136 prot_flag = PROT_READ | PROT_WRITE;137 mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);138 for (run = 0; run < total; run++) {139 map_size = sizes[run] + OVERFLOW + UNDERFLOW;140 ptr = (char *)mte_allocate_memory_tag_range(sizes[run], mem_type, mapping,141 UNDERFLOW, OVERFLOW);142 if (check_allocated_memory_range(ptr, sizes[run], mem_type,143 UNDERFLOW, OVERFLOW) != KSFT_PASS)144 return KSFT_FAIL;145 map_ptr = ptr - UNDERFLOW;146 /* Try to clear PROT_MTE property and verify it by tag checking */147 if (mprotect(map_ptr, map_size, prot_flag)) {148 mte_free_memory_tag_range((void *)ptr, sizes[run], mem_type,149 UNDERFLOW, OVERFLOW);150 ksft_print_msg("FAIL: mprotect not ignoring clear PROT_MTE property\n");151 return KSFT_FAIL;152 }153 result = check_mte_memory(ptr, sizes[run], mode, TAG_CHECK_ON);154 mte_free_memory_tag_range((void *)ptr, sizes[run], mem_type, UNDERFLOW, OVERFLOW);155 if (result != KSFT_PASS)156 return KSFT_FAIL;157 158 fd = create_temp_file();159 if (fd == -1)160 return KSFT_FAIL;161 ptr = (char *)mte_allocate_file_memory_tag_range(sizes[run], mem_type, mapping,162 UNDERFLOW, OVERFLOW, fd);163 if (check_allocated_memory_range(ptr, sizes[run], mem_type,164 UNDERFLOW, OVERFLOW) != KSFT_PASS) {165 close(fd);166 return KSFT_FAIL;167 }168 map_ptr = ptr - UNDERFLOW;169 /* Try to clear PROT_MTE property and verify it by tag checking */170 if (mprotect(map_ptr, map_size, prot_flag)) {171 ksft_print_msg("FAIL: mprotect not ignoring clear PROT_MTE property\n");172 mte_free_memory_tag_range((void *)ptr, sizes[run], mem_type,173 UNDERFLOW, OVERFLOW);174 close(fd);175 return KSFT_FAIL;176 }177 result = check_mte_memory(ptr, sizes[run], mode, TAG_CHECK_ON);178 mte_free_memory_tag_range((void *)ptr, sizes[run], mem_type, UNDERFLOW, OVERFLOW);179 close(fd);180 if (result != KSFT_PASS)181 return KSFT_FAIL;182 }183 return KSFT_PASS;184}185 186int main(int argc, char *argv[])187{188 int err;189 int item = ARRAY_SIZE(sizes);190 191 err = mte_default_setup();192 if (err)193 return err;194 page_size = getpagesize();195 if (!page_size) {196 ksft_print_msg("ERR: Unable to get page size\n");197 return KSFT_FAIL;198 }199 sizes[item - 3] = page_size - 1;200 sizes[item - 2] = page_size;201 sizes[item - 1] = page_size + 1;202 203 /* Register signal handlers */204 mte_register_signal(SIGBUS, mte_default_handler);205 mte_register_signal(SIGSEGV, mte_default_handler);206 207 /* Set test plan */208 ksft_set_plan(22);209 210 mte_enable_pstate_tco();211 212 evaluate_test(check_anonymous_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE, TAG_CHECK_OFF),213 "Check anonymous memory with private mapping, sync error mode, mmap memory and tag check off\n");214 evaluate_test(check_file_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_PRIVATE, TAG_CHECK_OFF),215 "Check file memory with private mapping, sync error mode, mmap/mprotect memory and tag check off\n");216 217 mte_disable_pstate_tco();218 evaluate_test(check_anonymous_memory_mapping(USE_MMAP, MTE_NONE_ERR, MAP_PRIVATE, TAG_CHECK_OFF),219 "Check anonymous memory with private mapping, no error mode, mmap memory and tag check off\n");220 evaluate_test(check_file_memory_mapping(USE_MPROTECT, MTE_NONE_ERR, MAP_PRIVATE, TAG_CHECK_OFF),221 "Check file memory with private mapping, no error mode, mmap/mprotect memory and tag check off\n");222 223 evaluate_test(check_anonymous_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE, TAG_CHECK_ON),224 "Check anonymous memory with private mapping, sync error mode, mmap memory and tag check on\n");225 evaluate_test(check_anonymous_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_PRIVATE, TAG_CHECK_ON),226 "Check anonymous memory with private mapping, sync error mode, mmap/mprotect memory and tag check on\n");227 evaluate_test(check_anonymous_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_SHARED, TAG_CHECK_ON),228 "Check anonymous memory with shared mapping, sync error mode, mmap memory and tag check on\n");229 evaluate_test(check_anonymous_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_SHARED, TAG_CHECK_ON),230 "Check anonymous memory with shared mapping, sync error mode, mmap/mprotect memory and tag check on\n");231 evaluate_test(check_anonymous_memory_mapping(USE_MMAP, MTE_ASYNC_ERR, MAP_PRIVATE, TAG_CHECK_ON),232 "Check anonymous memory with private mapping, async error mode, mmap memory and tag check on\n");233 evaluate_test(check_anonymous_memory_mapping(USE_MPROTECT, MTE_ASYNC_ERR, MAP_PRIVATE, TAG_CHECK_ON),234 "Check anonymous memory with private mapping, async error mode, mmap/mprotect memory and tag check on\n");235 evaluate_test(check_anonymous_memory_mapping(USE_MMAP, MTE_ASYNC_ERR, MAP_SHARED, TAG_CHECK_ON),236 "Check anonymous memory with shared mapping, async error mode, mmap memory and tag check on\n");237 evaluate_test(check_anonymous_memory_mapping(USE_MPROTECT, MTE_ASYNC_ERR, MAP_SHARED, TAG_CHECK_ON),238 "Check anonymous memory with shared mapping, async error mode, mmap/mprotect memory and tag check on\n");239 240 evaluate_test(check_file_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE, TAG_CHECK_ON),241 "Check file memory with private mapping, sync error mode, mmap memory and tag check on\n");242 evaluate_test(check_file_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_PRIVATE, TAG_CHECK_ON),243 "Check file memory with private mapping, sync error mode, mmap/mprotect memory and tag check on\n");244 evaluate_test(check_file_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_SHARED, TAG_CHECK_ON),245 "Check file memory with shared mapping, sync error mode, mmap memory and tag check on\n");246 evaluate_test(check_file_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_SHARED, TAG_CHECK_ON),247 "Check file memory with shared mapping, sync error mode, mmap/mprotect memory and tag check on\n");248 evaluate_test(check_file_memory_mapping(USE_MMAP, MTE_ASYNC_ERR, MAP_PRIVATE, TAG_CHECK_ON),249 "Check file memory with private mapping, async error mode, mmap memory and tag check on\n");250 evaluate_test(check_file_memory_mapping(USE_MPROTECT, MTE_ASYNC_ERR, MAP_PRIVATE, TAG_CHECK_ON),251 "Check file memory with private mapping, async error mode, mmap/mprotect memory and tag check on\n");252 evaluate_test(check_file_memory_mapping(USE_MMAP, MTE_ASYNC_ERR, MAP_SHARED, TAG_CHECK_ON),253 "Check file memory with shared mapping, async error mode, mmap memory and tag check on\n");254 evaluate_test(check_file_memory_mapping(USE_MPROTECT, MTE_ASYNC_ERR, MAP_SHARED, TAG_CHECK_ON),255 "Check file memory with shared mapping, async error mode, mmap/mprotect memory and tag check on\n");256 257 evaluate_test(check_clear_prot_mte_flag(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE),258 "Check clear PROT_MTE flags with private mapping, sync error mode and mmap memory\n");259 evaluate_test(check_clear_prot_mte_flag(USE_MPROTECT, MTE_SYNC_ERR, MAP_PRIVATE),260 "Check clear PROT_MTE flags with private mapping and sync error mode and mmap/mprotect memory\n");261 262 mte_restore_setup();263 ksft_print_cnts();264 return ksft_get_fail_cnt() == 0 ? KSFT_PASS : KSFT_FAIL;265}266