~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/net/af_unix/scm_rights.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /* Copyright Amazon.com Inc. or its affiliates. */
  3 #define _GNU_SOURCE
  4 #include <sched.h>
  5 
  6 #include <stdio.h>
  7 #include <string.h>
  8 #include <unistd.h>
  9 #include <sys/types.h>
 10 #include <sys/socket.h>
 11 #include <sys/un.h>
 12 
 13 #include "../../kselftest_harness.h"
 14 
 15 FIXTURE(scm_rights)
 16 {
 17         int fd[32];
 18 };
 19 
 20 FIXTURE_VARIANT(scm_rights)
 21 {
 22         char name[32];
 23         int type;
 24         int flags;
 25         bool test_listener;
 26 };
 27 
 28 FIXTURE_VARIANT_ADD(scm_rights, dgram)
 29 {
 30         .name = "UNIX ",
 31         .type = SOCK_DGRAM,
 32         .flags = 0,
 33         .test_listener = false,
 34 };
 35 
 36 FIXTURE_VARIANT_ADD(scm_rights, stream)
 37 {
 38         .name = "UNIX-STREAM ",
 39         .type = SOCK_STREAM,
 40         .flags = 0,
 41         .test_listener = false,
 42 };
 43 
 44 FIXTURE_VARIANT_ADD(scm_rights, stream_oob)
 45 {
 46         .name = "UNIX-STREAM ",
 47         .type = SOCK_STREAM,
 48         .flags = MSG_OOB,
 49         .test_listener = false,
 50 };
 51 
 52 FIXTURE_VARIANT_ADD(scm_rights, stream_listener)
 53 {
 54         .name = "UNIX-STREAM ",
 55         .type = SOCK_STREAM,
 56         .flags = 0,
 57         .test_listener = true,
 58 };
 59 
 60 FIXTURE_VARIANT_ADD(scm_rights, stream_listener_oob)
 61 {
 62         .name = "UNIX-STREAM ",
 63         .type = SOCK_STREAM,
 64         .flags = MSG_OOB,
 65         .test_listener = true,
 66 };
 67 
 68 static int count_sockets(struct __test_metadata *_metadata,
 69                          const FIXTURE_VARIANT(scm_rights) *variant)
 70 {
 71         int sockets = -1, len, ret;
 72         char *line = NULL;
 73         size_t unused;
 74         FILE *f;
 75 
 76         f = fopen("/proc/net/protocols", "r");
 77         ASSERT_NE(NULL, f);
 78 
 79         len = strlen(variant->name);
 80 
 81         while (getline(&line, &unused, f) != -1) {
 82                 int unused2;
 83 
 84                 if (strncmp(line, variant->name, len))
 85                         continue;
 86 
 87                 ret = sscanf(line + len, "%d %d", &unused2, &sockets);
 88                 ASSERT_EQ(2, ret);
 89 
 90                 break;
 91         }
 92 
 93         free(line);
 94 
 95         ret = fclose(f);
 96         ASSERT_EQ(0, ret);
 97 
 98         return sockets;
 99 }
