Skip to content

Commit a27e896

Browse files
author
Alexei Starovoitov
committed
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/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
2 parents c7d4274 + 7a4b212 commit a27e896

File tree

3 files changed

+21
-13
lines changed

3 files changed

+21
-13
lines changed

kernel/bpf/devmap.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -130,13 +130,14 @@ static int dev_map_init_map(struct bpf_dtab *dtab, union bpf_attr *attr)
130130
bpf_map_init_from_attr(&dtab->map, attr);
131131

132132
if (attr->map_type == BPF_MAP_TYPE_DEVMAP_HASH) {
133-
dtab->n_buckets = roundup_pow_of_two(dtab->map.max_entries);
134-
135-
if (!dtab->n_buckets) /* Overflow check */
133+
/* hash table size must be power of 2; roundup_pow_of_two() can
134+
* overflow into UB on 32-bit arches, so check that first
135+
*/
136+
if (dtab->map.max_entries > 1UL << 31)
136137
return -EINVAL;
137-
}
138138

139-
if (attr->map_type == BPF_MAP_TYPE_DEVMAP_HASH) {
139+
dtab->n_buckets = roundup_pow_of_two(dtab->map.max_entries);
140+
140141
dtab->dev_index_head = dev_map_create_hash(dtab->n_buckets,
141142
dtab->map.numa_node);
142143
if (!dtab->dev_index_head)

kernel/bpf/hashtab.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,13 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
499499
num_possible_cpus());
500500
}
501501

502-
/* hash table size must be power of 2 */
502+
/* hash table size must be power of 2; roundup_pow_of_two() can overflow
503+
* into UB on 32-bit arches, so check that first
504+
*/
505+
err = -E2BIG;
506+
if (htab->map.max_entries > 1UL << 31)
507+
goto free_htab;
508+
503509
htab->n_buckets = roundup_pow_of_two(htab->map.max_entries);
504510

505511
htab->elem_size = sizeof(struct htab_elem) +
@@ -509,10 +515,8 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
509515
else
510516
htab->elem_size += round_up(htab->map.value_size, 8);
511517

512-
err = -E2BIG;
513-
/* prevent zero size kmalloc and check for u32 overflow */
514-
if (htab->n_buckets == 0 ||
515-
htab->n_buckets > U32_MAX / sizeof(struct bucket))
518+
/* check for u32 overflow */
519+
if (htab->n_buckets > U32_MAX / sizeof(struct bucket))
516520
goto free_htab;
517521

518522
err = bpf_map_init_elem_count(&htab->map);

kernel/bpf/stackmap.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,14 @@ static struct bpf_map *stack_map_alloc(union bpf_attr *attr)
9191
} else if (value_size / 8 > sysctl_perf_event_max_stack)
9292
return ERR_PTR(-EINVAL);
9393

94-
/* hash table size must be power of 2 */
95-
n_buckets = roundup_pow_of_two(attr->max_entries);
96-
if (!n_buckets)
94+
/* hash table size must be power of 2; roundup_pow_of_two() can overflow
95+
* into UB on 32-bit arches, so check that first
96+
*/
97+
if (attr->max_entries > 1UL << 31)
9798
return ERR_PTR(-E2BIG);
9899

100+
n_buckets = roundup_pow_of_two(attr->max_entries);
101+
99102
cost = n_buckets * sizeof(struct stack_map_bucket *) + sizeof(*smap);
100103
smap = bpf_map_area_alloc(cost, bpf_map_attr_numa_node(attr));
101104
if (!smap)

0 commit comments

Comments
 (0)