2 * Check decoding of netlink attribute.
4 * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
5 * Copyright (c) 2017 The strace developers.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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.
37 #include <sys/socket.h>
38 #include <netinet/tcp.h>
40 #include <linux/rtnetlink.h>
41 #include <linux/sock_diag.h>
42 #include <linux/unix_diag.h>
45 test_nlattr(const int fd)
47 static const struct msg {
49 struct unix_diag_msg udm;
52 .nlmsg_len = sizeof(struct msg),
53 .nlmsg_type = SOCK_DIAG_BY_FAMILY,
54 .nlmsg_flags = NLM_F_DUMP
57 .udiag_family = AF_UNIX,
58 .udiag_type = SOCK_STREAM,
59 .udiag_state = TCP_FIN_WAIT1
67 /* fetch fail: len < sizeof(struct nlattr) */
68 msg_len = NLMSG_SPACE(sizeof(msg->udm)) + 2;
69 msg = tail_memdup(&c_msg, msg_len);
70 memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
71 nla = NLMSG_ATTR(msg, sizeof(msg->udm));
73 rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
74 printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
75 ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
76 ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
77 ", udiag_ino=0, udiag_cookie=[0, 0]}, \"\\x31\\x32\"}, %u"
78 ", MSG_DONTWAIT, NULL, 0) = %s\n",
79 fd, msg_len, msg_len, sprintrc(rc));
81 /* fetch fail: short read */
82 msg_len = NLMSG_SPACE(sizeof(msg->udm)) + sizeof(*nla);
83 msg = tail_memdup(&c_msg, msg_len - 1);
84 memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
85 rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
86 printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
87 ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
88 ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
89 ", udiag_ino=0, udiag_cookie=[0, 0]}, %p}, %u"
90 ", MSG_DONTWAIT, NULL, 0) = %s\n",
91 fd, msg_len, (void *) msg + NLMSG_SPACE(sizeof(msg->udm)),
92 msg_len, sprintrc(rc));
94 /* print one struct nlattr */
95 msg_len = NLMSG_SPACE(sizeof(msg->udm)) + sizeof(*nla);
96 msg = tail_memdup(&c_msg, msg_len);
97 memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
98 nla = NLMSG_ATTR(msg, sizeof(msg->udm));
99 *nla = (struct nlattr) {
100 .nla_len = sizeof(*nla),
101 .nla_type = UNIX_DIAG_NAME
103 rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
104 printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
105 ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
106 ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
107 ", udiag_ino=0, udiag_cookie=[0, 0]}, {nla_len=%u"
108 ", nla_type=UNIX_DIAG_NAME}}, %u, MSG_DONTWAIT, NULL, 0) = %s\n",
109 fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
111 /* print one struct nlattr with nla_len out of msg_len bounds */
113 rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
114 printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
115 ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
116 ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
117 ", udiag_ino=0, udiag_cookie=[0, 0]}, {nla_len=%u"
118 ", nla_type=UNIX_DIAG_NAME}}, %u, MSG_DONTWAIT, NULL, 0) = %s\n",
119 fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
121 /* print one struct nlattr and some data */
122 msg_len = NLMSG_SPACE(sizeof(msg->udm)) + NLA_HDRLEN + 4;
123 msg = tail_memdup(&c_msg, msg_len);
124 memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
125 nla = NLMSG_ATTR(msg, sizeof(msg->udm));
126 *nla = (struct nlattr) {
127 .nla_len = NLA_HDRLEN + 4,
128 .nla_type = UNIX_DIAG_SHUTDOWN + 1
130 memcpy(RTA_DATA(nla), "1234", 4);
131 rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
132 printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
133 ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
134 ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
135 ", udiag_ino=0, udiag_cookie=[0, 0]}, {{nla_len=%u"
136 ", nla_type=%#x /* UNIX_DIAG_??? */}"
137 ", \"\\x31\\x32\\x33\\x34\"}}"
138 ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
139 fd, msg_len, nla->nla_len, UNIX_DIAG_SHUTDOWN + 1,
140 msg_len, sprintrc(rc));
142 /* print one struct nlattr and fetch fail second struct nlattr */
143 msg_len = NLMSG_SPACE(sizeof(msg->udm)) + NLA_HDRLEN + 2;
144 msg = tail_memdup(&c_msg, msg_len);
145 memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
146 nla = NLMSG_ATTR(msg, sizeof(msg->udm));
147 *nla = (struct nlattr) {
148 .nla_len = NLA_HDRLEN,
149 .nla_type = UNIX_DIAG_NAME
151 memcpy(nla + 1, "12", 2);
152 rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
153 printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
154 ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
155 ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
156 ", udiag_ino=0, udiag_cookie=[0, 0]}, [{nla_len=%u"
157 ", nla_type=UNIX_DIAG_NAME}, \"\\x31\\x32\"]}, %u"
158 ", MSG_DONTWAIT, NULL, 0) = %s\n",
159 fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
161 /* print one struct nlattr and short read of second struct nlattr */
162 msg_len = NLMSG_SPACE(sizeof(msg->udm)) + NLA_HDRLEN * 2;
163 msg = tail_memdup(&c_msg, msg_len - 1);
164 memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
165 nla = NLMSG_ATTR(msg, sizeof(msg->udm));
166 *nla = (struct nlattr) {
167 .nla_len = NLA_HDRLEN,
168 .nla_type = UNIX_DIAG_NAME
170 rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
171 printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
172 ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
173 ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
174 ", udiag_ino=0, udiag_cookie=[0, 0]}, [{nla_len=%u"
175 ", nla_type=UNIX_DIAG_NAME}, %p]}, %u"
176 ", MSG_DONTWAIT, NULL, 0) = %s\n",
177 fd, msg_len, nla->nla_len, nla + 1, msg_len, sprintrc(rc));
179 /* print two struct nlattr */
180 msg_len = NLMSG_SPACE(sizeof(msg->udm)) + NLA_HDRLEN * 2;
181 msg = tail_memdup(&c_msg, msg_len);
182 memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
183 nla = NLMSG_ATTR(msg, sizeof(msg->udm));
184 *nla = (struct nlattr) {
185 .nla_len = NLA_HDRLEN,
186 .nla_type = UNIX_DIAG_NAME
188 *(nla + 1) = (struct nlattr) {
189 .nla_len = NLA_HDRLEN,
190 .nla_type = UNIX_DIAG_PEER
192 rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
193 printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
194 ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
195 ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
196 ", udiag_ino=0, udiag_cookie=[0, 0]}, [{nla_len=%u"
197 ", nla_type=UNIX_DIAG_NAME}, {nla_len=%u"
198 ", nla_type=UNIX_DIAG_PEER}]}, %u"
199 ", MSG_DONTWAIT, NULL, 0) = %s\n",
200 fd, msg_len, nla->nla_len, nla->nla_len,
201 msg_len, sprintrc(rc));
203 /* print first nlattr only when its nla_len is less than NLA_HDRLEN */
204 nla->nla_len = NLA_HDRLEN - 1;
205 rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
206 printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
207 ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
208 ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
209 ", udiag_ino=0, udiag_cookie=[0, 0]}, {nla_len=%u"
210 ", nla_type=UNIX_DIAG_NAME}}, %u, MSG_DONTWAIT, NULL, 0) = %s\n",
211 fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
213 /* abbreviated output */
214 #define ABBREV_LEN (DEFAULT_STRLEN + 1)
215 msg_len = NLA_HDRLEN * ABBREV_LEN + NLMSG_SPACE(sizeof(msg->udm));
216 msg = tail_memdup(&c_msg, msg_len);
217 memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
219 nla = NLMSG_ATTR(msg, sizeof(msg->udm));
220 for (i = 0; i < ABBREV_LEN; ++i)
221 nla[i] = (struct nlattr) {
222 .nla_len = NLA_HDRLEN,
223 .nla_type = UNIX_DIAG_SHUTDOWN + 1 + i
226 rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
227 printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
228 ", flags=NLM_F_DUMP, seq=0, pid=0}"
229 ", {udiag_family=AF_UNIX, udiag_type=SOCK_STREAM"
230 ", udiag_state=TCP_FIN_WAIT1, udiag_ino=0"
231 ", udiag_cookie=[0, 0]}, [",
233 for (i = 0; i < DEFAULT_STRLEN; ++i) {
236 printf("{nla_len=%u, nla_type=%#x /* UNIX_DIAG_??? */}",
237 nla->nla_len, UNIX_DIAG_SHUTDOWN + 1 + i);
239 printf(", ...]}, %u, MSG_DONTWAIT, NULL, 0) = %s\n",
240 msg_len, sprintrc(rc));
244 test_nla_type(const int fd)
246 static const struct msg {
248 struct unix_diag_msg udm;
251 .nlmsg_len = sizeof(struct msg),
252 .nlmsg_type = SOCK_DIAG_BY_FAMILY,
253 .nlmsg_flags = NLM_F_DUMP
256 .udiag_family = AF_UNIX,
257 .udiag_type = SOCK_STREAM,
258 .udiag_state = TCP_FIN_WAIT1
263 unsigned int msg_len;
266 msg_len = NLMSG_SPACE(sizeof(msg->udm)) + sizeof(*nla);
267 msg = tail_memdup(&c_msg, msg_len);
268 memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
269 nla = NLMSG_ATTR(msg, sizeof(msg->udm));
270 *nla = (struct nlattr) {
271 .nla_len = sizeof(*nla),
272 .nla_type = NLA_F_NESTED | UNIX_DIAG_NAME
274 rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
275 printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
276 ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
277 ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
278 ", udiag_ino=0, udiag_cookie=[0, 0]}, {nla_len=%u"
279 ", nla_type=NLA_F_NESTED|UNIX_DIAG_NAME}}"
280 ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
281 fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
283 nla->nla_type = NLA_F_NET_BYTEORDER | UNIX_DIAG_NAME;
284 rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
285 printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
286 ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
287 ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
288 ", udiag_ino=0, udiag_cookie=[0, 0]}, {nla_len=%u"
289 ", nla_type=NLA_F_NET_BYTEORDER|UNIX_DIAG_NAME}}"
290 ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
291 fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
293 nla->nla_type = NLA_F_NESTED | NLA_F_NET_BYTEORDER | UNIX_DIAG_NAME;
294 rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
295 printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
296 ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
297 ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
298 ", udiag_ino=0, udiag_cookie=[0, 0]}, {nla_len=%u"
299 ", nla_type=NLA_F_NESTED|NLA_F_NET_BYTEORDER|UNIX_DIAG_NAME}}"
300 ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
301 fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
303 nla->nla_type = NLA_F_NESTED | (UNIX_DIAG_SHUTDOWN + 1);
304 rc = sendto(fd, msg, msg->nlh.nlmsg_len, MSG_DONTWAIT, NULL, 0);
305 printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
306 ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
307 ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
308 ", udiag_ino=0, udiag_cookie=[0, 0]}, {nla_len=%u"
309 ", nla_type=NLA_F_NESTED|%#x /* UNIX_DIAG_??? */}}"
310 ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
311 fd, msg->nlh.nlmsg_len, nla->nla_len, UNIX_DIAG_SHUTDOWN + 1,
312 msg->nlh.nlmsg_len, sprintrc(rc));
317 skip_if_unavailable("/proc/self/fd/");
319 const int fd = create_nl_socket(NETLINK_SOCK_DIAG);
324 puts("+++ exited with 0 +++");