1 /* 2 * Check decoding of PR_SET_SPECULATION_CTRL and PR_GET_SPECULATION_CTRL 3 * prctl operations. 4 * 5 * Copyright (c) 2018 The strace developers. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "tests.h" 32 #include <asm/unistd.h> 33 34 #ifdef __NR_prctl 35 36 # include <stdio.h> 37 # include <stdlib.h> 38 # include <unistd.h> 39 # include <linux/prctl.h> 40 41 static long injected_val; 42 43 long 44 do_prctl(kernel_ulong_t cmd, kernel_ulong_t arg2, kernel_ulong_t arg3) 45 { 46 long rc = syscall(__NR_prctl, cmd, arg2, arg3); 47 48 if (rc != injected_val) 49 error_msg_and_fail("Return value (%ld) differs from expected " 50 "injected value (%ld)", 51 rc, injected_val); 52 53 return rc; 54 } 55 56 int 57 main(int argc, char **argv) 58 { 59 static const kernel_ulong_t bogus_arg2 = 60 (kernel_ulong_t) 0xdeadfacebadc0dedULL; 61 static const kernel_ulong_t bogus_arg3 = 62 (kernel_ulong_t) 0xdecafeedbeefda7eULL; 63 static const struct { 64 long arg; 65 const char *str; 66 } get_strs[] = { 67 { -1, "" }, 68 { 0, " (PR_SPEC_NOT_AFFECTED)" }, 69 { 1, " (PR_SPEC_PRCTL)" }, 70 { 3, " (PR_SPEC_PRCTL|PR_SPEC_ENABLE)" }, 71 { 8, " (PR_SPEC_FORCE_DISABLE)" }, 72 { 16, " (0x10)" }, 73 { 42, " (PR_SPEC_ENABLE|PR_SPEC_FORCE_DISABLE|0x20)" }, 74 }; 75 static const struct { 76 kernel_ulong_t arg; 77 const char *str; 78 } set_strs[] = { 79 { 0, "0 /* PR_SPEC_??? */" }, 80 { 1, "0x1 /* PR_SPEC_??? */" }, 81 { 2, "PR_SPEC_ENABLE" }, 82 { 3, "0x3 /* PR_SPEC_??? */" }, 83 { 8, "PR_SPEC_FORCE_DISABLE" }, 84 { 16, "0x10 /* PR_SPEC_??? */" }, 85 { (kernel_ulong_t) 0xdecafeedbeefda7eULL, "0x" 86 # if SIZEOF_KERNEL_LONG_T == 8 87 "decafeed" 88 # endif 89 "beefda7e /* PR_SPEC_??? */" }, 90 }; 91 92 long rc; 93 const char *str = NULL; 94 95 if (argc < 2) 96 error_msg_and_fail("Usage: %s INJECTED_VAL", argv[0]); 97 98 injected_val = strtol(argv[1], NULL, 0); 99 100 /* PR_GET_SPECULATION_CTRL */ 101 rc = do_prctl(52, 1, bogus_arg3); 102 printf("prctl(PR_GET_SPECULATION_CTRL, 0x1 /* PR_SPEC_??? */) " 103 "= %s (INJECTED)\n", sprintrc(rc)); 104 105 rc = do_prctl(52, bogus_arg2, bogus_arg3); 106 printf("prctl(PR_GET_SPECULATION_CTRL, %#llx /* PR_SPEC_??? */) " 107 "= %s (INJECTED)\n", 108 (unsigned long long) bogus_arg2, sprintrc(rc)); 109 110 rc = do_prctl(52, 0, bogus_arg3); 111 112 for (unsigned i = 0; i < ARRAY_SIZE(get_strs); i++) { 113 if (get_strs[i].arg == rc) { 114 str = get_strs[i].str; 115 break; 116 } 117 } 118 if (!str) 119 error_msg_and_fail("Unknown return value: %ld", rc); 120 121 printf("prctl(PR_GET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS) " 122 "= %s%s (INJECTED)\n", sprintrc(rc), str); 123 124 125 /* PR_SET_SPECULATION_CTRL*/ 126 rc = do_prctl(53, 1, bogus_arg3); 127 printf("prctl(PR_SET_SPECULATION_CTRL, 0x1 /* PR_SPEC_??? */, %#llx) " 128 "= %s (INJECTED)\n", 129 (unsigned long long) bogus_arg3, sprintrc(rc)); 130 131 rc = do_prctl(53, bogus_arg2, bogus_arg3); 132 printf("prctl(PR_SET_SPECULATION_CTRL, %#llx /* PR_SPEC_??? */, %#llx) " 133 "= %s (INJECTED)\n", 134 (unsigned long long) bogus_arg2, 135 (unsigned long long) bogus_arg3, 136 sprintrc(rc)); 137 138 for (unsigned i = 0; i < ARRAY_SIZE(set_strs); i++) { 139 rc = do_prctl(53, 0, set_strs[i].arg); 140 printf("prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS" 141 ", %s) = %s (INJECTED)\n", 142 set_strs[i].str, sprintrc(rc)); 143 } 144 145 puts("+++ exited with 0 +++"); 146 return 0; 147 } 148 149 #else 150 151 SKIP_MAIN_UNDEFINED("__NR_prctl") 152 153 #endif 154