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.

Merge tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf

Pull bpf fixes from Alexei Starovoitov:

- Fix use-after-free in libbpf when map is resized (Adin Scannell)

- Fix verifier assumptions about 2nd argument of bpf_sysctl_get_name
(Jerome Marchand)

- Fix verifier assumption of nullness of d_inode in dentry (Song Liu)

- Fix global starvation of LRU map (Willem de Bruijn)

- Fix potential NULL dereference in btf_dump__free (Yuan Chen)

* tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf:
selftests/bpf: adapt one more case in test_lru_map to the new target_free
libbpf: Fix possible use-after-free for externs
selftests/bpf: Convert test_sysctl to prog_tests
bpf: Specify access type of bpf_sysctl_get_name args
libbpf: Fix null pointer dereference in btf_dump__free on allocation failure
bpf: Adjust free target to avoid global starvation of LRU map
bpf: Mark dentry->d_inode as trusted_or_null

+142 -99
+7 -1
Documentation/bpf/map_hash.rst
··· 233 233 other CPUs involved in the following operation attempts: 234 234 235 235 - Attempt to use CPU-local state to batch operations 236 - - Attempt to fetch free nodes from global lists 236 + - Attempt to fetch ``target_free`` free nodes from global lists 237 237 - Attempt to pull any node from a global list and remove it from the hashmap 238 238 - Attempt to pull any node from any CPU's list and remove it from the hashmap 239 + 240 + The number of nodes to borrow from the global list in a batch, ``target_free``, 241 + depends on the size of the map. Larger batch size reduces lock contention, but 242 + may also exhaust the global structure. The value is computed at map init to 243 + avoid exhaustion, by limiting aggregate reservation by all CPUs to half the map 244 + size. With a minimum of a single element and maximum budget of 128 at a time. 239 245 240 246 This algorithm is described visually in the following diagram. See the 241 247 description in commit 3a08c2fd7634 ("bpf: LRU List") for a full explanation of
+3 -3
Documentation/bpf/map_lru_hash_update.dot
··· 35 35 fn_bpf_lru_list_pop_free_to_local [shape=rectangle,fillcolor=2, 36 36 label="Flush local pending, 37 37 Rotate Global list, move 38 - LOCAL_FREE_TARGET 38 + target_free 39 39 from global -> local"] 40 40 // Also corresponds to: 41 41 // fn__local_list_flush() 42 42 // fn_bpf_lru_list_rotate() 43 43 fn___bpf_lru_node_move_to_free[shape=diamond,fillcolor=2, 44 - label="Able to free\nLOCAL_FREE_TARGET\nnodes?"] 44 + label="Able to free\ntarget_free\nnodes?"] 45 45 46 46 fn___bpf_lru_list_shrink_inactive [shape=rectangle,fillcolor=3, 47 47 label="Shrink inactive list 48 48 up to remaining 49 - LOCAL_FREE_TARGET 49 + target_free 50 50 (global LRU -> local)"] 51 51 fn___bpf_lru_list_shrink [shape=diamond,fillcolor=2, 52 52 label="> 0 entries in\nlocal free list?"]
+6 -3
kernel/bpf/bpf_lru_list.c
··· 337 337 list) { 338 338 __bpf_lru_node_move_to_free(l, node, local_free_list(loc_l), 339 339 BPF_LRU_LOCAL_LIST_T_FREE); 340 - if (++nfree == LOCAL_FREE_TARGET) 340 + if (++nfree == lru->target_free) 341 341 break; 342 342 } 343 343 344 - if (nfree < LOCAL_FREE_TARGET) 345 - __bpf_lru_list_shrink(lru, l, LOCAL_FREE_TARGET - nfree, 344 + if (nfree < lru->target_free) 345 + __bpf_lru_list_shrink(lru, l, lru->target_free - nfree, 346 346 local_free_list(loc_l), 347 347 BPF_LRU_LOCAL_LIST_T_FREE); 348 348 ··· 577 577 list_add(&node->list, &l->lists[BPF_LRU_LIST_T_FREE]); 578 578 buf += elem_size; 579 579 } 580 + 581 + lru->target_free = clamp((nr_elems / num_possible_cpus()) / 2, 582 + 1, LOCAL_FREE_TARGET); 580 583 } 581 584 582 585 static void bpf_percpu_lru_populate(struct bpf_lru *lru, void *buf,
+1
kernel/bpf/bpf_lru_list.h
··· 58 58 del_from_htab_func del_from_htab; 59 59 void *del_arg; 60 60 unsigned int hash_offset; 61 + unsigned int target_free; 61 62 unsigned int nr_scans; 62 63 bool percpu; 63 64 };
+1 -1
kernel/bpf/cgroup.c
··· 2134 2134 .gpl_only = false, 2135 2135 .ret_type = RET_INTEGER, 2136 2136 .arg1_type = ARG_PTR_TO_CTX, 2137 - .arg2_type = ARG_PTR_TO_MEM, 2137 + .arg2_type = ARG_PTR_TO_MEM | MEM_WRITE, 2138 2138 .arg3_type = ARG_CONST_SIZE, 2139 2139 .arg4_type = ARG_ANYTHING, 2140 2140 };
+2 -3
kernel/bpf/verifier.c
··· 7027 7027 struct inode *f_inode; 7028 7028 }; 7029 7029 7030 - BTF_TYPE_SAFE_TRUSTED(struct dentry) { 7031 - /* no negative dentry-s in places where bpf can see it */ 7030 + BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct dentry) { 7032 7031 struct inode *d_inode; 7033 7032 }; 7034 7033 ··· 7065 7066 BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct bpf_iter__task)); 7066 7067 BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct linux_binprm)); 7067 7068 BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct file)); 7068 - BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct dentry)); 7069 7069 7070 7070 return btf_nested_type_is_trusted(&env->log, reg, field_name, btf_id, "__safe_trusted"); 7071 7071 } ··· 7074 7076 const char *field_name, u32 btf_id) 7075 7077 { 7076 7078 BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct socket)); 7079 + BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct dentry)); 7077 7080 7078 7081 return btf_nested_type_is_trusted(&env->log, reg, field_name, btf_id, 7079 7082 "__safe_trusted_or_null");
+3
tools/lib/bpf/btf_dump.c
··· 226 226 size_t bkt; 227 227 struct hashmap_entry *cur; 228 228 229 + if (!map) 230 + return; 231 + 229 232 hashmap__for_each_entry(map, cur, bkt) 230 233 free((void *)cur->pkey); 231 234
+7 -3
tools/lib/bpf/libbpf.c
··· 597 597 int sym_idx; 598 598 int btf_id; 599 599 int sec_btf_id; 600 - const char *name; 600 + char *name; 601 601 char *essent_name; 602 602 bool is_set; 603 603 bool is_weak; ··· 4259 4259 return ext->btf_id; 4260 4260 } 4261 4261 t = btf__type_by_id(obj->btf, ext->btf_id); 4262 - ext->name = btf__name_by_offset(obj->btf, t->name_off); 4262 + ext->name = strdup(btf__name_by_offset(obj->btf, t->name_off)); 4263 + if (!ext->name) 4264 + return -ENOMEM; 4263 4265 ext->sym_idx = i; 4264 4266 ext->is_weak = ELF64_ST_BIND(sym->st_info) == STB_WEAK; 4265 4267 ··· 9140 9138 zfree(&obj->btf_custom_path); 9141 9139 zfree(&obj->kconfig); 9142 9140 9143 - for (i = 0; i < obj->nr_extern; i++) 9141 + for (i = 0; i < obj->nr_extern; i++) { 9142 + zfree(&obj->externs[i].name); 9144 9143 zfree(&obj->externs[i].essent_name); 9144 + } 9145 9145 9146 9146 zfree(&obj->externs); 9147 9147 obj->nr_extern = 0;
-1
tools/testing/selftests/bpf/.gitignore
··· 21 21 flow_dissector_load 22 22 test_tcpnotify_user 23 23 test_libbpf 24 - test_sysctl 25 24 xdping 26 25 test_cpp 27 26 *.d
+2 -3
tools/testing/selftests/bpf/Makefile
··· 73 73 # Order correspond to 'make run_tests' order 74 74 TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_progs \ 75 75 test_sockmap \ 76 - test_tcpnotify_user test_sysctl \ 76 + test_tcpnotify_user \ 77 77 test_progs-no_alu32 78 78 TEST_INST_SUBDIRS := no_alu32 79 79 ··· 220 220 $(error Cannot find a vmlinux for VMLINUX_BTF at any of "$(VMLINUX_BTF_PATHS)") 221 221 endif 222 222 223 - # Define simple and short `make test_progs`, `make test_sysctl`, etc targets 223 + # Define simple and short `make test_progs`, `make test_maps`, etc targets 224 224 # to build individual tests. 225 225 # NOTE: Semicolon at the end is critical to override lib.mk's default static 226 226 # rule for binaries. ··· 329 329 $(OUTPUT)/test_sockmap: $(CGROUP_HELPERS) $(TESTING_HELPERS) 330 330 $(OUTPUT)/test_tcpnotify_user: $(CGROUP_HELPERS) $(TESTING_HELPERS) $(TRACE_HELPERS) 331 331 $(OUTPUT)/test_sock_fields: $(CGROUP_HELPERS) $(TESTING_HELPERS) 332 - $(OUTPUT)/test_sysctl: $(CGROUP_HELPERS) $(TESTING_HELPERS) 333 332 $(OUTPUT)/test_tag: $(TESTING_HELPERS) 334 333 $(OUTPUT)/test_lirc_mode2_user: $(TESTING_HELPERS) 335 334 $(OUTPUT)/xdping: $(TESTING_HELPERS)
+16
tools/testing/selftests/bpf/progs/test_global_map_resize.c
··· 32 32 33 33 int percpu_arr[1] SEC(".data.percpu_arr"); 34 34 35 + /* at least one extern is included, to ensure that a specific 36 + * regression is tested whereby resizing resulted in a free-after-use 37 + * bug after type information is invalidated by the resize operation. 38 + * 39 + * There isn't a particularly good API to test for this specific condition, 40 + * but by having externs for the resizing tests it will cover this path. 41 + */ 42 + extern int LINUX_KERNEL_VERSION __kconfig; 43 + long version_sink; 44 + 35 45 SEC("tp/syscalls/sys_enter_getpid") 36 46 int bss_array_sum(void *ctx) 37 47 { ··· 53 43 54 44 for (size_t i = 0; i < bss_array_len; ++i) 55 45 sum += array[i]; 46 + 47 + /* see above; ensure this is not optimized out */ 48 + version_sink = LINUX_KERNEL_VERSION; 56 49 57 50 return 0; 58 51 } ··· 71 58 72 59 for (size_t i = 0; i < data_array_len; ++i) 73 60 sum += my_array[i]; 61 + 62 + /* see above; ensure this is not optimized out */ 63 + version_sink = LINUX_KERNEL_VERSION; 74 64 75 65 return 0; 76 66 }
+18
tools/testing/selftests/bpf/progs/verifier_vfs_accept.c
··· 2 2 /* Copyright (c) 2024 Google LLC. */ 3 3 4 4 #include <vmlinux.h> 5 + #include <errno.h> 5 6 #include <bpf/bpf_helpers.h> 6 7 #include <bpf/bpf_tracing.h> 7 8 ··· 80 79 path = &file->f_path; 81 80 ret = bpf_path_d_path(path, buf, sizeof(buf)); 82 81 __sink(ret); 82 + return 0; 83 + } 84 + 85 + SEC("lsm.s/inode_rename") 86 + __success 87 + int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry, 88 + struct inode *new_dir, struct dentry *new_dentry, 89 + unsigned int flags) 90 + { 91 + struct inode *inode = new_dentry->d_inode; 92 + ino_t ino; 93 + 94 + if (!inode) 95 + return 0; 96 + ino = inode->i_ino; 97 + if (ino == 0) 98 + return -EACCES; 83 99 return 0; 84 100 } 85 101
+15
tools/testing/selftests/bpf/progs/verifier_vfs_reject.c
··· 2 2 /* Copyright (c) 2024 Google LLC. */ 3 3 4 4 #include <vmlinux.h> 5 + #include <errno.h> 5 6 #include <bpf/bpf_helpers.h> 6 7 #include <bpf/bpf_tracing.h> 7 8 #include <linux/limits.h> ··· 159 158 return 0; 160 159 } 161 160 161 + SEC("lsm.s/inode_rename") 162 + __failure __msg("invalid mem access 'trusted_ptr_or_null_'") 163 + int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry, 164 + struct inode *new_dir, struct dentry *new_dentry, 165 + unsigned int flags) 166 + { 167 + struct inode *inode = new_dentry->d_inode; 168 + ino_t ino; 169 + 170 + ino = inode->i_ino; 171 + if (ino == 0) 172 + return -EACCES; 173 + return 0; 174 + } 162 175 char _license[] SEC("license") = "GPL";
+53 -52
tools/testing/selftests/bpf/test_lru_map.c
··· 138 138 return ret; 139 139 } 140 140 141 + /* Derive target_free from map_size, same as bpf_common_lru_populate */ 142 + static unsigned int __tgt_size(unsigned int map_size) 143 + { 144 + return (map_size / nr_cpus) / 2; 145 + } 146 + 147 + /* Inverse of how bpf_common_lru_populate derives target_free from map_size. */ 148 + static unsigned int __map_size(unsigned int tgt_free) 149 + { 150 + return tgt_free * nr_cpus * 2; 151 + } 152 + 141 153 /* Size of the LRU map is 2 142 154 * Add key=1 (+1 key) 143 155 * Add key=2 (+1 key) ··· 243 231 printf("Pass\n"); 244 232 } 245 233 246 - /* Size of the LRU map is 1.5*tgt_free 247 - * Insert 1 to tgt_free (+tgt_free keys) 248 - * Lookup 1 to tgt_free/2 249 - * Insert 1+tgt_free to 2*tgt_free (+tgt_free keys) 250 - * => 1+tgt_free/2 to LOCALFREE_TARGET will be removed by LRU 234 + /* Verify that unreferenced elements are recycled before referenced ones. 235 + * Insert elements. 236 + * Reference a subset of these. 237 + * Insert more, enough to trigger recycling. 238 + * Verify that unreferenced are recycled. 251 239 */ 252 240 static void test_lru_sanity1(int map_type, int map_flags, unsigned int tgt_free) 253 241 { ··· 269 257 batch_size = tgt_free / 2; 270 258 assert(batch_size * 2 == tgt_free); 271 259 272 - map_size = tgt_free + batch_size; 260 + map_size = __map_size(tgt_free) + batch_size; 273 261 lru_map_fd = create_map(map_type, map_flags, map_size); 274 262 assert(lru_map_fd != -1); 275 263 ··· 278 266 279 267 value[0] = 1234; 280 268 281 - /* Insert 1 to tgt_free (+tgt_free keys) */ 282 - end_key = 1 + tgt_free; 269 + /* Insert map_size - batch_size keys */ 270 + end_key = 1 + __map_size(tgt_free); 283 271 for (key = 1; key < end_key; key++) 284 272 assert(!bpf_map_update_elem(lru_map_fd, &key, value, 285 273 BPF_NOEXIST)); 286 274 287 - /* Lookup 1 to tgt_free/2 */ 275 + /* Lookup 1 to batch_size */ 288 276 end_key = 1 + batch_size; 289 277 for (key = 1; key < end_key; key++) { 290 278 assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd, key, value)); ··· 292 280 BPF_NOEXIST)); 293 281 } 294 282 295 - /* Insert 1+tgt_free to 2*tgt_free 296 - * => 1+tgt_free/2 to LOCALFREE_TARGET will be 283 + /* Insert another map_size - batch_size keys 284 + * Map will contain 1 to batch_size plus these latest, i.e., 285 + * => previous 1+batch_size to map_size - batch_size will have been 297 286 * removed by LRU 298 287 */ 299 - key = 1 + tgt_free; 300 - end_key = key + tgt_free; 288 + key = 1 + __map_size(tgt_free); 289 + end_key = key + __map_size(tgt_free); 301 290 for (; key < end_key; key++) { 302 291 assert(!bpf_map_update_elem(lru_map_fd, &key, value, 303 292 BPF_NOEXIST)); ··· 314 301 printf("Pass\n"); 315 302 } 316 303 317 - /* Size of the LRU map 1.5 * tgt_free 318 - * Insert 1 to tgt_free (+tgt_free keys) 319 - * Update 1 to tgt_free/2 320 - * => The original 1 to tgt_free/2 will be removed due to 321 - * the LRU shrink process 322 - * Re-insert 1 to tgt_free/2 again and do a lookup immeidately 323 - * Insert 1+tgt_free to tgt_free*3/2 324 - * Insert 1+tgt_free*3/2 to tgt_free*5/2 325 - * => Key 1+tgt_free to tgt_free*3/2 326 - * will be removed from LRU because it has never 327 - * been lookup and ref bit is not set 304 + /* Verify that insertions exceeding map size will recycle the oldest. 305 + * Verify that unreferenced elements are recycled before referenced. 328 306 */ 329 307 static void test_lru_sanity2(int map_type, int map_flags, unsigned int tgt_free) 330 308 { ··· 338 334 batch_size = tgt_free / 2; 339 335 assert(batch_size * 2 == tgt_free); 340 336 341 - map_size = tgt_free + batch_size; 337 + map_size = __map_size(tgt_free) + batch_size; 342 338 lru_map_fd = create_map(map_type, map_flags, map_size); 343 339 assert(lru_map_fd != -1); 344 340 ··· 347 343 348 344 value[0] = 1234; 349 345 350 - /* Insert 1 to tgt_free (+tgt_free keys) */ 351 - end_key = 1 + tgt_free; 346 + /* Insert map_size - batch_size keys */ 347 + end_key = 1 + __map_size(tgt_free); 352 348 for (key = 1; key < end_key; key++) 353 349 assert(!bpf_map_update_elem(lru_map_fd, &key, value, 354 350 BPF_NOEXIST)); ··· 361 357 * shrink the inactive list to get tgt_free 362 358 * number of free nodes. 363 359 * 364 - * Hence, the oldest key 1 to tgt_free/2 365 - * are removed from the LRU list. 360 + * Hence, the oldest key is removed from the LRU list. 366 361 */ 367 362 key = 1; 368 363 if (map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) { ··· 373 370 BPF_EXIST)); 374 371 } 375 372 376 - /* Re-insert 1 to tgt_free/2 again and do a lookup 377 - * immeidately. 373 + /* Re-insert 1 to batch_size again and do a lookup immediately. 378 374 */ 379 375 end_key = 1 + batch_size; 380 376 value[0] = 4321; ··· 389 387 390 388 value[0] = 1234; 391 389 392 - /* Insert 1+tgt_free to tgt_free*3/2 */ 393 - end_key = 1 + tgt_free + batch_size; 394 - for (key = 1 + tgt_free; key < end_key; key++) 390 + /* Insert batch_size new elements */ 391 + key = 1 + __map_size(tgt_free); 392 + end_key = key + batch_size; 393 + for (; key < end_key; key++) 395 394 /* These newly added but not referenced keys will be 396 395 * gone during the next LRU shrink. 397 396 */ 398 397 assert(!bpf_map_update_elem(lru_map_fd, &key, value, 399 398 BPF_NOEXIST)); 400 399 401 - /* Insert 1+tgt_free*3/2 to tgt_free*5/2 */ 402 - end_key = key + tgt_free; 400 + /* Insert map_size - batch_size elements */ 401 + end_key += __map_size(tgt_free); 403 402 for (; key < end_key; key++) { 404 403 assert(!bpf_map_update_elem(lru_map_fd, &key, value, 405 404 BPF_NOEXIST)); ··· 416 413 printf("Pass\n"); 417 414 } 418 415 419 - /* Size of the LRU map is 2*tgt_free 420 - * It is to test the active/inactive list rotation 421 - * Insert 1 to 2*tgt_free (+2*tgt_free keys) 422 - * Lookup key 1 to tgt_free*3/2 423 - * Add 1+2*tgt_free to tgt_free*5/2 (+tgt_free/2 keys) 424 - * => key 1+tgt_free*3/2 to 2*tgt_free are removed from LRU 416 + /* Test the active/inactive list rotation 417 + * 418 + * Fill the whole map, deplete the free list. 419 + * Reference all except the last lru->target_free elements. 420 + * Insert lru->target_free new elements. This triggers one shrink. 421 + * Verify that the non-referenced elements are replaced. 425 422 */ 426 423 static void test_lru_sanity3(int map_type, int map_flags, unsigned int tgt_free) 427 424 { ··· 440 437 441 438 assert(sched_next_online(0, &next_cpu) != -1); 442 439 443 - batch_size = tgt_free / 2; 444 - assert(batch_size * 2 == tgt_free); 440 + batch_size = __tgt_size(tgt_free); 445 441 446 442 map_size = tgt_free * 2; 447 443 lru_map_fd = create_map(map_type, map_flags, map_size); ··· 451 449 452 450 value[0] = 1234; 453 451 454 - /* Insert 1 to 2*tgt_free (+2*tgt_free keys) */ 455 - end_key = 1 + (2 * tgt_free); 452 + /* Fill the map */ 453 + end_key = 1 + map_size; 456 454 for (key = 1; key < end_key; key++) 457 455 assert(!bpf_map_update_elem(lru_map_fd, &key, value, 458 456 BPF_NOEXIST)); 459 457 460 - /* Lookup key 1 to tgt_free*3/2 */ 461 - end_key = tgt_free + batch_size; 458 + /* Reference all but the last batch_size */ 459 + end_key = 1 + map_size - batch_size; 462 460 for (key = 1; key < end_key; key++) { 463 461 assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd, key, value)); 464 462 assert(!bpf_map_update_elem(expected_map_fd, &key, value, 465 463 BPF_NOEXIST)); 466 464 } 467 465 468 - /* Add 1+2*tgt_free to tgt_free*5/2 469 - * (+tgt_free/2 keys) 470 - */ 466 + /* Insert new batch_size: replaces the non-referenced elements */ 471 467 key = 2 * tgt_free + 1; 472 468 end_key = key + batch_size; 473 469 for (; key < end_key; key++) { ··· 500 500 lru_map_fd = create_map(map_type, map_flags, 501 501 3 * tgt_free * nr_cpus); 502 502 else 503 - lru_map_fd = create_map(map_type, map_flags, 3 * tgt_free); 503 + lru_map_fd = create_map(map_type, map_flags, 504 + 3 * __map_size(tgt_free)); 504 505 assert(lru_map_fd != -1); 505 506 506 507 expected_map_fd = create_map(BPF_MAP_TYPE_HASH, 0,
+8 -29
tools/testing/selftests/bpf/test_sysctl.c tools/testing/selftests/bpf/prog_tests/test_sysctl.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 // Copyright (c) 2019 Facebook 3 3 4 - #include <fcntl.h> 5 - #include <stdint.h> 6 - #include <stdio.h> 7 - #include <stdlib.h> 8 - #include <string.h> 9 - #include <unistd.h> 10 - 11 - #include <linux/filter.h> 12 - 13 - #include <bpf/bpf.h> 14 - #include <bpf/libbpf.h> 15 - 16 - #include <bpf/bpf_endian.h> 17 - #include "bpf_util.h" 4 + #include "test_progs.h" 18 5 #include "cgroup_helpers.h" 19 - #include "testing_helpers.h" 20 6 21 7 #define CG_PATH "/foo" 22 8 #define MAX_INSNS 512 ··· 1594 1608 return fails ? -1 : 0; 1595 1609 } 1596 1610 1597 - int main(int argc, char **argv) 1611 + void test_sysctl(void) 1598 1612 { 1599 - int cgfd = -1; 1600 - int err = 0; 1613 + int cgfd; 1601 1614 1602 1615 cgfd = cgroup_setup_and_join(CG_PATH); 1603 - if (cgfd < 0) 1604 - goto err; 1616 + if (!ASSERT_OK_FD(cgfd < 0, "create_cgroup")) 1617 + goto out; 1605 1618 1606 - /* Use libbpf 1.0 API mode */ 1607 - libbpf_set_strict_mode(LIBBPF_STRICT_ALL); 1619 + if (!ASSERT_OK(run_tests(cgfd), "run_tests")) 1620 + goto out; 1608 1621 1609 - if (run_tests(cgfd)) 1610 - goto err; 1611 - 1612 - goto out; 1613 - err: 1614 - err = -1; 1615 1622 out: 1616 1623 close(cgfd); 1617 1624 cleanup_cgroup_environment(); 1618 - return err; 1625 + return; 1619 1626 }