]> granicus.if.org Git - strace/blob - prctl.c
strace.spec.in: compress changelog files
[strace] / prctl.c
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
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 *
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
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
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 */