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 }