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

xdp_link.c (4820B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Copyright (c) 2020 Facebook */
      3#include <uapi/linux/if_link.h>
      4#include <test_progs.h>
      5#include "test_xdp_link.skel.h"
      6
      7#define IFINDEX_LO 1
      8
      9void serial_test_xdp_link(void)
     10{
     11	struct test_xdp_link *skel1 = NULL, *skel2 = NULL;
     12	__u32 id1, id2, id0 = 0, prog_fd1, prog_fd2;
     13	LIBBPF_OPTS(bpf_xdp_attach_opts, opts);
     14	struct bpf_link_info link_info;
     15	struct bpf_prog_info prog_info;
     16	struct bpf_link *link;
     17	int err;
     18	__u32 link_info_len = sizeof(link_info);
     19	__u32 prog_info_len = sizeof(prog_info);
     20
     21	skel1 = test_xdp_link__open_and_load();
     22	if (!ASSERT_OK_PTR(skel1, "skel_load"))
     23		goto cleanup;
     24	prog_fd1 = bpf_program__fd(skel1->progs.xdp_handler);
     25
     26	skel2 = test_xdp_link__open_and_load();
     27	if (!ASSERT_OK_PTR(skel2, "skel_load"))
     28		goto cleanup;
     29	prog_fd2 = bpf_program__fd(skel2->progs.xdp_handler);
     30
     31	memset(&prog_info, 0, sizeof(prog_info));
     32	err = bpf_obj_get_info_by_fd(prog_fd1, &prog_info, &prog_info_len);
     33	if (!ASSERT_OK(err, "fd_info1"))
     34		goto cleanup;
     35	id1 = prog_info.id;
     36
     37	memset(&prog_info, 0, sizeof(prog_info));
     38	err = bpf_obj_get_info_by_fd(prog_fd2, &prog_info, &prog_info_len);
     39	if (!ASSERT_OK(err, "fd_info2"))
     40		goto cleanup;
     41	id2 = prog_info.id;
     42
     43	/* set initial prog attachment */
     44	err = bpf_xdp_attach(IFINDEX_LO, prog_fd1, XDP_FLAGS_REPLACE, &opts);
     45	if (!ASSERT_OK(err, "fd_attach"))
     46		goto cleanup;
     47
     48	/* validate prog ID */
     49	err = bpf_xdp_query_id(IFINDEX_LO, 0, &id0);
     50	if (!ASSERT_OK(err, "id1_check_err") || !ASSERT_EQ(id0, id1, "id1_check_val"))
     51		goto cleanup;
     52
     53	/* BPF link is not allowed to replace prog attachment */
     54	link = bpf_program__attach_xdp(skel1->progs.xdp_handler, IFINDEX_LO);
     55	if (!ASSERT_ERR_PTR(link, "link_attach_should_fail")) {
     56		bpf_link__destroy(link);
     57		/* best-effort detach prog */
     58		opts.old_prog_fd = prog_fd1;
     59		bpf_xdp_detach(IFINDEX_LO, XDP_FLAGS_REPLACE, &opts);
     60		goto cleanup;
     61	}
     62
     63	/* detach BPF program */
     64	opts.old_prog_fd = prog_fd1;
     65	err = bpf_xdp_detach(IFINDEX_LO, XDP_FLAGS_REPLACE, &opts);
     66	if (!ASSERT_OK(err, "prog_detach"))
     67		goto cleanup;
     68
     69	/* now BPF link should attach successfully */
     70	link = bpf_program__attach_xdp(skel1->progs.xdp_handler, IFINDEX_LO);
     71	if (!ASSERT_OK_PTR(link, "link_attach"))
     72		goto cleanup;
     73	skel1->links.xdp_handler = link;
     74
     75	/* validate prog ID */
     76	err = bpf_xdp_query_id(IFINDEX_LO, 0, &id0);
     77	if (!ASSERT_OK(err, "id1_check_err") || !ASSERT_EQ(id0, id1, "id1_check_val"))
     78		goto cleanup;
     79
     80	/* BPF prog attach is not allowed to replace BPF link */
     81	opts.old_prog_fd = prog_fd1;
     82	err = bpf_xdp_attach(IFINDEX_LO, prog_fd2, XDP_FLAGS_REPLACE, &opts);
     83	if (!ASSERT_ERR(err, "prog_attach_fail"))
     84		goto cleanup;
     85
     86	/* Can't force-update when BPF link is active */
     87	err = bpf_xdp_attach(IFINDEX_LO, prog_fd2, 0, NULL);
     88	if (!ASSERT_ERR(err, "prog_update_fail"))
     89		goto cleanup;
     90
     91	/* Can't force-detach when BPF link is active */
     92	err = bpf_xdp_detach(IFINDEX_LO, 0, NULL);
     93	if (!ASSERT_ERR(err, "prog_detach_fail"))
     94		goto cleanup;
     95
     96	/* BPF link is not allowed to replace another BPF link */
     97	link = bpf_program__attach_xdp(skel2->progs.xdp_handler, IFINDEX_LO);
     98	if (!ASSERT_ERR_PTR(link, "link_attach_should_fail")) {
     99		bpf_link__destroy(link);
    100		goto cleanup;
    101	}
    102
    103	bpf_link__destroy(skel1->links.xdp_handler);
    104	skel1->links.xdp_handler = NULL;
    105
    106	/* new link attach should succeed */
    107	link = bpf_program__attach_xdp(skel2->progs.xdp_handler, IFINDEX_LO);
    108	if (!ASSERT_OK_PTR(link, "link_attach"))
    109		goto cleanup;
    110	skel2->links.xdp_handler = link;
    111
    112	err = bpf_xdp_query_id(IFINDEX_LO, 0, &id0);
    113	if (!ASSERT_OK(err, "id2_check_err") || !ASSERT_EQ(id0, id2, "id2_check_val"))
    114		goto cleanup;
    115
    116	/* updating program under active BPF link works as expected */
    117	err = bpf_link__update_program(link, skel1->progs.xdp_handler);
    118	if (!ASSERT_OK(err, "link_upd"))
    119		goto cleanup;
    120
    121	memset(&link_info, 0, sizeof(link_info));
    122	err = bpf_obj_get_info_by_fd(bpf_link__fd(link), &link_info, &link_info_len);
    123	if (!ASSERT_OK(err, "link_info"))
    124		goto cleanup;
    125
    126	ASSERT_EQ(link_info.type, BPF_LINK_TYPE_XDP, "link_type");
    127	ASSERT_EQ(link_info.prog_id, id1, "link_prog_id");
    128	ASSERT_EQ(link_info.xdp.ifindex, IFINDEX_LO, "link_ifindex");
    129
    130	/* updating program under active BPF link with different type fails */
    131	err = bpf_link__update_program(link, skel1->progs.tc_handler);
    132	if (!ASSERT_ERR(err, "link_upd_invalid"))
    133		goto cleanup;
    134
    135	err = bpf_link__detach(link);
    136	if (!ASSERT_OK(err, "link_detach"))
    137		goto cleanup;
    138
    139	memset(&link_info, 0, sizeof(link_info));
    140	err = bpf_obj_get_info_by_fd(bpf_link__fd(link), &link_info, &link_info_len);
    141
    142	ASSERT_OK(err, "link_info");
    143	ASSERT_EQ(link_info.prog_id, id1, "link_prog_id");
    144	/* ifindex should be zeroed out */
    145	ASSERT_EQ(link_info.xdp.ifindex, 0, "link_ifindex");
    146
    147cleanup:
    148	test_xdp_link__destroy(skel1);
    149	test_xdp_link__destroy(skel2);
    150}