]> granicus.if.org Git - strace/blob - clone.c
Remove traces of riscv64 mpers
[strace] / clone.c
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@altlinux.org>
7  * Copyright (c) 2014-2019 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 <sched.h>
15 #include "scno.h"
16
17 #ifndef CSIGNAL
18 # define CSIGNAL 0x000000ff
19 #endif
20
21 #include "print_fields.h"
22
23 #include "xlat/clone_flags.h"
24 #include "xlat/setns_types.h"
25 #include "xlat/unshare_flags.h"
26
27 #if defined IA64
28 # define ARG_FLAGS      0
29 # define ARG_STACK      1
30 # define ARG_STACKSIZE  (shuffle_scno(tcp->scno) == __NR_clone2 ? 2 : -1)
31 # define ARG_PTID       (shuffle_scno(tcp->scno) == __NR_clone2 ? 3 : 2)
32 # define ARG_CTID       (shuffle_scno(tcp->scno) == __NR_clone2 ? 4 : 3)
33 # define ARG_TLS        (shuffle_scno(tcp->scno) == __NR_clone2 ? 5 : 4)
34 #elif defined S390 || defined S390X
35 # define ARG_STACK      0
36 # define ARG_FLAGS      1
37 # define ARG_PTID       2
38 # define ARG_CTID       3
39 # define ARG_TLS        4
40 #elif defined X86_64 || defined X32
41 /* x86 personality processes have the last two arguments flipped. */
42 # define ARG_FLAGS      0
43 # define ARG_STACK      1
44 # define ARG_PTID       2
45 # define ARG_CTID       ((current_personality != 1) ? 3 : 4)
46 # define ARG_TLS        ((current_personality != 1) ? 4 : 3)
47 #elif defined ALPHA || defined TILE || defined OR1K || defined CSKY
48 # define ARG_FLAGS      0
49 # define ARG_STACK      1
50 # define ARG_PTID       2
51 # define ARG_CTID       3
52 # define ARG_TLS        4
53 #else
54 # define ARG_FLAGS      0
55 # define ARG_STACK      1
56 # define ARG_PTID       2
57 # define ARG_TLS        3
58 # define ARG_CTID       4
59 #endif
60
61 static void
62 print_tls_arg(struct tcb *const tcp, const kernel_ulong_t addr)
63 {
64 #ifdef HAVE_STRUCT_USER_DESC
65         if ((SUPPORTED_PERSONALITIES == 1) || (current_personality == 1))
66         {
67                 print_user_desc(tcp, addr, USER_DESC_BOTH);
68         }
69         else
70 #endif /* HAVE_STRUCT_USER_DESC */
71         {
72                 printaddr(addr);
73         }
74 }
75
76 SYS_FUNC(clone)
77 {
78         const kernel_ulong_t flags = tcp->u_arg[ARG_FLAGS] & ~CSIGNAL;
79
80         if (entering(tcp)) {
81                 const unsigned int sig = tcp->u_arg[ARG_FLAGS] & CSIGNAL;
82
83                 tprints("child_stack=");
84                 printaddr(tcp->u_arg[ARG_STACK]);
85                 tprints(", ");
86 #ifdef ARG_STACKSIZE
87                 if (ARG_STACKSIZE != -1)
88                         tprintf("stack_size=%#" PRI_klx ", ",
89                                 tcp->u_arg[ARG_STACKSIZE]);
90 #endif
91                 tprints("flags=");
92                 if (flags) {
93                         printflags64(clone_flags, flags, "CLONE_???");
94                         if (sig) {
95                                 tprints("|");
96                                 printsignal(sig);
97                         }
98                 } else {
99                         if (sig)
100                                 printsignal(sig);
101                         else
102                                 tprints("0");
103                 }
104                 /*
105                  * TODO on syscall entry:
106                  * We can clear CLONE_PTRACE here since it is an ancient hack
107                  * to allow us to catch children, and we use another hack for that.
108                  * But CLONE_PTRACE can conceivably be used by malicious programs
109                  * to subvert us. By clearing this bit, we can defend against it:
110                  * in untraced execution, CLONE_PTRACE should have no effect.
111                  *
112                  * We can also clear CLONE_UNTRACED, since it allows to start
113                  * children outside of our control. At the moment
114                  * I'm trying to figure out whether there is a *legitimate*
115                  * use of this flag which we should respect.
116                  */
117                 if ((flags & (CLONE_PARENT_SETTID|CLONE_PIDFD|CLONE_CHILD_SETTID
118                               |CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0)
119                         return RVAL_DECODED;
120         } else {
121                 if (flags & (CLONE_PARENT_SETTID|CLONE_PIDFD)) {
122                         kernel_ulong_t addr = tcp->u_arg[ARG_PTID];
123
124                         tprints(", parent_tid=");
125                         if (flags & CLONE_PARENT_SETTID)
126                                 printnum_int(tcp, addr, "%u");
127                         else
128                                 printnum_fd(tcp, addr);
129                 }
130                 if (flags & CLONE_SETTLS) {
131                         tprints(", tls=");
132                         print_tls_arg(tcp, tcp->u_arg[ARG_TLS]);
133                 }
134                 if (flags & (CLONE_CHILD_SETTID|CLONE_CHILD_CLEARTID)) {
135                         tprints(", child_tidptr=");
136                         printaddr(tcp->u_arg[ARG_CTID]);
137                 }
138         }
139         return 0;
140 }
141
142
143 struct strace_clone_args {
144         uint64_t flags;
145         uint64_t /* int * */ pidfd;
146         uint64_t /* int * */ child_tid;
147         uint64_t /* int * */ parent_tid;
148         uint64_t /* int */   exit_signal;
149         uint64_t stack;
150         uint64_t stack_size;
151         uint64_t tls;
152 };
153
154 /**
155  * Print a region of tracee memory only in case non-zero bytes are present
156  * there.  It almost fits into printstr_ex, but it has some pretty specific
157  * behaviour peculiarities (like printing of ellipsis on error) to readily
158  * integrate it there.
159  *
160  * Since it is expected to be used for printing tail of a structure in tracee's
161  * memory, it accepts a combination of start_addr/start_offs/total_len and does
162  * the relevant calculations itself.
163  *
164  * @param prefix     A string printed in cases something is going to be printed.
165  * @param start_addr Address of the beginning of a structure (whose tail
166  *                   is supposedly to be printed) in tracee's memory.
167  * @param start_offs Offset from the beginning of the structure where the tail
168  *                   data starts.
169  * @param total_len  Total size of the tracee's memory region containing
170  *                   the structure and the tail data.
171  *                   Caller is responsible for imposing a sensible (usually
172  *                   mandated by the kernel interface, like get_pagesize())
173  *                   limit here.
174  * @param style      Passed to string_quote as "style" parameter.
175  * @return           Returns true is anything was printed, false otherwise.
176  */
177 static bool
178 print_nonzero_bytes(struct tcb *const tcp, const char *prefix,
179                     const kernel_ulong_t start_addr,
180                     const unsigned int start_offs,
181                     const unsigned int total_len,
182                     const unsigned int style)
183 {
184         if (start_offs >= total_len)
185                 return false;
186
187         const kernel_ulong_t addr = start_addr + start_offs;
188         const unsigned int len = total_len - start_offs;
189         const unsigned int size = MIN(len, max_strlen);
190
191         char *str = malloc(len);
192
193         if (!str) {
194                 error_func_msg("memory exhausted when tried to allocate"
195                                " %u bytes", len);
196                 tprintf("%s???", prefix);
197                 return true;
198         }
199
200         bool ret = true;
201
202         if (umoven(tcp, addr, len, str)) {
203                 tprintf("%s???", prefix);
204         } else if (is_filled(str, 0, len)) {
205                 ret = false;
206         } else {
207                 tprints(prefix);
208                 tprintf("/* bytes %u..%u */ ", start_offs, total_len - 1);
209
210                 print_quoted_string(str, size, style);
211
212                 if (size < len)
213                         tprints("...");
214         }
215
216         free(str);
217         return ret;
218 }
219
220 SYS_FUNC(clone3)
221 {
222         static const size_t minsz = offsetofend(struct strace_clone_args, tls);
223
224         const kernel_ulong_t addr = tcp->u_arg[0];
225         const kernel_ulong_t size = tcp->u_arg[1];
226
227         struct strace_clone_args arg = { 0 };
228         kernel_ulong_t fetch_size;
229
230         fetch_size = MIN(size, sizeof(arg));
231
232         if (entering(tcp)) {
233                 if (fetch_size < minsz) {
234                         printaddr(addr);
235                         goto out;
236                 } else if (umoven_or_printaddr(tcp, addr, fetch_size, &arg)) {
237                         goto out;
238                 }
239
240                 PRINT_FIELD_FLAGS("{", arg, flags, clone_flags,
241                                   "CLONE_???");
242
243                 if (arg.flags & CLONE_PIDFD)
244                         PRINT_FIELD_ADDR64(", ", arg, pidfd);
245
246                 if (arg.flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID))
247                         PRINT_FIELD_ADDR64(", ", arg, child_tid);
248
249                 if (arg.flags & CLONE_PARENT_SETTID)
250                         PRINT_FIELD_ADDR64(", ", arg, parent_tid);
251
252                 tprints(", exit_signal=");
253                 if (arg.exit_signal < INT_MAX)
254                         printsignal(arg.exit_signal);
255                 else
256                         tprintf("%" PRIu64, arg.exit_signal);
257
258                 PRINT_FIELD_ADDR64(", ", arg, stack);
259                 PRINT_FIELD_X(", ", arg, stack_size);
260
261                 if (arg.flags & CLONE_SETTLS) {
262                         tprints(", tls=");
263                         print_tls_arg(tcp, arg.tls);
264                 }
265
266                 if (size > fetch_size)
267                         print_nonzero_bytes(tcp, ", ", addr, fetch_size,
268                                             MIN(size, get_pagesize()),
269                                             QUOTE_FORCE_HEX);
270
271                 tprints("}");
272
273                 if ((arg.flags & (CLONE_PIDFD | CLONE_PARENT_SETTID)) ||
274                     (size > fetch_size))
275                         return 0;
276
277                 goto out;
278         }
279
280         /* exiting */
281
282         if (syserror(tcp))
283                 goto out;
284
285         if (umoven(tcp, addr, fetch_size, &arg)) {
286                 tprints(" => ");
287                 printaddr(addr);
288                 goto out;
289         }
290
291         static const char initial_pfx[] = " => {";
292         const char *pfx = initial_pfx;
293
294         if (arg.flags & CLONE_PIDFD) {
295                 tprintf("%spidfd=", pfx);
296                 printnum_fd(tcp, arg.pidfd);
297                 pfx = ", ";
298         }
299
300         if (arg.flags & CLONE_PARENT_SETTID) {
301                 tprintf("%sparent_tid=", pfx);
302                 printnum_int(tcp, arg.parent_tid, "%d"); /* TID */
303                 pfx = ", ";
304         }
305
306         if (size > fetch_size) {
307                 /*
308                  * TODO: it is possible to also store the tail on entering
309                  *       and then compare against it on exiting in order
310                  *       to avoid double-printing, but it would also require yet
311                  *       another complication of print_nonzero_bytes interface.
312                  */
313                 if (print_nonzero_bytes(tcp, pfx, addr, fetch_size,
314                                         MIN(size, get_pagesize()),
315                                         QUOTE_FORCE_HEX))
316                         pfx = ", ";
317         }
318
319         if (pfx != initial_pfx)
320                 tprints("}");
321
322 out:
323         tprintf(", %" PRI_klu, size);
324
325         return RVAL_DECODED;
326 }
327
328
329 SYS_FUNC(setns)
330 {
331         printfd(tcp, tcp->u_arg[0]);
332         tprints(", ");
333         printxval(setns_types, tcp->u_arg[1], "CLONE_NEW???");
334
335         return RVAL_DECODED;
336 }
337
338 SYS_FUNC(unshare)
339 {
340         printflags64(unshare_flags, tcp->u_arg[0], "CLONE_???");
341         return RVAL_DECODED;
342 }
343
344 SYS_FUNC(fork)
345 {
346         return RVAL_DECODED;
347 }