brintos

brintos / linux-shallow public Read only

0
0
Text · 5.5 KiB · d663362 Raw
308 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright Amazon.com Inc. or its affiliates. */3#define _GNU_SOURCE4#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 15FIXTURE(scm_rights)16{17	int fd[32];18};19 20FIXTURE_VARIANT(scm_rights)21{22	char name[32];23	int type;24	int flags;25	bool test_listener;26};27 28FIXTURE_VARIANT_ADD(scm_rights, dgram)29{30	.name = "UNIX ",31	.type = SOCK_DGRAM,32	.flags = 0,33	.test_listener = false,34};35 36FIXTURE_VARIANT_ADD(scm_rights, stream)37{38	.name = "UNIX-STREAM ",39	.type = SOCK_STREAM,40	.flags = 0,41	.test_listener = false,42};43 44FIXTURE_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 52FIXTURE_VARIANT_ADD(scm_rights, stream_listener)53{54	.name = "UNIX-STREAM ",55	.type = SOCK_STREAM,56	.flags = 0,57	.test_listener = true,58};59 60FIXTURE_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 68static 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 101FIXTURE_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 112FIXTURE_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 122static 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 155static 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 170static 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	else180		create_socketpairs(_metadata, self, variant, n);181}182 183static 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 197void __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 1204	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 243TEST_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 254TEST_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 269TEST_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 288TEST_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 307TEST_HARNESS_MAIN308