Home | History | Annotate | Download | only in tests-m32
      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