1f3b2a26cSAmit Daniel Kachhap // SPDX-License-Identifier: GPL-2.0 2f3b2a26cSAmit Daniel Kachhap // Copyright (C) 2020 ARM Limited 3f3b2a26cSAmit Daniel Kachhap 4f3b2a26cSAmit Daniel Kachhap #define _GNU_SOURCE 5f3b2a26cSAmit Daniel Kachhap 6f3b2a26cSAmit Daniel Kachhap #include <errno.h> 7f3b2a26cSAmit Daniel Kachhap #include <signal.h> 8f3b2a26cSAmit Daniel Kachhap #include <stdio.h> 9f3b2a26cSAmit Daniel Kachhap #include <stdlib.h> 10f3b2a26cSAmit Daniel Kachhap #include <string.h> 11f3b2a26cSAmit Daniel Kachhap #include <ucontext.h> 12f3b2a26cSAmit Daniel Kachhap #include <sys/wait.h> 13f3b2a26cSAmit Daniel Kachhap 14f3b2a26cSAmit Daniel Kachhap #include "kselftest.h" 15f3b2a26cSAmit Daniel Kachhap #include "mte_common_util.h" 16f3b2a26cSAmit Daniel Kachhap #include "mte_def.h" 17f3b2a26cSAmit Daniel Kachhap 18f3b2a26cSAmit Daniel Kachhap #define BUFFER_SIZE (5 * MT_GRANULE_SIZE) 19f3b2a26cSAmit Daniel Kachhap #define RUNS (MT_TAG_COUNT * 2) 20f3b2a26cSAmit Daniel Kachhap #define MTE_LAST_TAG_MASK (0x7FFF) 21f3b2a26cSAmit Daniel Kachhap 22f3b2a26cSAmit Daniel Kachhap static int verify_mte_pointer_validity(char *ptr, int mode) 23f3b2a26cSAmit Daniel Kachhap { 24f3b2a26cSAmit Daniel Kachhap mte_initialize_current_context(mode, (uintptr_t)ptr, BUFFER_SIZE); 25f3b2a26cSAmit Daniel Kachhap /* Check the validity of the tagged pointer */ 26f3b2a26cSAmit Daniel Kachhap memset((void *)ptr, '1', BUFFER_SIZE); 27f3b2a26cSAmit Daniel Kachhap mte_wait_after_trig(); 28f3b2a26cSAmit Daniel Kachhap if (cur_mte_cxt.fault_valid) 29f3b2a26cSAmit Daniel Kachhap return KSFT_FAIL; 30f3b2a26cSAmit Daniel Kachhap /* Proceed further for nonzero tags */ 31f3b2a26cSAmit Daniel Kachhap if (!MT_FETCH_TAG((uintptr_t)ptr)) 32f3b2a26cSAmit Daniel Kachhap return KSFT_PASS; 33f3b2a26cSAmit Daniel Kachhap mte_initialize_current_context(mode, (uintptr_t)ptr, BUFFER_SIZE + 1); 34f3b2a26cSAmit Daniel Kachhap /* Check the validity outside the range */ 35f3b2a26cSAmit Daniel Kachhap ptr[BUFFER_SIZE] = '2'; 36f3b2a26cSAmit Daniel Kachhap mte_wait_after_trig(); 37f3b2a26cSAmit Daniel Kachhap if (!cur_mte_cxt.fault_valid) 38f3b2a26cSAmit Daniel Kachhap return KSFT_FAIL; 39f3b2a26cSAmit Daniel Kachhap else 40f3b2a26cSAmit Daniel Kachhap return KSFT_PASS; 41f3b2a26cSAmit Daniel Kachhap } 42f3b2a26cSAmit Daniel Kachhap 43f3b2a26cSAmit Daniel Kachhap static int check_single_included_tags(int mem_type, int mode) 44f3b2a26cSAmit Daniel Kachhap { 45f3b2a26cSAmit Daniel Kachhap char *ptr; 46f3b2a26cSAmit Daniel Kachhap int tag, run, result = KSFT_PASS; 47f3b2a26cSAmit Daniel Kachhap 48f3b2a26cSAmit Daniel Kachhap ptr = (char *)mte_allocate_memory(BUFFER_SIZE + MT_GRANULE_SIZE, mem_type, 0, false); 49f3b2a26cSAmit Daniel Kachhap if (check_allocated_memory(ptr, BUFFER_SIZE + MT_GRANULE_SIZE, 50f3b2a26cSAmit Daniel Kachhap mem_type, false) != KSFT_PASS) 51f3b2a26cSAmit Daniel Kachhap return KSFT_FAIL; 52f3b2a26cSAmit Daniel Kachhap 53f3b2a26cSAmit Daniel Kachhap for (tag = 0; (tag < MT_TAG_COUNT) && (result == KSFT_PASS); tag++) { 54f3b2a26cSAmit Daniel Kachhap mte_switch_mode(mode, MT_INCLUDE_VALID_TAG(tag)); 55f3b2a26cSAmit Daniel Kachhap /* Try to catch a excluded tag by a number of tries. */ 56f3b2a26cSAmit Daniel Kachhap for (run = 0; (run < RUNS) && (result == KSFT_PASS); run++) { 57f3b2a26cSAmit Daniel Kachhap ptr = (char *)mte_insert_tags(ptr, BUFFER_SIZE); 58f3b2a26cSAmit Daniel Kachhap /* Check tag value */ 59f3b2a26cSAmit Daniel Kachhap if (MT_FETCH_TAG((uintptr_t)ptr) == tag) { 60f3b2a26cSAmit Daniel Kachhap ksft_print_msg("FAIL: wrong tag = 0x%x with include mask=0x%x\n", 61f3b2a26cSAmit Daniel Kachhap MT_FETCH_TAG((uintptr_t)ptr), 62f3b2a26cSAmit Daniel Kachhap MT_INCLUDE_VALID_TAG(tag)); 63f3b2a26cSAmit Daniel Kachhap result = KSFT_FAIL; 64f3b2a26cSAmit Daniel Kachhap break; 65f3b2a26cSAmit Daniel Kachhap } 66f3b2a26cSAmit Daniel Kachhap result = verify_mte_pointer_validity(ptr, mode); 67f3b2a26cSAmit Daniel Kachhap } 68f3b2a26cSAmit Daniel Kachhap } 69f3b2a26cSAmit Daniel Kachhap mte_free_memory_tag_range((void *)ptr, BUFFER_SIZE, mem_type, 0, MT_GRANULE_SIZE); 70f3b2a26cSAmit Daniel Kachhap return result; 71f3b2a26cSAmit Daniel Kachhap } 72f3b2a26cSAmit Daniel Kachhap 73f3b2a26cSAmit Daniel Kachhap static int check_multiple_included_tags(int mem_type, int mode) 74f3b2a26cSAmit Daniel Kachhap { 75f3b2a26cSAmit Daniel Kachhap char *ptr; 76f3b2a26cSAmit Daniel Kachhap int tag, run, result = KSFT_PASS; 77f3b2a26cSAmit Daniel Kachhap unsigned long excl_mask = 0; 78f3b2a26cSAmit Daniel Kachhap 79f3b2a26cSAmit Daniel Kachhap ptr = (char *)mte_allocate_memory(BUFFER_SIZE + MT_GRANULE_SIZE, mem_type, 0, false); 80f3b2a26cSAmit Daniel Kachhap if (check_allocated_memory(ptr, BUFFER_SIZE + MT_GRANULE_SIZE, 81f3b2a26cSAmit Daniel Kachhap mem_type, false) != KSFT_PASS) 82f3b2a26cSAmit Daniel Kachhap return KSFT_FAIL; 83f3b2a26cSAmit Daniel Kachhap 84f3b2a26cSAmit Daniel Kachhap for (tag = 0; (tag < MT_TAG_COUNT - 1) && (result == KSFT_PASS); tag++) { 85f3b2a26cSAmit Daniel Kachhap excl_mask |= 1 << tag; 86f3b2a26cSAmit Daniel Kachhap mte_switch_mode(mode, MT_INCLUDE_VALID_TAGS(excl_mask)); 87f3b2a26cSAmit Daniel Kachhap /* Try to catch a excluded tag by a number of tries. */ 88f3b2a26cSAmit Daniel Kachhap for (run = 0; (run < RUNS) && (result == KSFT_PASS); run++) { 89f3b2a26cSAmit Daniel Kachhap ptr = (char *)mte_insert_tags(ptr, BUFFER_SIZE); 90f3b2a26cSAmit Daniel Kachhap /* Check tag value */ 91f3b2a26cSAmit Daniel Kachhap if (MT_FETCH_TAG((uintptr_t)ptr) < tag) { 92f3b2a26cSAmit Daniel Kachhap ksft_print_msg("FAIL: wrong tag = 0x%x with include mask=0x%x\n", 93f3b2a26cSAmit Daniel Kachhap MT_FETCH_TAG((uintptr_t)ptr), 94f3b2a26cSAmit Daniel Kachhap MT_INCLUDE_VALID_TAGS(excl_mask)); 95f3b2a26cSAmit Daniel Kachhap result = KSFT_FAIL; 96f3b2a26cSAmit Daniel Kachhap break; 97f3b2a26cSAmit Daniel Kachhap } 98f3b2a26cSAmit Daniel Kachhap result = verify_mte_pointer_validity(ptr, mode); 99f3b2a26cSAmit Daniel Kachhap } 100f3b2a26cSAmit Daniel Kachhap } 101f3b2a26cSAmit Daniel Kachhap mte_free_memory_tag_range((void *)ptr, BUFFER_SIZE, mem_type, 0, MT_GRANULE_SIZE); 102f3b2a26cSAmit Daniel Kachhap return result; 103f3b2a26cSAmit Daniel Kachhap } 104f3b2a26cSAmit Daniel Kachhap 105f3b2a26cSAmit Daniel Kachhap static int check_all_included_tags(int mem_type, int mode) 106f3b2a26cSAmit Daniel Kachhap { 107f3b2a26cSAmit Daniel Kachhap char *ptr; 108f3b2a26cSAmit Daniel Kachhap int run, result = KSFT_PASS; 109f3b2a26cSAmit Daniel Kachhap 110f3b2a26cSAmit Daniel Kachhap ptr = (char *)mte_allocate_memory(BUFFER_SIZE + MT_GRANULE_SIZE, mem_type, 0, false); 111f3b2a26cSAmit Daniel Kachhap if (check_allocated_memory(ptr, BUFFER_SIZE + MT_GRANULE_SIZE, 112f3b2a26cSAmit Daniel Kachhap mem_type, false) != KSFT_PASS) 113f3b2a26cSAmit Daniel Kachhap return KSFT_FAIL; 114f3b2a26cSAmit Daniel Kachhap 115f3b2a26cSAmit Daniel Kachhap mte_switch_mode(mode, MT_INCLUDE_TAG_MASK); 116f3b2a26cSAmit Daniel Kachhap /* Try to catch a excluded tag by a number of tries. */ 117f3b2a26cSAmit Daniel Kachhap for (run = 0; (run < RUNS) && (result == KSFT_PASS); run++) { 118f3b2a26cSAmit Daniel Kachhap ptr = (char *)mte_insert_tags(ptr, BUFFER_SIZE); 119f3b2a26cSAmit Daniel Kachhap /* 120f3b2a26cSAmit Daniel Kachhap * Here tag byte can be between 0x0 to 0xF (full allowed range) 121f3b2a26cSAmit Daniel Kachhap * so no need to match so just verify if it is writable. 122f3b2a26cSAmit Daniel Kachhap */ 123f3b2a26cSAmit Daniel Kachhap result = verify_mte_pointer_validity(ptr, mode); 124f3b2a26cSAmit Daniel Kachhap } 125f3b2a26cSAmit Daniel Kachhap mte_free_memory_tag_range((void *)ptr, BUFFER_SIZE, mem_type, 0, MT_GRANULE_SIZE); 126f3b2a26cSAmit Daniel Kachhap return result; 127f3b2a26cSAmit Daniel Kachhap } 128f3b2a26cSAmit Daniel Kachhap 129f3b2a26cSAmit Daniel Kachhap static int check_none_included_tags(int mem_type, int mode) 130f3b2a26cSAmit Daniel Kachhap { 131f3b2a26cSAmit Daniel Kachhap char *ptr; 132f3b2a26cSAmit Daniel Kachhap int run; 133f3b2a26cSAmit Daniel Kachhap 134f3b2a26cSAmit Daniel Kachhap ptr = (char *)mte_allocate_memory(BUFFER_SIZE, mem_type, 0, false); 135f3b2a26cSAmit Daniel Kachhap if (check_allocated_memory(ptr, BUFFER_SIZE, mem_type, false) != KSFT_PASS) 136f3b2a26cSAmit Daniel Kachhap return KSFT_FAIL; 137f3b2a26cSAmit Daniel Kachhap 138f3b2a26cSAmit Daniel Kachhap mte_switch_mode(mode, MT_EXCLUDE_TAG_MASK); 139f3b2a26cSAmit Daniel Kachhap /* Try to catch a excluded tag by a number of tries. */ 140f3b2a26cSAmit Daniel Kachhap for (run = 0; run < RUNS; run++) { 141f3b2a26cSAmit Daniel Kachhap ptr = (char *)mte_insert_tags(ptr, BUFFER_SIZE); 142f3b2a26cSAmit Daniel Kachhap /* Here all tags exluded so tag value generated should be 0 */ 143f3b2a26cSAmit Daniel Kachhap if (MT_FETCH_TAG((uintptr_t)ptr)) { 144f3b2a26cSAmit Daniel Kachhap ksft_print_msg("FAIL: included tag value found\n"); 145f3b2a26cSAmit Daniel Kachhap mte_free_memory((void *)ptr, BUFFER_SIZE, mem_type, true); 146f3b2a26cSAmit Daniel Kachhap return KSFT_FAIL; 147f3b2a26cSAmit Daniel Kachhap } 148f3b2a26cSAmit Daniel Kachhap mte_initialize_current_context(mode, (uintptr_t)ptr, BUFFER_SIZE); 149f3b2a26cSAmit Daniel Kachhap /* Check the write validity of the untagged pointer */ 150f3b2a26cSAmit Daniel Kachhap memset((void *)ptr, '1', BUFFER_SIZE); 151f3b2a26cSAmit Daniel Kachhap mte_wait_after_trig(); 152f3b2a26cSAmit Daniel Kachhap if (cur_mte_cxt.fault_valid) 153f3b2a26cSAmit Daniel Kachhap break; 154f3b2a26cSAmit Daniel Kachhap } 155f3b2a26cSAmit Daniel Kachhap mte_free_memory((void *)ptr, BUFFER_SIZE, mem_type, false); 156f3b2a26cSAmit Daniel Kachhap if (cur_mte_cxt.fault_valid) 157f3b2a26cSAmit Daniel Kachhap return KSFT_FAIL; 158f3b2a26cSAmit Daniel Kachhap else 159f3b2a26cSAmit Daniel Kachhap return KSFT_PASS; 160f3b2a26cSAmit Daniel Kachhap } 161f3b2a26cSAmit Daniel Kachhap 162f3b2a26cSAmit Daniel Kachhap int main(int argc, char *argv[]) 163f3b2a26cSAmit Daniel Kachhap { 164f3b2a26cSAmit Daniel Kachhap int err; 165f3b2a26cSAmit Daniel Kachhap 166f3b2a26cSAmit Daniel Kachhap err = mte_default_setup(); 167f3b2a26cSAmit Daniel Kachhap if (err) 168f3b2a26cSAmit Daniel Kachhap return err; 169f3b2a26cSAmit Daniel Kachhap 170f3b2a26cSAmit Daniel Kachhap /* Register SIGSEGV handler */ 171f3b2a26cSAmit Daniel Kachhap mte_register_signal(SIGSEGV, mte_default_handler); 172f3b2a26cSAmit Daniel Kachhap 173041fa41fSVincenzo Frascino /* Set test plan */ 174041fa41fSVincenzo Frascino ksft_set_plan(4); 175041fa41fSVincenzo Frascino 176f3b2a26cSAmit Daniel Kachhap evaluate_test(check_single_included_tags(USE_MMAP, MTE_SYNC_ERR), 177f3b2a26cSAmit Daniel Kachhap "Check an included tag value with sync mode\n"); 178f3b2a26cSAmit Daniel Kachhap evaluate_test(check_multiple_included_tags(USE_MMAP, MTE_SYNC_ERR), 179f3b2a26cSAmit Daniel Kachhap "Check different included tags value with sync mode\n"); 180f3b2a26cSAmit Daniel Kachhap evaluate_test(check_none_included_tags(USE_MMAP, MTE_SYNC_ERR), 181f3b2a26cSAmit Daniel Kachhap "Check none included tags value with sync mode\n"); 182f3b2a26cSAmit Daniel Kachhap evaluate_test(check_all_included_tags(USE_MMAP, MTE_SYNC_ERR), 183f3b2a26cSAmit Daniel Kachhap "Check all included tags value with sync mode\n"); 184f3b2a26cSAmit Daniel Kachhap 185f3b2a26cSAmit Daniel Kachhap mte_restore_setup(); 186f3b2a26cSAmit Daniel Kachhap ksft_print_cnts(); 187f3b2a26cSAmit Daniel Kachhap return ksft_get_fail_cnt() == 0 ? KSFT_PASS : KSFT_FAIL; 188f3b2a26cSAmit Daniel Kachhap } 189