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.
10 * SPDX-License-Identifier: LGPL-2.1-or-later
18 # define CSIGNAL 0x000000ff
21 #include "print_fields.h"
23 #include "xlat/clone_flags.h"
24 #include "xlat/setns_types.h"
25 #include "xlat/unshare_flags.h"
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
40 #elif defined X86_64 || defined X32
41 /* x86 personality processes have the last two arguments flipped. */
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
62 print_tls_arg(struct tcb *const tcp, const kernel_ulong_t addr)
64 #ifdef HAVE_STRUCT_USER_DESC
65 if ((SUPPORTED_PERSONALITIES == 1) || (current_personality == 1))
67 print_user_desc(tcp, addr, USER_DESC_BOTH);
70 #endif /* HAVE_STRUCT_USER_DESC */
78 const kernel_ulong_t flags = tcp->u_arg[ARG_FLAGS] & ~CSIGNAL;
81 const unsigned int sig = tcp->u_arg[ARG_FLAGS] & CSIGNAL;
83 tprints("child_stack=");
84 printaddr(tcp->u_arg[ARG_STACK]);
87 if (ARG_STACKSIZE != -1)
88 tprintf("stack_size=%#" PRI_klx ", ",
89 tcp->u_arg[ARG_STACKSIZE]);
93 printflags64(clone_flags, flags, "CLONE_???");
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.
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.
117 if ((flags & (CLONE_PARENT_SETTID|CLONE_PIDFD|CLONE_CHILD_SETTID
118 |CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0)
121 if (flags & (CLONE_PARENT_SETTID|CLONE_PIDFD)) {
122 kernel_ulong_t addr = tcp->u_arg[ARG_PTID];
124 tprints(", parent_tid=");
125 if (flags & CLONE_PARENT_SETTID)
126 printnum_int(tcp, addr, "%u");
128 printnum_fd(tcp, addr);
130 if (flags & CLONE_SETTLS) {
132 print_tls_arg(tcp, tcp->u_arg[ARG_TLS]);
134 if (flags & (CLONE_CHILD_SETTID|CLONE_CHILD_CLEARTID)) {
135 tprints(", child_tidptr=");
136 printaddr(tcp->u_arg[ARG_CTID]);
143 struct strace_clone_args {
145 uint64_t /* int * */ pidfd;
146 uint64_t /* int * */ child_tid;
147 uint64_t /* int * */ parent_tid;
148 uint64_t /* int */ exit_signal;
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.
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.
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
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())
174 * @param style Passed to string_quote as "style" parameter.
175 * @return Returns true is anything was printed, false otherwise.
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)
184 if (start_offs >= total_len)
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);
191 char *str = malloc(len);
194 error_func_msg("memory exhausted when tried to allocate"
196 tprintf("%s???", prefix);
202 if (umoven(tcp, addr, len, str)) {
203 tprintf("%s???", prefix);
204 } else if (is_filled(str, 0, len)) {
208 tprintf("/* bytes %u..%u */ ", start_offs, total_len - 1);
210 print_quoted_string(str, size, style);
222 static const size_t minsz = offsetofend(struct strace_clone_args, tls);
224 const kernel_ulong_t addr = tcp->u_arg[0];
225 const kernel_ulong_t size = tcp->u_arg[1];
227 struct strace_clone_args arg = { 0 };
228 kernel_ulong_t fetch_size;
230 fetch_size = MIN(size, sizeof(arg));
233 if (fetch_size < minsz) {
236 } else if (umoven_or_printaddr(tcp, addr, fetch_size, &arg)) {
240 PRINT_FIELD_FLAGS("{", arg, flags, clone_flags,
243 if (arg.flags & CLONE_PIDFD)
244 PRINT_FIELD_ADDR64(", ", arg, pidfd);
246 if (arg.flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID))
247 PRINT_FIELD_ADDR64(", ", arg, child_tid);
249 if (arg.flags & CLONE_PARENT_SETTID)
250 PRINT_FIELD_ADDR64(", ", arg, parent_tid);
252 tprints(", exit_signal=");
253 if (arg.exit_signal < INT_MAX)
254 printsignal(arg.exit_signal);
256 tprintf("%" PRIu64, arg.exit_signal);
258 PRINT_FIELD_ADDR64(", ", arg, stack);
259 PRINT_FIELD_X(", ", arg, stack_size);
261 if (arg.flags & CLONE_SETTLS) {
263 print_tls_arg(tcp, arg.tls);
266 if (size > fetch_size)
267 print_nonzero_bytes(tcp, ", ", addr, fetch_size,
268 MIN(size, get_pagesize()),
273 if ((arg.flags & (CLONE_PIDFD | CLONE_PARENT_SETTID)) ||
285 if (umoven(tcp, addr, fetch_size, &arg)) {
291 static const char initial_pfx[] = " => {";
292 const char *pfx = initial_pfx;
294 if (arg.flags & CLONE_PIDFD) {
295 tprintf("%spidfd=", pfx);
296 printnum_fd(tcp, arg.pidfd);
300 if (arg.flags & CLONE_PARENT_SETTID) {
301 tprintf("%sparent_tid=", pfx);
302 printnum_int(tcp, arg.parent_tid, "%d"); /* TID */
306 if (size > fetch_size) {
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.
313 if (print_nonzero_bytes(tcp, pfx, addr, fetch_size,
314 MIN(size, get_pagesize()),
319 if (pfx != initial_pfx)
323 tprintf(", %" PRI_klu, size);
331 printfd(tcp, tcp->u_arg[0]);
333 printxval(setns_types, tcp->u_arg[1], "CLONE_NEW???");
340 printflags64(unshare_flags, tcp->u_arg[0], "CLONE_???");