1f08c3bdfSopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) 2019-2020 Linux Test Project 4f08c3bdfSopenharmony_ci */ 5f08c3bdfSopenharmony_ci 6f08c3bdfSopenharmony_ci#define TST_NO_DEFAULT_MAIN 7f08c3bdfSopenharmony_ci#include "tst_test.h" 8f08c3bdfSopenharmony_ci#include "bpf_common.h" 9f08c3bdfSopenharmony_ci 10f08c3bdfSopenharmony_civoid rlimit_bump_memlock(void) 11f08c3bdfSopenharmony_ci{ 12f08c3bdfSopenharmony_ci struct rlimit memlock_r; 13f08c3bdfSopenharmony_ci 14f08c3bdfSopenharmony_ci SAFE_GETRLIMIT(RLIMIT_MEMLOCK, &memlock_r); 15f08c3bdfSopenharmony_ci memlock_r.rlim_cur += BPF_MEMLOCK_ADD; 16f08c3bdfSopenharmony_ci tst_res(TINFO, "Raising RLIMIT_MEMLOCK to %ld", 17f08c3bdfSopenharmony_ci (long)memlock_r.rlim_cur); 18f08c3bdfSopenharmony_ci 19f08c3bdfSopenharmony_ci if (memlock_r.rlim_cur <= memlock_r.rlim_max) { 20f08c3bdfSopenharmony_ci SAFE_SETRLIMIT(RLIMIT_MEMLOCK, &memlock_r); 21f08c3bdfSopenharmony_ci } else if ((geteuid() == 0)) { 22f08c3bdfSopenharmony_ci memlock_r.rlim_max += BPF_MEMLOCK_ADD; 23f08c3bdfSopenharmony_ci SAFE_SETRLIMIT(RLIMIT_MEMLOCK, &memlock_r); 24f08c3bdfSopenharmony_ci } else { 25f08c3bdfSopenharmony_ci tst_res(TINFO, "Can't raise RLIMIT_MEMLOCK, test may fail " 26f08c3bdfSopenharmony_ci "due to lack of max locked memory"); 27f08c3bdfSopenharmony_ci } 28f08c3bdfSopenharmony_ci} 29f08c3bdfSopenharmony_ci 30f08c3bdfSopenharmony_ciint bpf_map_create(union bpf_attr *const attr) 31f08c3bdfSopenharmony_ci{ 32f08c3bdfSopenharmony_ci int ret; 33f08c3bdfSopenharmony_ci 34f08c3bdfSopenharmony_ci ret = TST_RETRY_FUNC(bpf(BPF_MAP_CREATE, attr, sizeof(*attr)), 35f08c3bdfSopenharmony_ci TST_RETVAL_GE0); 36f08c3bdfSopenharmony_ci 37f08c3bdfSopenharmony_ci if (ret == -1) { 38f08c3bdfSopenharmony_ci if (errno == EPERM) { 39f08c3bdfSopenharmony_ci tst_res(TCONF, "Hint: check also /proc/sys/kernel/unprivileged_bpf_disabled"); 40f08c3bdfSopenharmony_ci tst_brk(TCONF | TERRNO, 41f08c3bdfSopenharmony_ci "bpf() requires CAP_SYS_ADMIN or CAP_BPF on this system"); 42f08c3bdfSopenharmony_ci } else { 43f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "Failed to create array map"); 44f08c3bdfSopenharmony_ci } 45f08c3bdfSopenharmony_ci } 46f08c3bdfSopenharmony_ci 47f08c3bdfSopenharmony_ci return ret; 48f08c3bdfSopenharmony_ci} 49f08c3bdfSopenharmony_ci 50f08c3bdfSopenharmony_ciint bpf_map_array_create(const uint32_t max_entries) 51f08c3bdfSopenharmony_ci{ 52f08c3bdfSopenharmony_ci union bpf_attr map_attr = { 53f08c3bdfSopenharmony_ci .map_type = BPF_MAP_TYPE_ARRAY, 54f08c3bdfSopenharmony_ci .key_size = 4, 55f08c3bdfSopenharmony_ci .value_size = 8, 56f08c3bdfSopenharmony_ci .max_entries = max_entries, 57f08c3bdfSopenharmony_ci .map_flags = 0 58f08c3bdfSopenharmony_ci }; 59f08c3bdfSopenharmony_ci 60f08c3bdfSopenharmony_ci return bpf_map_create(&map_attr); 61f08c3bdfSopenharmony_ci} 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_civoid bpf_map_array_get(const int map_fd, 64f08c3bdfSopenharmony_ci const uint32_t *const array_indx, 65f08c3bdfSopenharmony_ci uint64_t *const array_val) 66f08c3bdfSopenharmony_ci{ 67f08c3bdfSopenharmony_ci union bpf_attr elem_attr = { 68f08c3bdfSopenharmony_ci .map_fd = map_fd, 69f08c3bdfSopenharmony_ci .key = ptr_to_u64(array_indx), 70f08c3bdfSopenharmony_ci .value = ptr_to_u64(array_val), 71f08c3bdfSopenharmony_ci .flags = 0 72f08c3bdfSopenharmony_ci }; 73f08c3bdfSopenharmony_ci const int ret = bpf(BPF_MAP_LOOKUP_ELEM, &elem_attr, sizeof(elem_attr)); 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ci if (ret) { 76f08c3bdfSopenharmony_ci tst_brk(TBROK | TTERRNO, 77f08c3bdfSopenharmony_ci "Failed array map lookup: fd=%i [%"PRIu32"]", 78f08c3bdfSopenharmony_ci map_fd, *array_indx); 79f08c3bdfSopenharmony_ci } 80f08c3bdfSopenharmony_ci} 81f08c3bdfSopenharmony_ci 82f08c3bdfSopenharmony_civoid bpf_init_prog_attr(union bpf_attr *const attr, 83f08c3bdfSopenharmony_ci const struct bpf_insn *const prog, 84f08c3bdfSopenharmony_ci const size_t prog_size, char *const log_buf, 85f08c3bdfSopenharmony_ci const size_t log_size) 86f08c3bdfSopenharmony_ci{ 87f08c3bdfSopenharmony_ci static struct bpf_insn *buf; 88f08c3bdfSopenharmony_ci static size_t buf_size; 89f08c3bdfSopenharmony_ci const size_t prog_len = prog_size / sizeof(*prog); 90f08c3bdfSopenharmony_ci 91f08c3bdfSopenharmony_ci /* all guarded buffers will be free()d automatically by LTP library */ 92f08c3bdfSopenharmony_ci if (!buf || prog_size > buf_size) { 93f08c3bdfSopenharmony_ci buf = tst_alloc(prog_size); 94f08c3bdfSopenharmony_ci buf_size = prog_size; 95f08c3bdfSopenharmony_ci } 96f08c3bdfSopenharmony_ci 97f08c3bdfSopenharmony_ci memcpy(buf, prog, prog_size); 98f08c3bdfSopenharmony_ci memset(attr, 0, sizeof(*attr)); 99f08c3bdfSopenharmony_ci attr->prog_type = BPF_PROG_TYPE_SOCKET_FILTER; 100f08c3bdfSopenharmony_ci attr->insns = ptr_to_u64(buf); 101f08c3bdfSopenharmony_ci attr->insn_cnt = prog_len; 102f08c3bdfSopenharmony_ci attr->license = ptr_to_u64("GPL"); 103f08c3bdfSopenharmony_ci attr->log_buf = ptr_to_u64(log_buf); 104f08c3bdfSopenharmony_ci attr->log_size = log_size; 105f08c3bdfSopenharmony_ci attr->log_level = 1; 106f08c3bdfSopenharmony_ci} 107f08c3bdfSopenharmony_ci 108f08c3bdfSopenharmony_ciint bpf_load_prog(union bpf_attr *const attr, const char *const log) 109f08c3bdfSopenharmony_ci{ 110f08c3bdfSopenharmony_ci const int ret = TST_RETRY_FUNC(bpf(BPF_PROG_LOAD, attr, sizeof(*attr)), 111f08c3bdfSopenharmony_ci TST_RETVAL_GE0); 112f08c3bdfSopenharmony_ci 113f08c3bdfSopenharmony_ci if (ret >= 0) { 114f08c3bdfSopenharmony_ci tst_res(TPASS, "Loaded program"); 115f08c3bdfSopenharmony_ci return ret; 116f08c3bdfSopenharmony_ci } 117f08c3bdfSopenharmony_ci 118f08c3bdfSopenharmony_ci if (ret != -1) 119f08c3bdfSopenharmony_ci tst_brk(TBROK, "Invalid bpf() return value: %d", ret); 120f08c3bdfSopenharmony_ci 121f08c3bdfSopenharmony_ci if (log[0] != 0) { 122f08c3bdfSopenharmony_ci tst_printf("%s\n", log); 123f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "Failed verification"); 124f08c3bdfSopenharmony_ci } 125f08c3bdfSopenharmony_ci 126f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "Failed to load program"); 127f08c3bdfSopenharmony_ci return ret; 128f08c3bdfSopenharmony_ci} 129f08c3bdfSopenharmony_ci 130f08c3bdfSopenharmony_civoid bpf_run_prog(const int prog_fd, 131f08c3bdfSopenharmony_ci const char *const msg, const size_t msg_len) 132f08c3bdfSopenharmony_ci{ 133f08c3bdfSopenharmony_ci int sk[2]; 134f08c3bdfSopenharmony_ci 135f08c3bdfSopenharmony_ci SAFE_SOCKETPAIR(AF_UNIX, SOCK_DGRAM, 0, sk); 136f08c3bdfSopenharmony_ci SAFE_SETSOCKOPT(sk[1], SOL_SOCKET, SO_ATTACH_BPF, 137f08c3bdfSopenharmony_ci &prog_fd, sizeof(prog_fd)); 138f08c3bdfSopenharmony_ci 139f08c3bdfSopenharmony_ci SAFE_WRITE(SAFE_WRITE_ALL, sk[0], msg, msg_len); 140f08c3bdfSopenharmony_ci 141f08c3bdfSopenharmony_ci SAFE_CLOSE(sk[0]); 142f08c3bdfSopenharmony_ci SAFE_CLOSE(sk[1]); 143f08c3bdfSopenharmony_ci} 144