(root)/
strace-6.5/
tests-m32/
nlattr.c
       1  /*
       2   * Check decoding of netlink attribute.
       3   *
       4   * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
       5   * Copyright (c) 2017-2021 The strace developers.
       6   * All rights reserved.
       7   *
       8   * SPDX-License-Identifier: GPL-2.0-or-later
       9   */
      10  
      11  #include "tests.h"
      12  
      13  #include <stdio.h>
      14  #include <stdint.h>
      15  #include <string.h>
      16  #include <unistd.h>
      17  #include <sys/socket.h>
      18  #include <netinet/tcp.h>
      19  #include "netlink.h"
      20  #include <linux/rtnetlink.h>
      21  #include <linux/sock_diag.h>
      22  #include <linux/unix_diag.h>
      23  
      24  enum { UNIX_DIAG_FIRST_UNUSED = __UNIX_DIAG_MAX };
      25  
      26  static void
      27  test_nlattr(const int fd)
      28  {
      29  	static const struct msg {
      30  		struct nlmsghdr nlh;
      31  		struct unix_diag_msg udm;
      32  	} c_msg = {
      33  		.nlh = {
      34  			.nlmsg_len = sizeof(struct msg),
      35  			.nlmsg_type = SOCK_DIAG_BY_FAMILY,
      36  			.nlmsg_flags = NLM_F_DUMP
      37  		},
      38  		.udm = {
      39  			.udiag_family = AF_UNIX,
      40  			.udiag_type = SOCK_STREAM,
      41  			.udiag_state = TCP_FIN_WAIT1
      42  		}
      43  	};
      44  	struct msg *msg;
      45  	struct nlattr *nla;
      46  	unsigned int msg_len;
      47  	long rc;
      48  
      49  	/* fetch fail: len < sizeof(struct nlattr) */
      50  	msg_len = NLMSG_SPACE(sizeof(msg->udm)) + 2;
      51  	msg = tail_memdup(&c_msg, msg_len);
      52  	memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
      53  	nla = NLMSG_ATTR(msg, sizeof(msg->udm));
      54  	memcpy(nla, "12", 2);
      55  	rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
      56  	printf("sendto(%d, [{nlmsg_len=%u, nlmsg_type=SOCK_DIAG_BY_FAMILY"
      57  	       ", nlmsg_flags=NLM_F_DUMP, nlmsg_seq=0, nlmsg_pid=0}"
      58  	       ", {udiag_family=AF_UNIX, udiag_type=SOCK_STREAM"
      59  	       ", udiag_state=TCP_FIN_WAIT1, udiag_ino=0, udiag_cookie=[0, 0]}"
      60  	       ", \"\\x31\\x32\"], %u, MSG_DONTWAIT, NULL, 0) = %s\n",
      61  	       fd, msg_len, msg_len, sprintrc(rc));
      62  
      63  	/* fetch fail: short read */
      64  	msg_len = NLMSG_SPACE(sizeof(msg->udm)) + sizeof(*nla);
      65  	msg = tail_memdup(&c_msg, msg_len - 1);
      66  	memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
      67  	rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
      68  	printf("sendto(%d, [{nlmsg_len=%u, nlmsg_type=SOCK_DIAG_BY_FAMILY"
      69  	       ", nlmsg_flags=NLM_F_DUMP, nlmsg_seq=0, nlmsg_pid=0}"
      70  	       ", {udiag_family=AF_UNIX, udiag_type=SOCK_STREAM"
      71  	       ", udiag_state=TCP_FIN_WAIT1, udiag_ino=0"
      72  	       ", udiag_cookie=[0, 0]}, %p], %u, MSG_DONTWAIT, NULL, 0) = %s\n",
      73  	       fd, msg_len, (void *) msg + NLMSG_SPACE(sizeof(msg->udm)),
      74  	       msg_len, sprintrc(rc));
      75  
      76  	/* print one struct nlattr */
      77  	msg_len = NLMSG_SPACE(sizeof(msg->udm)) + sizeof(*nla);
      78  	msg = tail_memdup(&c_msg, msg_len);
      79  	memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
      80  	nla = NLMSG_ATTR(msg, sizeof(msg->udm));
      81  	*nla = (struct nlattr) {
      82  		.nla_len = sizeof(*nla),
      83  		.nla_type = UNIX_DIAG_NAME
      84  	};
      85  	rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
      86  	printf("sendto(%d, [{nlmsg_len=%u, nlmsg_type=SOCK_DIAG_BY_FAMILY"
      87  	       ", nlmsg_flags=NLM_F_DUMP, nlmsg_seq=0, nlmsg_pid=0}"
      88  	       ", {udiag_family=AF_UNIX, udiag_type=SOCK_STREAM"
      89  	       ", udiag_state=TCP_FIN_WAIT1, udiag_ino=0, udiag_cookie=[0, 0]}"
      90  	       ", {nla_len=%u, nla_type=UNIX_DIAG_NAME}]"
      91  	       ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
      92  	       fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
      93  
      94  	/* print one struct nlattr with nla_len out of msg_len bounds */
      95  	nla->nla_len += 8;
      96  	rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
      97  	printf("sendto(%d, [{nlmsg_len=%u, nlmsg_type=SOCK_DIAG_BY_FAMILY"
      98  	       ", nlmsg_flags=NLM_F_DUMP, nlmsg_seq=0, nlmsg_pid=0}"
      99  	       ", {udiag_family=AF_UNIX, udiag_type=SOCK_STREAM"
     100  	       ", udiag_state=TCP_FIN_WAIT1, udiag_ino=0, udiag_cookie=[0, 0]}"
     101  	       ", {nla_len=%u, nla_type=UNIX_DIAG_NAME}]"
     102  	       ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
     103  	       fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
     104  
     105  	/* print one struct nlattr and some data */
     106  	msg_len = NLMSG_SPACE(sizeof(msg->udm)) + NLA_HDRLEN + 4;
     107  	msg = tail_memdup(&c_msg, msg_len);
     108  	memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
     109  	nla = NLMSG_ATTR(msg, sizeof(msg->udm));
     110  	*nla = (struct nlattr) {
     111  		.nla_len = NLA_HDRLEN + 4,
     112  		.nla_type = UNIX_DIAG_FIRST_UNUSED
     113  	};
     114  	memcpy(RTA_DATA(nla), "1234", 4);
     115  	rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
     116  	printf("sendto(%d, [{nlmsg_len=%u, nlmsg_type=SOCK_DIAG_BY_FAMILY"
     117  	       ", nlmsg_flags=NLM_F_DUMP, nlmsg_seq=0, nlmsg_pid=0}"
     118  	       ", {udiag_family=AF_UNIX, udiag_type=SOCK_STREAM"
     119  	       ", udiag_state=TCP_FIN_WAIT1, udiag_ino=0, udiag_cookie=[0, 0]}"
     120  	       ", [{nla_len=%u, nla_type=%#x /* UNIX_DIAG_??? */}"
     121  	       ", \"\\x31\\x32\\x33\\x34\"]]"
     122  	       ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
     123  	       fd, msg_len, nla->nla_len, UNIX_DIAG_FIRST_UNUSED,
     124  	       msg_len, sprintrc(rc));
     125  
     126  	/* print one struct nlattr and fetch fail second struct nlattr */
     127  	msg_len = NLMSG_SPACE(sizeof(msg->udm)) + NLA_HDRLEN + 2;
     128  	msg = tail_memdup(&c_msg, msg_len);
     129  	memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
     130  	nla = NLMSG_ATTR(msg, sizeof(msg->udm));
     131  	SET_STRUCT(struct nlattr, nla,
     132  		.nla_len = NLA_HDRLEN,
     133  		.nla_type = UNIX_DIAG_NAME
     134  	);
     135  	memcpy(nla + 1, "12", 2);
     136  	rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
     137  	printf("sendto(%d, [{nlmsg_len=%u, nlmsg_type=SOCK_DIAG_BY_FAMILY"
     138  	       ", nlmsg_flags=NLM_F_DUMP, nlmsg_seq=0, nlmsg_pid=0}"
     139  	       ", {udiag_family=AF_UNIX, udiag_type=SOCK_STREAM"
     140  	       ", udiag_state=TCP_FIN_WAIT1, udiag_ino=0, udiag_cookie=[0, 0]}"
     141  	       ", [{nla_len=%u, nla_type=UNIX_DIAG_NAME}, \"\\x31\\x32\"]]"
     142  	       ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
     143  	       fd, msg_len, NLA_HDRLEN, msg_len, sprintrc(rc));
     144  
     145  	/* print one struct nlattr and short read of second struct nlattr */
     146  	msg_len = NLMSG_SPACE(sizeof(msg->udm)) + NLA_HDRLEN * 2;
     147  	msg = tail_memdup(&c_msg, msg_len - 1);
     148  	memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
     149  	nla = NLMSG_ATTR(msg, sizeof(msg->udm));
     150  	SET_STRUCT(struct nlattr, nla,
     151  		.nla_len = NLA_HDRLEN,
     152  		.nla_type = UNIX_DIAG_NAME
     153  	);
     154  	rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
     155  	printf("sendto(%d, [{nlmsg_len=%u, nlmsg_type=SOCK_DIAG_BY_FAMILY"
     156  	       ", nlmsg_flags=NLM_F_DUMP, nlmsg_seq=0, nlmsg_pid=0}"
     157  	       ", {udiag_family=AF_UNIX, udiag_type=SOCK_STREAM"
     158  	       ", udiag_state=TCP_FIN_WAIT1, udiag_ino=0, udiag_cookie=[0, 0]}"
     159  	       ", [{nla_len=%u, nla_type=UNIX_DIAG_NAME}, ... /* %p */]]"
     160  	       ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
     161  	       fd, msg_len, NLA_HDRLEN, nla + 1, msg_len, sprintrc(rc));
     162  
     163  	/* print two struct nlattr */
     164  	msg_len = NLMSG_SPACE(sizeof(msg->udm)) + NLA_HDRLEN * 2;
     165  	msg = tail_memdup(&c_msg, msg_len);
     166  	memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
     167  	nla = NLMSG_ATTR(msg, sizeof(msg->udm));
     168  	*nla = (struct nlattr) {
     169  		.nla_len = NLA_HDRLEN,
     170  		.nla_type = UNIX_DIAG_NAME
     171  	};
     172  	*(nla + 1) = (struct nlattr) {
     173  		.nla_len = NLA_HDRLEN,
     174  		.nla_type = UNIX_DIAG_PEER
     175  	};
     176  	rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
     177  	printf("sendto(%d, [{nlmsg_len=%u, nlmsg_type=SOCK_DIAG_BY_FAMILY"
     178  	       ", nlmsg_flags=NLM_F_DUMP, nlmsg_seq=0, nlmsg_pid=0}"
     179  	       ", {udiag_family=AF_UNIX, udiag_type=SOCK_STREAM"
     180  	       ", udiag_state=TCP_FIN_WAIT1, udiag_ino=0, udiag_cookie=[0, 0]}"
     181  	       ", [{nla_len=%u, nla_type=UNIX_DIAG_NAME}"
     182  	       ", {nla_len=%u, nla_type=UNIX_DIAG_PEER}]]"
     183  	       ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
     184  	       fd, msg_len, nla->nla_len, nla->nla_len,
     185  	       msg_len, sprintrc(rc));
     186  
     187  	/* print first nlattr only when its nla_len is less than NLA_HDRLEN */
     188  	nla->nla_len = NLA_HDRLEN - 1;
     189  	rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
     190  	printf("sendto(%d, [{nlmsg_len=%u, nlmsg_type=SOCK_DIAG_BY_FAMILY"
     191  	       ", nlmsg_flags=NLM_F_DUMP, nlmsg_seq=0, nlmsg_pid=0}"
     192  	       ", {udiag_family=AF_UNIX, udiag_type=SOCK_STREAM"
     193  	       ", udiag_state=TCP_FIN_WAIT1, udiag_ino=0, udiag_cookie=[0, 0]}"
     194  	       ", {nla_len=%u, nla_type=UNIX_DIAG_NAME}]"
     195  	       ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
     196  	       fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
     197  
     198  	/* unrecognized attribute data, abbreviated output */
     199  #define ABBREV_LEN (DEFAULT_STRLEN + 1)
     200  	msg_len = NLMSG_SPACE(sizeof(msg->udm)) + NLA_HDRLEN * ABBREV_LEN * 2;
     201  	msg = tail_alloc(msg_len);
     202  	memcpy(msg, &c_msg, sizeof(c_msg));
     203  	msg->nlh.nlmsg_len = msg_len;
     204  	nla = NLMSG_ATTR(msg, sizeof(msg->udm));
     205  	for (unsigned int i = 0; i < ABBREV_LEN; ++i) {
     206  		nla[i * 2] = (struct nlattr) {
     207  			.nla_len = NLA_HDRLEN * 2 - 1,
     208  			.nla_type = UNIX_DIAG_FIRST_UNUSED + i
     209  		};
     210  		fill_memory_ex(&nla[i * 2 + 1], NLA_HDRLEN,
     211  			       '0' + i, '~' - '0' - i);
     212  	}
     213  
     214  	rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
     215  	printf("sendto(%d, [{nlmsg_len=%u, nlmsg_type=SOCK_DIAG_BY_FAMILY"
     216  	       ", nlmsg_flags=NLM_F_DUMP, nlmsg_seq=0, nlmsg_pid=0}"
     217  	       ", {udiag_family=AF_UNIX, udiag_type=SOCK_STREAM"
     218  	       ", udiag_state=TCP_FIN_WAIT1, udiag_ino=0"
     219  	       ", udiag_cookie=[0, 0]}, [",
     220  	       fd, msg_len);
     221  	for (unsigned int i = 0; i < DEFAULT_STRLEN; ++i) {
     222  		if (i)
     223  			printf(", ");
     224  		printf("[{nla_len=%u, nla_type=%#x /* UNIX_DIAG_??? */}, ",
     225  		       nla->nla_len, UNIX_DIAG_FIRST_UNUSED + i);
     226  		print_quoted_hex(&nla[i * 2 + 1], NLA_HDRLEN - 1);
     227  		printf("]");
     228  	}
     229  	printf(", ...]], %u, MSG_DONTWAIT, NULL, 0) = %s\n",
     230  	       msg_len, sprintrc(rc));
     231  }
     232  
     233  static void
     234  test_nla_type(const int fd)
     235  {
     236  	static const struct msg {
     237  		struct nlmsghdr nlh;
     238  		struct unix_diag_msg udm;
     239  	} c_msg = {
     240  		.nlh = {
     241  			.nlmsg_len = sizeof(struct msg),
     242  			.nlmsg_type = SOCK_DIAG_BY_FAMILY,
     243  			.nlmsg_flags = NLM_F_DUMP
     244  		},
     245  		.udm = {
     246  			.udiag_family = AF_UNIX,
     247  			.udiag_type = SOCK_STREAM,
     248  			.udiag_state = TCP_FIN_WAIT1
     249  		}
     250  	};
     251  	struct msg *msg;
     252  	struct nlattr *nla;
     253  	unsigned int msg_len;
     254  	long rc;
     255  
     256  	msg_len = NLMSG_SPACE(sizeof(msg->udm)) + sizeof(*nla);
     257  	msg = tail_memdup(&c_msg, msg_len);
     258  	memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
     259  	nla = NLMSG_ATTR(msg, sizeof(msg->udm));
     260  	*nla = (struct nlattr) {
     261  		.nla_len = sizeof(*nla),
     262  		.nla_type = NLA_F_NESTED | UNIX_DIAG_NAME
     263  	};
     264  	rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
     265  	printf("sendto(%d, [{nlmsg_len=%u, nlmsg_type=SOCK_DIAG_BY_FAMILY"
     266  	       ", nlmsg_flags=NLM_F_DUMP, nlmsg_seq=0, nlmsg_pid=0}"
     267  	       ", {udiag_family=AF_UNIX, udiag_type=SOCK_STREAM"
     268  	       ", udiag_state=TCP_FIN_WAIT1, udiag_ino=0, udiag_cookie=[0, 0]}"
     269  	       ", {nla_len=%u, nla_type=NLA_F_NESTED|UNIX_DIAG_NAME}]"
     270  	       ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
     271  	       fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
     272  
     273  	nla->nla_type = NLA_F_NET_BYTEORDER | UNIX_DIAG_NAME;
     274  	rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
     275  	printf("sendto(%d, [{nlmsg_len=%u, nlmsg_type=SOCK_DIAG_BY_FAMILY"
     276  	       ", nlmsg_flags=NLM_F_DUMP, nlmsg_seq=0, nlmsg_pid=0}"
     277  	       ", {udiag_family=AF_UNIX, udiag_type=SOCK_STREAM"
     278  	       ", udiag_state=TCP_FIN_WAIT1, udiag_ino=0, udiag_cookie=[0, 0]}"
     279  	       ", {nla_len=%u, nla_type=NLA_F_NET_BYTEORDER|UNIX_DIAG_NAME}]"
     280  	       ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
     281  	       fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
     282  
     283  	nla->nla_type = NLA_F_NESTED | NLA_F_NET_BYTEORDER | UNIX_DIAG_NAME;
     284  	rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
     285  	printf("sendto(%d, [{nlmsg_len=%u, nlmsg_type=SOCK_DIAG_BY_FAMILY"
     286  	       ", nlmsg_flags=NLM_F_DUMP, nlmsg_seq=0, nlmsg_pid=0}"
     287  	       ", {udiag_family=AF_UNIX, udiag_type=SOCK_STREAM"
     288  	       ", udiag_state=TCP_FIN_WAIT1, udiag_ino=0, udiag_cookie=[0, 0]}"
     289  	       ", {nla_len=%u, nla_type=NLA_F_NESTED|NLA_F_NET_BYTEORDER"
     290  	       "|UNIX_DIAG_NAME}]"
     291  	       ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
     292  	       fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
     293  
     294  	nla->nla_type = NLA_F_NESTED | (UNIX_DIAG_FIRST_UNUSED);
     295  	rc = sendto(fd, msg, msg->nlh.nlmsg_len, MSG_DONTWAIT, NULL, 0);
     296  	printf("sendto(%d, [{nlmsg_len=%u, nlmsg_type=SOCK_DIAG_BY_FAMILY"
     297  	       ", nlmsg_flags=NLM_F_DUMP, nlmsg_seq=0, nlmsg_pid=0}"
     298  	       ", {udiag_family=AF_UNIX, udiag_type=SOCK_STREAM"
     299  	       ", udiag_state=TCP_FIN_WAIT1, udiag_ino=0, udiag_cookie=[0, 0]}"
     300  	       ", {nla_len=%u, nla_type=NLA_F_NESTED|%#x /* UNIX_DIAG_??? */}]"
     301  	       ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
     302  	       fd, msg->nlh.nlmsg_len, nla->nla_len, UNIX_DIAG_FIRST_UNUSED,
     303  	       msg->nlh.nlmsg_len, sprintrc(rc));
     304  }
     305  
     306  int main(void)
     307  {
     308  	skip_if_unavailable("/proc/self/fd/");
     309  
     310  	const int fd = create_nl_socket(NETLINK_SOCK_DIAG);
     311  
     312  	test_nlattr(fd);
     313  	test_nla_type(fd);
     314  
     315  	puts("+++ exited with 0 +++");
     316  
     317  	return 0;
     318  }