From dc54a9ab3a4a1fd426539798e58b41c570d05182 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 2 May 2018 11:16:25 -0700 Subject: [PATCH] 4.4-stable patches added patches: bpf-map_get_next_key-to-return-first-key-on-null.patch --- ...next_key-to-return-first-key-on-null.patch | 100 ++++++++++++++++++ queue-4.4/series | 1 + 2 files changed, 101 insertions(+) create mode 100644 queue-4.4/bpf-map_get_next_key-to-return-first-key-on-null.patch diff --git a/queue-4.4/bpf-map_get_next_key-to-return-first-key-on-null.patch b/queue-4.4/bpf-map_get_next_key-to-return-first-key-on-null.patch new file mode 100644 index 00000000000..aa448f37793 --- /dev/null +++ b/queue-4.4/bpf-map_get_next_key-to-return-first-key-on-null.patch @@ -0,0 +1,100 @@ +From 8fe45924387be6b5c1be59a7eb330790c61d5d10 Mon Sep 17 00:00:00 2001 +From: Teng Qin +Date: Mon, 24 Apr 2017 19:00:37 -0700 +Subject: bpf: map_get_next_key to return first key on NULL + +From: Teng Qin + +commit 8fe45924387be6b5c1be59a7eb330790c61d5d10 upstream. + +When iterating through a map, we need to find a key that does not exist +in the map so map_get_next_key will give us the first key of the map. +This often requires a lot of guessing in production systems. + +This patch makes map_get_next_key return the first key when the key +pointer in the parameter is NULL. + +Signed-off-by: Teng Qin +Signed-off-by: Alexei Starovoitov +Acked-by: Daniel Borkmann +Signed-off-by: David S. Miller +Signed-off-by: Chenbo Feng +Cc: Lorenzo Colitti +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/bpf/arraymap.c | 2 +- + kernel/bpf/hashtab.c | 9 +++++---- + kernel/bpf/syscall.c | 18 +++++++++++------- + 3 files changed, 17 insertions(+), 12 deletions(-) + +--- a/kernel/bpf/arraymap.c ++++ b/kernel/bpf/arraymap.c +@@ -102,7 +102,7 @@ static void *array_map_lookup_elem(struc + static int array_map_get_next_key(struct bpf_map *map, void *key, void *next_key) + { + struct bpf_array *array = container_of(map, struct bpf_array, map); +- u32 index = *(u32 *)key; ++ u32 index = key ? *(u32 *)key : U32_MAX; + u32 *next = (u32 *)next_key; + + if (index >= array->map.max_entries) { +--- a/kernel/bpf/hashtab.c ++++ b/kernel/bpf/hashtab.c +@@ -169,12 +169,15 @@ static int htab_map_get_next_key(struct + struct hlist_head *head; + struct htab_elem *l, *next_l; + u32 hash, key_size; +- int i; ++ int i = 0; + + WARN_ON_ONCE(!rcu_read_lock_held()); + + key_size = map->key_size; + ++ if (!key) ++ goto find_first_elem; ++ + hash = htab_map_hash(key, key_size); + + head = select_bucket(htab, hash); +@@ -182,10 +185,8 @@ static int htab_map_get_next_key(struct + /* lookup the key */ + l = lookup_elem_raw(head, hash, key, key_size); + +- if (!l) { +- i = 0; ++ if (!l) + goto find_first_elem; +- } + + /* key was found, get next key in the same bucket */ + next_l = hlist_entry_safe(rcu_dereference_raw(hlist_next_rcu(&l->hash_node)), +--- a/kernel/bpf/syscall.c ++++ b/kernel/bpf/syscall.c +@@ -390,14 +390,18 @@ static int map_get_next_key(union bpf_at + if (IS_ERR(map)) + return PTR_ERR(map); + +- err = -ENOMEM; +- key = kmalloc(map->key_size, GFP_USER); +- if (!key) +- goto err_put; ++ if (ukey) { ++ err = -ENOMEM; ++ key = kmalloc(map->key_size, GFP_USER); ++ if (!key) ++ goto err_put; + +- err = -EFAULT; +- if (copy_from_user(key, ukey, map->key_size) != 0) +- goto free_key; ++ err = -EFAULT; ++ if (copy_from_user(key, ukey, map->key_size) != 0) ++ goto free_key; ++ } else { ++ key = NULL; ++ } + + err = -ENOMEM; + next_key = kmalloc(map->key_size, GFP_USER); diff --git a/queue-4.4/series b/queue-4.4/series index ad4c44ab7a5..191eae87f2a 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -1 +1,2 @@ perf-core-fix-the-perf_cpu_time_max_percent-check.patch +bpf-map_get_next_key-to-return-first-key-on-null.patch -- 2.47.3