Skip to contentSkip to conversation

bpf: Use safer kvmalloc_array() where possible

PATCH Applied Dan Carpenter 4 participants 5 messages May 26, 2022 – Jun 1, 2022

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 bpf: Use safer kvmalloc_array() where possible

The kvmalloc_array() function is safer because it has a check for integer overflows. These sizes come from the user and I was not able to see any bounds checking so an integer overflow seems like a realistic concern.

Fixes 0dcac2725406 ("bpf: Add multi kprobe link")
---
 kernel/trace/bpf_trace.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
kernel/trace/bpf_trace.c +4 -4
index 10b157a6d73e..7a13e6ac6327 100644
@@ -2263,11 +2263,11 @@ static int copy_user_syms(struct user_syms *us, unsigned long __user *usyms, u32
 	int err = -ENOMEM;
 	unsigned int i;
 
-	syms = kvmalloc(cnt * sizeof(*syms), GFP_KERNEL);
+	syms = kvmalloc_array(cnt, sizeof(*syms), GFP_KERNEL);
 	if (!syms)
 		goto error;
 
-	buf = kvmalloc(cnt * KSYM_NAME_LEN, GFP_KERNEL);
+	buf = kvmalloc_array(cnt, KSYM_NAME_LEN, GFP_KERNEL);
 	if (!buf)
 		goto error;
 
@@ -2464,7 +2464,7 @@ int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
 		return -EINVAL;
 
 	size = cnt * sizeof(*addrs);
-	addrs = kvmalloc(size, GFP_KERNEL);
+	addrs = kvmalloc_array(cnt, sizeof(*addrs), GFP_KERNEL);
 	if (!addrs)
 		return -ENOMEM;
 
@@ -2489,7 +2489,7 @@ int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
 
 	ucookies = u64_to_user_ptr(attr->link_create.kprobe_multi.cookies);
 	if (ucookies) {
-		cookies = kvmalloc(size, GFP_KERNEL);
+		cookies = kvmalloc_array(cnt, sizeof(*addrs), GFP_KERNEL);
 		if (!cookies) {
 			err = -ENOMEM;
 			goto error;
Signature · 1 line
2.35.1
#1 lore raw

kernel/trace/bpf_trace.c int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr

Quoted 30 lines · Dan Carpenter

The kvmalloc_array() function is safer because it has a check for integer overflows. These sizes come from the user and I was not able to see any bounds checking so an integer overflow seems like a realistic concern.

Fixes 0dcac2725406 ("bpf: Add multi kprobe link")
---
  kernel/trace/bpf_trace.c | 8 ++++----
  1 file changed, 4 insertions(+), 4 deletions(-)
kernel/trace/bpf_trace.c +2 -2
index 10b157a6d73e..7a13e6ac6327 100644
@@ -2263,11 +2263,11 @@ static int copy_user_syms(struct user_syms *us, unsigned long __user *usyms, u32
  	int err = -ENOMEM;
  	unsigned int i;
 
-	syms = kvmalloc(cnt * sizeof(*syms), GFP_KERNEL);
+	syms = kvmalloc_array(cnt, sizeof(*syms), GFP_KERNEL);
  	if (!syms)
  		goto error;
 
-	buf = kvmalloc(cnt * KSYM_NAME_LEN, GFP_KERNEL);
+	buf = kvmalloc_array(cnt, KSYM_NAME_LEN, GFP_KERNEL);
  	if (!buf)
  		goto error;
 
@@ -2464,7 +2464,7 @@ int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr

For this part of change, there is a similar pending patch here:
https://lore.kernel.org/bpf/399e634781822329e856103cddba975f58f0498c.1652982525.git.esyr@redhat.com/
which waits for further review. That patch tries to detect the overflow explicitly to avoid possible kernel dmesg warnings. (See function kvmalloc_node()).

Quoted 17 lines
kernel/trace/bpf_trace.c +2 -2
  		return -EINVAL;
 
  	size = cnt * sizeof(*addrs);
-	addrs = kvmalloc(size, GFP_KERNEL);
+	addrs = kvmalloc_array(cnt, sizeof(*addrs), GFP_KERNEL);
  	if (!addrs)
  		return -ENOMEM;
 
@@ -2489,7 +2489,7 @@ int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
 
  	ucookies = u64_to_user_ptr(attr->link_create.kprobe_multi.cookies);
  	if (ucookies) {
-		cookies = kvmalloc(size, GFP_KERNEL);
+		cookies = kvmalloc_array(cnt, sizeof(*addrs), GFP_KERNEL);
  		if (!cookies) {
  			err = -ENOMEM;
  			goto error;
#2 lore raw
Quoted 28 lines · Yonghong Song
Quoted 25 lines · Dan Carpenter

The kvmalloc_array() function is safer because it has a check for integer overflows. These sizes come from the user and I was not able to see any bounds checking so an integer overflow seems like a realistic concern.

Fixes 0dcac2725406 ("bpf: Add multi kprobe link")
---
  kernel/trace/bpf_trace.c | 8 ++++----
  1 file changed, 4 insertions(+), 4 deletions(-)
kernel/trace/bpf_trace.c +2 -2
index 10b157a6d73e..7a13e6ac6327 100644
@@ -2263,11 +2263,11 @@ static int copy_user_syms(struct user_syms *us, unsigned long __user *usyms, u32
  	int err = -ENOMEM;
  	unsigned int i;
-	syms = kvmalloc(cnt * sizeof(*syms), GFP_KERNEL);
+	syms = kvmalloc_array(cnt, sizeof(*syms), GFP_KERNEL);
  	if (!syms)
  		goto error;
-	buf = kvmalloc(cnt * KSYM_NAME_LEN, GFP_KERNEL);
+	buf = kvmalloc_array(cnt, KSYM_NAME_LEN, GFP_KERNEL);
  	if (!buf)
Quoted 8 lines

kernel/trace/bpf_trace.c int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr

Quoted 2 lines
kernel/trace/bpf_trace.c +0 -0
  		goto error;
@@ -2464,7 +2464,7 @@ int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr

For this part of change, there is a similar pending patch here:
https://lore.kernel.org/bpf/399e634781822329e856103cddba975f58f0498c.1652982525.git.esyr@redhat.com/
which waits for further review. That patch tries to detect the overflow explicitly to avoid possible kernel dmesg warnings. (See function kvmalloc_node()).

That patch doesn't apply any more.

Static checkers will insist that kvmalloc_array() is cleaner and safer than kvmalloc(n * size, and they don't care if the integer overflow is real or not.

-EOVERFLOW is the wrong error code. Just return -ENOMEM. Checking for size > INT_MAX is ugly. Use a correct limit based on what the maximum reasonable size is. Or if we only want to prevent the stack dump then just pass __GFP_NOWARN.

It annoyed me that size was type unsigned int. Sizes should be unsigned long. Every alloc() function takes an unsigned long so using a u32 temporary value for the size is what made this code so dangerous. If it had been:

	addrs = kvmalloc(cnt * sizeof(*addrs), GFP_KERNEL);

instead of:

	size = cnt * sizeof(*addrs);
	addrs = kvmalloc(size, GFP_KERNEL);

Then the integer overflow bug would only have affected 32 bit systems and those are pretty rare. Choosing the wrong type took a minor bug and made it affect everyone.

regards,
dan carpenter

#3 lore raw
In reply to Dan Carpenter
Quoted 7 lines · Dan Carpenter

The kvmalloc_array() function is safer because it has a check for integer overflows. These sizes come from the user and I was not able to see any bounds checking so an integer overflow seems like a realistic concern.

Fixes 0dcac2725406 ("bpf: Add multi kprobe link")

Eugene was addressing these:
https://lore.kernel.org/bpf/399e634781822329e856103cddba975f58f0498c.1652982525.git.esyr@redhat.com/

I think using kvmalloc_array was one of the review comments

jirka

Quoted 43 lines
---
 kernel/trace/bpf_trace.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
kernel/trace/bpf_trace.c +4 -4
index 10b157a6d73e..7a13e6ac6327 100644
@@ -2263,11 +2263,11 @@ static int copy_user_syms(struct user_syms *us, unsigned long __user *usyms, u32
 	int err = -ENOMEM;
 	unsigned int i;
 
-	syms = kvmalloc(cnt * sizeof(*syms), GFP_KERNEL);
+	syms = kvmalloc_array(cnt, sizeof(*syms), GFP_KERNEL);
 	if (!syms)
 		goto error;
 
-	buf = kvmalloc(cnt * KSYM_NAME_LEN, GFP_KERNEL);
+	buf = kvmalloc_array(cnt, KSYM_NAME_LEN, GFP_KERNEL);
 	if (!buf)
 		goto error;
 
@@ -2464,7 +2464,7 @@ int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
 		return -EINVAL;
 
 	size = cnt * sizeof(*addrs);
-	addrs = kvmalloc(size, GFP_KERNEL);
+	addrs = kvmalloc_array(cnt, sizeof(*addrs), GFP_KERNEL);
 	if (!addrs)
 		return -ENOMEM;
 
@@ -2489,7 +2489,7 @@ int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
 
 	ucookies = u64_to_user_ptr(attr->link_create.kprobe_multi.cookies);
 	if (ucookies) {
-		cookies = kvmalloc(size, GFP_KERNEL);
+		cookies = kvmalloc_array(cnt, sizeof(*addrs), GFP_KERNEL);
 		if (!cookies) {
 			err = -ENOMEM;
 			goto error;
Signature · 1 line
2.35.1
#4 lore raw
In reply to Dan Carpenter
This patch was applied to bpf/bpf-next.git (master) by Andrii Nakryiko <[email protected]>:

Hello:

This patch was applied to bpf/bpf-next.git (master) by Andrii Nakryiko <[email protected]>:

Quoted 9 lines · On Thu, 26 May 2022 13:24:05 +0300 you wrote:

The kvmalloc_array() function is safer because it has a check for integer overflows. These sizes come from the user and I was not able to see any bounds checking so an integer overflow seems like a realistic concern.

Fixes 0dcac2725406 ("bpf: Add multi kprobe link")

[...]

Here is the summary with links:
- bpf: Use safer kvmalloc_array() where possible

    https://git.kernel.org/bpf/bpf-next/c/dafd0f870eae

You are awesome, thank you!

Signature · 2 lines
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html