linux/tools/testing/selftests/arm64/mte/check_mmap_options.c
<<
>>
Prefs
   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 <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_SIZE
  23#define OVERFLOW                MT_GRANULE_SIZE
  24#define TAG_CHECK_ON            0
  25#define TAG_CHECK_OFF           1
  26
  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 */ 0
  31};
  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 = sizeof(sizes)/sizeof(int);
  65
  66        item = sizeof(sizes)/sizeof(int);
  67        mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);
  68        for (run = 0; run < item; run++) {
  69                map_size = sizes[run] + OVERFLOW + UNDERFLOW;
  70                map_ptr = (char *)mte_allocate_memory(map_size, mem_type, mapping, false);
  71                if (check_allocated_memory(map_ptr, map_size, mem_type, false) != KSFT_PASS)
  72                        return KSFT_FAIL;
  73
  74                ptr = map_ptr + UNDERFLOW;
  75                mte_initialize_current_context(mode, (uintptr_t)ptr, sizes[run]);
  76                /* Only mte enabled memory will allow tag insertion */
  77                ptr = mte_insert_tags((void *)ptr, sizes[run]);
  78                if (!ptr || cur_mte_cxt.fault_valid == true) {
  79                        ksft_print_msg("FAIL: Insert tags on anonymous mmap memory\n");
  80                        munmap((void *)map_ptr, map_size);
  81                        return KSFT_FAIL;
  82                }
  83                result = check_mte_memory(ptr, sizes[run], mode, tag_check);
  84                mte_clear_tags((void *)ptr, sizes[run]);
  85                mte_free_memory((void *)map_ptr, map_size, mem_type, false);
  86                if (result == KSFT_FAIL)
  87                        return KSFT_FAIL;
  88        }
  89        return KSFT_PASS;
  90}
  91
  92static int check_file_memory_mapping(int mem_type, int mode, int mapping, int tag_check)
  93{
  94        char *ptr, *map_ptr;
  95        int run, fd, map_size;
  96        int total = sizeof(sizes)/sizeof(int);
  97        int result = KSFT_PASS;
  98
  99        mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);
 100        for (run = 0; run < total; run++) {
 101                fd = create_temp_file();
 102                if (fd == -1)
 103                        return KSFT_FAIL;
 104
 105                map_size = sizes[run] + UNDERFLOW + OVERFLOW;
 106                map_ptr = (char *)mte_allocate_file_memory(map_size, mem_type, mapping, false, fd);
 107                if (check_allocated_memory(map_ptr, map_size, mem_type, false) != KSFT_PASS) {
 108                        close(fd);
 109                        return KSFT_FAIL;
 110                }
 111                ptr = map_ptr + UNDERFLOW;
 112                mte_initialize_current_context(mode, (uintptr_t)ptr, sizes[run]);
 113                /* Only mte enabled memory will allow tag insertion */
 114                ptr = mte_insert_tags((void *)ptr, sizes[run]);
 115                if (!ptr || cur_mte_cxt.fault_valid == true) {
 116                        ksft_print_msg("FAIL: Insert tags on file based memory\n");
 117                        munmap((void *)map_ptr, map_size);
 118                        close(fd);
 119                        return KSFT_FAIL;
 120                }
 121                result = check_mte_memory(ptr, sizes[run], mode, tag_check);
 122                mte_clear_tags((void *)ptr, sizes[run]);
 123                munmap((void *)map_ptr, map_size);
 124                close(fd);
 125                if (result == KSFT_FAIL)
 126                        break;
 127        }
 128        return result;
 129}
 130
 131static int check_clear_prot_mte_flag(int mem_type, int mode, int mapping)
 132{
 133        char *ptr, *map_ptr;
 134        int run, prot_flag, result, fd, map_size;
 135        int total = sizeof(sizes)/sizeof(int);
 136
 137        prot_flag = PROT_READ | PROT_WRITE;
 138        mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);
 139        for (run = 0; run < total; run++) {
 140                map_size = sizes[run] + OVERFLOW + UNDERFLOW;
 141                ptr = (char *)mte_allocate_memory_tag_range(sizes[run], mem_type, mapping,
 142                                                            UNDERFLOW, OVERFLOW);
 143                if (check_allocated_memory_range(ptr, sizes[run], mem_type,
 144                                                 UNDERFLOW, OVERFLOW) != KSFT_PASS)
 145                        return KSFT_FAIL;
 146                map_ptr = ptr - UNDERFLOW;
 147                /* Try to clear PROT_MTE property and verify it by tag checking */
 148                if (mprotect(map_ptr, map_size, prot_flag)) {
 149                        mte_free_memory_tag_range((void *)ptr, sizes[run], mem_type,
 150                                                  UNDERFLOW, OVERFLOW);
 151                        ksft_print_msg("FAIL: mprotect not ignoring clear PROT_MTE property\n");
 152                        return KSFT_FAIL;
 153                }
 154                result = check_mte_memory(ptr, sizes[run], mode, TAG_CHECK_ON);
 155                mte_free_memory_tag_range((void *)ptr, sizes[run], mem_type, UNDERFLOW, OVERFLOW);
 156                if (result != KSFT_PASS)
 157                        return KSFT_FAIL;
 158
 159                fd = create_temp_file();
 160                if (fd == -1)
 161                        return KSFT_FAIL;
 162                ptr = (char *)mte_allocate_file_memory_tag_range(sizes[run], mem_type, mapping,
 163                                                                 UNDERFLOW, OVERFLOW, fd);
 164                if (check_allocated_memory_range(ptr, sizes[run], mem_type,
 165                                                 UNDERFLOW, OVERFLOW) != KSFT_PASS) {
 166                        close(fd);
 167                        return KSFT_FAIL;
 168                }
 169                map_ptr = ptr - UNDERFLOW;
 170                /* Try to clear PROT_MTE property and verify it by tag checking */
 171                if (mprotect(map_ptr, map_size, prot_flag)) {
 172                        ksft_print_msg("FAIL: mprotect not ignoring clear PROT_MTE property\n");
 173                        mte_free_memory_tag_range((void *)ptr, sizes[run], mem_type,
 174                                                  UNDERFLOW, OVERFLOW);
 175                        close(fd);
 176                        return KSFT_FAIL;
 177                }
 178                result = check_mte_memory(ptr, sizes[run], mode, TAG_CHECK_ON);
 179                mte_free_memory_tag_range((void *)ptr, sizes[run], mem_type, UNDERFLOW, OVERFLOW);
 180                close(fd);
 181                if (result != KSFT_PASS)
 182                        return KSFT_FAIL;
 183        }
 184        return KSFT_PASS;
 185}
 186
 187int main(int argc, char *argv[])
 188{
 189        int err;
 190        int item = sizeof(sizes)/sizeof(int);
 191
 192        err = mte_default_setup();
 193        if (err)
 194                return err;
 195        page_size = getpagesize();
 196        if (!page_size) {
 197                ksft_print_msg("ERR: Unable to get page size\n");
 198                return KSFT_FAIL;
 199        }
 200        sizes[item - 3] = page_size - 1;
 201        sizes[item - 2] = page_size;
 202        sizes[item - 1] = page_size + 1;
 203
 204        /* Register signal handlers */
 205        mte_register_signal(SIGBUS, mte_default_handler);
 206        mte_register_signal(SIGSEGV, mte_default_handler);
 207
 208        /* Set test plan */
 209        ksft_set_plan(22);
 210
 211        mte_enable_pstate_tco();
 212
 213        evaluate_test(check_anonymous_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE, TAG_CHECK_OFF),
 214        "Check anonymous memory with private mapping, sync error mode, mmap memory and tag check off\n");
 215        evaluate_test(check_file_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_PRIVATE, TAG_CHECK_OFF),
 216        "Check file memory with private mapping, sync error mode, mmap/mprotect memory and tag check off\n");
 217
 218        mte_disable_pstate_tco();
 219        evaluate_test(check_anonymous_memory_mapping(USE_MMAP, MTE_NONE_ERR, MAP_PRIVATE, TAG_CHECK_OFF),
 220        "Check anonymous memory with private mapping, no error mode, mmap memory and tag check off\n");
 221        evaluate_test(check_file_memory_mapping(USE_MPROTECT, MTE_NONE_ERR, MAP_PRIVATE, TAG_CHECK_OFF),
 222        "Check file memory with private mapping, no error mode, mmap/mprotect memory and tag check off\n");
 223
 224        evaluate_test(check_anonymous_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE, TAG_CHECK_ON),
 225        "Check anonymous memory with private mapping, sync error mode, mmap memory and tag check on\n");
 226        evaluate_test(check_anonymous_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_PRIVATE, TAG_CHECK_ON),
 227        "Check anonymous memory with private mapping, sync error mode, mmap/mprotect memory and tag check on\n");
 228        evaluate_test(check_anonymous_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_SHARED, TAG_CHECK_ON),
 229        "Check anonymous memory with shared mapping, sync error mode, mmap memory and tag check on\n");
 230        evaluate_test(check_anonymous_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_SHARED, TAG_CHECK_ON),
 231        "Check anonymous memory with shared mapping, sync error mode, mmap/mprotect memory and tag check on\n");
 232        evaluate_test(check_anonymous_memory_mapping(USE_MMAP, MTE_ASYNC_ERR, MAP_PRIVATE, TAG_CHECK_ON),
 233        "Check anonymous memory with private mapping, async error mode, mmap memory and tag check on\n");
 234        evaluate_test(check_anonymous_memory_mapping(USE_MPROTECT, MTE_ASYNC_ERR, MAP_PRIVATE, TAG_CHECK_ON),
 235        "Check anonymous memory with private mapping, async error mode, mmap/mprotect memory and tag check on\n");
 236        evaluate_test(check_anonymous_memory_mapping(USE_MMAP, MTE_ASYNC_ERR, MAP_SHARED, TAG_CHECK_ON),
 237        "Check anonymous memory with shared mapping, async error mode, mmap memory and tag check on\n");
 238        evaluate_test(check_anonymous_memory_mapping(USE_MPROTECT, MTE_ASYNC_ERR, MAP_SHARED, TAG_CHECK_ON),
 239        "Check anonymous memory with shared mapping, async error mode, mmap/mprotect memory and tag check on\n");
 240
 241        evaluate_test(check_file_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE, TAG_CHECK_ON),
 242        "Check file memory with private mapping, sync error mode, mmap memory and tag check on\n");
 243        evaluate_test(check_file_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_PRIVATE, TAG_CHECK_ON),
 244        "Check file memory with private mapping, sync error mode, mmap/mprotect memory and tag check on\n");
 245        evaluate_test(check_file_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_SHARED, TAG_CHECK_ON),
 246        "Check file memory with shared mapping, sync error mode, mmap memory and tag check on\n");
 247        evaluate_test(check_file_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_SHARED, TAG_CHECK_ON),
 248        "Check file memory with shared mapping, sync error mode, mmap/mprotect memory and tag check on\n");
 249        evaluate_test(check_file_memory_mapping(USE_MMAP, MTE_ASYNC_ERR, MAP_PRIVATE, TAG_CHECK_ON),
 250        "Check file memory with private mapping, async error mode, mmap memory and tag check on\n");
 251        evaluate_test(check_file_memory_mapping(USE_MPROTECT, MTE_ASYNC_ERR, MAP_PRIVATE, TAG_CHECK_ON),
 252        "Check file memory with private mapping, async error mode, mmap/mprotect memory and tag check on\n");
 253        evaluate_test(check_file_memory_mapping(USE_MMAP, MTE_ASYNC_ERR, MAP_SHARED, TAG_CHECK_ON),
 254        "Check file memory with shared mapping, async error mode, mmap memory and tag check on\n");
 255        evaluate_test(check_file_memory_mapping(USE_MPROTECT, MTE_ASYNC_ERR, MAP_SHARED, TAG_CHECK_ON),
 256        "Check file memory with shared mapping, async error mode, mmap/mprotect memory and tag check on\n");
 257
 258        evaluate_test(check_clear_prot_mte_flag(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE),
 259        "Check clear PROT_MTE flags with private mapping, sync error mode and mmap memory\n");
 260        evaluate_test(check_clear_prot_mte_flag(USE_MPROTECT, MTE_SYNC_ERR, MAP_PRIVATE),
 261        "Check clear PROT_MTE flags with private mapping and sync error mode and mmap/mprotect memory\n");
 262
 263        mte_restore_setup();
 264        ksft_print_cnts();
 265        return ksft_get_fail_cnt() == 0 ? KSFT_PASS : KSFT_FAIL;
 266}
 267