linux/tools/testing/selftests/bpf/prog_tests/global_data.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include <test_progs.h>
   3
   4static void test_global_data_number(struct bpf_object *obj, __u32 duration)
   5{
   6        int i, err, map_fd;
   7        uint64_t num;
   8
   9        map_fd = bpf_find_map(__func__, obj, "result_number");
  10        if (CHECK_FAIL(map_fd < 0))
  11                return;
  12
  13        struct {
  14                char *name;
  15                uint32_t key;
  16                uint64_t num;
  17        } tests[] = {
  18                { "relocate .bss reference",     0, 0 },
  19                { "relocate .data reference",    1, 42 },
  20                { "relocate .rodata reference",  2, 24 },
  21                { "relocate .bss reference",     3, 0 },
  22                { "relocate .data reference",    4, 0xffeeff },
  23                { "relocate .rodata reference",  5, 0xabab },
  24                { "relocate .bss reference",     6, 1234 },
  25                { "relocate .bss reference",     7, 0 },
  26                { "relocate .rodata reference",  8, 0xab },
  27                { "relocate .rodata reference",  9, 0x1111111111111111 },
  28                { "relocate .rodata reference", 10, ~0 },
  29        };
  30
  31        for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
  32                err = bpf_map_lookup_elem(map_fd, &tests[i].key, &num);
  33                CHECK(err || num != tests[i].num, tests[i].name,
  34                      "err %d result %lx expected %lx\n",
  35                      err, num, tests[i].num);
  36        }
  37}
  38
  39static void test_global_data_string(struct bpf_object *obj, __u32 duration)
  40{
  41        int i, err, map_fd;
  42        char str[32];
  43
  44        map_fd = bpf_find_map(__func__, obj, "result_string");
  45        if (CHECK_FAIL(map_fd < 0))
  46                return;
  47
  48        struct {
  49                char *name;
  50                uint32_t key;
  51                char str[32];
  52        } tests[] = {
  53                { "relocate .rodata reference", 0, "abcdefghijklmnopqrstuvwxyz" },
  54                { "relocate .data reference",   1, "abcdefghijklmnopqrstuvwxyz" },
  55                { "relocate .bss reference",    2, "" },
  56                { "relocate .data reference",   3, "abcdexghijklmnopqrstuvwxyz" },
  57                { "relocate .bss reference",    4, "\0\0hello" },
  58        };
  59
  60        for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
  61                err = bpf_map_lookup_elem(map_fd, &tests[i].key, str);
  62                CHECK(err || memcmp(str, tests[i].str, sizeof(str)),
  63                      tests[i].name, "err %d result \'%s\' expected \'%s\'\n",
  64                      err, str, tests[i].str);
  65        }
  66}
  67
  68struct foo {
  69        __u8  a;
  70        __u32 b;
  71        __u64 c;
  72};
  73
  74static void test_global_data_struct(struct bpf_object *obj, __u32 duration)
  75{
  76        int i, err, map_fd;
  77        struct foo val;
  78
  79        map_fd = bpf_find_map(__func__, obj, "result_struct");
  80        if (CHECK_FAIL(map_fd < 0))
  81                return;
  82
  83        struct {
  84                char *name;
  85                uint32_t key;
  86                struct foo val;
  87        } tests[] = {
  88                { "relocate .rodata reference", 0, { 42, 0xfefeefef, 0x1111111111111111ULL, } },
  89                { "relocate .bss reference",    1, { } },
  90                { "relocate .rodata reference", 2, { } },
  91                { "relocate .data reference",   3, { 41, 0xeeeeefef, 0x2111111111111111ULL, } },
  92        };
  93
  94        for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
  95                err = bpf_map_lookup_elem(map_fd, &tests[i].key, &val);
  96                CHECK(err || memcmp(&val, &tests[i].val, sizeof(val)),
  97                      tests[i].name, "err %d result { %u, %u, %llu } expected { %u, %u, %llu }\n",
  98                      err, val.a, val.b, val.c, tests[i].val.a, tests[i].val.b, tests[i].val.c);
  99        }
 100}
 101
 102static void test_global_data_rdonly(struct bpf_object *obj, __u32 duration)
 103{
 104        int err = -ENOMEM, map_fd, zero = 0;
 105        struct bpf_map *map;
 106        __u8 *buff;
 107
 108        map = bpf_object__find_map_by_name(obj, "test_glo.rodata");
 109        if (CHECK_FAIL(!map || !bpf_map__is_internal(map)))
 110                return;
 111
 112        map_fd = bpf_map__fd(map);
 113        if (CHECK_FAIL(map_fd < 0))
 114                return;
 115
 116        buff = malloc(bpf_map__def(map)->value_size);
 117        if (buff)
 118                err = bpf_map_update_elem(map_fd, &zero, buff, 0);
 119        free(buff);
 120        CHECK(!err || errno != EPERM, "test .rodata read-only map",
 121              "err %d errno %d\n", err, errno);
 122}
 123
 124void test_global_data(void)
 125{
 126        const char *file = "./test_global_data.o";
 127        __u32 duration = 0, retval;
 128        struct bpf_object *obj;
 129        int err, prog_fd;
 130
 131        err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
 132        if (CHECK(err, "load program", "error %d loading %s\n", err, file))
 133                return;
 134
 135        err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4),
 136                                NULL, NULL, &retval, &duration);
 137        CHECK(err || retval, "pass global data run",
 138              "err %d errno %d retval %d duration %d\n",
 139              err, errno, retval, duration);
 140
 141        test_global_data_number(obj, duration);
 142        test_global_data_string(obj, duration);
 143        test_global_data_struct(obj, duration);
 144        test_global_data_rdonly(obj, duration);
 145
 146        bpf_object__close(obj);
 147}
 148