mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-03 13:32:07 -04:00
Merge branch 'fix-hash-bucket-overflow-checks-for-32-bit-arches'
Toke Høiland-Jørgensen says: ==================== Fix hash bucket overflow checks for 32-bit arches Syzbot managed to trigger a crash by creating a DEVMAP_HASH map with a large number of buckets because the overflow check relies on well-defined behaviour that is only correct on 64-bit arches. Fix the overflow checks to happen before values are rounded up in all the affected map types. v3: - Keep the htab->n_buckets > U32_MAX / sizeof(struct bucket) check - Use 1UL << 31 instead of U32_MAX / 2 + 1 as the constant to check against - Add patch to fix stackmap.c v2: - Fix off-by-one error in overflow check - Apply the same fix to hashtab, where the devmap_hash code was copied from (John) Toke Høiland-Jørgensen (3): bpf: Fix DEVMAP_HASH overflow check on 32-bit arches bpf: Fix hashtab overflow check on 32-bit arches bpf: Fix stackmap overflow check on 32-bit arches kernel/bpf/devmap.c | 11 ++++++----- kernel/bpf/hashtab.c | 14 +++++++++----- kernel/bpf/stackmap.c | 9 ++++++--- 3 files changed, 21 insertions(+), 13 deletions(-) ==================== Link: https://lore.kernel.org/r/20240307120340.99577-1-toke@redhat.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
@@ -130,13 +130,14 @@ static int dev_map_init_map(struct bpf_dtab *dtab, union bpf_attr *attr)
|
||||
bpf_map_init_from_attr(&dtab->map, attr);
|
||||
|
||||
if (attr->map_type == BPF_MAP_TYPE_DEVMAP_HASH) {
|
||||
/* hash table size must be power of 2; roundup_pow_of_two() can
|
||||
* overflow into UB on 32-bit arches, so check that first
|
||||
*/
|
||||
if (dtab->map.max_entries > 1UL << 31)
|
||||
return -EINVAL;
|
||||
|
||||
dtab->n_buckets = roundup_pow_of_two(dtab->map.max_entries);
|
||||
|
||||
if (!dtab->n_buckets) /* Overflow check */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (attr->map_type == BPF_MAP_TYPE_DEVMAP_HASH) {
|
||||
dtab->dev_index_head = dev_map_create_hash(dtab->n_buckets,
|
||||
dtab->map.numa_node);
|
||||
if (!dtab->dev_index_head)
|
||||
|
||||
@@ -499,7 +499,13 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
|
||||
num_possible_cpus());
|
||||
}
|
||||
|
||||
/* hash table size must be power of 2 */
|
||||
/* hash table size must be power of 2; roundup_pow_of_two() can overflow
|
||||
* into UB on 32-bit arches, so check that first
|
||||
*/
|
||||
err = -E2BIG;
|
||||
if (htab->map.max_entries > 1UL << 31)
|
||||
goto free_htab;
|
||||
|
||||
htab->n_buckets = roundup_pow_of_two(htab->map.max_entries);
|
||||
|
||||
htab->elem_size = sizeof(struct htab_elem) +
|
||||
@@ -509,10 +515,8 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
|
||||
else
|
||||
htab->elem_size += round_up(htab->map.value_size, 8);
|
||||
|
||||
err = -E2BIG;
|
||||
/* prevent zero size kmalloc and check for u32 overflow */
|
||||
if (htab->n_buckets == 0 ||
|
||||
htab->n_buckets > U32_MAX / sizeof(struct bucket))
|
||||
/* check for u32 overflow */
|
||||
if (htab->n_buckets > U32_MAX / sizeof(struct bucket))
|
||||
goto free_htab;
|
||||
|
||||
err = bpf_map_init_elem_count(&htab->map);
|
||||
|
||||
@@ -91,11 +91,14 @@ static struct bpf_map *stack_map_alloc(union bpf_attr *attr)
|
||||
} else if (value_size / 8 > sysctl_perf_event_max_stack)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/* hash table size must be power of 2 */
|
||||
n_buckets = roundup_pow_of_two(attr->max_entries);
|
||||
if (!n_buckets)
|
||||
/* hash table size must be power of 2; roundup_pow_of_two() can overflow
|
||||
* into UB on 32-bit arches, so check that first
|
||||
*/
|
||||
if (attr->max_entries > 1UL << 31)
|
||||
return ERR_PTR(-E2BIG);
|
||||
|
||||
n_buckets = roundup_pow_of_two(attr->max_entries);
|
||||
|
||||
cost = n_buckets * sizeof(struct stack_map_bucket *) + sizeof(*smap);
|
||||
smap = bpf_map_area_alloc(cost, bpf_map_attr_numa_node(attr));
|
||||
if (!smap)
|
||||
|
||||
Reference in New Issue
Block a user