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 https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next

Andrii Nakryiko says:

====================
pull-request: bpf-next 2023-03-08

We've added 23 non-merge commits during the last 2 day(s) which contain
a total of 28 files changed, 414 insertions(+), 104 deletions(-).

The main changes are:

1) Add more precise memory usage reporting for all BPF map types,
from Yafang Shao.

2) Add ARM32 USDT support to libbpf, from Puranjay Mohan.

3) Fix BTF_ID_LIST size causing problems in !CONFIG_DEBUG_INFO_BTF,
from Nathan Chancellor.

4) IMA selftests fix, from Roberto Sassu.

5) libbpf fix in APK support code, from Daniel Müller.

* https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next: (23 commits)
selftests/bpf: Fix IMA test
libbpf: USDT arm arg parsing support
libbpf: Refactor parse_usdt_arg() to re-use code
libbpf: Fix theoretical u32 underflow in find_cd() function
bpf: enforce all maps having memory usage callback
bpf: offload map memory usage
bpf, net: xskmap memory usage
bpf, net: sock_map memory usage
bpf, net: bpf_local_storage memory usage
bpf: local_storage memory usage
bpf: bpf_struct_ops memory usage
bpf: queue_stack_maps memory usage
bpf: devmap memory usage
bpf: cpumap memory usage
bpf: bloom_filter memory usage
bpf: ringbuf memory usage
bpf: reuseport_array memory usage
bpf: stackmap memory usage
bpf: arraymap memory usage
bpf: hashtab memory usage
...
====================

