summaryrefslogtreecommitdiff
path: root/kernel/bpf/arraymap.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-01-14 19:01:33 +0300
committerDavid S. Miller <davem@davemloft.net>2018-01-14 19:01:33 +0300
commit8155aedf512edd3f88ef19f7cacf476ace7d1322 (patch)
tree3113dc2556227d089f65dcae87833583a80ab4f9 /kernel/bpf/arraymap.c
parent5dd966c680b616911a66d4576a9ed53aaf5f89ea (diff)
parentbbeb6e4323dad9b5e0ee9f60c223dd532e2403b1 (diff)
downloadlinux-8155aedf512edd3f88ef19f7cacf476ace7d1322.tar.xz
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
Daniel Borkmann says: ==================== pull-request: bpf 2018-01-13 The following pull-request contains BPF updates for your *net* tree. The main changes are: 1) Follow-up fix to the recent BPF out-of-bounds speculation fix that prevents max_entries overflows and an undefined behavior on 32 bit archs on index_mask calculation, from Daniel. 2) Reject unsupported BPF_ARSH opcode in 32 bit ALU mode that was otherwise throwing an unknown opcode warning in the interpreter, from Daniel. 3) Typo fix in one of the user facing verbose() messages that was added during the BPF out-of-bounds speculation fix, from Colin. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'kernel/bpf/arraymap.c')
-rw-r--r--kernel/bpf/arraymap.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
index aaa319848e7d..ab94d304a634 100644
--- a/kernel/bpf/arraymap.c
+++ b/kernel/bpf/arraymap.c
@@ -56,7 +56,7 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr)
u32 elem_size, index_mask, max_entries;
bool unpriv = !capable(CAP_SYS_ADMIN);
struct bpf_array *array;
- u64 array_size;
+ u64 array_size, mask64;
/* check sanity of attributes */
if (attr->max_entries == 0 || attr->key_size != 4 ||
@@ -74,13 +74,25 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr)
elem_size = round_up(attr->value_size, 8);
max_entries = attr->max_entries;
- index_mask = roundup_pow_of_two(max_entries) - 1;
- if (unpriv)
+ /* On 32 bit archs roundup_pow_of_two() with max_entries that has
+ * upper most bit set in u32 space is undefined behavior due to
+ * resulting 1U << 32, so do it manually here in u64 space.
+ */
+ mask64 = fls_long(max_entries - 1);
+ mask64 = 1ULL << mask64;
+ mask64 -= 1;
+
+ index_mask = mask64;
+ 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 for overflows. */
+ if (max_entries < attr->max_entries)
+ return ERR_PTR(-E2BIG);
+ }
array_size = sizeof(*array);
if (percpu)