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