--- zzzz-none-000/linux-4.4.60/kernel/bpf/arraymap.c 2017-04-08 07:53:53.000000000 +0000 +++ wasp-540e-714/linux-4.4.60/kernel/bpf/arraymap.c 2019-07-03 09:21:34.000000000 +0000 @@ -22,6 +22,8 @@ { struct bpf_array *array; u32 elem_size, array_size; + u32 index_mask, max_entries; + bool unpriv = !capable(CAP_SYS_ADMIN); /* check sanity of attributes */ if (attr->max_entries == 0 || attr->key_size != 4 || @@ -36,12 +38,22 @@ elem_size = round_up(attr->value_size, 8); + max_entries = attr->max_entries; + index_mask = roundup_pow_of_two(max_entries) - 1; + + if (unpriv) + /* round up array size to nearest power of 2, + * since cpu will speculate within index_mask limits + */ + max_entries = index_mask + 1; + + /* check round_up into zero and u32 overflow */ if (elem_size == 0 || attr->max_entries > (U32_MAX - PAGE_SIZE - sizeof(*array)) / elem_size) return ERR_PTR(-ENOMEM); - array_size = sizeof(*array) + attr->max_entries * elem_size; + array_size = sizeof(*array) + max_entries * elem_size; /* allocate all map elements and zero-initialize them */ array = kzalloc(array_size, GFP_USER | __GFP_NOWARN); @@ -51,6 +63,9 @@ return ERR_PTR(-ENOMEM); } + array->index_mask = index_mask; + array->map.unpriv_array = unpriv; + /* copy mandatory map attributes */ array->map.key_size = attr->key_size; array->map.value_size = attr->value_size; @@ -70,7 +85,7 @@ if (index >= array->map.max_entries) return NULL; - return array->value + array->elem_size * index; + return array->value + array->elem_size * (index & array->index_mask); } /* Called from syscall */ @@ -111,7 +126,9 @@ /* all elements already exist */ return -EEXIST; - memcpy(array->value + array->elem_size * index, value, map->value_size); + memcpy(array->value + + array->elem_size * (index & array->index_mask), + value, map->value_size); return 0; }