1 /*
2 * Copyright (c) 1999-2000 Wichert Akkerman <wichert@cistron.nl>
3 * Copyright (c) 2002-2005 Roland McGrath <roland@redhat.com>
4 * Copyright (c) 2008 Jan Kratochvil <jan.kratochvil@redhat.com>
5 * Copyright (c) 2009-2013 Denys Vlasenko <dvlasenk@redhat.com>
6 * Copyright (c) 2006-2015 Dmitry V. Levin <ldv@strace.io>
7 * Copyright (c) 2014-2022 The strace developers.
8 * All rights reserved.
9 *
10 * SPDX-License-Identifier: LGPL-2.1-or-later
11 */
12
13 #include "defs.h"
14 #include "scno.h"
15 #include <linux/sched.h>
16
17 #include "xlat/clone_flags.h"
18 #include "xlat/clone3_flags.h"
19 #include "xlat/setns_types.h"
20 #include "xlat/unshare_flags.h"
21
22 #if defined IA64
23 # define ARG_FLAGS 0
24 # define ARG_STACK 1
25 # define ARG_STACKSIZE (shuffle_scno(tcp->scno) == __NR_clone2 ? 2 : -1)
26 # define ARG_PTID (shuffle_scno(tcp->scno) == __NR_clone2 ? 3 : 2)
27 # define ARG_CTID (shuffle_scno(tcp->scno) == __NR_clone2 ? 4 : 3)
28 # define ARG_TLS (shuffle_scno(tcp->scno) == __NR_clone2 ? 5 : 4)
29 #elif defined S390 || defined S390X
30 # define ARG_STACK 0
31 # define ARG_FLAGS 1
32 # define ARG_PTID 2
33 # define ARG_CTID 3
34 # define ARG_TLS 4
35 #elif defined X86_64 || defined X32
36 /* x86 personality processes have the last two arguments flipped. */
37 # define ARG_FLAGS 0
38 # define ARG_STACK 1
39 # define ARG_PTID 2
40 # define ARG_CTID ((current_personality != 1) ? 3 : 4)
41 # define ARG_TLS ((current_personality != 1) ? 4 : 3)
42 #elif defined ALPHA || defined TILE || defined OR1K || defined CSKY
43 # define ARG_FLAGS 0
44 # define ARG_STACK 1
45 # define ARG_PTID 2
46 # define ARG_CTID 3
47 # define ARG_TLS 4
48 #else
49 # define ARG_FLAGS 0
50 # define ARG_STACK 1
51 # define ARG_PTID 2
52 # define ARG_TLS 3
53 # define ARG_CTID 4
54 #endif
55
56 static void
57 print_tls_arg(struct tcb *const tcp, const kernel_ulong_t addr)
58 {
59 #ifdef HAVE_STRUCT_USER_DESC
60 if ((SUPPORTED_PERSONALITIES == 1) || (current_personality == 1))
61 {
62 print_user_desc(tcp, addr, USER_DESC_BOTH);
63 }
64 else
65 #endif /* HAVE_STRUCT_USER_DESC */
66 {
67 printaddr(addr);
68 }
69 }
70
71 SYS_FUNC(clone)
72 {
73 const kernel_ulong_t flags = tcp->u_arg[ARG_FLAGS] & ~CSIGNAL;
74
75 if (entering(tcp)) {
76 const unsigned int sig = tcp->u_arg[ARG_FLAGS] & CSIGNAL;
77
78 tprints_arg_name_begin("child_stack");
79 printaddr(tcp->u_arg[ARG_STACK]);
80 tprint_arg_name_end();
81 tprint_arg_next();
82 #ifdef ARG_STACKSIZE
83 if (ARG_STACKSIZE != -1) {
84 tprints_arg_name_begin("stack_size");
85 PRINT_VAL_X(tcp->u_arg[ARG_STACKSIZE]);
86 tprint_arg_name_end();
87 tprint_arg_next();
88 }
89 #endif
90 tprints_arg_name_begin("flags");
91 if (flags) {
92 tprint_flags_begin();
93 printflags64_in(clone_flags, flags, "CLONE_???");
94 if (sig) {
95 tprint_flags_or();
96 printsignal(sig);
97 }
98 tprint_flags_end();
99 } else {
100 printsignal(sig);
101 }
102 tprint_arg_name_end();
103 /*
104 * TODO on syscall entry:
105 * We can clear CLONE_PTRACE here since it is an ancient hack
106 * to allow us to catch children, and we use another hack for that.
107 * But CLONE_PTRACE can conceivably be used by malicious programs
108 * to subvert us. By clearing this bit, we can defend against it:
109 * in untraced execution, CLONE_PTRACE should have no effect.
110 *
111 * We can also clear CLONE_UNTRACED, since it allows to start
112 * children outside of our control. At the moment
113 * I'm trying to figure out whether there is a *legitimate*
114 * use of this flag which we should respect.
115 */
116 if ((flags & (CLONE_PARENT_SETTID|CLONE_PIDFD|CLONE_CHILD_SETTID
117 |CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0)
118 return RVAL_DECODED | RVAL_TID;
119 } else {
120 if (flags & (CLONE_PARENT_SETTID|CLONE_PIDFD)) {
121 kernel_ulong_t addr = tcp->u_arg[ARG_PTID];
122
123 tprint_arg_next();
124 tprints_arg_name_begin("parent_tid");
125 if (flags & CLONE_PARENT_SETTID)
126 printnum_pid(tcp, addr, PT_TID);
127 else
128 printnum_fd(tcp, addr);
129 tprint_arg_name_end();
130 }
131 if (flags & CLONE_SETTLS) {
132 tprint_arg_next();
133 tprints_arg_name_begin("tls");
134 print_tls_arg(tcp, tcp->u_arg[ARG_TLS]);
135 tprint_arg_name_end();
136 }
137 if (flags & (CLONE_CHILD_SETTID|CLONE_CHILD_CLEARTID)) {
138 tprint_arg_next();
139 tprints_arg_name_begin("child_tidptr");
140 printaddr(tcp->u_arg[ARG_CTID]);
141 tprint_arg_name_end();
142 }
143 }
144 return RVAL_TID;
145 }
146
147 static void
148 tprint_value_changed_struct_begin(void)
149 {
150 tprint_value_changed();
151 tprint_struct_begin();
152 }
153
154 SYS_FUNC(clone3)
155 {
156 static const size_t minsz = offsetofend(struct clone_args, tls);
157
158 const kernel_ulong_t addr = tcp->u_arg[0];
159 const kernel_ulong_t size = tcp->u_arg[1];
160
161 struct clone_args arg = { 0 };
162 kernel_ulong_t fetch_size;
163
164 fetch_size = MIN(size, sizeof(arg));
165
166 if (entering(tcp)) {
167 if (fetch_size < minsz) {
168 printaddr(addr);
169 goto out;
170 } else if (umoven_or_printaddr(tcp, addr, fetch_size, &arg)) {
171 goto out;
172 }
173
174 tprint_struct_begin();
175 tprints_field_name("flags");
176 tprint_flags_begin();
177 printflags_ex(arg.flags, "CLONE_???", XLAT_STYLE_DEFAULT,
178 clone_flags, clone3_flags, NULL);
179 tprint_flags_end();
180
181 if (arg.flags & CLONE_PIDFD) {
182 tprint_struct_next();
183 PRINT_FIELD_ADDR64(arg, pidfd);
184 }
185
186 if (arg.flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) {
187 tprint_struct_next();
188 PRINT_FIELD_ADDR64(arg, child_tid);
189 }
190
191 if (arg.flags & CLONE_PARENT_SETTID) {
192 tprint_struct_next();
193 PRINT_FIELD_ADDR64(arg, parent_tid);
194 }
195
196 if (arg.exit_signal < INT_MAX) {
197 tprint_struct_next();
198 PRINT_FIELD_OBJ_VAL(arg, exit_signal, printsignal);
199 } else {
200 tprint_struct_next();
201 PRINT_FIELD_U(arg, exit_signal);
202 }
203
204 tprint_struct_next();
205 PRINT_FIELD_ADDR64(arg, stack);
206 tprint_struct_next();
207 PRINT_FIELD_X(arg, stack_size);
208
209 if (arg.flags & CLONE_SETTLS) {
210 tprint_struct_next();
211 PRINT_FIELD_OBJ_TCB_VAL(arg, tls, tcp,
212 print_tls_arg);
213 }
214
215 if (arg.set_tid || arg.set_tid_size) {
216 static const unsigned int max_set_tid_size = 32;
217
218 if (!arg.set_tid || !arg.set_tid_size ||
219 arg.set_tid_size > max_set_tid_size) {
220 tprint_struct_next();
221 PRINT_FIELD_ADDR64(arg, set_tid);
222 } else {
223 int buf;
224
225 tprint_struct_next();
226 PRINT_FIELD_OBJ_TCB_VAL(arg, set_tid, tcp,
227 print_array, arg.set_tid_size,
228 &buf, sizeof(buf), tfetch_mem,
229 print_int_array_member, 0);
230 }
231 tprint_struct_next();
232 PRINT_FIELD_U(arg, set_tid_size);
233 }
234
235 if (fetch_size > offsetof(struct clone_args, cgroup)
236 && (arg.cgroup || arg.flags & CLONE_INTO_CGROUP)) {
237 tprint_struct_next();
238 PRINT_FIELD_U(arg, cgroup);
239 }
240
241 if (size > fetch_size)
242 print_nonzero_bytes(tcp, tprint_struct_next,
243 addr, fetch_size,
244 MIN(size, get_pagesize()),
245 QUOTE_FORCE_HEX);
246
247 tprint_struct_end();
248
249 if ((arg.flags & (CLONE_PIDFD | CLONE_PARENT_SETTID)) ||
250 (size > fetch_size))
251 return RVAL_TID;
252
253 goto out;
254 }
255
256 /* exiting */
257
258 if (syserror(tcp))
259 goto out;
260
261 if (umoven(tcp, addr, fetch_size, &arg)) {
262 tprint_value_changed();
263 printaddr(addr);
264 goto out;
265 }
266
267 void (*prefix_fun)(void) = tprint_value_changed_struct_begin;
268
269 if (arg.flags & CLONE_PIDFD) {
270 prefix_fun();
271 prefix_fun = tprint_struct_next;
272 tprints_field_name("pidfd");
273 printnum_fd(tcp, arg.pidfd);
274 }
275
276 if (arg.flags & CLONE_PARENT_SETTID) {
277 prefix_fun();
278 prefix_fun = tprint_struct_next;
279 tprints_field_name("parent_tid");
280 printnum_pid(tcp, arg.parent_tid, PT_TID);
281 }
282
283 if (size > fetch_size) {
284 /*
285 * TODO: it is possible to also store the tail on entering
286 * and then compare against it on exiting in order
287 * to avoid double-printing, but it would also require yet
288 * another complication of print_nonzero_bytes interface.
289 */
290 if (print_nonzero_bytes(tcp, prefix_fun, addr, fetch_size,
291 MIN(size, get_pagesize()),
292 QUOTE_FORCE_HEX)) {
293 prefix_fun = tprint_struct_next;
294 }
295 }
296
297 if (prefix_fun != tprint_value_changed_struct_begin)
298 tprint_struct_end();
299
300 out:
301 tprint_arg_next();
302 PRINT_VAL_U(size);
303
304 return RVAL_DECODED | RVAL_TID;
305 }
306
307
308 SYS_FUNC(setns)
309 {
310 printfd(tcp, tcp->u_arg[0]);
311 tprint_arg_next();
312 printflags(setns_types, tcp->u_arg[1], "CLONE_NEW???");
313
314 return RVAL_DECODED;
315 }
316
317 SYS_FUNC(unshare)
318 {
319 printflags64(unshare_flags, tcp->u_arg[0], "CLONE_???");
320 return RVAL_DECODED;
321 }
322
323 SYS_FUNC(fork)
324 {
325 return RVAL_DECODED | RVAL_TGID;
326 }