cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sockmap_ktls.c (4353B)


      1// SPDX-License-Identifier: GPL-2.0
      2// Copyright (c) 2020 Cloudflare
      3/*
      4 * Tests for sockmap/sockhash holding kTLS sockets.
      5 */
      6
      7#include <netinet/tcp.h>
      8#include "test_progs.h"
      9
     10#define MAX_TEST_NAME 80
     11#define TCP_ULP 31
     12
     13static int tcp_server(int family)
     14{
     15	int err, s;
     16
     17	s = socket(family, SOCK_STREAM, 0);
     18	if (CHECK_FAIL(s == -1)) {
     19		perror("socket");
     20		return -1;
     21	}
     22
     23	err = listen(s, SOMAXCONN);
     24	if (CHECK_FAIL(err)) {
     25		perror("listen");
     26		return -1;
     27	}
     28
     29	return s;
     30}
     31
     32static int disconnect(int fd)
     33{
     34	struct sockaddr unspec = { AF_UNSPEC };
     35
     36	return connect(fd, &unspec, sizeof(unspec));
     37}
     38
     39/* Disconnect (unhash) a kTLS socket after removing it from sockmap. */
     40static void test_sockmap_ktls_disconnect_after_delete(int family, int map)
     41{
     42	struct sockaddr_storage addr = {0};
     43	socklen_t len = sizeof(addr);
     44	int err, cli, srv, zero = 0;
     45
     46	srv = tcp_server(family);
     47	if (srv == -1)
     48		return;
     49
     50	err = getsockname(srv, (struct sockaddr *)&addr, &len);
     51	if (CHECK_FAIL(err)) {
     52		perror("getsockopt");
     53		goto close_srv;
     54	}
     55
     56	cli = socket(family, SOCK_STREAM, 0);
     57	if (CHECK_FAIL(cli == -1)) {
     58		perror("socket");
     59		goto close_srv;
     60	}
     61
     62	err = connect(cli, (struct sockaddr *)&addr, len);
     63	if (CHECK_FAIL(err)) {
     64		perror("connect");
     65		goto close_cli;
     66	}
     67
     68	err = bpf_map_update_elem(map, &zero, &cli, 0);
     69	if (CHECK_FAIL(err)) {
     70		perror("bpf_map_update_elem");
     71		goto close_cli;
     72	}
     73
     74	err = setsockopt(cli, IPPROTO_TCP, TCP_ULP, "tls", strlen("tls"));
     75	if (CHECK_FAIL(err)) {
     76		perror("setsockopt(TCP_ULP)");
     77		goto close_cli;
     78	}
     79
     80	err = bpf_map_delete_elem(map, &zero);
     81	if (CHECK_FAIL(err)) {
     82		perror("bpf_map_delete_elem");
     83		goto close_cli;
     84	}
     85
     86	err = disconnect(cli);
     87	if (CHECK_FAIL(err))
     88		perror("disconnect");
     89
     90close_cli:
     91	close(cli);
     92close_srv:
     93	close(srv);
     94}
     95
     96static void test_sockmap_ktls_update_fails_when_sock_has_ulp(int family, int map)
     97{
     98	struct sockaddr_storage addr = {};
     99	socklen_t len = sizeof(addr);
    100	struct sockaddr_in6 *v6;
    101	struct sockaddr_in *v4;
    102	int err, s, zero = 0;
    103
    104	switch (family) {
    105	case AF_INET:
    106		v4 = (struct sockaddr_in *)&addr;
    107		v4->sin_family = AF_INET;
    108		break;
    109	case AF_INET6:
    110		v6 = (struct sockaddr_in6 *)&addr;
    111		v6->sin6_family = AF_INET6;
    112		break;
    113	default:
    114		PRINT_FAIL("unsupported socket family %d", family);
    115		return;
    116	}
    117
    118	s = socket(family, SOCK_STREAM, 0);
    119	if (!ASSERT_GE(s, 0, "socket"))
    120		return;
    121
    122	err = bind(s, (struct sockaddr *)&addr, len);
    123	if (!ASSERT_OK(err, "bind"))
    124		goto close;
    125
    126	err = getsockname(s, (struct sockaddr *)&addr, &len);
    127	if (!ASSERT_OK(err, "getsockname"))
    128		goto close;
    129
    130	err = connect(s, (struct sockaddr *)&addr, len);
    131	if (!ASSERT_OK(err, "connect"))
    132		goto close;
    133
    134	/* save sk->sk_prot and set it to tls_prots */
    135	err = setsockopt(s, IPPROTO_TCP, TCP_ULP, "tls", strlen("tls"));
    136	if (!ASSERT_OK(err, "setsockopt(TCP_ULP)"))
    137		goto close;
    138
    139	/* sockmap update should not affect saved sk_prot */
    140	err = bpf_map_update_elem(map, &zero, &s, BPF_ANY);
    141	if (!ASSERT_ERR(err, "sockmap update elem"))
    142		goto close;
    143
    144	/* call sk->sk_prot->setsockopt to dispatch to saved sk_prot */
    145	err = setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &zero, sizeof(zero));
    146	ASSERT_OK(err, "setsockopt(TCP_NODELAY)");
    147
    148close:
    149	close(s);
    150}
    151
    152static const char *fmt_test_name(const char *subtest_name, int family,
    153				 enum bpf_map_type map_type)
    154{
    155	const char *map_type_str = BPF_MAP_TYPE_SOCKMAP ? "SOCKMAP" : "SOCKHASH";
    156	const char *family_str = AF_INET ? "IPv4" : "IPv6";
    157	static char test_name[MAX_TEST_NAME];
    158
    159	snprintf(test_name, MAX_TEST_NAME,
    160		 "sockmap_ktls %s %s %s",
    161		 subtest_name, family_str, map_type_str);
    162
    163	return test_name;
    164}
    165
    166static void run_tests(int family, enum bpf_map_type map_type)
    167{
    168	int map;
    169
    170	map = bpf_map_create(map_type, NULL, sizeof(int), sizeof(int), 1, NULL);
    171	if (CHECK_FAIL(map < 0)) {
    172		perror("bpf_map_create");
    173		return;
    174	}
    175
    176	if (test__start_subtest(fmt_test_name("disconnect_after_delete", family, map_type)))
    177		test_sockmap_ktls_disconnect_after_delete(family, map);
    178	if (test__start_subtest(fmt_test_name("update_fails_when_sock_has_ulp", family, map_type)))
    179		test_sockmap_ktls_update_fails_when_sock_has_ulp(family, map);
    180
    181	close(map);
    182}
    183
    184void test_sockmap_ktls(void)
    185{
    186	run_tests(AF_INET, BPF_MAP_TYPE_SOCKMAP);
    187	run_tests(AF_INET, BPF_MAP_TYPE_SOCKHASH);
    188	run_tests(AF_INET6, BPF_MAP_TYPE_SOCKMAP);
    189	run_tests(AF_INET6, BPF_MAP_TYPE_SOCKHASH);
    190}