blob: cd51d4c0c24302cca3d26be6653e7bf14bc8bf07 [file] [log] [blame]
Dmitry V. Levin38a34c92015-12-17 17:56:48 +00001/*
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 * 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
Dmitry V. Levin53c993d2014-12-11 19:25:02 +000031#include "defs.h"
32
Dmitry V. Levin53c993d2014-12-11 19:25:02 +000033#include <sys/prctl.h>
34
35#include "xlat/prctl_options.h"
Dmitry V. Levineb76c4b2015-12-06 15:33:53 +000036#include "xlat/pr_cap_ambient.h"
Dmitry V. Levin1e880732015-02-14 01:51:03 +000037#include "xlat/pr_mce_kill.h"
38#include "xlat/pr_mce_kill_policy.h"
39#include "xlat/pr_set_mm.h"
40#include "xlat/pr_tsc.h"
Dmitry V. Levineb76c4b2015-12-06 15:33:53 +000041#include "xlat/pr_unalign_flags.h"
Dmitry V. Levin53c993d2014-12-11 19:25:02 +000042
Dmitry V. Levin1e880732015-02-14 01:51:03 +000043#ifndef TASK_COMM_LEN
44# define TASK_COMM_LEN 16
Dmitry V. Levin53c993d2014-12-11 19:25:02 +000045#endif
Dmitry V. Levin53c993d2014-12-11 19:25:02 +000046
Dmitry V. Levin2af69032015-02-04 23:50:50 +000047#ifdef HAVE_LINUX_SECCOMP_H
48# include <linux/seccomp.h>
49#endif
Dmitry V. Levin2af69032015-02-04 23:50:50 +000050#include "xlat/seccomp_mode.h"
51
Dmitry V. Levin1e880732015-02-14 01:51:03 +000052#ifdef HAVE_LINUX_SECUREBITS_H
53# include <linux/securebits.h>
54#endif
55#include "xlat/secbits.h"
56
57/* these constants are the same as in <linux/capability.h> */
58enum {
59#include "caps0.h"
60#include "caps1.h"
61};
62
63#include "xlat/cap.h"
64
Dmitry V. Levin36915622015-07-25 09:43:01 +000065static void
66print_prctl_args(struct tcb *tcp, const unsigned int first)
67{
68 unsigned int i;
69
70 for (i = first; i < tcp->s_ent->nargs; ++i)
71 tprintf(", %#lx", tcp->u_arg[i]);
72}
73
Dmitry V. Levin210a6b62015-07-17 21:49:17 +000074SYS_FUNC(prctl)
Dmitry V. Levin1e880732015-02-14 01:51:03 +000075{
Dmitry V. Levinb8eec602016-05-16 22:19:31 +000076 const unsigned int option = tcp->u_arg[0];
Dmitry V. Levin1e880732015-02-14 01:51:03 +000077 unsigned int i;
78
Dmitry V. Levin210a6b62015-07-17 21:49:17 +000079 if (entering(tcp))
Dmitry V. Levinb8eec602016-05-16 22:19:31 +000080 printxval(prctl_options, option, "PR_???");
Dmitry V. Levin1e880732015-02-14 01:51:03 +000081
Dmitry V. Levinb8eec602016-05-16 22:19:31 +000082 switch (option) {
Dmitry V. Levin1e880732015-02-14 01:51:03 +000083 case PR_GET_DUMPABLE:
Dmitry V. Levin210a6b62015-07-17 21:49:17 +000084 case PR_GET_KEEPCAPS:
85 case PR_GET_SECCOMP:
86 case PR_GET_TIMERSLACK:
87 case PR_GET_TIMING:
Dmitry V. Levin1b283302015-12-06 15:29:04 +000088 return RVAL_DECODED;
Dmitry V. Levin210a6b62015-07-17 21:49:17 +000089
90 case PR_GET_CHILD_SUBREAPER:
Dmitry V. Levin1e880732015-02-14 01:51:03 +000091 case PR_GET_ENDIAN:
92 case PR_GET_FPEMU:
93 case PR_GET_FPEXC:
Dmitry V. Levin210a6b62015-07-17 21:49:17 +000094 if (entering(tcp))
95 tprints(", ");
96 else
97 printnum_int(tcp, tcp->u_arg[1], "%u");
98 break;
99
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000100 case PR_GET_NAME:
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000101 if (entering(tcp))
102 tprints(", ");
103 else {
104 if (syserror(tcp))
105 printaddr(tcp->u_arg[1]);
106 else
107 printstr(tcp, tcp->u_arg[1], -1);
108 }
109 break;
110
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000111 case PR_GET_PDEATHSIG:
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000112 if (entering(tcp))
113 tprints(", ");
114 else if (!umove_or_printaddr(tcp, tcp->u_arg[1], &i)) {
115 tprints("[");
116 tprints(signame(i));
117 tprints("]");
118 }
119 break;
120
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000121 case PR_GET_SECUREBITS:
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000122 if (entering(tcp))
123 break;
124 if (syserror(tcp) || tcp->u_rval == 0)
125 return 0;
Dmitry V. Levin6274ecc2016-05-15 14:23:06 +0000126 tcp->auxstr = sprintflags("", secbits,
127 (unsigned long) tcp->u_rval);
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000128 return RVAL_STR;
129
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000130 case PR_GET_TID_ADDRESS:
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000131 if (entering(tcp))
132 tprints(", ");
133 else
Dmitry V. Levin2479ef02015-08-18 14:58:27 +0000134 printnum_ptr(tcp, tcp->u_arg[1]);
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000135 break;
136
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000137 case PR_GET_TSC:
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000138 if (entering(tcp))
139 tprints(", ");
140 else if (!umove_or_printaddr(tcp, tcp->u_arg[1], &i)) {
141 tprints("[");
142 printxval(pr_tsc, i, "PR_TSC_???");
143 tprints("]");
144 }
145 break;
146
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000147 case PR_GET_UNALIGN:
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000148 if (entering(tcp))
149 tprints(", ");
150 else if (!umove_or_printaddr(tcp, tcp->u_arg[1], &i)) {
151 tprints("[");
152 printflags(pr_unalign_flags, i, "PR_UNALIGN_???");
153 tprints("]");
154 }
155 break;
156
157 /* PR_TASK_PERF_EVENTS_* take no arguments. */
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000158 case PR_TASK_PERF_EVENTS_DISABLE:
159 case PR_TASK_PERF_EVENTS_ENABLE:
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000160 return RVAL_DECODED;
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000161
162 case PR_SET_CHILD_SUBREAPER:
163 case PR_SET_DUMPABLE:
164 case PR_SET_ENDIAN:
165 case PR_SET_FPEMU:
166 case PR_SET_FPEXC:
167 case PR_SET_KEEPCAPS:
168 case PR_SET_TIMING:
169 tprintf(", %lu", tcp->u_arg[1]);
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000170 return RVAL_DECODED;
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000171
172 case PR_CAPBSET_DROP:
Dmitry V. Levin1b283302015-12-06 15:29:04 +0000173 case PR_CAPBSET_READ:
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000174 tprints(", ");
Dmitry V. Levinc5f68632016-05-16 23:22:11 +0000175 printxval_long(cap, tcp->u_arg[1], "CAP_???");
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000176 return RVAL_DECODED;
177
Dmitry V. Levineb76c4b2015-12-06 15:33:53 +0000178 case PR_CAP_AMBIENT:
179 tprints(", ");
Dmitry V. Levinc5f68632016-05-16 23:22:11 +0000180 printxval_long(pr_cap_ambient, tcp->u_arg[1],
181 "PR_CAP_AMBIENT_???");
Dmitry V. Levineb76c4b2015-12-06 15:33:53 +0000182 switch (tcp->u_arg[1]) {
183 case PR_CAP_AMBIENT_RAISE:
184 case PR_CAP_AMBIENT_LOWER:
185 case PR_CAP_AMBIENT_IS_SET:
186 tprints(", ");
Dmitry V. Levinc5f68632016-05-16 23:22:11 +0000187 printxval_long(cap, tcp->u_arg[2], "CAP_???");
Dmitry V. Levineb76c4b2015-12-06 15:33:53 +0000188 print_prctl_args(tcp, 3);
189 break;
190 default:
191 print_prctl_args(tcp, 2);
192 break;
193 }
194 return RVAL_DECODED;
195
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000196 case PR_MCE_KILL:
197 tprints(", ");
Dmitry V. Levinc5f68632016-05-16 23:22:11 +0000198 printxval_long(pr_mce_kill, tcp->u_arg[1], "PR_MCE_KILL_???");
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000199 tprints(", ");
200 if (PR_MCE_KILL_SET == tcp->u_arg[1])
Dmitry V. Levinc5f68632016-05-16 23:22:11 +0000201 printxval_long(pr_mce_kill_policy, tcp->u_arg[2],
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000202 "PR_MCE_KILL_???");
203 else
204 tprintf("%#lx", tcp->u_arg[2]);
Dmitry V. Levin36915622015-07-25 09:43:01 +0000205 print_prctl_args(tcp, 3);
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000206 return RVAL_DECODED;
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000207
208 case PR_SET_NAME:
209 tprints(", ");
210 printstr(tcp, tcp->u_arg[1], TASK_COMM_LEN);
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000211 return RVAL_DECODED;
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000212
Elliott Hughes1d246ce2015-07-29 22:49:38 +0000213#ifdef __ANDROID__
Elliott Hughes1d246ce2015-07-29 22:49:38 +0000214# ifndef PR_SET_VMA_ANON_NAME
215# define PR_SET_VMA_ANON_NAME 0
216# endif
217 case PR_SET_VMA:
218 if (tcp->u_arg[1] == PR_SET_VMA_ANON_NAME) {
Elliott Hughes612368b2016-04-06 14:41:36 -0700219 tprintf(", PR_SET_VMA_ANON_NAME, %#lx", tcp->u_arg[2]);
Elliott Hughes1d246ce2015-07-29 22:49:38 +0000220 tprintf(", %lu, ", tcp->u_arg[3]);
221 printstr(tcp, tcp->u_arg[4], -1);
222 } else {
223 /* There are no other sub-options now, but there
224 * might be in future... */
225 print_prctl_args(tcp, 1);
226 }
227 return RVAL_DECODED;
228#endif
229
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000230 case PR_SET_MM:
231 tprints(", ");
232 printxval(pr_set_mm, tcp->u_arg[1], "PR_SET_MM_???");
Dmitry V. Levin36915622015-07-25 09:43:01 +0000233 print_prctl_args(tcp, 2);
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000234 return RVAL_DECODED;
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000235
236 case PR_SET_PDEATHSIG:
237 tprints(", ");
238 if ((unsigned long) tcp->u_arg[1] > 128)
239 tprintf("%lu", tcp->u_arg[1]);
240 else
241 tprints(signame(tcp->u_arg[1]));
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000242 return RVAL_DECODED;
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000243
244 case PR_SET_PTRACER:
245 tprints(", ");
246 if (tcp->u_arg[1] == -1)
247 tprints("PR_SET_PTRACER_ANY");
248 else
249 tprintf("%lu", tcp->u_arg[1]);
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000250 return RVAL_DECODED;
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000251
252 case PR_SET_SECCOMP:
253 tprints(", ");
Dmitry V. Levinc5f68632016-05-16 23:22:11 +0000254 printxval_long(seccomp_mode, tcp->u_arg[1],
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000255 "SECCOMP_MODE_???");
256 if (SECCOMP_MODE_STRICT == tcp->u_arg[1])
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000257 return RVAL_DECODED;
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000258 if (SECCOMP_MODE_FILTER == tcp->u_arg[1]) {
259 tprints(", ");
260 print_seccomp_filter(tcp, tcp->u_arg[2]);
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000261 return RVAL_DECODED;
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000262 }
Dmitry V. Levin36915622015-07-25 09:43:01 +0000263 print_prctl_args(tcp, 2);
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000264 return RVAL_DECODED;
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000265
266 case PR_SET_SECUREBITS:
267 tprints(", ");
Dmitry V. Levinc5f68632016-05-16 23:22:11 +0000268 printflags_long(secbits, tcp->u_arg[1], "SECBIT_???");
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000269 return RVAL_DECODED;
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000270
271 case PR_SET_TIMERSLACK:
272 tprintf(", %ld", tcp->u_arg[1]);
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000273 return RVAL_DECODED;
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000274
275 case PR_SET_TSC:
276 tprints(", ");
277 printxval(pr_tsc, tcp->u_arg[1], "PR_TSC_???");
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000278 return RVAL_DECODED;
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000279
280 case PR_SET_UNALIGN:
281 tprints(", ");
282 printflags(pr_unalign_flags, tcp->u_arg[1], "PR_UNALIGN_???");
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000283 return RVAL_DECODED;
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000284
285 case PR_SET_NO_NEW_PRIVS:
286 case PR_SET_THP_DISABLE:
287 tprintf(", %lu", tcp->u_arg[1]);
Dmitry V. Levin36915622015-07-25 09:43:01 +0000288 print_prctl_args(tcp, 2);
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000289 return RVAL_DECODED;
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000290
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000291 case PR_MCE_KILL_GET:
Dmitry V. Levin36915622015-07-25 09:43:01 +0000292 if (entering(tcp)) {
293 print_prctl_args(tcp, 1);
294 return 0;
295 }
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000296 if (syserror(tcp))
297 return 0;
Dmitry V. Levin9134aab2016-05-14 21:46:05 +0000298 tcp->auxstr = xlookup(pr_mce_kill_policy,
299 (unsigned long) tcp->u_rval);
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000300 return tcp->auxstr ? RVAL_STR : RVAL_UDECIMAL;
301
Dmitry V. Levin1b283302015-12-06 15:29:04 +0000302 case PR_GET_NO_NEW_PRIVS:
303 case PR_GET_THP_DISABLE:
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000304 case PR_MPX_DISABLE_MANAGEMENT:
305 case PR_MPX_ENABLE_MANAGEMENT:
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000306 default:
Dmitry V. Levin36915622015-07-25 09:43:01 +0000307 print_prctl_args(tcp, 1);
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000308 return RVAL_DECODED;
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000309 }
310 return 0;
311}
312
Dmitry V. Levin53c993d2014-12-11 19:25:02 +0000313#if defined X86_64 || defined X32
314# include <asm/prctl.h>
315# include "xlat/archvals.h"
316
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000317SYS_FUNC(arch_prctl)
Dmitry V. Levin53c993d2014-12-11 19:25:02 +0000318{
Dmitry V. Levinb8eec602016-05-16 22:19:31 +0000319 const unsigned int option = tcp->u_arg[0];
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000320
Dmitry V. Levinb8eec602016-05-16 22:19:31 +0000321 if (entering(tcp))
322 printxval(archvals, option, "ARCH_???");
323
324 switch (option) {
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000325 case ARCH_GET_GS:
326 case ARCH_GET_FS:
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000327 if (entering(tcp))
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000328 tprints(", ");
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000329 else
Dmitry V. Levin2479ef02015-08-18 14:58:27 +0000330 printnum_ptr(tcp, tcp->u_arg[1]);
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000331 return 0;
Dmitry V. Levin53c993d2014-12-11 19:25:02 +0000332 }
Dmitry V. Levin1e880732015-02-14 01:51:03 +0000333
334 tprintf(", %#lx", tcp->u_arg[1]);
Dmitry V. Levin210a6b62015-07-17 21:49:17 +0000335 return RVAL_DECODED;
Dmitry V. Levin53c993d2014-12-11 19:25:02 +0000336}
337#endif /* X86_64 || X32 */