]> granicus.if.org Git - strace/blob - prctl.c
tests/ioctl_kvm_run.c: handle cpuid at the end of vcpu dentry
[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_sve_vl_flags.h"
46 #include "xlat/pr_tsc.h"
47 #include "xlat/pr_unalign_flags.h"
48
49 #ifndef TASK_COMM_LEN
50 # define TASK_COMM_LEN 16
51 #endif
52
53 #ifdef HAVE_LINUX_SECCOMP_H
54 # include <linux/seccomp.h>
55 #endif
56 #include "xlat/seccomp_mode.h"
57
58 #ifdef HAVE_LINUX_SECUREBITS_H
59 # include <linux/securebits.h>
60 #endif
61 #include "xlat/secbits.h"
62
63 /* these constants are the same as in <linux/capability.h> */
64 enum {
65 #include "caps0.h"
66 #include "caps1.h"
67 };
68
69 #include "xlat/cap.h"
70
71 #ifndef PR_SVE_VL_LEN_MASK
72 # define PR_SVE_VL_LEN_MASK 0xffff
73 #endif
74
75
76 static void
77 print_prctl_args(struct tcb *tcp, const unsigned int first)
78 {
79         unsigned int i;
80
81         for (i = first; i < tcp->s_ent->nargs; ++i)
82                 tprintf(", %#" PRI_klx, tcp->u_arg[i]);
83 }
84
85 static char *
86 sprint_sve_val(kernel_ulong_t arg)
87 {
88         static char out[sizeof("PR_SVE_SET_VL_ONEXEC|PR_SVE_VL_INHERIT|0x") +
89                         sizeof(kernel_ulong_t) * 2];
90
91         kernel_ulong_t vl = arg & PR_SVE_VL_LEN_MASK;
92         kernel_ulong_t flags = arg & ~PR_SVE_VL_LEN_MASK;
93         const char *flags_str = sprintflags("", pr_sve_vl_flags, flags);
94
95         xsprintf(out, "%s%s%#" PRI_klx,
96                  flags_str ?: "", flags_str ? "|" : "", vl);
97
98         return out;
99 }
100
101 SYS_FUNC(prctl)
102 {
103         const unsigned int option = tcp->u_arg[0];
104         const kernel_ulong_t arg2 = tcp->u_arg[1];
105         const kernel_ulong_t arg3 = tcp->u_arg[2];
106         /*
107          * PR_SET_VMA is the only command which actually uses these arguments
108          * currently, and it is available only on Android for now.
109          */
110 #ifdef __ANDROID__
111         const kernel_ulong_t arg4 = tcp->u_arg[3];
112         const kernel_ulong_t arg5 = tcp->u_arg[4];
113 #endif
114         unsigned int i;
115
116         if (entering(tcp))
117                 printxval(prctl_options, option, "PR_???");
118
119         switch (option) {
120         case PR_GET_KEEPCAPS:
121         case PR_GET_SECCOMP:
122         case PR_GET_TIMERSLACK:
123         case PR_GET_TIMING:
124                 return RVAL_DECODED;
125
126         case PR_GET_CHILD_SUBREAPER:
127         case PR_GET_ENDIAN:
128         case PR_GET_FPEMU:
129         case PR_GET_FPEXC:
130                 if (entering(tcp))
131                         tprints(", ");
132                 else
133                         printnum_int(tcp, arg2, "%u");
134                 break;
135
136         case PR_GET_DUMPABLE:
137                 if (entering(tcp))
138                         break;
139                 if (syserror(tcp))
140                         return 0;
141                 tcp->auxstr = xlookup(pr_dumpable, (kernel_ulong_t) tcp->u_rval);
142                 return RVAL_STR;
143
144         case PR_GET_NAME:
145                 if (entering(tcp)) {
146                         tprints(", ");
147                 } else {
148                         if (syserror(tcp))
149                                 printaddr(arg2);
150                         else
151                                 printstr_ex(tcp, arg2, TASK_COMM_LEN,
152                                             QUOTE_0_TERMINATED);
153                 }
154                 break;
155
156         case PR_GET_PDEATHSIG:
157                 if (entering(tcp)) {
158                         tprints(", ");
159                 } else if (!umove_or_printaddr(tcp, arg2, &i)) {
160                         tprints("[");
161                         tprints(signame(i));
162                         tprints("]");
163                 }
164                 break;
165
166         case PR_GET_SECUREBITS:
167                 if (entering(tcp))
168                         break;
169                 if (syserror(tcp) || tcp->u_rval == 0)
170                         return 0;
171                 tcp->auxstr = sprintflags("", secbits,
172                                           (kernel_ulong_t) tcp->u_rval);
173                 return RVAL_STR;
174
175         case PR_GET_TID_ADDRESS:
176                 if (entering(tcp))
177                         tprints(", ");
178                 else
179                         printnum_kptr(tcp, arg2);
180                 break;
181
182         case PR_GET_TSC:
183                 if (entering(tcp)) {
184                         tprints(", ");
185                 } else if (!umove_or_printaddr(tcp, arg2, &i)) {
186                         tprints("[");
187                         printxval(pr_tsc, i, "PR_TSC_???");
188                         tprints("]");
189                 }
190                 break;
191
192         case PR_GET_UNALIGN:
193                 if (entering(tcp)) {
194                         tprints(", ");
195                 } else if (!umove_or_printaddr(tcp, arg2, &i)) {
196                         tprints("[");
197                         printflags(pr_unalign_flags, i, "PR_UNALIGN_???");
198                         tprints("]");
199                 }
200                 break;
201
202         case PR_GET_FP_MODE:
203                 if (entering(tcp))
204                         break;
205                 if (syserror(tcp) || tcp->u_rval == 0)
206                         return 0;
207                 tcp->auxstr = sprintflags("", pr_fp_mode,
208                                           (kernel_ulong_t) tcp->u_rval);
209                 return RVAL_STR;
210
211         case PR_SVE_SET_VL:
212                 if (entering(tcp)) {
213                         tprintf(", %s", sprint_sve_val(arg2));
214                         return 0;
215                 }
216                 ATTRIBUTE_FALLTHROUGH;
217
218         case PR_SVE_GET_VL:
219                 if (entering(tcp))
220                         break;
221                 if (syserror(tcp) || tcp->u_rval == 0)
222                         return 0;
223
224                 tcp->auxstr = sprint_sve_val(tcp->u_rval);
225
226                 return RVAL_STR;
227
228         /* PR_TASK_PERF_EVENTS_* take no arguments. */
229         case PR_TASK_PERF_EVENTS_DISABLE:
230         case PR_TASK_PERF_EVENTS_ENABLE:
231                 return RVAL_DECODED;
232
233         case PR_SET_CHILD_SUBREAPER:
234         case PR_SET_ENDIAN:
235         case PR_SET_FPEMU:
236         case PR_SET_FPEXC:
237         case PR_SET_KEEPCAPS:
238         case PR_SET_TIMING:
239                 tprintf(", %" PRI_klu, arg2);
240                 return RVAL_DECODED;
241
242         case PR_SET_DUMPABLE:
243                 tprints(", ");
244                 printxval64(pr_dumpable, arg2, "SUID_DUMP_???");
245                 return RVAL_DECODED;
246
247         case PR_CAPBSET_DROP:
248         case PR_CAPBSET_READ:
249                 tprints(", ");
250                 printxval64(cap, arg2, "CAP_???");
251                 return RVAL_DECODED;
252
253         case PR_CAP_AMBIENT:
254                 tprints(", ");
255                 printxval64(pr_cap_ambient, arg2,
256                                "PR_CAP_AMBIENT_???");
257                 switch (arg2) {
258                 case PR_CAP_AMBIENT_RAISE:
259                 case PR_CAP_AMBIENT_LOWER:
260                 case PR_CAP_AMBIENT_IS_SET:
261                         tprints(", ");
262                         printxval64(cap, arg3, "CAP_???");
263                         print_prctl_args(tcp, 3);
264                         break;
265                 default:
266                         print_prctl_args(tcp, 2);
267                         break;
268                 }
269                 return RVAL_DECODED;
270
271         case PR_MCE_KILL:
272                 tprints(", ");
273                 printxval64(pr_mce_kill, arg2, "PR_MCE_KILL_???");
274                 tprints(", ");
275                 if (PR_MCE_KILL_SET == arg2)
276                         printxval64(pr_mce_kill_policy, arg3,
277                                     "PR_MCE_KILL_???");
278                 else
279                         tprintf("%#" PRI_klx, arg3);
280                 print_prctl_args(tcp, 3);
281                 return RVAL_DECODED;
282
283         case PR_SET_NAME:
284                 tprints(", ");
285                 printstr_ex(tcp, arg2, TASK_COMM_LEN - 1,
286                             QUOTE_0_TERMINATED);
287                 return RVAL_DECODED;
288
289 #ifdef __ANDROID__
290 # ifndef PR_SET_VMA_ANON_NAME
291 #  define PR_SET_VMA_ANON_NAME    0
292 # endif
293         case PR_SET_VMA:
294                 if (arg2 == PR_SET_VMA_ANON_NAME) {
295                         tprintf(", PR_SET_VMA_ANON_NAME, %#" PRI_klx, arg3);
296                         tprintf(", %" PRI_klu ", ", arg4);
297                         printstr(tcp, arg5);
298                 } else {
299                         /* There are no other sub-options now, but there
300                          * might be in future... */
301                         print_prctl_args(tcp, 1);
302                 }
303                 return RVAL_DECODED;
304 #endif
305
306         case PR_SET_MM:
307                 tprints(", ");
308                 printxval(pr_set_mm, arg2, "PR_SET_MM_???");
309                 print_prctl_args(tcp, 2);
310                 return RVAL_DECODED;
311
312         case PR_SET_PDEATHSIG:
313                 tprints(", ");
314                 if (arg2 > 128)
315                         tprintf("%" PRI_klu, arg2);
316                 else
317                         tprints(signame(arg2));
318                 return RVAL_DECODED;
319
320         case PR_SET_PTRACER:
321                 tprints(", ");
322                 if ((int) arg2 == -1) {
323                         print_xlat_ex(arg2, "PR_SET_PTRACER_ANY",
324                                       XLAT_STYLE_DEFAULT);
325                 } else {
326                         tprintf("%" PRI_klu, arg2);
327                 }
328                 return RVAL_DECODED;
329
330         case PR_SET_SECCOMP:
331                 tprints(", ");
332                 printxval64(seccomp_mode, arg2,
333                             "SECCOMP_MODE_???");
334                 if (SECCOMP_MODE_STRICT == arg2)
335                         return RVAL_DECODED;
336                 if (SECCOMP_MODE_FILTER == arg2) {
337                         tprints(", ");
338                         decode_seccomp_fprog(tcp, arg3);
339                         return RVAL_DECODED;
340                 }
341                 print_prctl_args(tcp, 2);
342                 return RVAL_DECODED;
343
344         case PR_SET_SECUREBITS:
345                 tprints(", ");
346                 printflags64(secbits, arg2, "SECBIT_???");
347                 return RVAL_DECODED;
348
349         case PR_SET_TIMERSLACK:
350                 tprintf(", %" PRI_kld, arg2);
351                 return RVAL_DECODED;
352
353         case PR_SET_TSC:
354                 tprints(", ");
355                 printxval(pr_tsc, arg2, "PR_TSC_???");
356                 return RVAL_DECODED;
357
358         case PR_SET_UNALIGN:
359                 tprints(", ");
360                 printflags(pr_unalign_flags, arg2, "PR_UNALIGN_???");
361                 return RVAL_DECODED;
362
363         case PR_SET_NO_NEW_PRIVS:
364         case PR_SET_THP_DISABLE:
365                 tprintf(", %" PRI_klu, arg2);
366                 print_prctl_args(tcp, 2);
367                 return RVAL_DECODED;
368
369         case PR_MCE_KILL_GET:
370                 if (entering(tcp)) {
371                         print_prctl_args(tcp, 1);
372                         return 0;
373                 }
374                 if (syserror(tcp))
375                         return 0;
376                 tcp->auxstr = xlookup(pr_mce_kill_policy,
377                                       (kernel_ulong_t) tcp->u_rval);
378                 return RVAL_STR;
379
380         case PR_SET_FP_MODE:
381                 tprints(", ");
382                 printflags(pr_fp_mode, arg2, "PR_FP_MODE_???");
383                 return RVAL_DECODED;
384
385         case PR_GET_NO_NEW_PRIVS:
386         case PR_GET_THP_DISABLE:
387         case PR_MPX_DISABLE_MANAGEMENT:
388         case PR_MPX_ENABLE_MANAGEMENT:
389         default:
390                 print_prctl_args(tcp, 1);
391                 return RVAL_DECODED;
392         }
393         return 0;
394 }
395
396 #if defined X86_64 || defined X32 || defined I386
397 # include "xlat/archvals.h"
398
399 SYS_FUNC(arch_prctl)
400 {
401         const unsigned int option = tcp->u_arg[0];
402         const kernel_ulong_t addr = tcp->u_arg[1];
403
404         if (entering(tcp))
405                 printxval(archvals, option, "ARCH_???");
406
407         switch (option) {
408         case ARCH_GET_GS:
409         case ARCH_GET_FS:
410                 if (entering(tcp))
411                         tprints(", ");
412                 else
413                         printnum_ptr(tcp, addr);
414                 return 0;
415         }
416
417         tprintf(", %#" PRI_klx, addr);
418         return RVAL_DECODED;
419 }
420 #endif /* X86_64 || X32 || I386 */