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