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.

mmsghdr.c 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /*
  2. * Copyright (c) 2010 Andreas Schwab <schwab@linux-m68k.org>
  3. * Copyright (c) 2012-2013 Denys Vlasenko <vda.linux@googlemail.com>
  4. * Copyright (c) 2014 Masatake YAMATO <yamato@redhat.com>
  5. * Copyright (c) 2010-2016 Dmitry V. Levin <ldv@altlinux.org>
  6. * Copyright (c) 2016-2019 The strace developers.
  7. * All rights reserved.
  8. *
  9. * SPDX-License-Identifier: LGPL-2.1-or-later
  10. */
  11. #include "defs.h"
  12. #include "msghdr.h"
  13. #include "xstring.h"
  14. #include <limits.h>
  15. static bool
  16. fetch_struct_mmsghdr_for_print(struct tcb *const tcp,
  17. const kernel_ulong_t addr,
  18. const unsigned int len, void *const mh)
  19. {
  20. return (entering(tcp) || !syserror(tcp)) &&
  21. fetch_struct_mmsghdr(tcp, addr, mh);
  22. }
  23. struct print_struct_mmsghdr_config {
  24. const int *p_user_msg_namelen;
  25. unsigned int msg_len_vlen;
  26. unsigned int count;
  27. bool use_msg_len;
  28. };
  29. static bool
  30. print_struct_mmsghdr(struct tcb *tcp, void *elem_buf,
  31. size_t elem_size, void *data)
  32. {
  33. const struct mmsghdr *const mmsg = elem_buf;
  34. struct print_struct_mmsghdr_config *const c = data;
  35. if (!c->count) {
  36. tprints("...");
  37. return false;
  38. }
  39. --c->count;
  40. tprints("{msg_hdr=");
  41. print_struct_msghdr(tcp, &mmsg->msg_hdr, c->p_user_msg_namelen,
  42. c->use_msg_len ? mmsg->msg_len : (kernel_ulong_t) -1);
  43. if (c->msg_len_vlen) {
  44. tprintf(", msg_len=%u", mmsg->msg_len);
  45. --c->msg_len_vlen;
  46. }
  47. tprints("}");
  48. if (c->p_user_msg_namelen)
  49. ++c->p_user_msg_namelen;
  50. return true;
  51. }
  52. static void
  53. free_mmsgvec_data(void *ptr)
  54. {
  55. char **pstr = ptr;
  56. free(*pstr);
  57. *pstr = 0;
  58. free(ptr);
  59. }
  60. struct mmsgvec_data {
  61. char *timeout;
  62. unsigned int count;
  63. int namelen[IOV_MAX];
  64. };
  65. static void
  66. save_mmsgvec_namelen(struct tcb *const tcp, kernel_ulong_t addr,
  67. unsigned int len, const char *const timeout)
  68. {
  69. if (len > IOV_MAX)
  70. len = IOV_MAX;
  71. const size_t data_size = offsetof(struct mmsgvec_data, namelen)
  72. + sizeof(int) * len;
  73. struct mmsgvec_data *const data = xmalloc(data_size);
  74. data->timeout = xstrdup(timeout);
  75. unsigned int i, fetched;
  76. for (i = 0; i < len; ++i, addr += fetched) {
  77. struct mmsghdr mh;
  78. fetched = fetch_struct_mmsghdr(tcp, addr, &mh);
  79. if (!fetched)
  80. break;
  81. data->namelen[i] = mh.msg_hdr.msg_namelen;
  82. }
  83. data->count = i;
  84. set_tcb_priv_data(tcp, data, free_mmsgvec_data);
  85. }
  86. static void
  87. decode_mmsgvec(struct tcb *const tcp, const kernel_ulong_t addr,
  88. const unsigned int vlen, const unsigned int msg_len_vlen,
  89. const bool use_msg_len)
  90. {
  91. struct mmsghdr mmsg;
  92. struct print_struct_mmsghdr_config c = {
  93. .msg_len_vlen = msg_len_vlen,
  94. .count = IOV_MAX,
  95. .use_msg_len = use_msg_len
  96. };
  97. const struct mmsgvec_data *const data = get_tcb_priv_data(tcp);
  98. if (data) {
  99. if (data->count < c.count)
  100. c.count = data->count;
  101. c.p_user_msg_namelen = data->namelen;
  102. }
  103. print_array(tcp, addr, vlen, &mmsg, sizeof_struct_mmsghdr(),
  104. fetch_struct_mmsghdr_for_print,
  105. print_struct_mmsghdr, &c);
  106. }
  107. void
  108. dumpiov_in_mmsghdr(struct tcb *const tcp, kernel_ulong_t addr)
  109. {
  110. unsigned int len = tcp->u_rval;
  111. unsigned int i, fetched;
  112. struct mmsghdr mmsg;
  113. for (i = 0; i < len; ++i, addr += fetched) {
  114. fetched = fetch_struct_mmsghdr(tcp, addr, &mmsg);
  115. if (!fetched)
  116. break;
  117. tprintf(" = %" PRI_klu " buffers in vector %u\n",
  118. (kernel_ulong_t) mmsg.msg_hdr.msg_iovlen, i);
  119. dumpiov_upto(tcp, mmsg.msg_hdr.msg_iovlen,
  120. ptr_to_kulong(mmsg.msg_hdr.msg_iov),
  121. mmsg.msg_len);
  122. }
  123. }
  124. SYS_FUNC(sendmmsg)
  125. {
  126. if (entering(tcp)) {
  127. /* sockfd */
  128. printfd(tcp, tcp->u_arg[0]);
  129. tprints(", ");
  130. if (!verbose(tcp)) {
  131. /* msgvec */
  132. printaddr(tcp->u_arg[1]);
  133. /* vlen */
  134. tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
  135. /* flags */
  136. printflags(msg_flags, tcp->u_arg[3], "MSG_???");
  137. return RVAL_DECODED;
  138. }
  139. } else {
  140. const unsigned int msg_len_vlen =
  141. syserror(tcp) ? 0 : tcp->u_rval;
  142. /* msgvec */
  143. temporarily_clear_syserror(tcp);
  144. decode_mmsgvec(tcp, tcp->u_arg[1], tcp->u_arg[2],
  145. msg_len_vlen, false);
  146. restore_cleared_syserror(tcp);
  147. /* vlen */
  148. tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
  149. /* flags */
  150. printflags(msg_flags, tcp->u_arg[3], "MSG_???");
  151. }
  152. return 0;
  153. }
  154. static int
  155. do_recvmmsg(struct tcb *const tcp, const print_obj_by_addr_fn print_ts,
  156. const sprint_obj_by_addr_fn sprint_ts)
  157. {
  158. if (entering(tcp)) {
  159. printfd(tcp, tcp->u_arg[0]);
  160. tprints(", ");
  161. if (verbose(tcp)) {
  162. save_mmsgvec_namelen(tcp, tcp->u_arg[1], tcp->u_arg[2],
  163. sprint_ts(tcp, tcp->u_arg[4]));
  164. } else {
  165. /* msgvec */
  166. printaddr(tcp->u_arg[1]);
  167. /* vlen */
  168. tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
  169. /* flags */
  170. printflags(msg_flags, tcp->u_arg[3], "MSG_???");
  171. tprints(", ");
  172. print_ts(tcp, tcp->u_arg[4]);
  173. }
  174. return 0;
  175. } else {
  176. if (verbose(tcp)) {
  177. /* msgvec */
  178. decode_mmsgvec(tcp, tcp->u_arg[1], tcp->u_rval,
  179. tcp->u_rval, true);
  180. /* vlen */
  181. tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
  182. /* flags */
  183. printflags(msg_flags, tcp->u_arg[3], "MSG_???");
  184. tprints(", ");
  185. /* timeout on entrance */
  186. tprints(*(const char **) get_tcb_priv_data(tcp));
  187. }
  188. if (syserror(tcp))
  189. return 0;
  190. if (tcp->u_rval == 0) {
  191. tcp->auxstr = "Timeout";
  192. return RVAL_STR;
  193. }
  194. if (!verbose(tcp) || !tcp->u_arg[4])
  195. return 0;
  196. /* timeout on exit */
  197. static char str[sizeof("left") + TIMESPEC_TEXT_BUFSIZE];
  198. xsprintf(str, "left %s", sprint_ts(tcp, tcp->u_arg[4]));
  199. tcp->auxstr = str;
  200. return RVAL_STR;
  201. }
  202. }
  203. #if HAVE_ARCH_TIME32_SYSCALLS
  204. SYS_FUNC(recvmmsg_time32)
  205. {
  206. return do_recvmmsg(tcp, print_timespec32, sprint_timespec32);
  207. }
  208. #endif
  209. SYS_FUNC(recvmmsg_time64)
  210. {
  211. return do_recvmmsg(tcp, print_timespec64, sprint_timespec64);
  212. }