Mirror of strace – the linux syscall tracer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

clone.c 8.7KB

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