brintos

brintos / linux-shallow public Read only

0
0
Text · 3.5 KiB · 9f1c175 Raw
158 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Check what features does the kernel support (where the selftest is running).3 * Somewhat inspired by CRIU kerndat/kdat kernel features detector.4 */5#include <pthread.h>6#include "aolib.h"7 8struct kconfig_t {9	int _error;		/* negative errno if not supported */10	int (*check_kconfig)(int *error);11};12 13static int has_net_ns(int *err)14{15	if (access("/proc/self/ns/net", F_OK) < 0) {16		*err = errno;17		if (errno == ENOENT)18			return 0;19		test_print("Unable to access /proc/self/ns/net: %m");20		return -errno;21	}22	return *err = errno = 0;23}24 25static int has_veth(int *err)26{27	int orig_netns, ns_a, ns_b;28 29	orig_netns = open_netns();30	ns_a = unshare_open_netns();31	ns_b = unshare_open_netns();32 33	*err = add_veth("check_veth", ns_a, ns_b);34 35	switch_ns(orig_netns);36	close(orig_netns);37	close(ns_a);38	close(ns_b);39	return 0;40}41 42static int has_tcp_ao(int *err)43{44	struct sockaddr_in addr = {45		.sin_family = test_family,46	};47	struct tcp_ao_add tmp = {};48	const char *password = DEFAULT_TEST_PASSWORD;49	int sk, ret = 0;50 51	sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);52	if (sk < 0) {53		test_print("socket(): %m");54		return -errno;55	}56 57	tmp.sndid = 100;58	tmp.rcvid = 100;59	tmp.keylen = strlen(password);60	memcpy(tmp.key, password, strlen(password));61	strcpy(tmp.alg_name, "hmac(sha1)");62	memcpy(&tmp.addr, &addr, sizeof(addr));63	*err = 0;64	if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &tmp, sizeof(tmp)) < 0) {65		*err = -errno;66		if (errno != ENOPROTOOPT)67			ret = -errno;68	}69	close(sk);70	return ret;71}72 73static int has_tcp_md5(int *err)74{75	union tcp_addr addr_any = {};76	int sk, ret = 0;77 78	sk = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);79	if (sk < 0) {80		test_print("socket(): %m");81		return -errno;82	}83 84	/*85	 * Under CONFIG_CRYPTO_FIPS=y it fails with ENOMEM, rather with86	 * anything more descriptive. Oh well.87	 */88	*err = 0;89	if (test_set_md5(sk, addr_any, 0, -1, DEFAULT_TEST_PASSWORD)) {90		*err = -errno;91		if (errno != ENOPROTOOPT && errno == ENOMEM) {92			test_print("setsockopt(TCP_MD5SIG_EXT): %m");93			ret = -errno;94		}95	}96	close(sk);97	return ret;98}99 100static int has_vrfs(int *err)101{102	int orig_netns, ns_test, ret = 0;103 104	orig_netns = open_netns();105	ns_test = unshare_open_netns();106 107	*err = add_vrf("ksft-check", 55, 101, ns_test);108	if (*err && *err != -EOPNOTSUPP) {109		test_print("Failed to add a VRF: %d", *err);110		ret = *err;111	}112 113	switch_ns(orig_netns);114	close(orig_netns);115	close(ns_test);116	return ret;117}118 119static int has_ftrace(int *err)120{121	*err = test_setup_tracing();122	return 0;123}124 125#define KCONFIG_UNKNOWN			1126static pthread_mutex_t kconfig_lock = PTHREAD_MUTEX_INITIALIZER;127static struct kconfig_t kconfig[__KCONFIG_LAST__] = {128	{ KCONFIG_UNKNOWN, has_net_ns },129	{ KCONFIG_UNKNOWN, has_veth },130	{ KCONFIG_UNKNOWN, has_tcp_ao },131	{ KCONFIG_UNKNOWN, has_tcp_md5 },132	{ KCONFIG_UNKNOWN, has_vrfs },133	{ KCONFIG_UNKNOWN, has_ftrace },134};135 136const char *tests_skip_reason[__KCONFIG_LAST__] = {137	"Tests require network namespaces support (CONFIG_NET_NS)",138	"Tests require veth support (CONFIG_VETH)",139	"Tests require TCP-AO support (CONFIG_TCP_AO)",140	"setsockopt(TCP_MD5SIG_EXT) is not supported (CONFIG_TCP_MD5)",141	"VRFs are not supported (CONFIG_NET_VRF)",142	"Ftrace points are not supported (CONFIG_TRACEPOINTS)",143};144 145bool kernel_config_has(enum test_needs_kconfig k)146{147	bool ret;148 149	pthread_mutex_lock(&kconfig_lock);150	if (kconfig[k]._error == KCONFIG_UNKNOWN) {151		if (kconfig[k].check_kconfig(&kconfig[k]._error))152			test_error("Failed to initialize kconfig %u", k);153	}154	ret = kconfig[k]._error == 0;155	pthread_mutex_unlock(&kconfig_lock);156	return ret;157}158