1 /*
2 * Copyright (c) 1994-1996 Rick Sladkey <jrs@world.std.com>
3 * Copyright (c) 1996-2000 Wichert Akkerman <wichert@cistron.nl>
4 * Copyright (c) 2005-2007 Roland McGrath <roland@redhat.com>
5 * Copyright (c) 2008-2015 Dmitry V. Levin <ldv@altlinux.org>
6 * Copyright (c) 2014-2018 The strace developers.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "defs.h"
33
34 #include <linux/prctl.h>
35
36 #include "xstring.h"
37
38 #include "xlat/prctl_options.h"
39 #include "xlat/pr_cap_ambient.h"
40 #include "xlat/pr_dumpable.h"
41 #include "xlat/pr_fp_mode.h"
42 #include "xlat/pr_mce_kill.h"
43 #include "xlat/pr_mce_kill_policy.h"
44 #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"
48 #include "xlat/pr_sve_vl_flags.h"
49 #include "xlat/pr_tsc.h"
50 #include "xlat/pr_unalign_flags.h"
51
52 #ifndef TASK_COMM_LEN
53 # define TASK_COMM_LEN 16
54 #endif
55
56 #ifdef HAVE_LINUX_SECCOMP_H
57 # include <linux/seccomp.h>
58 #endif
59 #include "xlat/seccomp_mode.h"
60
61 #ifdef HAVE_LINUX_SECUREBITS_H
62 # include <linux/securebits.h>
63 #endif
64 #include "xlat/secbits.h"
65
66 /* these constants are the same as in <linux/capability.h> */
67 enum {
68 #include "caps0.h"
69 #include "caps1.h"
70 };
71
72 #include "xlat/cap.h"
73
74 #ifndef PR_SVE_VL_LEN_MASK
75 # define PR_SVE_VL_LEN_MASK 0xffff
76 #endif
77
78
79 static void
print_prctl_args(struct tcb * tcp,const unsigned int first)80 print_prctl_args(struct tcb *tcp, const unsigned int first)
81 {
82 unsigned int i;
83
84 for (i = first; i < tcp->s_ent->nargs; ++i)
85 tprintf(", %#" PRI_klx, tcp->u_arg[i]);
86 }
87
88 static char *
sprint_sve_val(kernel_ulong_t arg)89 sprint_sve_val(kernel_ulong_t arg)
90 {
91 static char out[sizeof("PR_SVE_SET_VL_ONEXEC|PR_SVE_VL_INHERIT|0x") +
92 sizeof(kernel_ulong_t) * 2];
93
94 kernel_ulong_t vl = arg & PR_SVE_VL_LEN_MASK;
95 kernel_ulong_t flags = arg & ~PR_SVE_VL_LEN_MASK;
96 const char *flags_str = sprintflags("", pr_sve_vl_flags, flags);
97
98 xsprintf(out, "%s%s%#" PRI_klx,
99 flags_str ?: "", flags_str ? "|" : "", vl);
100
101 return out;
102 }
103
SYS_FUNC(prctl)104 SYS_FUNC(prctl)
105 {
106 const unsigned int option = tcp->u_arg[0];
107 const kernel_ulong_t arg2 = tcp->u_arg[1];
108 const kernel_ulong_t arg3 = tcp->u_arg[2];
109 /*
110 * PR_SET_VMA is the only command which actually uses these arguments
111 * currently, and it is available only on Android for now.
112 */
113 #ifdef __ANDROID__
114 const kernel_ulong_t arg4 = tcp->u_arg[3];
115 const kernel_ulong_t arg5 = tcp->u_arg[4];
116 #endif
117 unsigned int i;
118
119 if (entering(tcp))
120 printxval(prctl_options, option, "PR_???");
121
122 switch (option) {
123 case PR_GET_KEEPCAPS:
124 case PR_GET_SECCOMP:
125 case PR_GET_TIMERSLACK:
126 case PR_GET_TIMING:
127 return RVAL_DECODED;
128
129 case PR_GET_CHILD_SUBREAPER:
130 case PR_GET_ENDIAN:
131 case PR_GET_FPEMU:
132 case PR_GET_FPEXC:
133 if (entering(tcp))
134 tprints(", ");
135 else
136 printnum_int(tcp, arg2, "%u");
137 break;
138
139 case PR_GET_DUMPABLE:
140 if (entering(tcp))
141 break;
142 if (syserror(tcp))
143 return 0;
144 tcp->auxstr = xlookup(pr_dumpable, (kernel_ulong_t) tcp->u_rval);
145 return RVAL_STR;
146
147 case PR_GET_NAME:
148 if (entering(tcp)) {
149 tprints(", ");
150 } else {
151 if (syserror(tcp))
152 printaddr(arg2);
153 else
154 printstr_ex(tcp, arg2, TASK_COMM_LEN,
155 QUOTE_0_TERMINATED);
156 }
157 break;
158
159 case PR_GET_PDEATHSIG:
160 if (entering(tcp)) {
161 tprints(", ");
162 } else if (!umove_or_printaddr(tcp, arg2, &i)) {
163 tprints("[");
164 tprints(signame(i));
165 tprints("]");
166 }
167 break;
168
169 case PR_GET_SECUREBITS:
170 if (entering(tcp))
171 break;
172 if (syserror(tcp) || tcp->u_rval == 0)
173 return 0;
174 tcp->auxstr = sprintflags("", secbits,
175 (kernel_ulong_t) tcp->u_rval);
176 return RVAL_STR;
177
178 case PR_GET_TID_ADDRESS:
179 if (entering(tcp))
180 tprints(", ");
181 else
182 printnum_kptr(tcp, arg2);
183 break;
184
185 case PR_GET_TSC:
186 if (entering(tcp)) {
187 tprints(", ");
188 } else if (!umove_or_printaddr(tcp, arg2, &i)) {
189 tprints("[");
190 printxval(pr_tsc, i, "PR_TSC_???");
191 tprints("]");
192 }
193 break;
194
195 case PR_GET_UNALIGN:
196 if (entering(tcp)) {
197 tprints(", ");
198 } else if (!umove_or_printaddr(tcp, arg2, &i)) {
199 tprints("[");
200 printflags(pr_unalign_flags, i, "PR_UNALIGN_???");
201 tprints("]");
202 }
203 break;
204
205 case PR_GET_FP_MODE:
206 if (entering(tcp))
207 break;
208 if (syserror(tcp) || tcp->u_rval == 0)
209 return 0;
210 tcp->auxstr = sprintflags("", pr_fp_mode,
211 (kernel_ulong_t) tcp->u_rval);
212 return RVAL_STR;
213
214 case PR_SVE_SET_VL:
215 if (entering(tcp)) {
216 tprintf(", %s", sprint_sve_val(arg2));
217 return 0;
218 }
219 ATTRIBUTE_FALLTHROUGH;
220
221 case PR_SVE_GET_VL:
222 if (entering(tcp))
223 break;
224 if (syserror(tcp) || tcp->u_rval == 0)
225 return 0;
226
227 tcp->auxstr = sprint_sve_val(tcp->u_rval);
228
229 return RVAL_STR;
230
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
252 /* PR_TASK_PERF_EVENTS_* take no arguments. */
253 case PR_TASK_PERF_EVENTS_DISABLE:
254 case PR_TASK_PERF_EVENTS_ENABLE:
255 return RVAL_DECODED;
256
257 case PR_SET_CHILD_SUBREAPER:
258 case PR_SET_ENDIAN:
259 case PR_SET_FPEMU:
260 case PR_SET_FPEXC:
261 case PR_SET_KEEPCAPS:
262 case PR_SET_TIMING:
263 tprintf(", %" PRI_klu, arg2);
264 return RVAL_DECODED;
265
266 case PR_SET_DUMPABLE:
267 tprints(", ");
268 printxval64(pr_dumpable, arg2, "SUID_DUMP_???");
269 return RVAL_DECODED;
270
271 case PR_CAPBSET_DROP:
272 case PR_CAPBSET_READ:
273 tprints(", ");
274 printxval64(cap, arg2, "CAP_???");
275 return RVAL_DECODED;
276
277 case PR_CAP_AMBIENT:
278 tprints(", ");
279 printxval64(pr_cap_ambient, arg2,
280 "PR_CAP_AMBIENT_???");
281 switch (arg2) {
282 case PR_CAP_AMBIENT_RAISE:
283 case PR_CAP_AMBIENT_LOWER:
284 case PR_CAP_AMBIENT_IS_SET:
285 tprints(", ");
286 printxval64(cap, arg3, "CAP_???");
287 print_prctl_args(tcp, 3);
288 break;
289 default:
290 print_prctl_args(tcp, 2);
291 break;
292 }
293 return RVAL_DECODED;
294
295 case PR_MCE_KILL:
296 tprints(", ");
297 printxval64(pr_mce_kill, arg2, "PR_MCE_KILL_???");
298 tprints(", ");
299 if (PR_MCE_KILL_SET == arg2)
300 printxval64(pr_mce_kill_policy, arg3,
301 "PR_MCE_KILL_???");
302 else
303 tprintf("%#" PRI_klx, arg3);
304 print_prctl_args(tcp, 3);
305 return RVAL_DECODED;
306
307 case PR_SET_NAME:
308 tprints(", ");
309 printstr_ex(tcp, arg2, TASK_COMM_LEN - 1,
310 QUOTE_0_TERMINATED);
311 return RVAL_DECODED;
312
313 #ifdef __ANDROID__
314 # ifndef PR_SET_VMA_ANON_NAME
315 # define PR_SET_VMA_ANON_NAME 0
316 # endif
317 case PR_SET_VMA:
318 if (arg2 == PR_SET_VMA_ANON_NAME) {
319 tprintf(", PR_SET_VMA_ANON_NAME, %#" PRI_klx, arg3);
320 tprintf(", %" PRI_klu ", ", arg4);
321 printstr(tcp, arg5);
322 } else {
323 /* There are no other sub-options now, but there
324 * might be in future... */
325 print_prctl_args(tcp, 1);
326 }
327 return RVAL_DECODED;
328 #endif
329
330 case PR_SET_MM:
331 tprints(", ");
332 printxval(pr_set_mm, arg2, "PR_SET_MM_???");
333 print_prctl_args(tcp, 2);
334 return RVAL_DECODED;
335
336 case PR_SET_PDEATHSIG:
337 tprints(", ");
338 if (arg2 > 128)
339 tprintf("%" PRI_klu, arg2);
340 else
341 tprints(signame(arg2));
342 return RVAL_DECODED;
343
344 case PR_SET_PTRACER:
345 tprints(", ");
346 if ((int) arg2 == -1) {
347 print_xlat_ex(arg2, "PR_SET_PTRACER_ANY",
348 XLAT_STYLE_DEFAULT);
349 } else {
350 tprintf("%" PRI_klu, arg2);
351 }
352 return RVAL_DECODED;
353
354 case PR_SET_SECCOMP:
355 tprints(", ");
356 printxval64(seccomp_mode, arg2,
357 "SECCOMP_MODE_???");
358 if (SECCOMP_MODE_STRICT == arg2)
359 return RVAL_DECODED;
360 if (SECCOMP_MODE_FILTER == arg2) {
361 tprints(", ");
362 decode_seccomp_fprog(tcp, arg3);
363 return RVAL_DECODED;
364 }
365 print_prctl_args(tcp, 2);
366 return RVAL_DECODED;
367
368 case PR_SET_SECUREBITS:
369 tprints(", ");
370 printflags64(secbits, arg2, "SECBIT_???");
371 return RVAL_DECODED;
372
373 case PR_SET_TIMERSLACK:
374 tprintf(", %" PRI_kld, arg2);
375 return RVAL_DECODED;
376
377 case PR_SET_TSC:
378 tprints(", ");
379 printxval(pr_tsc, arg2, "PR_TSC_???");
380 return RVAL_DECODED;
381
382 case PR_SET_UNALIGN:
383 tprints(", ");
384 printflags(pr_unalign_flags, arg2, "PR_UNALIGN_???");
385 return RVAL_DECODED;
386
387 case PR_SET_NO_NEW_PRIVS:
388 case PR_SET_THP_DISABLE:
389 tprintf(", %" PRI_klu, arg2);
390 print_prctl_args(tcp, 2);
391 return RVAL_DECODED;
392
393 case PR_MCE_KILL_GET:
394 if (entering(tcp)) {
395 print_prctl_args(tcp, 1);
396 return 0;
397 }
398 if (syserror(tcp))
399 return 0;
400 tcp->auxstr = xlookup(pr_mce_kill_policy,
401 (kernel_ulong_t) tcp->u_rval);
402 return RVAL_STR;
403
404 case PR_SET_FP_MODE:
405 tprints(", ");
406 printflags(pr_fp_mode, arg2, "PR_FP_MODE_???");
407 return RVAL_DECODED;
408
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
426 case PR_GET_NO_NEW_PRIVS:
427 case PR_GET_THP_DISABLE:
428 case PR_MPX_DISABLE_MANAGEMENT:
429 case PR_MPX_ENABLE_MANAGEMENT:
430 default:
431 print_prctl_args(tcp, 1);
432 return RVAL_DECODED;
433 }
434 return 0;
435 }
436
437 #if defined X86_64 || defined X32 || defined I386
438 # include "xlat/archvals.h"
439
SYS_FUNC(arch_prctl)440 SYS_FUNC(arch_prctl)
441 {
442 const unsigned int option = tcp->u_arg[0];
443 const kernel_ulong_t addr = tcp->u_arg[1];
444
445 if (entering(tcp))
446 printxval(archvals, option, "ARCH_???");
447
448 switch (option) {
449 case ARCH_GET_GS:
450 case ARCH_GET_FS:
451 if (entering(tcp))
452 tprints(", ");
453 else
454 printnum_ptr(tcp, addr);
455 return 0;
456 }
457
458 tprintf(", %#" PRI_klx, addr);
459 return RVAL_DECODED;
460 }
461 #endif /* X86_64 || X32 || I386 */
462