Skip to content

Commit be0d6a8

Browse files
esyrldv-alt
authored andcommitted
prctl: add PR_GET_SPECULATION_CTRL/PR_SET_SPECULATION_CTRL decoding
* xlat/pr_spec_cmds.in: New fille. * xlat/pr_spec_get_store_bypass_flags.in: Likewise. * xlat/pr_spec_set_store_bypass_flags.in: Likewise. * xlat/prctl_options.in (PR_GET_SPECULATION_CTRL, PR_SET_SPECULATION_CTRL): New constants, introduced by Linux commit v4.17-rc3-15-gb617cfc. * prctl.c (SYS_FUNC(prctl)) <case PR_GET_SPECULATION_CTRL, case PR_SET_SPECULATION_CTRL>: Implement decoding of new prctl options. * tests/Makefile.am (check_PROGRAMS): Add prctl-spec-inject. (DECODER_TESTS): Add prctl-spec-inject.test. * tests/prctl-spec-inject.c: New file. * tests/prctl-spec-inject.test: New test. * tests/.gitignore: Add prctl-spec-inject.
1 parent 42c9ff9 commit be0d6a8

File tree

9 files changed

+235
-0
lines changed

9 files changed

+235
-0
lines changed

prctl.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
#include "xlat/pr_mce_kill.h"
4343
#include "xlat/pr_mce_kill_policy.h"
4444
#include "xlat/pr_set_mm.h"
45+
#include "xlat/pr_spec_cmds.h"
46+
#include "xlat/pr_spec_get_store_bypass_flags.h"
47+
#include "xlat/pr_spec_set_store_bypass_flags.h"
4548
#include "xlat/pr_sve_vl_flags.h"
4649
#include "xlat/pr_tsc.h"
4750
#include "xlat/pr_unalign_flags.h"
@@ -225,6 +228,27 @@ SYS_FUNC(prctl)
225228

226229
return RVAL_STR;
227230

231+
case PR_GET_SPECULATION_CTRL:
232+
if (entering(tcp)) {
233+
tprints(", ");
234+
printxval64(pr_spec_cmds, arg2, "PR_SPEC_???");
235+
236+
break;
237+
}
238+
239+
if (syserror(tcp))
240+
return 0;
241+
242+
switch (arg2) {
243+
case PR_SPEC_STORE_BYPASS:
244+
tcp->auxstr = sprintflags("",
245+
pr_spec_get_store_bypass_flags,
246+
(kernel_ulong_t) tcp->u_rval);
247+
break;
248+
}
249+
250+
return RVAL_STR;
251+
228252
/* PR_TASK_PERF_EVENTS_* take no arguments. */
229253
case PR_TASK_PERF_EVENTS_DISABLE:
230254
case PR_TASK_PERF_EVENTS_ENABLE:
@@ -382,6 +406,23 @@ SYS_FUNC(prctl)
382406
printflags(pr_fp_mode, arg2, "PR_FP_MODE_???");
383407
return RVAL_DECODED;
384408

409+
case PR_SET_SPECULATION_CTRL:
410+
tprints(", ");
411+
printxval64(pr_spec_cmds, arg2, "PR_SPEC_???");
412+
tprints(", ");
413+
414+
switch (arg2) {
415+
case PR_SPEC_STORE_BYPASS:
416+
printxval64(pr_spec_set_store_bypass_flags, arg3,
417+
"PR_SPEC_???");
418+
break;
419+
420+
default:
421+
tprintf("%#" PRI_klx, arg3);
422+
}
423+
424+
return RVAL_DECODED;
425+
385426
case PR_GET_NO_NEW_PRIVS:
386427
case PR_GET_THP_DISABLE:
387428
case PR_MPX_DISABLE_MANAGEMENT:

tests/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ prctl-pdeathsig
346346
prctl-seccomp-filter-v
347347
prctl-seccomp-strict
348348
prctl-securebits
349+
prctl-spec-inject
349350
prctl-tid_address
350351
prctl-tsc
351352
pread64-pwrite64

tests/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \
137137
ppoll-v \
138138
prctl-seccomp-filter-v \
139139
prctl-seccomp-strict \
140+
prctl-spec-inject \
140141
print_maxfd \
141142
qual_fault \
142143
qual_inject-error-signal \
@@ -258,6 +259,7 @@ DECODER_TESTS = \
258259
prctl-seccomp-filter-v.test \
259260
prctl-seccomp-strict.test \
260261
prctl-securebits.test \
262+
prctl-spec-inject.test \
261263
prctl-tid_address.test \
262264
prctl-tsc.test \
263265
qual_fault-exit_group.test \

tests/prctl-spec-inject.c

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
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

tests/prctl-spec-inject.test

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/bin/sh -efu
2+
3+
. "${srcdir=.}/scno_tampering.sh"
4+
5+
fault_args='-a53 -e trace=prctl -e inject=prctl:'
6+
prog="../$NAME"
7+
8+
test_run_rval()
9+
{
10+
local run rval injexpr
11+
run="$1"; shift
12+
rval="$1"; shift
13+
injexpr="$1"; shift
14+
15+
run_strace $fault_args$injexpr $prog $rval > "$EXP"
16+
LC_ALL=C grep -Ev '^prctl\(PR_[GS]ET_([^S][^P][^E][^C]])' \
17+
< "$LOG" > "$OUT"
18+
match_diff "$OUT" "$EXP"
19+
}
20+
21+
test_run_rval 0 -1 "error=ENOTTY"
22+
test_run_rval 1 0 "retval=0"
23+
test_run_rval 2 1 "retval=1"
24+
test_run_rval 3 3 "retval=3"
25+
test_run_rval 4 8 "retval=8"
26+
test_run_rval 5 16 "retval=16"
27+
test_run_rval 6 42 "retval=42"

xlat/pr_spec_cmds.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
PR_SPEC_STORE_BYPASS 0
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
PR_SPEC_NOT_AFFECTED 0
2+
PR_SPEC_PRCTL (1 << 0)
3+
PR_SPEC_ENABLE (1 << 1)
4+
PR_SPEC_DISABLE (1 << 2)
5+
PR_SPEC_FORCE_DISABLE (1 << 3)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
PR_SPEC_ENABLE (1 << 1)
2+
PR_SPEC_DISABLE (1 << 2)
3+
PR_SPEC_FORCE_DISABLE (1 << 3)

xlat/prctl_options.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,6 @@ PR_GET_FP_MODE 46
4646
PR_CAP_AMBIENT 47
4747
PR_SVE_SET_VL 50
4848
PR_SVE_GET_VL 51
49+
PR_GET_SPECULATION_CTRL 52
50+
PR_SET_SPECULATION_CTRL 53
4951
PR_SET_VMA 0x53564d41

0 commit comments

Comments
 (0)