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

btf_skc_cls_ingress.c (6094B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Copyright (c) 2020 Facebook */
      3
      4#define _GNU_SOURCE
      5#include <netinet/in.h>
      6#include <arpa/inet.h>
      7#include <unistd.h>
      8#include <stdlib.h>
      9#include <string.h>
     10#include <errno.h>
     11#include <sched.h>
     12#include <linux/compiler.h>
     13#include <bpf/libbpf.h>
     14
     15#include "network_helpers.h"
     16#include "test_progs.h"
     17#include "test_btf_skc_cls_ingress.skel.h"
     18
     19static struct test_btf_skc_cls_ingress *skel;
     20static struct sockaddr_in6 srv_sa6;
     21static __u32 duration;
     22
     23#define PROG_PIN_FILE "/sys/fs/bpf/btf_skc_cls_ingress"
     24
     25static int write_sysctl(const char *sysctl, const char *value)
     26{
     27	int fd, err, len;
     28
     29	fd = open(sysctl, O_WRONLY);
     30	if (CHECK(fd == -1, "open sysctl", "open(%s): %s (%d)\n",
     31		  sysctl, strerror(errno), errno))
     32		return -1;
     33
     34	len = strlen(value);
     35	err = write(fd, value, len);
     36	close(fd);
     37	if (CHECK(err != len, "write sysctl",
     38		  "write(%s, %s, %d): err:%d %s (%d)\n",
     39		  sysctl, value, len, err, strerror(errno), errno))
     40		return -1;
     41
     42	return 0;
     43}
     44
     45static int prepare_netns(void)
     46{
     47	if (CHECK(unshare(CLONE_NEWNET), "create netns",
     48		  "unshare(CLONE_NEWNET): %s (%d)",
     49		  strerror(errno), errno))
     50		return -1;
     51
     52	if (CHECK(system("ip link set dev lo up"),
     53		  "ip link set dev lo up", "failed\n"))
     54		return -1;
     55
     56	if (CHECK(system("tc qdisc add dev lo clsact"),
     57		  "tc qdisc add dev lo clsact", "failed\n"))
     58		return -1;
     59
     60	if (CHECK(system("tc filter add dev lo ingress bpf direct-action object-pinned " PROG_PIN_FILE),
     61		  "install tc cls-prog at ingress", "failed\n"))
     62		return -1;
     63
     64	/* Ensure 20 bytes options (i.e. in total 40 bytes tcp header) for the
     65	 * bpf_tcp_gen_syncookie() helper.
     66	 */
     67	if (write_sysctl("/proc/sys/net/ipv4/tcp_window_scaling", "1") ||
     68	    write_sysctl("/proc/sys/net/ipv4/tcp_timestamps", "1") ||
     69	    write_sysctl("/proc/sys/net/ipv4/tcp_sack", "1"))
     70		return -1;
     71
     72	return 0;
     73}
     74
     75static void reset_test(void)
     76{
     77	memset(&skel->bss->srv_sa6, 0, sizeof(skel->bss->srv_sa6));
     78	skel->bss->listen_tp_sport = 0;
     79	skel->bss->req_sk_sport = 0;
     80	skel->bss->recv_cookie = 0;
     81	skel->bss->gen_cookie = 0;
     82	skel->bss->linum = 0;
     83}
     84
     85static void print_err_line(void)
     86{
     87	if (skel->bss->linum)
     88		printf("bpf prog error at line %u\n", skel->bss->linum);
     89}
     90
     91static void test_conn(void)
     92{
     93	int listen_fd = -1, cli_fd = -1, srv_fd = -1, err;
     94	socklen_t addrlen = sizeof(srv_sa6);
     95	int srv_port;
     96
     97	if (write_sysctl("/proc/sys/net/ipv4/tcp_syncookies", "1"))
     98		return;
     99
    100	listen_fd = start_server(AF_INET6, SOCK_STREAM, "::1", 0, 0);
    101	if (CHECK_FAIL(listen_fd == -1))
    102		return;
    103
    104	err = getsockname(listen_fd, (struct sockaddr *)&srv_sa6, &addrlen);
    105	if (CHECK(err, "getsockname(listen_fd)", "err:%d errno:%d\n", err,
    106		  errno))
    107		goto done;
    108	memcpy(&skel->bss->srv_sa6, &srv_sa6, sizeof(srv_sa6));
    109	srv_port = ntohs(srv_sa6.sin6_port);
    110
    111	cli_fd = connect_to_fd(listen_fd, 0);
    112	if (CHECK_FAIL(cli_fd == -1))
    113		goto done;
    114
    115	srv_fd = accept(listen_fd, NULL, NULL);
    116	if (CHECK_FAIL(srv_fd == -1))
    117		goto done;
    118
    119	if (CHECK(skel->bss->listen_tp_sport != srv_port ||
    120		  skel->bss->req_sk_sport != srv_port,
    121		  "Unexpected sk src port",
    122		  "listen_tp_sport:%u req_sk_sport:%u expected:%u\n",
    123		  skel->bss->listen_tp_sport, skel->bss->req_sk_sport,
    124		  srv_port))
    125		goto done;
    126
    127	if (CHECK(skel->bss->gen_cookie || skel->bss->recv_cookie,
    128		  "Unexpected syncookie states",
    129		  "gen_cookie:%u recv_cookie:%u\n",
    130		  skel->bss->gen_cookie, skel->bss->recv_cookie))
    131		goto done;
    132
    133	CHECK(skel->bss->linum, "bpf prog detected error", "at line %u\n",
    134	      skel->bss->linum);
    135
    136done:
    137	if (listen_fd != -1)
    138		close(listen_fd);
    139	if (cli_fd != -1)
    140		close(cli_fd);
    141	if (srv_fd != -1)
    142		close(srv_fd);
    143}
    144
    145static void test_syncookie(void)
    146{
    147	int listen_fd = -1, cli_fd = -1, srv_fd = -1, err;
    148	socklen_t addrlen = sizeof(srv_sa6);
    149	int srv_port;
    150
    151	/* Enforce syncookie mode */
    152	if (write_sysctl("/proc/sys/net/ipv4/tcp_syncookies", "2"))
    153		return;
    154
    155	listen_fd = start_server(AF_INET6, SOCK_STREAM, "::1", 0, 0);
    156	if (CHECK_FAIL(listen_fd == -1))
    157		return;
    158
    159	err = getsockname(listen_fd, (struct sockaddr *)&srv_sa6, &addrlen);
    160	if (CHECK(err, "getsockname(listen_fd)", "err:%d errno:%d\n", err,
    161		  errno))
    162		goto done;
    163	memcpy(&skel->bss->srv_sa6, &srv_sa6, sizeof(srv_sa6));
    164	srv_port = ntohs(srv_sa6.sin6_port);
    165
    166	cli_fd = connect_to_fd(listen_fd, 0);
    167	if (CHECK_FAIL(cli_fd == -1))
    168		goto done;
    169
    170	srv_fd = accept(listen_fd, NULL, NULL);
    171	if (CHECK_FAIL(srv_fd == -1))
    172		goto done;
    173
    174	if (CHECK(skel->bss->listen_tp_sport != srv_port,
    175		  "Unexpected tp src port",
    176		  "listen_tp_sport:%u expected:%u\n",
    177		  skel->bss->listen_tp_sport, srv_port))
    178		goto done;
    179
    180	if (CHECK(skel->bss->req_sk_sport,
    181		  "Unexpected req_sk src port",
    182		  "req_sk_sport:%u expected:0\n",
    183		   skel->bss->req_sk_sport))
    184		goto done;
    185
    186	if (CHECK(!skel->bss->gen_cookie ||
    187		  skel->bss->gen_cookie != skel->bss->recv_cookie,
    188		  "Unexpected syncookie states",
    189		  "gen_cookie:%u recv_cookie:%u\n",
    190		  skel->bss->gen_cookie, skel->bss->recv_cookie))
    191		goto done;
    192
    193	CHECK(skel->bss->linum, "bpf prog detected error", "at line %u\n",
    194	      skel->bss->linum);
    195
    196done:
    197	if (listen_fd != -1)
    198		close(listen_fd);
    199	if (cli_fd != -1)
    200		close(cli_fd);
    201	if (srv_fd != -1)
    202		close(srv_fd);
    203}
    204
    205struct test {
    206	const char *desc;
    207	void (*run)(void);
    208};
    209
    210#define DEF_TEST(name) { #name, test_##name }
    211static struct test tests[] = {
    212	DEF_TEST(conn),
    213	DEF_TEST(syncookie),
    214};
    215
    216void test_btf_skc_cls_ingress(void)
    217{
    218	int i, err;
    219
    220	skel = test_btf_skc_cls_ingress__open_and_load();
    221	if (CHECK(!skel, "test_btf_skc_cls_ingress__open_and_load", "failed\n"))
    222		return;
    223
    224	err = bpf_program__pin(skel->progs.cls_ingress, PROG_PIN_FILE);
    225	if (CHECK(err, "bpf_program__pin",
    226		  "cannot pin bpf prog to %s. err:%d\n", PROG_PIN_FILE, err)) {
    227		test_btf_skc_cls_ingress__destroy(skel);
    228		return;
    229	}
    230
    231	for (i = 0; i < ARRAY_SIZE(tests); i++) {
    232		if (!test__start_subtest(tests[i].desc))
    233			continue;
    234
    235		if (prepare_netns())
    236			break;
    237
    238		tests[i].run();
    239
    240		print_err_line();
    241		reset_test();
    242	}
    243
    244	bpf_program__unpin(skel->progs.cls_ingress, PROG_PIN_FILE);
    245	test_btf_skc_cls_ingress__destroy(skel);
    246}