Branch data Line data Source code
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 : : * All rights reserved.
7 : : *
8 : : * Redistribution and use in source and binary forms, with or without
9 : : * modification, are permitted provided that the following conditions
10 : : * are met:
11 : : * 1. Redistributions of source code must retain the above copyright
12 : : * notice, this list of conditions and the following disclaimer.
13 : : * 2. Redistributions in binary form must reproduce the above copyright
14 : : * notice, this list of conditions and the following disclaimer in the
15 : : * documentation and/or other materials provided with the distribution.
16 : : * 3. The name of the author may not be used to endorse or promote products
17 : : * derived from this software without specific prior written permission.
18 : : *
19 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 : : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 : : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 : : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 : : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 : : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 : : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 : : */
30 : :
31 : : #include "defs.h"
32 : : #include "msghdr.h"
33 : : #include <limits.h>
34 : :
35 : : static int
36 : 14622 : fetch_struct_mmsghdr_or_printaddr(struct tcb *const tcp,
37 : : const kernel_ulong_t addr,
38 : : const unsigned int len, void *const mh)
39 : : {
40 [ + - ][ + + ]: 14622 : if ((entering(tcp) || !syserror(tcp))
41 [ + + ]: 14616 : && fetch_struct_mmsghdr(tcp, addr, mh)) {
42 : 14604 : return 0;
43 : : } else {
44 : 18 : printaddr(addr);
45 : 18 : return -1;
46 : : }
47 : : }
48 : :
49 : : struct print_struct_mmsghdr_config {
50 : : const int *p_user_msg_namelen;
51 : : unsigned int msg_len_vlen;
52 : : unsigned int count;
53 : : bool use_msg_len;
54 : : };
55 : :
56 : : static bool
57 : 14586 : print_struct_mmsghdr(struct tcb *tcp, void *elem_buf,
58 : : size_t elem_size, void *data)
59 : : {
60 : 14586 : const struct mmsghdr *const mmsg = elem_buf;
61 : 14586 : struct print_struct_mmsghdr_config *const c = data;
62 : :
63 [ + + ]: 14586 : if (!c->count) {
64 : 12 : tprints("...");
65 : 12 : return false;
66 : : }
67 : 14574 : --c->count;
68 : :
69 : 14574 : tprints("{msg_hdr=");
70 [ + + ]: 14574 : print_struct_msghdr(tcp, &mmsg->msg_hdr, c->p_user_msg_namelen,
71 : 16452 : c->use_msg_len ? mmsg->msg_len : (kernel_ulong_t) -1);
72 [ + + ]: 14574 : if (c->msg_len_vlen) {
73 : 3750 : tprintf(", msg_len=%u", mmsg->msg_len);
74 : 3750 : --c->msg_len_vlen;
75 : : }
76 : 14574 : tprints("}");
77 : :
78 [ + + ]: 14574 : if (c->p_user_msg_namelen)
79 : 1878 : ++c->p_user_msg_namelen;
80 : :
81 : 14574 : return true;
82 : : }
83 : :
84 : : static void
85 : 30 : free_mmsgvec_data(void *ptr)
86 : : {
87 : 30 : char **pstr = ptr;
88 : 30 : free(*pstr);
89 : 30 : *pstr = 0;
90 : :
91 : 30 : free(ptr);
92 : 30 : }
93 : :
94 : : struct mmsgvec_data {
95 : : char *timeout;
96 : : unsigned int count;
97 : : int namelen[IOV_MAX];
98 : : };
99 : :
100 : : static void
101 : 30 : save_mmsgvec_namelen(struct tcb *const tcp, kernel_ulong_t addr,
102 : : unsigned int len, const char *const timeout)
103 : : {
104 [ + + ]: 30 : if (len > IOV_MAX)
105 : 12 : len = IOV_MAX;
106 : :
107 : 30 : const size_t data_size = offsetof(struct mmsgvec_data, namelen)
108 : 30 : + sizeof(int) * len;
109 : 30 : struct mmsgvec_data *const data = xmalloc(data_size);
110 : 30 : data->timeout = xstrdup(timeout);
111 : :
112 : : unsigned int i, fetched;
113 : :
114 [ + + ]: 12342 : for (i = 0; i < len; ++i, addr += fetched) {
115 : : struct mmsghdr mh;
116 : :
117 : 12312 : fetched = fetch_struct_mmsghdr(tcp, addr, &mh);
118 [ - + ]: 12312 : if (!fetched)
119 : 0 : break;
120 : 12312 : data->namelen[i] = mh.msg_hdr.msg_namelen;
121 : : }
122 : 30 : data->count = i;
123 : :
124 : 30 : set_tcb_priv_data(tcp, data, free_mmsgvec_data);
125 : 30 : }
126 : :
127 : : static void
128 : 72 : decode_mmsgvec(struct tcb *const tcp, const kernel_ulong_t addr,
129 : : const unsigned int vlen, const unsigned int msg_len_vlen,
130 : : const bool use_msg_len)
131 : : {
132 : : struct mmsghdr mmsg;
133 : 72 : struct print_struct_mmsghdr_config c = {
134 : : .msg_len_vlen = msg_len_vlen,
135 : : .count = IOV_MAX,
136 : : .use_msg_len = use_msg_len
137 : : };
138 : 72 : const struct mmsgvec_data *const data = get_tcb_priv_data(tcp);
139 : :
140 [ + + ]: 72 : if (data) {
141 [ + + ]: 30 : if (data->count < c.count)
142 : 18 : c.count = data->count;
143 : 30 : c.p_user_msg_namelen = data->namelen;
144 : : }
145 : :
146 : 72 : print_array(tcp, addr, vlen, &mmsg, sizeof_struct_mmsghdr(),
147 : : fetch_struct_mmsghdr_or_printaddr,
148 : : print_struct_mmsghdr, &c);
149 : 72 : }
150 : :
151 : : void
152 : 12 : dumpiov_in_mmsghdr(struct tcb *const tcp, kernel_ulong_t addr)
153 : : {
154 : 12 : unsigned int len = tcp->u_rval;
155 : : unsigned int i, fetched;
156 : : struct mmsghdr mmsg;
157 : :
158 [ + + ]: 36 : for (i = 0; i < len; ++i, addr += fetched) {
159 : 24 : fetched = fetch_struct_mmsghdr(tcp, addr, &mmsg);
160 [ - + ]: 24 : if (!fetched)
161 : 0 : break;
162 : 24 : tprintf(" = %" PRI_klu " buffers in vector %u\n",
163 : 24 : (kernel_ulong_t) mmsg.msg_hdr.msg_iovlen, i);
164 : 24 : dumpiov_upto(tcp, mmsg.msg_hdr.msg_iovlen,
165 : 24 : ptr_to_kulong(mmsg.msg_hdr.msg_iov),
166 : 24 : mmsg.msg_len);
167 : : }
168 : 12 : }
169 : :
170 : 90 : SYS_FUNC(sendmmsg)
171 : : {
172 [ + + ]: 90 : if (entering(tcp)) {
173 : : /* sockfd */
174 : 48 : printfd(tcp, tcp->u_arg[0]);
175 : 48 : tprints(", ");
176 [ + + ]: 48 : if (!verbose(tcp)) {
177 : : /* msgvec */
178 : 6 : printaddr(tcp->u_arg[1]);
179 : : /* vlen */
180 : 6 : tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
181 : : /* flags */
182 : 6 : printflags(msg_flags, tcp->u_arg[3], "MSG_???");
183 : 6 : return RVAL_DECODED;
184 : : }
185 : : } else {
186 [ + + ]: 42 : const unsigned int msg_len_vlen =
187 : 60 : syserror(tcp) ? 0 : tcp->u_rval;
188 : : /* msgvec */
189 : 42 : temporarily_clear_syserror(tcp);
190 : 42 : decode_mmsgvec(tcp, tcp->u_arg[1], tcp->u_arg[2],
191 : : msg_len_vlen, false);
192 : 42 : restore_cleared_syserror(tcp);
193 : : /* vlen */
194 : 42 : tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
195 : : /* flags */
196 : 42 : printflags(msg_flags, tcp->u_arg[3], "MSG_???");
197 : : }
198 : 84 : return 0;
199 : : }
200 : :
201 : 72 : SYS_FUNC(recvmmsg)
202 : : {
203 [ + + ]: 72 : if (entering(tcp)) {
204 : 36 : printfd(tcp, tcp->u_arg[0]);
205 : 36 : tprints(", ");
206 [ + + ]: 36 : if (verbose(tcp)) {
207 : 30 : save_mmsgvec_namelen(tcp, tcp->u_arg[1], tcp->u_arg[2],
208 : 30 : sprint_timespec(tcp, tcp->u_arg[4]));
209 : : } else {
210 : : /* msgvec */
211 : 6 : printaddr(tcp->u_arg[1]);
212 : : /* vlen */
213 : 6 : tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
214 : : /* flags */
215 : 6 : printflags(msg_flags, tcp->u_arg[3], "MSG_???");
216 : 6 : tprints(", ");
217 : 6 : print_timespec(tcp, tcp->u_arg[4]);
218 : : }
219 : 36 : return 0;
220 : : } else {
221 [ + + ]: 36 : if (verbose(tcp)) {
222 : : /* msgvec */
223 : 30 : decode_mmsgvec(tcp, tcp->u_arg[1], tcp->u_rval,
224 : 30 : tcp->u_rval, true);
225 : : /* vlen */
226 : 30 : tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
227 : : /* flags */
228 : 30 : printflags(msg_flags, tcp->u_arg[3], "MSG_???");
229 : 30 : tprints(", ");
230 : : /* timeout on entrance */
231 : 30 : tprints(*(const char **) get_tcb_priv_data(tcp));
232 : : }
233 [ + + ]: 36 : if (syserror(tcp))
234 : 6 : return 0;
235 [ - + ]: 30 : if (tcp->u_rval == 0) {
236 : 0 : tcp->auxstr = "Timeout";
237 : 0 : return RVAL_STR;
238 : : }
239 [ + + ][ + + ]: 30 : if (!verbose(tcp) || !tcp->u_arg[4])
240 : 24 : return 0;
241 : : /* timeout on exit */
242 : : static char str[sizeof("left") + TIMESPEC_TEXT_BUFSIZE];
243 : 6 : snprintf(str, sizeof(str), "left %s",
244 : 6 : sprint_timespec(tcp, tcp->u_arg[4]));
245 : 6 : tcp->auxstr = str;
246 : 6 : return RVAL_STR;
247 : : }
248 : : }
|