100 
101 FIXTURE_SETUP(scm_rights)
102 {
103         int ret;
104 
105         ret = unshare(CLONE_NEWNET);
106         ASSERT_EQ(0, ret);
107 
108         ret = count_sockets(_metadata, variant);
109         ASSERT_EQ(0, ret);
110 }
111 
112 FIXTURE_TEARDOWN(scm_rights)
113 {
114         int ret;
115 
116         sleep(1);
117 
118         ret = count_sockets(_metadata, variant);
119         ASSERT_EQ(0, ret);
120 }
121 
122 static void create_listeners(struct __test_metadata *_metadata,
123                              FIXTURE_DATA(scm_rights) *self,
124                              int n)
125 {
126         struct sockaddr_un addr = {
127                 .sun_family = AF_UNIX,
128         };
129         socklen_t addrlen;
130         int i, ret;
131 
132         for (i = 0; i < n * 2; i += 2) {
133                 self->fd[i] = socket(AF_UNIX, SOCK_STREAM, 0);
134                 ASSERT_LE(0, self->fd[i]);
135 
136                 addrlen = sizeof(addr.sun_family);
137                 ret = bind(self->fd[i], (struct sockaddr *)&addr, addrlen);
138                 ASSERT_EQ(0, ret);
139 
140                 ret = listen(self->fd[i], -1);
141                 ASSERT_EQ(0, ret);
142 
143                 addrlen = sizeof(addr);
144                 ret = getsockname(self->fd[i], (struct sockaddr *)&addr, &addrlen);
145                 ASSERT_EQ(0, ret);
146 
147                 self->fd[i + 1] = socket(AF_UNIX, SOCK_STREAM, 0);
148                 ASSERT_LE(0, self->fd[i + 1]);
149 
150                 ret = connect(self->fd[i + 1], (struct sockaddr *)&addr, addrlen);
151                 ASSERT_EQ(0, ret);
152         }
153 }
154 
155 static void create_socketpairs(struct __test_metadata *_metadata,
156                                FIXTURE_DATA(scm_rights) *self,
157                                const FIXTURE_VARIANT(scm_rights) *variant,
158                                int n)
159 {
160         int i, ret;
161 
162         ASSERT_GE(sizeof(self->fd) / sizeof(int), n);
163 
164         for (i = 0; i < n * 2; i += 2) {
165                 ret = socketpair(AF_UNIX, variant->type, 0, self->fd + i);
166                 ASSERT_EQ(0, ret);
167         }
168 }
169 
170 static void __create_sockets(struct __test_metadata *_metadata,
171                              FIXTURE_DATA(scm_rights) *self,
172                              const FIXTURE_VARIANT(scm_rights) *variant,
173                              int n)
174 {
175         ASSERT_LE(n * 2, sizeof(self->fd) / sizeof(self->fd[0]));
176 
177         if (variant->test_listener)
178                 create_listeners(_metadata, self, n);
179         else
180                 create_socketpairs(_metadata, self, variant, n);
181 }
182 
183 static void __close_sockets(struct __test_metadata *_metadata,
184                             FIXTURE_DATA(scm_rights) *self,
185                             int n)
186 {
187         int i, ret;
188 
189         ASSERT_GE(sizeof(self->fd) / sizeof(int), n);
190 
191         for (i = 0; i < n * 2; i++) {
192                 ret = close(self->fd[i]);
193                 ASSERT_EQ(0, ret);
194         }
195 }
196 
197 void __send_fd(struct __test_metadata *_metadata,
198                const FIXTURE_DATA(scm_rights) *self,
199                const FIXTURE_VARIANT(scm_rights) *variant,
200                int inflight, int receiver)
201 {
202 #define MSG "x"
203 #define MSGLEN 1
204         struct {
205                 struct cmsghdr cmsghdr;
206                 int fd[2];
207         } cmsg = {
208                 .cmsghdr = {
209                         .cmsg_len = CMSG_LEN(sizeof(cmsg.fd)),
210                         .cmsg_level = SOL_SOCKET,
211                         .cmsg_type = SCM_RIGHTS,
212                 },
213                 .fd = {
214                         self->fd[inflight * 2],
215                         self->fd[inflight * 2],
216                 },
217         };
218         struct iovec iov = {
219                 .iov_base = MSG,
220                 .iov_len = MSGLEN,
221         };
222         struct msghdr msg = {
223                 .msg_name = NULL,
224                 .msg_namelen = 0,
225                 .msg_iov = &iov,
226                 .msg_iovlen = 1,
227                 .msg_control = &cmsg,
228                 .msg_controllen = CMSG_SPACE(sizeof(cmsg.fd)),
229         };
230         int ret;
231 
232         ret = sendmsg(self->fd[receiver * 2 + 1], &msg, variant->flags);
233         ASSERT_EQ(MSGLEN, ret);
234 }
235 
236 #define create_sockets(n)                                       \
237         __create_sockets(_metadata, self, variant, n)
238 #define close_sockets(n)                                        \
239         __close_sockets(_metadata, self, n)
240 #define send_fd(inflight, receiver)                             \
241         __send_fd(_metadata, self, variant, inflight, receiver)
242 
243 TEST_F(scm_rights, self_ref)
244 {
245         create_sockets(2);
246 
247         send_fd(0, 0);
248 
249         send_fd(1, 1);
250 
251         close_sockets(2);
252 }
253 
254 TEST_F(scm_rights, triangle)
255 {
256         create_sockets(6);
257 
258         send_fd(0, 1);
259         send_fd(1, 2);
260         send_fd(2, 0);
261 
262         send_fd(3, 4);
263         send_fd(4, 5);
264         send_fd(5, 3);
265 
266         close_sockets(6);
267 }
268 
269 TEST_F(scm_rights, cross_edge)
270 {
271         create_sockets(8);
272 
273         send_fd(0, 1);
274         send_fd(1, 2);
275         send_fd(2, 0);
276         send_fd(1, 3);
277         send_fd(3, 2);
278 
279         send_fd(4, 5);
280         send_fd(5, 6);
281         send_fd(6, 4);
282         send_fd(5, 7);
283         send_fd(7, 6);
284 
285         close_sockets(8);
286 }
287 
288 TEST_F(scm_rights, backtrack_from_scc)
289 {
290         create_sockets(10);
291 
292         send_fd(0, 1);
293         send_fd(0, 4);
294         send_fd(1, 2);
295         send_fd(2, 3);
296         send_fd(3, 1);
297 
298         send_fd(5, 6);
299         send_fd(5, 9);
300         send_fd(6, 7);
301         send_fd(7, 8);
302         send_fd(8, 6);
303 
304         close_sockets(10);
305 }
306 
307 TEST_HARNESS_MAIN
308 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php