Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 371 lines 8.9 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2 3#include <stdlib.h> 4#include <unistd.h> 5#include <fcntl.h> 6#include <stdint.h> 7#include <sys/stat.h> 8#include <stdbool.h> 9#include <linux/bpf.h> 10#include <bpf/libbpf.h> 11#include <bpftool_helpers.h> 12#include <test_progs.h> 13#include <bpf/bpf.h> 14#include "security_bpf_map.skel.h" 15 16#define PROTECTED_MAP_NAME "prot_map" 17#define UNPROTECTED_MAP_NAME "not_prot_map" 18#define BPF_ITER_FILE "bpf_iter_map_elem.bpf.o" 19#define BPFFS_PIN_DIR "/sys/fs/bpf/test_bpftool_map" 20#define INNER_MAP_NAME "inner_map_tt" 21#define OUTER_MAP_NAME "outer_map_tt" 22 23#define MAP_NAME_MAX_LEN 64 24#define PATH_MAX_LEN 128 25 26enum map_protection { 27 PROTECTED, 28 UNPROTECTED 29}; 30 31struct test_desc { 32 char *name; 33 enum map_protection protection; 34 struct bpf_map *map; 35 char *map_name; 36 bool pinned; 37 char pin_path[PATH_MAX_LEN]; 38 bool write_must_fail; 39}; 40 41static struct security_bpf_map *general_setup(void) 42{ 43 struct security_bpf_map *skel; 44 uint32_t key, value; 45 int ret, i; 46 47 skel = security_bpf_map__open_and_load(); 48 if (!ASSERT_OK_PTR(skel, "open and load skeleton")) 49 goto end; 50 51 struct bpf_map *maps[] = {skel->maps.prot_map, skel->maps.not_prot_map}; 52 53 ret = security_bpf_map__attach(skel); 54 if (!ASSERT_OK(ret, "attach maps security programs")) 55 goto end_destroy; 56 57 for (i = 0; i < sizeof(maps)/sizeof(struct bpf_map *); i++) { 58 for (key = 0; key < 2; key++) { 59 int ret = bpf_map__update_elem(maps[i], &key, 60 sizeof(key), &key, sizeof(key), 61 0); 62 if (!ASSERT_OK(ret, "set initial map value")) 63 goto end_destroy; 64 } 65 } 66 67 key = 0; 68 value = 1; 69 ret = bpf_map__update_elem(skel->maps.prot_status_map, &key, 70 sizeof(key), &value, sizeof(value), 0); 71 if (!ASSERT_OK(ret, "configure map protection")) 72 goto end_destroy; 73 74 if (!ASSERT_OK(mkdir(BPFFS_PIN_DIR, S_IFDIR), "create bpffs pin dir")) 75 goto end_destroy; 76 77 return skel; 78end_destroy: 79 security_bpf_map__destroy(skel); 80end: 81 return NULL; 82} 83 84static void general_cleanup(struct security_bpf_map *skel) 85{ 86 rmdir(BPFFS_PIN_DIR); 87 security_bpf_map__destroy(skel); 88} 89 90static void update_test_desc(struct security_bpf_map *skel, 91 struct test_desc *test) 92{ 93 /* Now that the skeleton is loaded, update all missing fields to 94 * have the subtest properly configured 95 */ 96 if (test->protection == PROTECTED) { 97 test->map = skel->maps.prot_map; 98 test->map_name = PROTECTED_MAP_NAME; 99 } else { 100 test->map = skel->maps.not_prot_map; 101 test->map_name = UNPROTECTED_MAP_NAME; 102 } 103} 104 105static int test_setup(struct security_bpf_map *skel, struct test_desc *desc) 106{ 107 int ret; 108 109 update_test_desc(skel, desc); 110 111 if (desc->pinned) { 112 ret = snprintf(desc->pin_path, PATH_MAX_LEN, "%s/%s", BPFFS_PIN_DIR, 113 desc->name); 114 if (!ASSERT_GT(ret, 0, "format pin path")) 115 return 1; 116 ret = bpf_map__pin(desc->map, desc->pin_path); 117 if (!ASSERT_OK(ret, "pin map")) 118 return 1; 119 } 120 121 return 0; 122} 123 124static void test_cleanup(struct test_desc *desc) 125{ 126 if (desc->pinned) 127 bpf_map__unpin(desc->map, NULL); 128} 129 130static int lookup_map_value(char *map_handle) 131{ 132 char cmd[MAX_BPFTOOL_CMD_LEN]; 133 int ret = 0; 134 135 ret = snprintf(cmd, MAX_BPFTOOL_CMD_LEN, "map lookup %s key 0 0 0 0", 136 map_handle); 137 if (!ASSERT_GT(ret, 0, "format map lookup cmd")) 138 return 1; 139 return run_bpftool_command(cmd); 140} 141 142static int read_map_btf_data(char *map_handle) 143{ 144 char cmd[MAX_BPFTOOL_CMD_LEN]; 145 int ret = 0; 146 147 ret = snprintf(cmd, MAX_BPFTOOL_CMD_LEN, "btf dump map %s", 148 map_handle); 149 if (!ASSERT_GT(ret, 0, "format map btf dump cmd")) 150 return 1; 151 return run_bpftool_command(cmd); 152} 153 154static int write_map_value(char *map_handle) 155{ 156 char cmd[MAX_BPFTOOL_CMD_LEN]; 157 int ret = 0; 158 159 ret = snprintf(cmd, MAX_BPFTOOL_CMD_LEN, 160 "map update %s key 0 0 0 0 value 1 1 1 1", map_handle); 161 if (!ASSERT_GT(ret, 0, "format value write cmd")) 162 return 1; 163 return run_bpftool_command(cmd); 164} 165 166static int delete_map_value(char *map_handle) 167{ 168 char cmd[MAX_BPFTOOL_CMD_LEN]; 169 int ret = 0; 170 171 ret = snprintf(cmd, MAX_BPFTOOL_CMD_LEN, 172 "map delete %s key 0 0 0 0", map_handle); 173 if (!ASSERT_GT(ret, 0, "format value deletion cmd")) 174 return 1; 175 return run_bpftool_command(cmd); 176} 177 178static int iterate_on_map_values(char *map_handle, char *iter_pin_path) 179{ 180 char cmd[MAX_BPFTOOL_CMD_LEN]; 181 int ret = 0; 182 183 184 ret = snprintf(cmd, MAX_BPFTOOL_CMD_LEN, "iter pin %s %s map %s", 185 BPF_ITER_FILE, iter_pin_path, map_handle); 186 if (!ASSERT_GT(ret, 0, "format iterator creation cmd")) 187 return 1; 188 ret = run_bpftool_command(cmd); 189 if (ret) 190 return ret; 191 ret = snprintf(cmd, MAP_NAME_MAX_LEN, "cat %s", iter_pin_path); 192 if (ret < 0) 193 goto cleanup; 194 ret = system(cmd); 195 196cleanup: 197 unlink(iter_pin_path); 198 return ret; 199} 200 201static int create_inner_map(void) 202{ 203 char cmd[MAX_BPFTOOL_CMD_LEN]; 204 int ret = 0; 205 206 ret = snprintf( 207 cmd, MAX_BPFTOOL_CMD_LEN, 208 "map create %s/%s type array key 4 value 4 entries 4 name %s", 209 BPFFS_PIN_DIR, INNER_MAP_NAME, INNER_MAP_NAME); 210 if (!ASSERT_GT(ret, 0, "format inner map create cmd")) 211 return 1; 212 return run_bpftool_command(cmd); 213} 214 215static int create_outer_map(void) 216{ 217 char cmd[MAX_BPFTOOL_CMD_LEN]; 218 int ret = 0; 219 220 ret = snprintf( 221 cmd, MAX_BPFTOOL_CMD_LEN, 222 "map create %s/%s type hash_of_maps key 4 value 4 entries 2 name %s inner_map name %s", 223 BPFFS_PIN_DIR, OUTER_MAP_NAME, OUTER_MAP_NAME, INNER_MAP_NAME); 224 if (!ASSERT_GT(ret, 0, "format outer map create cmd")) 225 return 1; 226 return run_bpftool_command(cmd); 227} 228 229static void delete_pinned_map(char *map_name) 230{ 231 char pin_path[PATH_MAX_LEN]; 232 int ret; 233 234 ret = snprintf(pin_path, PATH_MAX_LEN, "%s/%s", BPFFS_PIN_DIR, 235 map_name); 236 if (ret >= 0) 237 unlink(pin_path); 238} 239 240static int add_outer_map_entry(int key) 241{ 242 char cmd[MAX_BPFTOOL_CMD_LEN]; 243 int ret = 0; 244 245 ret = snprintf( 246 cmd, MAX_BPFTOOL_CMD_LEN, 247 "map update pinned %s/%s key %d 0 0 0 value name %s", 248 BPFFS_PIN_DIR, OUTER_MAP_NAME, key, INNER_MAP_NAME); 249 if (!ASSERT_GT(ret, 0, "format outer map value addition cmd")) 250 return 1; 251 return run_bpftool_command(cmd); 252} 253 254static void test_basic_access(struct test_desc *desc) 255{ 256 char map_handle[MAP_NAME_MAX_LEN]; 257 char iter_pin_path[PATH_MAX_LEN]; 258 int ret; 259 260 if (desc->pinned) 261 ret = snprintf(map_handle, MAP_NAME_MAX_LEN, "pinned %s", 262 desc->pin_path); 263 else 264 ret = snprintf(map_handle, MAP_NAME_MAX_LEN, "name %s", 265 desc->map_name); 266 if (!ASSERT_GT(ret, 0, "format map handle")) 267 return; 268 269 ret = lookup_map_value(map_handle); 270 ASSERT_OK(ret, "read map value"); 271 272 ret = read_map_btf_data(map_handle); 273 ASSERT_OK(ret, "read map btf data"); 274 275 ret = write_map_value(map_handle); 276 ASSERT_OK(desc->write_must_fail ? !ret : ret, "write map value"); 277 278 ret = delete_map_value(map_handle); 279 ASSERT_OK(desc->write_must_fail ? !ret : ret, "delete map value"); 280 /* Restore deleted value */ 281 if (!ret) 282 write_map_value(map_handle); 283 284 ret = snprintf(iter_pin_path, PATH_MAX_LEN, "%s/iter", BPFFS_PIN_DIR); 285 if (ASSERT_GT(ret, 0, "format iter pin path")) { 286 ret = iterate_on_map_values(map_handle, iter_pin_path); 287 ASSERT_OK(ret, "iterate on map values"); 288 } 289} 290 291static void test_create_nested_maps(void) 292{ 293 if (!ASSERT_OK(create_inner_map(), "create inner map")) 294 return; 295 if (!ASSERT_OK(create_outer_map(), "create outer map")) 296 goto end_cleanup_inner; 297 ASSERT_OK(add_outer_map_entry(0), "add a first entry in outer map"); 298 ASSERT_OK(add_outer_map_entry(1), "add a second entry in outer map"); 299 ASSERT_NEQ(add_outer_map_entry(2), 0, "add a third entry in outer map"); 300 301 delete_pinned_map(OUTER_MAP_NAME); 302end_cleanup_inner: 303 delete_pinned_map(INNER_MAP_NAME); 304} 305 306static void test_btf_list(void) 307{ 308 ASSERT_OK(run_bpftool_command("btf list"), "list btf data"); 309} 310 311static struct test_desc tests[] = { 312 { 313 .name = "unprotected_unpinned", 314 .protection = UNPROTECTED, 315 .map_name = UNPROTECTED_MAP_NAME, 316 .pinned = false, 317 .write_must_fail = false, 318 }, 319 { 320 .name = "unprotected_pinned", 321 .protection = UNPROTECTED, 322 .map_name = UNPROTECTED_MAP_NAME, 323 .pinned = true, 324 .write_must_fail = false, 325 }, 326 { 327 .name = "protected_unpinned", 328 .protection = PROTECTED, 329 .map_name = UNPROTECTED_MAP_NAME, 330 .pinned = false, 331 .write_must_fail = true, 332 }, 333 { 334 .name = "protected_pinned", 335 .protection = PROTECTED, 336 .map_name = UNPROTECTED_MAP_NAME, 337 .pinned = true, 338 .write_must_fail = true, 339 } 340}; 341 342static const size_t tests_count = ARRAY_SIZE(tests); 343 344void test_bpftool_maps_access(void) 345{ 346 struct security_bpf_map *skel; 347 struct test_desc *current; 348 int i; 349 350 skel = general_setup(); 351 if (!ASSERT_OK_PTR(skel, "prepare programs")) 352 goto cleanup; 353 354 for (i = 0; i < tests_count; i++) { 355 current = &tests[i]; 356 if (!test__start_subtest(current->name)) 357 continue; 358 if (ASSERT_OK(test_setup(skel, current), "subtest setup")) { 359 test_basic_access(current); 360 test_cleanup(current); 361 } 362 } 363 if (test__start_subtest("nested_maps")) 364 test_create_nested_maps(); 365 if (test__start_subtest("btf_list")) 366 test_btf_list(); 367 368cleanup: 369 general_cleanup(skel); 370} 371