Link: https://lore.kernel.org/r/20230308193533.1671597-1-andrii@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+414 -104
+8
include/linux/bpf.h
··· 161 161 bpf_callback_t callback_fn, 162 162 void *callback_ctx, u64 flags); 163 163 164 + u64 (*map_mem_usage)(const struct bpf_map *map); 165 + 164 166 /* BTF id of struct allocated by map_alloc */ 165 167 int *map_btf_id; 166 168 ··· 2624 2622 2625 2623 struct bpf_map *bpf_map_offload_map_alloc(union bpf_attr *attr); 2626 2624 void bpf_map_offload_map_free(struct bpf_map *map); 2625 + u64 bpf_map_offload_map_mem_usage(const struct bpf_map *map); 2627 2626 int bpf_prog_test_run_syscall(struct bpf_prog *prog, 2628 2627 const union bpf_attr *kattr, 2629 2628 union bpf_attr __user *uattr); ··· 2694 2691 2695 2692 static inline void bpf_map_offload_map_free(struct bpf_map *map) 2696 2693 { 2694 + } 2695 + 2696 + static inline u64 bpf_map_offload_map_mem_usage(const struct bpf_map *map) 2697 + { 2698 + return 0; 2697 2699 } 2698 2700 2699 2701 static inline int bpf_prog_test_run_syscall(struct bpf_prog *prog,
+1
include/linux/bpf_local_storage.h
··· 164 164 void *value, u64 map_flags, gfp_t gfp_flags); 165 165 166 166 void bpf_local_storage_free_rcu(struct rcu_head *rcu); 167 + u64 bpf_local_storage_map_mem_usage(const struct bpf_map *map); 167 168 168 169 #endif /* _BPF_LOCAL_STORAGE_H */
+1 -1
include/linux/btf_ids.h
··· 204 204 205 205 #else 206 206 207 - #define BTF_ID_LIST(name) static u32 __maybe_unused name[16]; 207 + #define BTF_ID_LIST(name) static u32 __maybe_unused name[64]; 208 208 #define BTF_ID(prefix, name) 209 209 #define BTF_ID_FLAGS(prefix, name, ...) 210 210 #define BTF_ID_UNUSED
+1
include/net/xdp_sock.h
··· 38 38 struct xsk_map { 39 39 struct bpf_map map; 40 40 spinlock_t lock; /* Synchronize map updates */ 41 + atomic_t count; 41 42 struct xdp_sock __rcu *xsk_map[]; 42 43 }; 43 44
+28
kernel/bpf/arraymap.c
··· 721 721 return num_elems; 722 722 } 723 723 724 + static u64 array_map_mem_usage(const struct bpf_map *map) 725 + { 726 + struct bpf_array *array = container_of(map, struct bpf_array, map); 727 + bool percpu = map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY; 728 + u32 elem_size = array->elem_size; 729 + u64 entries = map->max_entries; 730 + u64 usage = sizeof(*array); 731 + 732 + if (percpu) { 733 + usage += entries * sizeof(void *); 734 + usage += entries * elem_size * num_possible_cpus(); 735 + } else { 736 + if (map->map_flags & BPF_F_MMAPABLE) { 737 + usage = PAGE_ALIGN(usage); 738 + usage += PAGE_ALIGN(entries * elem_size); 739 + } else { 740 + usage += entries * elem_size; 741 + } 742 + } 743 + return usage; 744 + } 745 + 724 746 BTF_ID_LIST_SINGLE(array_map_btf_ids, struct, bpf_array) 725 747 const struct bpf_map_ops array_map_ops = { 726 748 .map_meta_equal = array_map_meta_equal, ··· 764 742 .map_update_batch = generic_map_update_batch, 765 743 .map_set_for_each_callback_args = map_set_for_each_callback_args, 766 744 .map_for_each_callback = bpf_for_each_array_elem, 745 + .map_mem_usage = array_map_mem_usage, 767 746 .map_btf_id = &array_map_btf_ids[0], 768 747 .iter_seq_info = &iter_seq_info, 769 748 }; ··· 785 762 .map_update_batch = generic_map_update_batch, 786 763 .map_set_for_each_callback_args = map_set_for_each_callback_args, 787 764 .map_for_each_callback = bpf_for_each_array_elem, 765 + .map_mem_usage = array_map_mem_usage, 788 766 .map_btf_id = &array_map_btf_ids[0], 789 767 .iter_seq_info = &iter_seq_info, 790 768 }; ··· 1180 1156 .map_fd_sys_lookup_elem = prog_fd_array_sys_lookup_elem, 1181 1157 .map_release_uref = prog_array_map_clear, 1182 1158 .map_seq_show_elem = prog_array_map_seq_show_elem, 1159 + .map_mem_usage = array_map_mem_usage, 1183 1160 .map_btf_id = &array_map_btf_ids[0], 1184 1161 }; 1185 1162 ··· 1282 1257 .map_fd_put_ptr = perf_event_fd_array_put_ptr, 1283 1258 .map_release = perf_event_fd_array_release, 1284 1259 .map_check_btf = map_check_no_btf, 1260 + .map_mem_usage = array_map_mem_usage, 1285 1261 .map_btf_id = &array_map_btf_ids[0], 1286 1262 }; 1287 1263 ··· 1317 1291 .map_fd_get_ptr = cgroup_fd_array_get_ptr, 1318 1292 .map_fd_put_ptr = cgroup_fd_array_put_ptr, 1319 1293 .map_check_btf = map_check_no_btf, 1294 + .map_mem_usage = array_map_mem_usage, 1320 1295 .map_btf_id = &array_map_btf_ids[0], 1321 1296 }; 1322 1297 #endif ··· 1406 1379 .map_lookup_batch = generic_map_lookup_batch, 1407 1380 .map_update_batch = generic_map_update_batch, 1408 1381 .map_check_btf = map_check_no_btf, 1382 + .map_mem_usage = array_map_mem_usage, 1409 1383 .map_btf_id = &array_map_btf_ids[0], 1410 1384 };
+12
kernel/bpf/bloom_filter.c
··· 193 193 return btf_type_is_void(key_type) ? 0 : -EINVAL; 194 194 } 195 195 196 + static u64 bloom_map_mem_usage(const struct bpf_map *map) 197 + { 198 + struct bpf_bloom_filter *bloom; 199 + u64 bitset_bytes; 200 + 201 + bloom = container_of(map, struct bpf_bloom_filter, map); 202 + bitset_bytes = BITS_TO_BYTES((u64)bloom->bitset_mask + 1); 203 + bitset_bytes = roundup(bitset_bytes, sizeof(unsigned long)); 204 + return sizeof(*bloom) + bitset_bytes; 205 + } 206 + 196 207 BTF_ID_LIST_SINGLE(bpf_bloom_map_btf_ids, struct, bpf_bloom_filter) 197 208 const struct bpf_map_ops bloom_filter_map_ops = { 198 209 .map_meta_equal = bpf_map_meta_equal, ··· 217 206 .map_update_elem = bloom_map_update_elem, 218 207 .map_delete_elem = bloom_map_delete_elem, 219 208 .map_check_btf = bloom_map_check_btf, 209 + .map_mem_usage = bloom_map_mem_usage, 220 210 .map_btf_id = &bpf_bloom_map_btf_ids[0], 221 211 };
+1
kernel/bpf/bpf_cgrp_storage.c
··· 221 221 .map_update_elem = bpf_cgrp_storage_update_elem, 222 222 .map_delete_elem = bpf_cgrp_storage_delete_elem, 223 223 .map_check_btf = bpf_local_storage_map_check_btf, 224 + .map_mem_usage = bpf_local_storage_map_mem_usage, 224 225 .map_btf_id = &bpf_local_storage_map_btf_id[0], 225 226 .map_owner_storage_ptr = cgroup_storage_ptr, 226 227 };
+1
kernel/bpf/bpf_inode_storage.c
··· 223 223 .map_update_elem = bpf_fd_inode_storage_update_elem, 224 224 .map_delete_elem = bpf_fd_inode_storage_delete_elem, 225 225 .map_check_btf = bpf_local_storage_map_check_btf, 226 + .map_mem_usage = bpf_local_storage_map_mem_usage, 226 227 .map_btf_id = &bpf_local_storage_map_btf_id[0], 227 228 .map_owner_storage_ptr = inode_storage_ptr, 228 229 };
+10
kernel/bpf/bpf_local_storage.c
··· 685 685 return free_storage; 686 686 } 687 687 688 + u64 bpf_local_storage_map_mem_usage(const struct bpf_map *map) 689 + { 690 + struct bpf_local_storage_map *smap = (struct bpf_local_storage_map *)map; 691 + u64 usage = sizeof(*smap); 692 + 693 + /* The dynamically callocated selems are not counted currently. */ 694 + usage += sizeof(*smap->buckets) * (1ULL << smap->bucket_log); 695 + return usage; 696 + } 697 + 688 698 struct bpf_map * 689 699 bpf_local_storage_map_alloc(union bpf_attr *attr, 690 700 struct bpf_local_storage_cache *cache)
+16
kernel/bpf/bpf_struct_ops.c
··· 641 641 return map; 642 642 } 643 643 644 + static u64 bpf_struct_ops_map_mem_usage(const struct bpf_map *map) 645 + { 646 + struct bpf_struct_ops_map *st_map = (struct bpf_struct_ops_map *)map; 647 + const struct bpf_struct_ops *st_ops = st_map->st_ops; 648 + const struct btf_type *vt = st_ops->value_type; 649 + u64 usage; 650 + 651 + usage = sizeof(*st_map) + 652 + vt->size - sizeof(struct bpf_struct_ops_value); 653 + usage += vt->size; 654 + usage += btf_type_vlen(vt) * sizeof(struct bpf_links *); 655 + usage += PAGE_SIZE; 656 + return usage; 657 + } 658 + 644 659 BTF_ID_LIST_SINGLE(bpf_struct_ops_map_btf_ids, struct, bpf_struct_ops_map) 645 660 const struct bpf_map_ops bpf_struct_ops_map_ops = { 646 661 .map_alloc_check = bpf_struct_ops_map_alloc_check, ··· 666 651 .map_delete_elem = bpf_struct_ops_map_delete_elem, 667 652 .map_update_elem = bpf_struct_ops_map_update_elem, 668 653 .map_seq_show_elem = bpf_struct_ops_map_seq_show_elem, 654 + .map_mem_usage = bpf_struct_ops_map_mem_usage, 669 655 .map_btf_id = &bpf_struct_ops_map_btf_ids[0], 670 656 }; 671 657
+1
kernel/bpf/bpf_task_storage.c
··· 335 335 .map_update_elem = bpf_pid_task_storage_update_elem, 336 336 .map_delete_elem = bpf_pid_task_storage_delete_elem, 337 337 .map_check_btf = bpf_local_storage_map_check_btf, 338 + .map_mem_usage = bpf_local_storage_map_mem_usage, 338 339 .map_btf_id = &bpf_local_storage_map_btf_id[0], 339 340 .map_owner_storage_ptr = task_storage_ptr, 340 341 };
+10
kernel/bpf/cpumap.c
··· 673 673 __cpu_map_lookup_elem); 674 674 } 675 675 676 + static u64 cpu_map_mem_usage(const struct bpf_map *map) 677 + { 678 + u64 usage = sizeof(struct bpf_cpu_map); 679 + 680 + /* Currently the dynamically allocated elements are not counted */ 681 + usage += (u64)map->max_entries * sizeof(struct bpf_cpu_map_entry *); 682 + return usage; 683 + } 684 + 676 685 BTF_ID_LIST_SINGLE(cpu_map_btf_ids, struct, bpf_cpu_map) 677 686 const struct bpf_map_ops cpu_map_ops = { 678 687 .map_meta_equal = bpf_map_meta_equal, ··· 692 683 .map_lookup_elem = cpu_map_lookup_elem, 693 684 .map_get_next_key = cpu_map_get_next_key, 694 685 .map_check_btf = map_check_no_btf, 686 + .map_mem_usage = cpu_map_mem_usage, 695 687 .map_btf_id = &cpu_map_btf_ids[0], 696 688 .map_redirect = cpu_map_redirect, 697 689 };
+24 -2
kernel/bpf/devmap.c
··· 819 819 return -EINVAL; 820 820 821 821 old_dev = unrcu_pointer(xchg(&dtab->netdev_map[k], NULL)); 822 - if (old_dev) 822 + if (old_dev) { 823 823 call_rcu(&old_dev->rcu, __dev_map_entry_free); 824 + atomic_dec((atomic_t *)&dtab->items); 825 + } 824 826 return 0; 825 827 } 826 828 ··· 933 931 old_dev = unrcu_pointer(xchg(&dtab->netdev_map[i], RCU_INITIALIZER(dev))); 934 932 if (old_dev) 935 933 call_rcu(&old_dev->rcu, __dev_map_entry_free); 934 + else 935 + atomic_inc((atomic_t *)&dtab->items); 936 936 937 937 return 0; 938 938 } ··· 1020 1016 __dev_map_hash_lookup_elem); 1021 1017 } 1022 1018 1019 + static u64 dev_map_mem_usage(const struct bpf_map *map) 1020 + { 1021 + struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map); 1022 + u64 usage = sizeof(struct bpf_dtab); 1023 + 1024 + if (map->map_type == BPF_MAP_TYPE_DEVMAP_HASH) 1025 + usage += (u64)dtab->n_buckets * sizeof(struct hlist_head); 1026 + else 1027 + usage += (u64)map->max_entries * sizeof(struct bpf_dtab_netdev *); 1028 + usage += atomic_read((atomic_t *)&dtab->items) * 1029 + (u64)sizeof(struct bpf_dtab_netdev); 1030 + return usage; 1031 + } 1032 + 1023 1033 BTF_ID_LIST_SINGLE(dev_map_btf_ids, struct, bpf_dtab) 1024 1034 const struct bpf_map_ops dev_map_ops = { 1025 1035 .map_meta_equal = bpf_map_meta_equal, ··· 1044 1026 .map_update_elem = dev_map_update_elem, 1045 1027 .map_delete_elem = dev_map_delete_elem, 1046 1028 .map_check_btf = map_check_no_btf, 1029 + .map_mem_usage = dev_map_mem_usage, 1047 1030 .map_btf_id = &dev_map_btf_ids[0], 1048 1031 .map_redirect = dev_map_redirect, 1049 1032 }; ··· 1058 1039 .map_update_elem = dev_map_hash_update_elem, 1059 1040 .map_delete_elem = dev_map_hash_delete_elem, 1060 1041 .map_check_btf = map_check_no_btf, 1042 + .map_mem_usage = dev_map_mem_usage, 1061 1043 .map_btf_id = &dev_map_btf_ids[0], 1062 1044 .map_redirect = dev_hash_map_redirect, 1063 1045 }; ··· 1129 1109 if (!dev || netdev != dev->dev) 1130 1110 continue; 1131 1111 odev = unrcu_pointer(cmpxchg(&dtab->netdev_map[i], RCU_INITIALIZER(dev), NULL)); 1132 - if (dev == odev) 1112 + if (dev == odev) { 1133 1113 call_rcu(&dev->rcu, 1134 1114 __dev_map_entry_free); 1115 + atomic_dec((atomic_t *)&dtab->items); 1116 + } 1135 1117 } 1136 1118 } 1137 1119 rcu_read_unlock();
+43
kernel/bpf/hashtab.c
··· 2190 2190 return num_elems; 2191 2191 } 2192 2192 2193 + static u64 htab_map_mem_usage(const struct bpf_map *map) 2194 + { 2195 + struct bpf_htab *htab = container_of(map, struct bpf_htab, map); 2196 + u32 value_size = round_up(htab->map.value_size, 8); 2197 + bool prealloc = htab_is_prealloc(htab); 2198 + bool percpu = htab_is_percpu(htab); 2199 + bool lru = htab_is_lru(htab); 2200 + u64 num_entries; 2201 + u64 usage = sizeof(struct bpf_htab); 2202 + 2203 + usage += sizeof(struct bucket) * htab->n_buckets; 2204 + usage += sizeof(int) * num_possible_cpus() * HASHTAB_MAP_LOCK_COUNT; 2205 + if (prealloc) { 2206 + num_entries = map->max_entries; 2207 + if (htab_has_extra_elems(htab)) 2208 + num_entries += num_possible_cpus(); 2209 + 2210 + usage += htab->elem_size * num_entries; 2211 + 2212 + if (percpu) 2213 + usage += value_size * num_possible_cpus() * num_entries; 2214 + else if (!lru) 2215 + usage += sizeof(struct htab_elem *) * num_possible_cpus(); 2216 + } else { 2217 + #define LLIST_NODE_SZ sizeof(struct llist_node) 2218 + 2219 + num_entries = htab->use_percpu_counter ? 2220 + percpu_counter_sum(&htab->pcount) : 2221 + atomic_read(&htab->count); 2222 + usage += (htab->elem_size + LLIST_NODE_SZ) * num_entries; 2223 + if (percpu) { 2224 + usage += (LLIST_NODE_SZ + sizeof(void *)) * num_entries; 2225 + usage += value_size * num_possible_cpus() * num_entries; 2226 + } 2227 + } 2228 + return usage; 2229 + } 2230 + 2193 2231 BTF_ID_LIST_SINGLE(htab_map_btf_ids, struct, bpf_htab) 2194 2232 const struct bpf_map_ops htab_map_ops = { 2195 2233 .map_meta_equal = bpf_map_meta_equal, ··· 2244 2206 .map_seq_show_elem = htab_map_seq_show_elem, 2245 2207 .map_set_for_each_callback_args = map_set_for_each_callback_args, 2246 2208 .map_for_each_callback = bpf_for_each_hash_elem, 2209 + .map_mem_usage = htab_map_mem_usage, 2247 2210 BATCH_OPS(htab), 2248 2211 .map_btf_id = &htab_map_btf_ids[0], 2249 2212 .iter_seq_info = &iter_seq_info, ··· 2266 2227 .map_seq_show_elem = htab_map_seq_show_elem, 2267 2228 .map_set_for_each_callback_args = map_set_for_each_callback_args, 2268 2229 .map_for_each_callback = bpf_for_each_hash_elem, 2230 + .map_mem_usage = htab_map_mem_usage, 2269 2231 BATCH_OPS(htab_lru), 2270 2232 .map_btf_id = &htab_map_btf_ids[0], 2271 2233 .iter_seq_info = &iter_seq_info, ··· 2418 2378 .map_seq_show_elem = htab_percpu_map_seq_show_elem, 2419 2379 .map_set_for_each_callback_args = map_set_for_each_callback_args, 2420 2380 .map_for_each_callback = bpf_for_each_hash_elem, 2381 + .map_mem_usage = htab_map_mem_usage, 2421 2382 BATCH_OPS(htab_percpu), 2422 2383 .map_btf_id = &htab_map_btf_ids[0], 2423 2384 .iter_seq_info = &iter_seq_info, ··· 2438 2397 .map_seq_show_elem = htab_percpu_map_seq_show_elem, 2439 2398 .map_set_for_each_callback_args = map_set_for_each_callback_args, 2440 2399 .map_for_each_callback = bpf_for_each_hash_elem, 2400 + .map_mem_usage = htab_map_mem_usage, 2441 2401 BATCH_OPS(htab_lru_percpu), 2442 2402 .map_btf_id = &htab_map_btf_ids[0], 2443 2403 .iter_seq_info = &iter_seq_info, ··· 2576 2534 .map_fd_sys_lookup_elem = bpf_map_fd_sys_lookup_elem, 2577 2535 .map_gen_lookup = htab_of_map_gen_lookup, 2578 2536 .map_check_btf = map_check_no_btf, 2537 + .map_mem_usage = htab_map_mem_usage, 2579 2538 BATCH_OPS(htab), 2580 2539 .map_btf_id = &htab_map_btf_ids[0], 2581 2540 };
+7
kernel/bpf/local_storage.c
··· 446 446 rcu_read_unlock(); 447 447 } 448 448 449 + static u64 cgroup_storage_map_usage(const struct bpf_map *map) 450 + { 451 + /* Currently the dynamically allocated elements are not counted. */ 452 + return sizeof(struct bpf_cgroup_storage_map); 453 + } 454 + 449 455 BTF_ID_LIST_SINGLE(cgroup_storage_map_btf_ids, struct, 450 456 bpf_cgroup_storage_map) 451 457 const struct bpf_map_ops cgroup_storage_map_ops = { ··· 463 457 .map_delete_elem = cgroup_storage_delete_elem, 464 458 .map_check_btf = cgroup_storage_check_btf, 465 459 .map_seq_show_elem = cgroup_storage_seq_show_elem, 460 + .map_mem_usage = cgroup_storage_map_usage, 466 461 .map_btf_id = &cgroup_storage_map_btf_ids[0], 467 462 }; 468 463
+11
kernel/bpf/lpm_trie.c
··· 720 720 -EINVAL : 0; 721 721 } 722 722 723 + static u64 trie_mem_usage(const struct bpf_map *map) 724 + { 725 + struct lpm_trie *trie = container_of(map, struct lpm_trie, map); 726 + u64 elem_size; 727 + 728 + elem_size = sizeof(struct lpm_trie_node) + trie->data_size + 729 + trie->map.value_size; 730 + return elem_size * READ_ONCE(trie->n_entries); 731 + } 732 + 723 733 BTF_ID_LIST_SINGLE(trie_map_btf_ids, struct, lpm_trie) 724 734 const struct bpf_map_ops trie_map_ops = { 725 735 .map_meta_equal = bpf_map_meta_equal, ··· 743 733 .map_update_batch = generic_map_update_batch, 744 734 .map_delete_batch = generic_map_delete_batch, 745 735 .map_check_btf = trie_check_btf, 736 + .map_mem_usage = trie_mem_usage, 746 737 .map_btf_id = &trie_map_btf_ids[0], 747 738 };
+6
kernel/bpf/offload.c
··· 563 563 bpf_map_area_free(offmap); 564 564 } 565 565 566 + u64 bpf_map_offload_map_mem_usage(const struct bpf_map *map) 567 + { 568 + /* The memory dynamically allocated in netdev dev_ops is not counted */ 569 + return sizeof(struct bpf_offloaded_map); 570 + } 571 + 566 572 int bpf_map_offload_lookup_elem(struct bpf_map *map, void *key, void *value) 567 573 { 568 574 struct bpf_offloaded_map *offmap = map_to_offmap(map);
+10
kernel/bpf/queue_stack_maps.c
··· 246 246 return -EINVAL; 247 247 } 248 248 249 + static u64 queue_stack_map_mem_usage(const struct bpf_map *map) 250 + { 251 + u64 usage = sizeof(struct bpf_queue_stack); 252 + 253 + usage += ((u64)map->max_entries + 1) * map->value_size; 254 + return usage; 255 + } 256 + 249 257 BTF_ID_LIST_SINGLE(queue_map_btf_ids, struct, bpf_queue_stack) 250 258 const struct bpf_map_ops queue_map_ops = { 251 259 .map_meta_equal = bpf_map_meta_equal, ··· 267 259 .map_pop_elem = queue_map_pop_elem, 268 260 .map_peek_elem = queue_map_peek_elem, 269 261 .map_get_next_key = queue_stack_map_get_next_key, 262 + .map_mem_usage = queue_stack_map_mem_usage, 270 263 .map_btf_id = &queue_map_btf_ids[0], 271 264 }; 272 265 ··· 283 274 .map_pop_elem = stack_map_pop_elem, 284 275 .map_peek_elem = stack_map_peek_elem, 285 276 .map_get_next_key = queue_stack_map_get_next_key, 277 + .map_mem_usage = queue_stack_map_mem_usage, 286 278 .map_btf_id = &queue_map_btf_ids[0], 287 279 };
+8
kernel/bpf/reuseport_array.c
··· 335 335 return 0; 336 336 } 337 337 338 + static u64 reuseport_array_mem_usage(const struct bpf_map *map) 339 + { 340 + struct reuseport_array *array; 341 + 342 + return struct_size(array, ptrs, map->max_entries); 343 + } 344 + 338 345 BTF_ID_LIST_SINGLE(reuseport_array_map_btf_ids, struct, reuseport_array) 339 346 const struct bpf_map_ops reuseport_array_ops = { 340 347 .map_meta_equal = bpf_map_meta_equal, ··· 351 344 .map_lookup_elem = reuseport_array_lookup_elem, 352 345 .map_get_next_key = reuseport_array_get_next_key, 353 346 .map_delete_elem = reuseport_array_delete_elem, 347 + .map_mem_usage = reuseport_array_mem_usage, 354 348 .map_btf_id = &reuseport_array_map_btf_ids[0], 355 349 };
+19 -1
kernel/bpf/ringbuf.c
··· 19 19 (offsetof(struct bpf_ringbuf, consumer_pos) >> PAGE_SHIFT) 20 20 /* consumer page and producer page */ 21 21 #define RINGBUF_POS_PAGES 2 22 + #define RINGBUF_NR_META_PAGES (RINGBUF_PGOFF + RINGBUF_POS_PAGES) 22 23 23 24 #define RINGBUF_MAX_RECORD_SZ (UINT_MAX/4) 24 25 ··· 97 96 { 98 97 const gfp_t flags = GFP_KERNEL_ACCOUNT | __GFP_RETRY_MAYFAIL | 99 98 __GFP_NOWARN | __GFP_ZERO; 100 - int nr_meta_pages = RINGBUF_PGOFF + RINGBUF_POS_PAGES; 99 + int nr_meta_pages = RINGBUF_NR_META_PAGES; 101 100 int nr_data_pages = data_sz >> PAGE_SHIFT; 102 101 int nr_pages = nr_meta_pages + nr_data_pages; 103 102 struct page **pages, *page; ··· 337 336 return 0; 338 337 } 339 338 339 + static u64 ringbuf_map_mem_usage(const struct bpf_map *map) 340 + { 341 + struct bpf_ringbuf *rb; 342 + int nr_data_pages; 343 + int nr_meta_pages; 344 + u64 usage = sizeof(struct bpf_ringbuf_map); 345 + 346 + rb = container_of(map, struct bpf_ringbuf_map, map)->rb; 347 + usage += (u64)rb->nr_pages << PAGE_SHIFT; 348 + nr_meta_pages = RINGBUF_NR_META_PAGES; 349 + nr_data_pages = map->max_entries >> PAGE_SHIFT; 350 + usage += (nr_meta_pages + 2 * nr_data_pages) * sizeof(struct page *); 351 + return usage; 352 + } 353 + 340 354 BTF_ID_LIST_SINGLE(ringbuf_map_btf_ids, struct, bpf_ringbuf_map) 341 355 const struct bpf_map_ops ringbuf_map_ops = { 342 356 .map_meta_equal = bpf_map_meta_equal, ··· 363 347 .map_update_elem = ringbuf_map_update_elem, 364 348 .map_delete_elem = ringbuf_map_delete_elem, 365 349 .map_get_next_key = ringbuf_map_get_next_key, 350 + .map_mem_usage = ringbuf_map_mem_usage, 366 351 .map_btf_id = &ringbuf_map_btf_ids[0], 367 352 }; 368 353 ··· 378 361 .map_update_elem = ringbuf_map_update_elem, 379 362 .map_delete_elem = ringbuf_map_delete_elem, 380 363 .map_get_next_key = ringbuf_map_get_next_key, 364 + .map_mem_usage = ringbuf_map_mem_usage, 381 365 .map_btf_id = &user_ringbuf_map_btf_ids[0], 382 366 }; 383 367
+14
kernel/bpf/stackmap.c
··· 654 654 put_callchain_buffers(); 655 655 } 656 656 657 + static u64 stack_map_mem_usage(const struct bpf_map *map) 658 + { 659 + struct bpf_stack_map *smap = container_of(map, struct bpf_stack_map, map); 660 + u64 value_size = map->value_size; 661 + u64 n_buckets = smap->n_buckets; 662 + u64 enties = map->max_entries; 663 + u64 usage = sizeof(*smap); 664 + 665 + usage += n_buckets * sizeof(struct stack_map_bucket *); 666 + usage += enties * (sizeof(struct stack_map_bucket) + value_size); 667 + return usage; 668 + } 669 + 657 670 BTF_ID_LIST_SINGLE(stack_trace_map_btf_ids, struct, bpf_stack_map) 658 671 const struct bpf_map_ops stack_trace_map_ops = { 659 672 .map_meta_equal = bpf_map_meta_equal, ··· 677 664 .map_update_elem = stack_map_update_elem, 678 665 .map_delete_elem = stack_map_delete_elem, 679 666 .map_check_btf = map_check_no_btf, 667 + .map_mem_usage = stack_map_mem_usage, 680 668 .map_btf_id = &stack_trace_map_btf_ids[0], 681 669 };
+8 -12
kernel/bpf/syscall.c
··· 105 105 .map_alloc = bpf_map_offload_map_alloc, 106 106 .map_free = bpf_map_offload_map_free, 107 107 .map_check_btf = map_check_no_btf, 108 + .map_mem_usage = bpf_map_offload_map_mem_usage, 108 109 }; 109 110 110 111 static struct bpf_map *find_and_alloc_map(union bpf_attr *attr) ··· 129 128 } 130 129 if (attr->map_ifindex) 131 130 ops = &bpf_map_offload_ops; 131 + if (!ops->map_mem_usage) 132 + return ERR_PTR(-EINVAL); 132 133 map = ops->map_alloc(attr); 133 134 if (IS_ERR(map)) 134 135 return map; ··· 774 771 } 775 772 776 773 #ifdef CONFIG_PROC_FS 777 - /* Provides an approximation of the map's memory footprint. 778 - * Used only to provide a backward compatibility and display 779 - * a reasonable "memlock" info. 780 - */ 781 - static unsigned long bpf_map_memory_footprint(const struct bpf_map *map) 774 + /* Show the memory usage of a bpf map */ 775 + static u64 bpf_map_memory_usage(const struct bpf_map *map) 782 776 { 783 - unsigned long size; 784 - 785 - size = round_up(map->key_size + bpf_map_value_size(map), 8); 786 - 787 - return round_up(map->max_entries * size, PAGE_SIZE); 777 + return map->ops->map_mem_usage(map); 788 778 } 789 779 790 780 static void bpf_map_show_fdinfo(struct seq_file *m, struct file *filp) ··· 799 803 "max_entries:\t%u\n" 800 804 "map_flags:\t%#x\n" 801 805 "map_extra:\t%#llx\n" 802 - "memlock:\t%lu\n" 806 + "memlock:\t%llu\n" 803 807 "map_id:\t%u\n" 804 808 "frozen:\t%u\n", 805 809 map->map_type, ··· 808 812 map->max_entries, 809 813 map->map_flags, 810 814 (unsigned long long)map->map_extra, 811 - bpf_map_memory_footprint(map), 815 + bpf_map_memory_usage(map), 812 816 map->id, 813 817 READ_ONCE(map->frozen)); 814 818 if (type) {
+1
net/core/bpf_sk_storage.c
··· 324 324 .map_local_storage_charge = bpf_sk_storage_charge, 325 325 .map_local_storage_uncharge = bpf_sk_storage_uncharge, 326 326 .map_owner_storage_ptr = bpf_sk_storage_ptr, 327 + .map_mem_usage = bpf_local_storage_map_mem_usage, 327 328 }; 328 329 329 330 const struct bpf_func_proto bpf_sk_storage_get_proto = {
+20
net/core/sock_map.c
··· 797 797 bpf_map_put_with_uref(info->map); 798 798 } 799 799 800 + static u64 sock_map_mem_usage(const struct bpf_map *map) 801 + { 802 + u64 usage = sizeof(struct bpf_stab); 803 + 804 + usage += (u64)map->max_entries * sizeof(struct sock *); 805 + return usage; 806 + } 807 + 800 808 static const struct bpf_iter_seq_info sock_map_iter_seq_info = { 801 809 .seq_ops = &sock_map_seq_ops, 802 810 .init_seq_private = sock_map_init_seq_private, ··· 824 816 .map_lookup_elem = sock_map_lookup, 825 817 .map_release_uref = sock_map_release_progs, 826 818 .map_check_btf = map_check_no_btf, 819 + .map_mem_usage = sock_map_mem_usage, 827 820 .map_btf_id = &sock_map_btf_ids[0], 828 821 .iter_seq_info = &sock_map_iter_seq_info, 829 822 }; ··· 1406 1397 bpf_map_put_with_uref(info->map); 1407 1398 } 1408 1399 1400 + static u64 sock_hash_mem_usage(const struct bpf_map *map) 1401 + { 1402 + struct bpf_shtab *htab = container_of(map, struct bpf_shtab, map); 1403 + u64 usage = sizeof(*htab); 1404 + 1405 + usage += htab->buckets_num * sizeof(struct bpf_shtab_bucket); 1406 + usage += atomic_read(&htab->count) * (u64)htab->elem_size; 1407 + return usage; 1408 + } 1409 + 1409 1410 static const struct bpf_iter_seq_info sock_hash_iter_seq_info = { 1410 1411 .seq_ops = &sock_hash_seq_ops, 1411 1412 .init_seq_private = sock_hash_init_seq_private, ··· 1435 1416 .map_lookup_elem_sys_only = sock_hash_lookup_sys, 1436 1417 .map_release_uref = sock_hash_release_progs, 1437 1418 .map_check_btf = map_check_no_btf, 1419 + .map_mem_usage = sock_hash_mem_usage, 1438 1420 .map_btf_id = &sock_hash_map_btf_ids[0], 1439 1421 .iter_seq_info = &sock_hash_iter_seq_info, 1440 1422 };
+13
net/xdp/xskmap.c
··· 24 24 return ERR_PTR(-ENOMEM); 25 25 26 26 bpf_map_inc(&map->map); 27 + atomic_inc(&map->count); 27 28 28 29 node->map = map; 29 30 node->map_entry = map_entry; ··· 33 32 34 33 static void xsk_map_node_free(struct xsk_map_node *node) 35 34 { 35 + struct xsk_map *map = node->map; 36 + 36 37 bpf_map_put(&node->map->map); 37 38 kfree(node); 39 + atomic_dec(&map->count); 38 40 } 39 41 40 42 static void xsk_map_sock_add(struct xdp_sock *xs, struct xsk_map_node *node) ··· 87 83 spin_lock_init(&m->lock); 88 84 89 85 return &m->map; 86 + } 87 + 88 + static u64 xsk_map_mem_usage(const struct bpf_map *map) 89 + { 90 + struct xsk_map *m = container_of(map, struct xsk_map, map); 91 + 92 + return struct_size(m, xsk_map, map->max_entries) + 93 + (u64)atomic_read(&m->count) * sizeof(struct xsk_map_node); 90 94 } 91 95 92 96 static void xsk_map_free(struct bpf_map *map) ··· 279 267 .map_update_elem = xsk_map_update_elem, 280 268 .map_delete_elem = xsk_map_delete_elem, 281 269 .map_check_btf = map_check_no_btf, 270 + .map_mem_usage = xsk_map_mem_usage, 282 271 .map_btf_id = &xsk_map_btf_ids[0], 283 272 .map_redirect = xsk_map_redirect, 284 273 };
+118 -78
tools/lib/bpf/usdt.c
··· 1141 1141 return 0; 1142 1142 } 1143 1143 1144 - static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg); 1144 + static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz); 1145 1145 1146 1146 static int parse_usdt_spec(struct usdt_spec *spec, const struct usdt_note *note, __u64 usdt_cookie) 1147 1147 { 1148 + struct usdt_arg_spec *arg; 1148 1149 const char *s; 1149 - int len; 1150 + int arg_sz, len; 1150 1151 1151 1152 spec->usdt_cookie = usdt_cookie; 1152 1153 spec->arg_cnt = 0; ··· 1160 1159 return -E2BIG; 1161 1160 } 1162 1161 1163 - len = parse_usdt_arg(s, spec->arg_cnt, &spec->args[spec->arg_cnt]); 1162 + arg = &spec->args[spec->arg_cnt]; 1163 + len = parse_usdt_arg(s, spec->arg_cnt, arg, &arg_sz); 1164 1164 if (len < 0) 1165 1165 return len; 1166 + 1167 + arg->arg_signed = arg_sz < 0; 1168 + if (arg_sz < 0) 1169 + arg_sz = -arg_sz; 1170 + 1171 + switch (arg_sz) { 1172 + case 1: case 2: case 4: case 8: 1173 + arg->arg_bitshift = 64 - arg_sz * 8; 1174 + break; 1175 + default: 1176 + pr_warn("usdt: unsupported arg #%d (spec '%s') size: %d\n", 1177 + spec->arg_cnt, s, arg_sz); 1178 + return -EINVAL; 1179 + } 1166 1180 1167 1181 s += len; 1168 1182 spec->arg_cnt++; ··· 1235 1219 return -ENOENT; 1236 1220 } 1237 1221 1238 - static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg) 1222 + static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz) 1239 1223 { 1240 1224 char reg_name[16]; 1241 - int arg_sz, len, reg_off; 1225 + int len, reg_off; 1242 1226 long off; 1243 1227 1244 - if (sscanf(arg_str, " %d @ %ld ( %%%15[^)] ) %n", &arg_sz, &off, reg_name, &len) == 3) { 1228 + if (sscanf(arg_str, " %d @ %ld ( %%%15[^)] ) %n", arg_sz, &off, reg_name, &len) == 3) { 1245 1229 /* Memory dereference case, e.g., -4@-20(%rbp) */ 1246 1230 arg->arg_type = USDT_ARG_REG_DEREF; 1247 1231 arg->val_off = off; ··· 1249 1233 if (reg_off < 0) 1250 1234 return reg_off; 1251 1235 arg->reg_off = reg_off; 1252 - } else if (sscanf(arg_str, " %d @ ( %%%15[^)] ) %n", &arg_sz, reg_name, &len) == 2) { 1236 + } else if (sscanf(arg_str, " %d @ ( %%%15[^)] ) %n", arg_sz, reg_name, &len) == 2) { 1253 1237 /* Memory dereference case without offset, e.g., 8@(%rsp) */ 1254 1238 arg->arg_type = USDT_ARG_REG_DEREF; 1255 1239 arg->val_off = 0; ··· 1257 1241 if (reg_off < 0) 1258 1242 return reg_off; 1259 1243 arg->reg_off = reg_off; 1260 - } else if (sscanf(arg_str, " %d @ %%%15s %n", &arg_sz, reg_name, &len) == 2) { 1244 + } else if (sscanf(arg_str, " %d @ %%%15s %n", arg_sz, reg_name, &len) == 2) { 1261 1245 /* Register read case, e.g., -4@%eax */ 1262 1246 arg->arg_type = USDT_ARG_REG; 1263 1247 arg->val_off = 0; ··· 1266 1250 if (reg_off < 0) 1267 1251 return reg_off; 1268 1252 arg->reg_off = reg_off; 1269 - } else if (sscanf(arg_str, " %d @ $%ld %n", &arg_sz, &off, &len) == 2) { 1253 + } else if (sscanf(arg_str, " %d @ $%ld %n", arg_sz, &off, &len) == 2) { 1270 1254 /* Constant value case, e.g., 4@$71 */ 1271 1255 arg->arg_type = USDT_ARG_CONST; 1272 1256 arg->val_off = off; 1273 1257 arg->reg_off = 0; 1274 1258 } else { 1275 1259 pr_warn("usdt: unrecognized arg #%d spec '%s'\n", arg_num, arg_str); 1276 - return -EINVAL; 1277 - } 1278 - 1279 - arg->arg_signed = arg_sz < 0; 1280 - if (arg_sz < 0) 1281 - arg_sz = -arg_sz; 1282 - 1283 - switch (arg_sz) { 1284 - case 1: case 2: case 4: case 8: 1285 - arg->arg_bitshift = 64 - arg_sz * 8; 1286 - break; 1287 - default: 1288 - pr_warn("usdt: unsupported arg #%d (spec '%s') size: %d\n", 1289 - arg_num, arg_str, arg_sz); 1290 1260 return -EINVAL; 1291 1261 } 1292 1262 ··· 1283 1281 1284 1282 /* Do not support __s390__ for now, since user_pt_regs is broken with -m31. */ 1285 1283 1286 - static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg) 1284 + static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz) 1287 1285 { 1288 1286 unsigned int reg; 1289 - int arg_sz, len; 1287 + int len; 1290 1288 long off; 1291 1289 1292 - if (sscanf(arg_str, " %d @ %ld ( %%r%u ) %n", &arg_sz, &off, &reg, &len) == 3) { 1290 + if (sscanf(arg_str, " %d @ %ld ( %%r%u ) %n", arg_sz, &off, &reg, &len) == 3) { 1293 1291 /* Memory dereference case, e.g., -2@-28(%r15) */ 1294 1292 arg->arg_type = USDT_ARG_REG_DEREF; 1295 1293 arg->val_off = off; ··· 1298 1296 return -EINVAL; 1299 1297 } 1300 1298 arg->reg_off = offsetof(user_pt_regs, gprs[reg]); 1301 - } else if (sscanf(arg_str, " %d @ %%r%u %n", &arg_sz, &reg, &len) == 2) { 1299 + } else if (sscanf(arg_str, " %d @ %%r%u %n", arg_sz, &reg, &len) == 2) { 1302 1300 /* Register read case, e.g., -8@%r0 */ 1303 1301 arg->arg_type = USDT_ARG_REG; 1304 1302 arg->val_off = 0; ··· 1307 1305 return -EINVAL; 1308 1306 } 1309 1307 arg->reg_off = offsetof(user_pt_regs, gprs[reg]); 1310 - } else if (sscanf(arg_str, " %d @ %ld %n", &arg_sz, &off, &len) == 2) { 1308 + } else if (sscanf(arg_str, " %d @ %ld %n", arg_sz, &off, &len) == 2) { 1311 1309 /* Constant value case, e.g., 4@71 */ 1312 1310 arg->arg_type = USDT_ARG_CONST; 1313 1311 arg->val_off = off; 1314 1312 arg->reg_off = 0; 1315 1313 } else { 1316 1314 pr_warn("usdt: unrecognized arg #%d spec '%s'\n", arg_num, arg_str); 1317 - return -EINVAL; 1318 - } 1319 - 1320 - arg->arg_signed = arg_sz < 0; 1321 - if (arg_sz < 0) 1322 - arg_sz = -arg_sz; 1323 - 1324 - switch (arg_sz) { 1325 - case 1: case 2: case 4: case 8: 1326 - arg->arg_bitshift = 64 - arg_sz * 8; 1327 - break; 1328 - default: 1329 - pr_warn("usdt: unsupported arg #%d (spec '%s') size: %d\n", 1330 - arg_num, arg_str, arg_sz); 1331 1315 return -EINVAL; 1332 1316 } 1333 1317 ··· 1336 1348 return -ENOENT; 1337 1349 } 1338 1350 1339 - static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg) 1351 + static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz) 1340 1352 { 1341 1353 char reg_name[16]; 1342 - int arg_sz, len, reg_off; 1354 + int len, reg_off; 1343 1355 long off; 1344 1356 1345 - if (sscanf(arg_str, " %d @ \[ %15[a-z0-9], %ld ] %n", &arg_sz, reg_name, &off, &len) == 3) { 1357 + if (sscanf(arg_str, " %d @ \[ %15[a-z0-9] , %ld ] %n", arg_sz, reg_name, &off, &len) == 3) { 1346 1358 /* Memory dereference case, e.g., -4@[sp, 96] */ 1347 1359 arg->arg_type = USDT_ARG_REG_DEREF; 1348 1360 arg->val_off = off; ··· 1350 1362 if (reg_off < 0) 1351 1363 return reg_off; 1352 1364 arg->reg_off = reg_off; 1353 - } else if (sscanf(arg_str, " %d @ \[ %15[a-z0-9] ] %n", &arg_sz, reg_name, &len) == 2) { 1365 + } else if (sscanf(arg_str, " %d @ \[ %15[a-z0-9] ] %n", arg_sz, reg_name, &len) == 2) { 1354 1366 /* Memory dereference case, e.g., -4@[sp] */ 1355 1367 arg->arg_type = USDT_ARG_REG_DEREF; 1356 1368 arg->val_off = 0; ··· 1358 1370 if (reg_off < 0) 1359 1371 return reg_off; 1360 1372 arg->reg_off = reg_off; 1361 - } else if (sscanf(arg_str, " %d @ %ld %n", &arg_sz, &off, &len) == 2) { 1373 + } else if (sscanf(arg_str, " %d @ %ld %n", arg_sz, &off, &len) == 2) { 1362 1374 /* Constant value case, e.g., 4@5 */ 1363 1375 arg->arg_type = USDT_ARG_CONST; 1364 1376 arg->val_off = off; 1365 1377 arg->reg_off = 0; 1366 - } else if (sscanf(arg_str, " %d @ %15[a-z0-9] %n", &arg_sz, reg_name, &len) == 2) { 1378 + } else if (sscanf(arg_str, " %d @ %15[a-z0-9] %n", arg_sz, reg_name, &len) == 2) { 1367 1379 /* Register read case, e.g., -8@x4 */ 1368 1380 arg->arg_type = USDT_ARG_REG; 1369 1381 arg->val_off = 0; ··· 1373 1385 arg->reg_off = reg_off; 1374 1386 } else { 1375 1387 pr_warn("usdt: unrecognized arg #%d spec '%s'\n", arg_num, arg_str); 1376 - return -EINVAL; 1377 - } 1378 - 1379 - arg->arg_signed = arg_sz < 0; 1380 - if (arg_sz < 0) 1381 - arg_sz = -arg_sz; 1382 - 1383 - switch (arg_sz) { 1384 - case 1: case 2: case 4: case 8: 1385 - arg->arg_bitshift = 64 - arg_sz * 8; 1386 - break; 1387 - default: 1388 - pr_warn("usdt: unsupported arg #%d (spec '%s') size: %d\n", 1389 - arg_num, arg_str, arg_sz); 1390 1388 return -EINVAL; 1391 1389 } 1392 1390 ··· 1430 1456 return -ENOENT; 1431 1457 } 1432 1458 1433 - static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg) 1459 + static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz) 1434 1460 { 1435 1461 char reg_name[16]; 1436 - int arg_sz, len, reg_off; 1462 + int len, reg_off; 1437 1463 long off; 1438 1464 1439 - if (sscanf(arg_str, " %d @ %ld ( %15[a-z0-9] ) %n", &arg_sz, &off, reg_name, &len) == 3) { 1465 + if (sscanf(arg_str, " %d @ %ld ( %15[a-z0-9] ) %n", arg_sz, &off, reg_name, &len) == 3) { 1440 1466 /* Memory dereference case, e.g., -8@-88(s0) */ 1441 1467 arg->arg_type = USDT_ARG_REG_DEREF; 1442 1468 arg->val_off = off; ··· 1444 1470 if (reg_off < 0) 1445 1471 return reg_off; 1446 1472 arg->reg_off = reg_off; 1447 - } else if (sscanf(arg_str, " %d @ %ld %n", &arg_sz, &off, &len) == 2) { 1473 + } else if (sscanf(arg_str, " %d @ %ld %n", arg_sz, &off, &len) == 2) { 1448 1474 /* Constant value case, e.g., 4@5 */ 1449 1475 arg->arg_type = USDT_ARG_CONST; 1450 1476 arg->val_off = off; 1451 1477 arg->reg_off = 0; 1452 - } else if (sscanf(arg_str, " %d @ %15[a-z0-9] %n", &arg_sz, reg_name, &len) == 2) { 1478 + } else if (sscanf(arg_str, " %d @ %15[a-z0-9] %n", arg_sz, reg_name, &len) == 2) { 1453 1479 /* Register read case, e.g., -8@a1 */ 1454 1480 arg->arg_type = USDT_ARG_REG; 1455 1481 arg->val_off = 0; ··· 1462 1488 return -EINVAL; 1463 1489 } 1464 1490 1465 - arg->arg_signed = arg_sz < 0; 1466 - if (arg_sz < 0) 1467 - arg_sz = -arg_sz; 1491 + return len; 1492 + } 1468 1493 1469 - switch (arg_sz) { 1470 - case 1: case 2: case 4: case 8: 1471 - arg->arg_bitshift = 64 - arg_sz * 8; 1472 - break; 1473 - default: 1474 - pr_warn("usdt: unsupported arg #%d (spec '%s') size: %d\n", 1475 - arg_num, arg_str, arg_sz); 1494 + #elif defined(__arm__) 1495 + 1496 + static int calc_pt_regs_off(const char *reg_name) 1497 + { 1498 + static struct { 1499 + const char *name; 1500 + size_t pt_regs_off; 1501 + } reg_map[] = { 1502 + { "r0", offsetof(struct pt_regs, uregs[0]) }, 1503 + { "r1", offsetof(struct pt_regs, uregs[1]) }, 1504 + { "r2", offsetof(struct pt_regs, uregs[2]) }, 1505 + { "r3", offsetof(struct pt_regs, uregs[3]) }, 1506 + { "r4", offsetof(struct pt_regs, uregs[4]) }, 1507 + { "r5", offsetof(struct pt_regs, uregs[5]) }, 1508 + { "r6", offsetof(struct pt_regs, uregs[6]) }, 1509 + { "r7", offsetof(struct pt_regs, uregs[7]) }, 1510 + { "r8", offsetof(struct pt_regs, uregs[8]) }, 1511 + { "r9", offsetof(struct pt_regs, uregs[9]) }, 1512 + { "r10", offsetof(struct pt_regs, uregs[10]) }, 1513 + { "fp", offsetof(struct pt_regs, uregs[11]) }, 1514 + { "ip", offsetof(struct pt_regs, uregs[12]) }, 1515 + { "sp", offsetof(struct pt_regs, uregs[13]) }, 1516 + { "lr", offsetof(struct pt_regs, uregs[14]) }, 1517 + { "pc", offsetof(struct pt_regs, uregs[15]) }, 1518 + }; 1519 + int i; 1520 + 1521 + for (i = 0; i < ARRAY_SIZE(reg_map); i++) { 1522 + if (strcmp(reg_name, reg_map[i].name) == 0) 1523 + return reg_map[i].pt_regs_off; 1524 + } 1525 + 1526 + pr_warn("usdt: unrecognized register '%s'\n", reg_name); 1527 + return -ENOENT; 1528 + } 1529 + 1530 + static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz) 1531 + { 1532 + char reg_name[16]; 1533 + int len, reg_off; 1534 + long off; 1535 + 1536 + if (sscanf(arg_str, " %d @ \[ %15[a-z0-9] , #%ld ] %n", 1537 + arg_sz, reg_name, &off, &len) == 3) { 1538 + /* Memory dereference case, e.g., -4@[fp, #96] */ 1539 + arg->arg_type = USDT_ARG_REG_DEREF; 1540 + arg->val_off = off; 1541 + reg_off = calc_pt_regs_off(reg_name); 1542 + if (reg_off < 0) 1543 + return reg_off; 1544 + arg->reg_off = reg_off; 1545 + } else if (sscanf(arg_str, " %d @ \[ %15[a-z0-9] ] %n", arg_sz, reg_name, &len) == 2) { 1546 + /* Memory dereference case, e.g., -4@[sp] */ 1547 + arg->arg_type = USDT_ARG_REG_DEREF; 1548 + arg->val_off = 0; 1549 + reg_off = calc_pt_regs_off(reg_name); 1550 + if (reg_off < 0) 1551 + return reg_off; 1552 + arg->reg_off = reg_off; 1553 + } else if (sscanf(arg_str, " %d @ #%ld %n", arg_sz, &off, &len) == 2) { 1554 + /* Constant value case, e.g., 4@#5 */ 1555 + arg->arg_type = USDT_ARG_CONST; 1556 + arg->val_off = off; 1557 + arg->reg_off = 0; 1558 + } else if (sscanf(arg_str, " %d @ %15[a-z0-9] %n", arg_sz, reg_name, &len) == 2) { 1559 + /* Register read case, e.g., -8@r4 */ 1560 + arg->arg_type = USDT_ARG_REG; 1561 + arg->val_off = 0; 1562 + reg_off = calc_pt_regs_off(reg_name); 1563 + if (reg_off < 0) 1564 + return reg_off; 1565 + arg->reg_off = reg_off; 1566 + } else { 1567 + pr_warn("usdt: unrecognized arg #%d spec '%s'\n", arg_num, arg_str); 1476 1568 return -EINVAL; 1477 1569 } 1478 1570 ··· 1547 1507 1548 1508 #else 1549 1509 1550 - static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg) 1510 + static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz) 1551 1511 { 1552 1512 pr_warn("usdt: libbpf doesn't support USDTs on current architecture\n"); 1553 1513 return -ENOTSUP;
+1 -2
tools/lib/bpf/zip.c
··· 168 168 169 169 static int find_cd(struct zip_archive *archive) 170 170 { 171 + int64_t limit, offset; 171 172 int rc = -EINVAL; 172 - int64_t limit; 173 - __u32 offset; 174 173 175 174 if (archive->size <= sizeof(struct end_of_cd_record)) 176 175 return -EINVAL;
+21 -8
tools/testing/selftests/bpf/prog_tests/test_ima.c
··· 70 70 u64 bin_true_sample; 71 71 char cmd[256]; 72 72 73 - int err, duration = 0; 73 + int err, duration = 0, fresh_digest_idx = 0; 74 74 struct ima *skel = NULL; 75 75 76 76 skel = ima__open_and_load(); ··· 129 129 /* 130 130 * Test #3 131 131 * - Goal: confirm that bpf_ima_inode_hash() returns a non-fresh digest 132 - * - Expected result: 2 samples (/bin/true: non-fresh, fresh) 132 + * - Expected result: 133 + * 1 sample (/bin/true: fresh) if commit 62622dab0a28 applied 134 + * 2 samples (/bin/true: non-fresh, fresh) if commit 62622dab0a28 is 135 + * not applied 136 + * 137 + * If commit 62622dab0a28 ("ima: return IMA digest value only when 138 + * IMA_COLLECTED flag is set") is applied, bpf_ima_inode_hash() refuses 139 + * to give a non-fresh digest, hence the correct result is 1 instead of 140 + * 2. 133 141 */ 134 142 test_init(skel->bss); 135 143 ··· 152 144 goto close_clean; 153 145 154 146 err = ring_buffer__consume(ringbuf); 155 - ASSERT_EQ(err, 2, "num_samples_or_err"); 156 - ASSERT_NEQ(ima_hash_from_bpf[0], 0, "ima_hash"); 157 - ASSERT_NEQ(ima_hash_from_bpf[1], 0, "ima_hash"); 158 - ASSERT_EQ(ima_hash_from_bpf[0], bin_true_sample, "sample_equal_or_err"); 147 + ASSERT_GE(err, 1, "num_samples_or_err"); 148 + if (err == 2) { 149 + ASSERT_NEQ(ima_hash_from_bpf[0], 0, "ima_hash"); 150 + ASSERT_EQ(ima_hash_from_bpf[0], bin_true_sample, 151 + "sample_equal_or_err"); 152 + fresh_digest_idx = 1; 153 + } 154 + 155 + ASSERT_NEQ(ima_hash_from_bpf[fresh_digest_idx], 0, "ima_hash"); 159 156 /* IMA refreshed the digest. */ 160 - ASSERT_NEQ(ima_hash_from_bpf[1], bin_true_sample, 161 - "sample_different_or_err"); 157 + ASSERT_NEQ(ima_hash_from_bpf[fresh_digest_idx], bin_true_sample, 158 + "sample_equal_or_err"); 162 159 163 160 /* 164 161 * Test #4