Home | History | Annotate | Download | only in tests-mx32
      1 /*
      2  * Check decoding of netlink attribute.
      3  *
      4  * Copyright (c) 2017 JingPiao Chen <chenjingpiao (at) gmail.com>
      5  * Copyright (c) 2017 The strace developers.
      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 "tests.h"
     32 
     33 #include <stdio.h>
     34 #include <stdint.h>
     35 #include <string.h>
     36 #include <unistd.h>
     37 #include <sys/socket.h>
     38 #include <netinet/tcp.h>
     39 #include "netlink.h"
     40 #include <linux/rtnetlink.h>
     41 #include <linux/sock_diag.h>
     42 #include <linux/unix_diag.h>
     43 
     44 static void
     45 test_nlattr(const int fd)
     46 {
     47 	static const struct msg {
     48 		struct nlmsghdr nlh;
     49 		struct unix_diag_msg udm;
     50 	} c_msg = {
     51 		.nlh = {
     52 			.nlmsg_len = sizeof(struct msg),
     53 			.nlmsg_type = SOCK_DIAG_BY_FAMILY,
     54 			.nlmsg_flags = NLM_F_DUMP
     55 		},
     56 		.udm = {
     57 			.udiag_family = AF_UNIX,
     58 			.udiag_type = SOCK_STREAM,
     59 			.udiag_state = TCP_FIN_WAIT1
     60 		}
     61 	};
     62 	struct msg *msg;
     63 	struct nlattr *nla;
     64 	unsigned int msg_len;
     65 	long rc;
     66 
     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));
     72 	memcpy(nla, "12", 2);
     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]}, \"12\"}, %u"
     78 	       ", MSG_DONTWAIT, NULL, 0) = %s\n",
     79 	       fd, msg_len, msg_len, sprintrc(rc));
     80 
     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));
     93 
     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
    102 	};
    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));
    110 
    111 	/* print one struct nlattr with nla_len out of msg_len bounds */
    112 	nla->nla_len += 8;
    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));
    120 
    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
    129 	};
    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_??? */}, \"1234\"}}"
    137 	       ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
    138 	       fd, msg_len, nla->nla_len, UNIX_DIAG_SHUTDOWN + 1,
    139 	       msg_len, sprintrc(rc));
    140 
    141 	/* print one struct nlattr and fetch fail second struct nlattr */
    142 	msg_len = NLMSG_SPACE(sizeof(msg->udm)) + NLA_HDRLEN + 2;
    143 	msg = tail_memdup(&c_msg, msg_len);
    144 	memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
    145 	nla = NLMSG_ATTR(msg, sizeof(msg->udm));
    146 	*nla = (struct nlattr) {
    147 		.nla_len = NLA_HDRLEN,
    148 		.nla_type = UNIX_DIAG_NAME
    149 	};
    150 	memcpy(nla + 1, "12", 2);
    151 	rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
    152 	printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
    153 	       ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
    154 	       ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
    155 	       ", udiag_ino=0, udiag_cookie=[0, 0]}, [{nla_len=%u"
    156 	       ", nla_type=UNIX_DIAG_NAME}, \"12\"]}, %u"
    157 	       ", MSG_DONTWAIT, NULL, 0) = %s\n",
    158 	       fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
    159 
    160 	/* print one struct nlattr and short read of second struct nlattr */
    161 	msg_len = NLMSG_SPACE(sizeof(msg->udm)) + NLA_HDRLEN * 2;
    162 	msg = tail_memdup(&c_msg, msg_len - 1);
    163 	memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
    164 	nla = NLMSG_ATTR(msg, sizeof(msg->udm));
    165 	*nla = (struct nlattr) {
    166 		.nla_len = NLA_HDRLEN,
    167 		.nla_type = UNIX_DIAG_NAME
    168 	};
    169 	rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
    170 	printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
    171 	       ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
    172 	       ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
    173 	       ", udiag_ino=0, udiag_cookie=[0, 0]}, [{nla_len=%u"
    174 	       ", nla_type=UNIX_DIAG_NAME}, %p]}, %u"
    175 	       ", MSG_DONTWAIT, NULL, 0) = %s\n",
    176 	       fd, msg_len, nla->nla_len, nla + 1, msg_len, sprintrc(rc));
    177 
    178 	/* print two struct nlattr */
    179 	msg_len = NLMSG_SPACE(sizeof(msg->udm)) + NLA_HDRLEN * 2;
    180 	msg = tail_memdup(&c_msg, msg_len);
    181 	memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
    182 	nla = NLMSG_ATTR(msg, sizeof(msg->udm));
    183 	*nla = (struct nlattr) {
    184 		.nla_len = NLA_HDRLEN,
    185 		.nla_type = UNIX_DIAG_NAME
    186 	};
    187 	*(nla + 1) = (struct nlattr) {
    188 		.nla_len = NLA_HDRLEN,
    189 		.nla_type = UNIX_DIAG_PEER
    190 	};
    191 	rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
    192 	printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
    193 	       ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
    194 	       ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
    195 	       ", udiag_ino=0, udiag_cookie=[0, 0]}, [{nla_len=%u"
    196 	       ", nla_type=UNIX_DIAG_NAME}, {nla_len=%u"
    197 	       ", nla_type=UNIX_DIAG_PEER}]}, %u"
    198 	       ", MSG_DONTWAIT, NULL, 0) = %s\n",
    199 	       fd, msg_len, nla->nla_len, nla->nla_len,
    200 	       msg_len, sprintrc(rc));
    201 
    202 	/* print first nlattr only when its nla_len is less than NLA_HDRLEN */
    203 	nla->nla_len = NLA_HDRLEN - 1;
    204 	rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
    205 	printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
    206 	       ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
    207 	       ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
    208 	       ", udiag_ino=0, udiag_cookie=[0, 0]}, {nla_len=%u"
    209 	       ", nla_type=UNIX_DIAG_NAME}}, %u, MSG_DONTWAIT, NULL, 0) = %s\n",
    210 	       fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
    211 
    212 	/* abbreviated output */
    213 #define ABBREV_LEN (DEFAULT_STRLEN + 1)
    214 	msg_len = NLA_HDRLEN * ABBREV_LEN + NLMSG_SPACE(sizeof(msg->udm));
    215 	msg = tail_memdup(&c_msg, msg_len);
    216 	memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
    217 	unsigned int i;
    218 	nla = NLMSG_ATTR(msg, sizeof(msg->udm));
    219 	for (i = 0; i < ABBREV_LEN; ++i)
    220 		nla[i] = (struct nlattr) {
    221 			.nla_len = NLA_HDRLEN,
    222 			.nla_type = UNIX_DIAG_SHUTDOWN + 1 + i
    223 		};
    224 
    225 	rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
    226 	printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
    227 	       ", flags=NLM_F_DUMP, seq=0, pid=0}"
    228 	       ", {udiag_family=AF_UNIX, udiag_type=SOCK_STREAM"
    229 	       ", udiag_state=TCP_FIN_WAIT1, udiag_ino=0"
    230 	       ", udiag_cookie=[0, 0]}, [",
    231 	       fd, msg_len);
    232 	for (i = 0; i < DEFAULT_STRLEN; ++i) {
    233 		if (i)
    234 			printf(", ");
    235 		printf("{nla_len=%u, nla_type=%#x /* UNIX_DIAG_??? */}",
    236 		       nla->nla_len, UNIX_DIAG_SHUTDOWN + 1 + i);
    237 	}
    238 	printf(", ...]}, %u, MSG_DONTWAIT, NULL, 0) = %s\n",
    239 	       msg_len, sprintrc(rc));
    240 }
    241 
    242 static void
    243 test_nla_type(const int fd)
    244 {
    245 	static const struct msg {
    246 		struct nlmsghdr nlh;
    247 		struct unix_diag_msg udm;
    248 	} c_msg = {
    249 		.nlh = {
    250 			.nlmsg_len = sizeof(struct msg),
    251 			.nlmsg_type = SOCK_DIAG_BY_FAMILY,
    252 			.nlmsg_flags = NLM_F_DUMP
    253 		},
    254 		.udm = {
    255 			.udiag_family = AF_UNIX,
    256 			.udiag_type = SOCK_STREAM,
    257 			.udiag_state = TCP_FIN_WAIT1
    258 		}
    259 	};
    260 	struct msg *msg;
    261 	struct nlattr *nla;
    262 	unsigned int msg_len;
    263 	long rc;
    264 
    265 	msg_len = NLMSG_SPACE(sizeof(msg->udm)) + sizeof(*nla);
    266 	msg = tail_memdup(&c_msg, msg_len);
    267 	memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
    268 	nla = NLMSG_ATTR(msg, sizeof(msg->udm));
    269 	*nla = (struct nlattr) {
    270 		.nla_len = sizeof(*nla),
    271 		.nla_type = NLA_F_NESTED | UNIX_DIAG_NAME
    272 	};
    273 	rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
    274 	printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
    275 	       ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
    276 	       ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
    277 	       ", udiag_ino=0, udiag_cookie=[0, 0]}, {nla_len=%u"
    278 	       ", nla_type=NLA_F_NESTED|UNIX_DIAG_NAME}}"
    279 	       ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
    280 	       fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
    281 
    282 	nla->nla_type = NLA_F_NET_BYTEORDER | UNIX_DIAG_NAME;
    283 	rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
    284 	printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
    285 	       ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
    286 	       ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
    287 	       ", udiag_ino=0, udiag_cookie=[0, 0]}, {nla_len=%u"
    288 	       ", nla_type=NLA_F_NET_BYTEORDER|UNIX_DIAG_NAME}}"
    289 	       ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
    290 	       fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
    291 
    292 	nla->nla_type = NLA_F_NESTED | NLA_F_NET_BYTEORDER | UNIX_DIAG_NAME;
    293 	rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
    294 	printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
    295 	       ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
    296 	       ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
    297 	       ", udiag_ino=0, udiag_cookie=[0, 0]}, {nla_len=%u"
    298 	       ", nla_type=NLA_F_NESTED|NLA_F_NET_BYTEORDER|UNIX_DIAG_NAME}}"
    299 	       ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
    300 	       fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
    301 
    302 	nla->nla_type = NLA_F_NESTED | (UNIX_DIAG_SHUTDOWN + 1);
    303 	rc = sendto(fd, msg, msg->nlh.nlmsg_len, MSG_DONTWAIT, NULL, 0);
    304 	printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
    305 	       ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
    306 	       ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
    307 	       ", udiag_ino=0, udiag_cookie=[0, 0]}, {nla_len=%u"
    308 	       ", nla_type=NLA_F_NESTED|%#x /* UNIX_DIAG_??? */}}"
    309 	       ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
    310 	       fd, msg->nlh.nlmsg_len, nla->nla_len, UNIX_DIAG_SHUTDOWN + 1,
    311 	       msg->nlh.nlmsg_len, sprintrc(rc));
    312 }
    313 
    314 int main(void)
    315 {
    316 	skip_if_unavailable("/proc/self/fd/");
    317 
    318 	const int fd = create_nl_socket(NETLINK_SOCK_DIAG);
    319 
    320 	test_nlattr(fd);
    321 	test_nla_type(fd);
    322 
    323 	puts("+++ exited with 0 +++");
    324 
    325 	return 0;
    326 }
    327