[PATCH bpf-next] bpf: use kvmalloc in map_lookup_elem

Subsystems: bpf [core], bpf [general] (safe dynamic programs and tools), the rest

STALE1815d

4 messages, 3 authors, 2021-08-16 · open the first message on its own page

[PATCH bpf-next] bpf: use kvmalloc in map_lookup_elem

From: Stanislav Fomichev <hidden>
Date: 2021-08-16 16:48:38

Use kvmalloc/kvfree for temporary value when looking up a map.
kmalloc might not be sufficient for percpu maps where the value is big.

Can be reproduced with netcnt test on qemu with "-smp 255".

Signed-off-by: Stanislav Fomichev <redacted>
---
 kernel/bpf/syscall.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 9a2068e39d23..ae0b1c1c8ece 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -1076,7 +1076,7 @@ static int map_lookup_elem(union bpf_attr *attr)
 	value_size = bpf_map_value_size(map);
 
 	err = -ENOMEM;
-	value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
+	value = kvmalloc(value_size, GFP_USER | __GFP_NOWARN);
 	if (!value)
 		goto free_key;
 
@@ -1091,7 +1091,7 @@ static int map_lookup_elem(union bpf_attr *attr)
 	err = 0;
 
 free_value:
-	kfree(value);
+	kvfree(value);
 free_key:
 	kfree(key);
 err_put:
-- 
2.33.0.rc1.237.g0d66db33f3-goog

Re: [PATCH bpf-next] bpf: use kvmalloc in map_lookup_elem

From: Daniel Borkmann <daniel@iogearbox.net>
Date: 2021-08-16 21:43:25

On 8/16/21 6:48 PM, Stanislav Fomichev wrote:
quoted hunk
Use kvmalloc/kvfree for temporary value when looking up a map.
kmalloc might not be sufficient for percpu maps where the value is big.

Can be reproduced with netcnt test on qemu with "-smp 255".

Signed-off-by: Stanislav Fomichev <redacted>
---
  kernel/bpf/syscall.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 9a2068e39d23..ae0b1c1c8ece 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -1076,7 +1076,7 @@ static int map_lookup_elem(union bpf_attr *attr)
  	value_size = bpf_map_value_size(map);
  
  	err = -ENOMEM;
-	value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
+	value = kvmalloc(value_size, GFP_USER | __GFP_NOWARN);
  	if (!value)
  		goto free_key;
What about other cases like map_update_elem(), shouldn't they be adapted
similarly?

Thanks,
Daniel

Re: [PATCH bpf-next] bpf: use kvmalloc in map_lookup_elem

From: Andrii Nakryiko <hidden>
Date: 2021-08-16 22:33:07

On Mon, Aug 16, 2021 at 2:43 PM Daniel Borkmann [off-list ref] wrote:
On 8/16/21 6:48 PM, Stanislav Fomichev wrote:
quoted
Use kvmalloc/kvfree for temporary value when looking up a map.
kmalloc might not be sufficient for percpu maps where the value is big.

Can be reproduced with netcnt test on qemu with "-smp 255".

Signed-off-by: Stanislav Fomichev <redacted>
---
  kernel/bpf/syscall.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 9a2068e39d23..ae0b1c1c8ece 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -1076,7 +1076,7 @@ static int map_lookup_elem(union bpf_attr *attr)
      value_size = bpf_map_value_size(map);

      err = -ENOMEM;
-     value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
+     value = kvmalloc(value_size, GFP_USER | __GFP_NOWARN);
      if (!value)
              goto free_key;
What about other cases like map_update_elem(), shouldn't they be adapted
similarly?
And in the same vein (with keys potentially being big as well), should
we switch __bpf_copy_key() to use vmemdup_user() instead of
memdup_user()?
Thanks,
Daniel

Re: [PATCH bpf-next] bpf: use kvmalloc in map_lookup_elem

From: <hidden>
Date: 2021-08-16 22:46:55

On 08/16, Andrii Nakryiko wrote:
On Mon, Aug 16, 2021 at 2:43 PM Daniel Borkmann [off-list ref]  
wrote:
quoted
On 8/16/21 6:48 PM, Stanislav Fomichev wrote:
quoted
Use kvmalloc/kvfree for temporary value when looking up a map.
kmalloc might not be sufficient for percpu maps where the value is  
big.
quoted
quoted
Can be reproduced with netcnt test on qemu with "-smp 255".

Signed-off-by: Stanislav Fomichev <redacted>
---
  kernel/bpf/syscall.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 9a2068e39d23..ae0b1c1c8ece 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -1076,7 +1076,7 @@ static int map_lookup_elem(union bpf_attr *attr)
      value_size = bpf_map_value_size(map);

      err = -ENOMEM;
-     value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
+     value = kvmalloc(value_size, GFP_USER | __GFP_NOWARN);
      if (!value)
              goto free_key;
What about other cases like map_update_elem(), shouldn't they be adapted
similarly?
And in the same vein (with keys potentially being big as well), should
we switch __bpf_copy_key() to use vmemdup_user() instead of
memdup_user()?
Those are good questions :-)

I'm assuming that whatever is doing kmalloc on top of
bpf_map_value_size() should definitely use kvmalloc since
bpf_map_value_size() can blow up the value size. (will resend)

For __bpf_copy_key I'm less sure, but it might be a good idea as well.
Let me try to look at bit more into it, but feels like there shouldn't
be any downsides?
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help