(root)/
strace-6.5/
tests/
mmsg_name.c
       1  /*
       2   * Check decoding of msg_name* fields of struct msghdr array argument
       3   * of sendmmsg and recvmmsg syscalls.
       4   *
       5   * Copyright (c) 2016 Dmitry V. Levin <ldv@strace.io>
       6   * Copyright (c) 2016-2021 The strace developers.
       7   * All rights reserved.
       8   *
       9   * SPDX-License-Identifier: GPL-2.0-or-later
      10   */
      11  
      12  #include "tests.h"
      13  
      14  #include <errno.h>
      15  #include <limits.h>
      16  #include <stddef.h>
      17  #include <stdio.h>
      18  #include <string.h>
      19  #include <unistd.h>
      20  #include <sys/un.h>
      21  
      22  #include "msghdr.h"
      23  
      24  #define IOV_MAX1 (IOV_MAX + 1)
      25  
      26  #ifndef TEST_NAME
      27  # define TEST_NAME "mmsg_name"
      28  #endif
      29  
      30  static void
      31  print_msghdr(const struct msghdr *const msg, const int user_msg_namelen)
      32  {
      33  	const struct sockaddr_un *const un = msg->msg_name;
      34  	const int offsetof_sun_path = offsetof(struct sockaddr_un, sun_path);
      35  
      36  	printf("{msg_name=");
      37  	if (!un)
      38  		printf("NULL");
      39  	else if (user_msg_namelen < offsetof_sun_path) {
      40  		printf("%p", un);
      41  	} else {
      42  		printf("{sa_family=AF_UNIX");
      43  		if (user_msg_namelen > offsetof_sun_path) {
      44  			int len = user_msg_namelen < (int) msg->msg_namelen ?
      45  				  user_msg_namelen : (int) msg->msg_namelen;
      46  			len -= offsetof_sun_path;
      47  			if (len > (int) sizeof(un->sun_path))
      48  				len = sizeof(un->sun_path);
      49  			printf(", sun_path=\"%.*s\"", len, un->sun_path);
      50  		}
      51  		printf("}");
      52  	}
      53  	printf(", msg_namelen=");
      54  	if (user_msg_namelen != (int) msg->msg_namelen) {
      55  		printf("%d => ", user_msg_namelen);
      56  	}
      57  	printf("%d, msg_iov=[{iov_base=\"%c\", iov_len=1}]"
      58  	       ", msg_iovlen=1, msg_controllen=0, msg_flags=0}",
      59  	       (int) msg->msg_namelen, *(char *) msg->msg_iov[0].iov_base);
      60  }
      61  
      62  static void
      63  test_mmsg_name(const int send_fd, const int recv_fd)
      64  {
      65  	struct sockaddr_un *const send_addr =
      66  		tail_alloc(sizeof(*send_addr) * IOV_MAX1);
      67  	char *const send_buf = tail_alloc(sizeof(*send_buf) * IOV_MAX1);
      68  	struct iovec *const send_iov = tail_alloc(sizeof(*send_iov) * IOV_MAX1);
      69  	struct mmsghdr *const send_mh = tail_alloc(sizeof(*send_mh) * IOV_MAX1);
      70  
      71  	int rc;
      72  
      73  	for (int i = 0; i < IOV_MAX1; ++i) {
      74  		int sun_len = i + 1 > (int) sizeof(send_addr[i].sun_path)
      75  				    ? (int) sizeof(send_addr[i].sun_path)
      76  				    : i + 1;
      77  
      78  		send_addr[i].sun_family = AF_UNIX;
      79  		memset(send_addr[i].sun_path, 'a' + i % 26, sun_len);
      80  
      81  		send_buf[i] = '0' + i % 10;
      82  
      83  		send_iov[i].iov_base = &send_buf[i];
      84  		send_iov[i].iov_len = sizeof(*send_buf);
      85  
      86  		send_mh[i].msg_hdr.msg_iov = &send_iov[i];
      87  		send_mh[i].msg_hdr.msg_iovlen = 1;
      88  		send_mh[i].msg_hdr.msg_name = &send_addr[i];
      89  		send_mh[i].msg_hdr.msg_namelen = i + 1;
      90  		send_mh[i].msg_hdr.msg_control = 0;
      91  		send_mh[i].msg_hdr.msg_controllen = 0;
      92  		send_mh[i].msg_hdr.msg_flags = 0;
      93  	}
      94  
      95  	rc = send_mmsg(send_fd, send_mh, IOV_MAX1, MSG_DONTWAIT);
      96  	int saved_errno = errno;
      97  
      98  	printf("sendmmsg(%d, [", send_fd);
      99  	for (int i = 0; i < IOV_MAX1; ++i) {
     100  		if (i)
     101  			printf(", ");
     102  		if (i >= IOV_MAX
     103  #if !VERBOSE
     104  			|| i >= DEFAULT_STRLEN
     105  #endif
     106  		   ) {
     107  			printf("...");
     108  			break;
     109  		}
     110  		printf("{msg_hdr=");
     111  		print_msghdr(&send_mh[i].msg_hdr, i + 1);
     112  		printf("}");
     113  	}
     114  	errno = saved_errno;
     115  	printf("], %u, MSG_DONTWAIT) = %d %s (%m)\n",
     116  	       IOV_MAX1, rc, errno2name());
     117  
     118  	for (int i = 0; i < IOV_MAX1; ++i) {
     119  		send_mh[i].msg_hdr.msg_name = 0;
     120  		send_mh[i].msg_hdr.msg_namelen = 0;
     121  	}
     122  
     123  	/*
     124  	 * When recvmmsg is called with a valid descriptor
     125  	 * but inaccessible memory, it causes segfaults on some architectures.
     126  	 * As in these cases we test decoding of failed recvmmsg calls,
     127  	 * it's ok to fail recvmmsg with any reason as long as
     128  	 * it doesn't read that inaccessible memory.
     129  	 */
     130  	rc = send_mmsg(-1, &send_mh[IOV_MAX], 2, MSG_DONTWAIT);
     131  	saved_errno = errno;
     132  	printf("sendmmsg(-1, [{msg_hdr=");
     133  	print_msghdr(&send_mh[IOV_MAX].msg_hdr, 0);
     134  	errno = saved_errno;
     135  	printf("}, ... /* %p */], %u, MSG_DONTWAIT) = %d %s (%m)\n",
     136  	       &send_mh[IOV_MAX1], 2, rc, errno2name());
     137  
     138  	rc = send_mmsg(send_fd, send_mh, IOV_MAX1, MSG_DONTWAIT);
     139  	if (rc < 0)
     140  		perror_msg_and_skip("sendmmsg");
     141  
     142  	printf("sendmmsg(%d, [", send_fd);
     143  	for (int i = 0; i < IOV_MAX1; ++i) {
     144  		if (i)
     145  			printf(", ");
     146  		if (i >= IOV_MAX
     147  #if !VERBOSE
     148  			|| i >= DEFAULT_STRLEN
     149  #endif
     150  		   ) {
     151  			printf("...");
     152  			break;
     153  		}
     154  		printf("{msg_hdr=");
     155  		print_msghdr(&send_mh[i].msg_hdr, 0);
     156  		printf("%s}", i < rc ? ", msg_len=1" : "");
     157  	}
     158  	printf("], %u, MSG_DONTWAIT) = %d\n", IOV_MAX1, rc);
     159  
     160  	struct sockaddr_un *const recv_addr =
     161  		tail_alloc(sizeof(*recv_addr) * IOV_MAX1);
     162  	char *const recv_buf = tail_alloc(sizeof(*recv_buf) * IOV_MAX1);
     163  	struct iovec *const recv_iov = tail_alloc(sizeof(*recv_iov) * IOV_MAX1);
     164  	struct mmsghdr *const recv_mh = tail_alloc(sizeof(*recv_mh) * IOV_MAX1);
     165  
     166  	for (int i = 0; i < IOV_MAX1; ++i) {
     167  		recv_iov[i].iov_base = &recv_buf[i];
     168  		recv_iov[i].iov_len = sizeof(*recv_buf);
     169  
     170  		recv_mh[i].msg_hdr.msg_name = &recv_addr[i];
     171  		recv_mh[i].msg_hdr.msg_namelen = i;
     172  		recv_mh[i].msg_hdr.msg_iov = &recv_iov[i];
     173  		recv_mh[i].msg_hdr.msg_iovlen = 1;
     174  		recv_mh[i].msg_hdr.msg_control = 0;
     175  		recv_mh[i].msg_hdr.msg_controllen = 0;
     176  		recv_mh[i].msg_hdr.msg_flags = 0;
     177  	}
     178  
     179  	rc = recv_mmsg(recv_fd, recv_mh, IOV_MAX1, MSG_DONTWAIT, 0);
     180  	if (rc < 0)
     181  		perror_msg_and_skip("recvmmsg");
     182  
     183  	printf("recvmmsg(%d, [", recv_fd);
     184  	for (int i = 0; i < rc; ++i) {
     185  		if (i)
     186  			printf(", ");
     187  #if !VERBOSE
     188  		if (i >= DEFAULT_STRLEN) {
     189  			printf("...");
     190  			break;
     191  		}
     192  #endif
     193  		printf("{msg_hdr=");
     194  		print_msghdr(&recv_mh[i].msg_hdr, i);
     195  		printf(", msg_len=1}");
     196  	}
     197  	printf("], %u, MSG_DONTWAIT, NULL) = %d\n", IOV_MAX1, rc);
     198  }
     199  
     200  int
     201  main(void)
     202  {
     203  	int fds[2];
     204  	if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
     205  		perror_msg_and_skip("socketpair");
     206  
     207  	const struct sockaddr_un un = {
     208  		.sun_family = AF_UNIX,
     209  		.sun_path = TEST_NAME "-recvmmsg.test.send.socket"
     210  	};
     211  
     212  	(void) unlink(un.sun_path);
     213  	if (bind(fds[1], (const void *) &un, sizeof(un)))
     214  		perror_msg_and_skip("bind");
     215  	(void) unlink(un.sun_path);
     216  
     217  	test_mmsg_name(fds[1], fds[0]);
     218  
     219  	puts("+++ exited with 0 +++");
     220  	return 0;
     221  }