(root)/
strace-6.5/
tests/
so_peerpidfd.c
       1  /*
       2   * Check decoding of SO_PEERPIDFD socket option.
       3   *
       4   * Copyright (c) 2023 Dmitry V. Levin <ldv@strace.io>
       5   * All rights reserved.
       6   *
       7   * SPDX-License-Identifier: GPL-2.0-or-later
       8   */
       9  
      10  #include "tests.h"
      11  #include <stdio.h>
      12  #include <unistd.h>
      13  #include <sys/socket.h>
      14  
      15  #define XLAT_MACROS_ONLY
      16  # include "xlat/sock_options.h"
      17  #undef XLAT_MACROS_ONLY
      18  
      19  static const char *errstr;
      20  static int rc;
      21  
      22  static int
      23  get_peerpidfd(int fd, void *val, socklen_t *len)
      24  {
      25  	rc = getsockopt(fd, SOL_SOCKET, SO_PEERPIDFD, val, len);
      26  	errstr = sprintrc(rc);
      27  	printf("getsockopt(%d<socket:[%lu]>, SOL_SOCKET, SO_PEERPIDFD, ",
      28  	       fd, inode_of_sockfd(fd));
      29  	return rc;
      30  }
      31  
      32  static void
      33  print_pidfd(int *p)
      34  {
      35  	static const char pidfd_suffix[] = "<anon_inode:[pidfd]>";
      36  
      37  	if (rc < 0)
      38  		printf("%p", p);
      39  	else
      40  		printf("%d%s", *p, pidfd_suffix);
      41  }
      42  
      43  static void
      44  print_optlen(int oldval, int newval)
      45  {
      46  	printf(", [%d", oldval);
      47  	if (oldval != newval)
      48  		printf(" => %d", newval);
      49  	printf("]) = %s\n", errstr);
      50  }
      51  
      52  int
      53  main(void)
      54  {
      55  	skip_if_unavailable("/proc/self/fd/");
      56  
      57  	TAIL_ALLOC_OBJECT_CONST_PTR(int, val);
      58  	TAIL_ALLOC_OBJECT_CONST_ARR(int, bigval, 2);
      59  	TAIL_ALLOC_OBJECT_CONST_PTR(socklen_t, len);
      60  	void *const efault = val + 1;
      61  
      62  	int sv[2];
      63  	if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv))
      64                  perror_msg_and_skip("socketpair AF_UNIX SOCK_STREAM");
      65  	int fd = sv[0];
      66  
      67  	/* classic */
      68  	*len = sizeof(*val);
      69  	rc = get_peerpidfd(fd, val, len);
      70  	print_pidfd(val);
      71  	print_optlen(sizeof(*val), *len);
      72  
      73  	/* optlen larger than accessible memory */
      74  	*len = sizeof(*val) + 1;
      75  	get_peerpidfd(fd, val, len);
      76  	print_pidfd(val);
      77  	print_optlen(sizeof(*val) + 1, *len);
      78  
      79  	/* optlen larger than necessary */
      80  	*len = sizeof(*bigval);
      81  	get_peerpidfd(fd, bigval, len);
      82  	print_pidfd(bigval);
      83  	print_optlen(sizeof(*bigval), *len);
      84  
      85  	/* zero optlen - print returned optlen */
      86  	*len = 0;
      87  	get_peerpidfd(fd, NULL, len);
      88  	printf("NULL");
      89  	print_optlen(0, *len);
      90  
      91  	/* optlen shorter than necessary */
      92  	*len = sizeof(*val) - 1;
      93  	get_peerpidfd(fd, val, len);
      94  	if (rc < 0)
      95  		printf("%p", val);
      96  	else
      97  		print_quoted_hex(val, sizeof(*val) - 1);
      98  	print_optlen(sizeof(*val) - 1, *len);
      99  
     100  	/* optval EFAULT - print address */
     101  	*len = sizeof(*val);
     102  	get_peerpidfd(fd, efault, len);
     103  	printf("%p", efault);
     104  	print_optlen(sizeof(*val), *len);
     105  
     106  	/* optlen EFAULT - print address */
     107  	get_peerpidfd(fd, val, len + 1);
     108  	printf("%p, %p) = %s\n", val, len + 1, errstr);
     109  
     110  	puts("+++ exited with 0 +++");
     111  	return 0;
     112  }