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