1/* 2 * Copyright (c) 2015, Google Inc. All rights reserved 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining 5 * a copy of this software and associated documentation files 6 * (the "Software"), to deal in the Software without restriction, 7 * including without limitation the rights to use, copy, modify, merge, 8 * publish, distribute, sublicense, and/or sell copies of the Software, 9 * and to permit persons to whom the Software is furnished to do so, 10 * subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23 24#include <asm.h> 25#include <arch/asm_macros.h> 26#include <err.h> 27 28/** 29 * int mmutest_arch_rodata_pnx(void) - Test that rodata section is mapped pnx 30 * 31 * Returns ERR_FAULT if rodata is not executable. 32 * Return 0 if rodata is executable. 33 */ 34.section .rodata 35 set_fault_handler .Lmmutest_fault 36FUNCTION(mmutest_arch_rodata_pnx) 37 xor %eax, %eax 38 39 ret 40 41/** 42 * int mmutest_arch_data_pnx(void) - Test that data section is mapped pnx 43 * 44 * Returns ERR_FAULT if data is not executable. 45 * Return 0 if data is executable. 46 */ 47.section .data 48 set_fault_handler .Lmmutest_fault 49FUNCTION(mmutest_arch_data_pnx) 50 xor %eax, %eax 51 52 ret 53.section .text 54 55/** 56 * int mmutest_arch_rodata_ro(void) - Test that rodata section is mapped read-only 57 * 58 * Returns ERR_FAULT if rodata is not writable 59 * Returns 1 if write to rodata is silently dropped 60 * Returns 0 if rodata is writable 61 */ 62FUNCTION(mmutest_arch_rodata_ro) 63 leaq .Ltest_rodata_long(%rip), %rax 64 65 set_fault_handler .Lmmutest_fault 66 movl $0, (%rax) 67 68 movl (%rax), %eax 69 ret 70 71.section .rodata 72 .balign 4 73.Ltest_rodata_long: 74 .long 0x1 75 76.section .text 77 78/** 79 * int mmutest_arch_store_uint32(uint32_t *ptr, bool user) - Test if ptr is writable 80 * @ptr: Memory location to test 81 * @user: Use unprivileged store 82 * 83 * Returns ERR_FAULT if ptr is not writable 84 * Returns ERR_GENERIC if ptr is not readable 85 * Returns 2 if write does not fault, but data is lost on readback from memory 86 * Returns 1 if write does not fault, but data is lost on readback from cache 87 * Returns 0 if ptr is writable 88 */ 89FUNCTION(mmutest_arch_store_uint32) 90 test %sil, %sil 91 jnz .Lmmutest_arch_store_uint32_user 92 93 set_fault_handler .Lmmutest_setup_fault 94 movl (%rdi), %edx 95 not %edx 96 97 set_fault_handler .Lmmutest_fault 98 movl %edx, (%rdi) 99 mfence 100 movl (%rdi), %ecx 101 102 jmp .Lmmutest_arch_store_uint32_str_done 103 104.Lmmutest_arch_store_uint32_user: 105 /* TODO: call helper functions to write then read from user-space */ 106 movl $ERR_NOT_IMPLEMENTED, %eax 107 ret 108 109.Lmmutest_arch_store_uint32_str_done: 110 111 cmp %edx, %ecx 112 jne .Lmmutest_arch_store_uint32_cache_read_mismatch 113 114 push %rdi 115 push %rsi 116 push %rdx 117 movq $4, %rsi 118 call arch_clean_invalidate_cache_range 119 pop %rdx 120 pop %rsi 121 pop %rdi 122 123 test %sil, %sil 124 jnz .Lmmutest_arch_store_uint32_memory_reload_user 125 126 movl (%rdi), %ecx 127 jmp .Lmmutest_arch_store_uint32_memory_reload_done 128 129.Lmmutest_arch_store_uint32_memory_reload_user: 130 /* TODO: call helper function to read from user-space */ 131 132.Lmmutest_arch_store_uint32_memory_reload_done: 133 cmp %edx, %ecx 134 jne .Lmmutest_arch_store_uint32_memory_mismatch 135 136 xor %eax, %eax 137 ret 138 139.Lmmutest_arch_store_uint32_cache_read_mismatch: 140 movl $1, %eax 141 ret 142 143.Lmmutest_arch_store_uint32_memory_mismatch: 144 movl $2, %eax 145 ret 146 147/** 148 * int mmutest_arch_nop(int ret) - Return ret 149 * 150 * Returns ret if run from executable page. 151 * Does not return if run from non-executable page. 152 */ 153FUNCTION(mmutest_arch_nop) 154 ret 155FUNCTION(mmutest_arch_nop_end) 156 157.Lmmutest_setup_fault: 158 movl $ERR_GENERIC, %eax 159 ret 160 161.Lmmutest_fault: 162 movl $ERR_FAULT, %eax 163 ret 164