Skip to contentSkip to conversation

kcsan: test: Adjust "expect" allocation type for kmalloc_obj

PATCH Superseded Kees Cook 2 participants 7 messages Feb 23 – Feb 24 KCSAN

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore

Kees Cook

author
#0 lore raw

PATCH 1/1 kcsan: test: Adjust "expect" allocation type for kmalloc_obj

Instead of depending on the implicit case between a pointer to pointers and pointer to arrays, use the assigned variable type for the allocation type so they correctly match. Solves the following build error:

../kernel/kcsan/kcsan_test.c: In function '__report_matches':
../kernel/kcsan/kcsan_test.c:171:16: error: assignment to 'char (*)[512]' from incompatible pointer type 'char (*)[3][512]' [-Wincompatible-pointer-types]
171 | expect = kmalloc_obj(observed.lines);
| ^

Tested with:

$ ./tools/testing/kunit/kunit.py run \
	--kconfig_add CONFIG_DEBUG_KERNEL=y \
	--kconfig_add CONFIG_KCSAN=y \
	--kconfig_add CONFIG_KCSAN_KUNIT_TEST=y \
	--arch=x86_64 --qemu_args '-smp 2' kcsan
Fixes 69050f8d6d07 ("treewide: Replace kmalloc with kmalloc_obj for non-scalar types")

---
Cc: Marco Elver <[email protected]>
Cc: Dmitry Vyukov <[email protected]>
Cc: <[email protected]>

---
 kernel/kcsan/kcsan_test.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/kcsan/kcsan_test.c +1 -1
index 79e655ea4ca1..056fa859ad9a 100644
@@ -168,7 +168,7 @@ static bool __report_matches(const struct expect_report *r)
 	if (!report_available())
 		return false;
 
-	expect = kmalloc_obj(observed.lines);
+	expect = kmalloc_obj(*expect);
 	if (WARN_ON(!expect))
 		return false;
 
Signature · 1 line
2.34.1
maintainer
#1 lore raw
Quoted 35 lines · Kees Cook

Instead of depending on the implicit case between a pointer to pointers and pointer to arrays, use the assigned variable type for the allocation type so they correctly match. Solves the following build error:

../kernel/kcsan/kcsan_test.c: In function '__report_matches':
../kernel/kcsan/kcsan_test.c:171:16: error: assignment to 'char (*)[512]' from incompatible pointer type 'char (*)[3][512]' [-Wincompatible-pointer-types]
171 | expect = kmalloc_obj(observed.lines);
| ^

Tested with:

$ ./tools/testing/kunit/kunit.py run \
        --kconfig_add CONFIG_DEBUG_KERNEL=y \
        --kconfig_add CONFIG_KCSAN=y \
        --kconfig_add CONFIG_KCSAN_KUNIT_TEST=y \
        --arch=x86_64 --qemu_args '-smp 2' kcsan
Fixes 69050f8d6d07 ("treewide: Replace kmalloc with kmalloc_obj for non-scalar types")

---
Cc: Marco Elver <[email protected]>
Cc: Dmitry Vyukov <[email protected]>
Cc: <[email protected]>

---
 kernel/kcsan/kcsan_test.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/kcsan/kcsan_test.c +0 -0
index 79e655ea4ca1..056fa859ad9a 100644

kernel/kcsan/kcsan_test.c static bool __report_matches(const struct expect_report *r) · line 171

Quoted 5 lines
kernel/kcsan/kcsan_test.c +1 -1
@@ -168,7 +168,7 @@ static bool __report_matches(const struct expect_report *r)
        if (!report_available())
                return false;
 
-       expect = kmalloc_obj(observed.lines);
+       expect = kmalloc_obj(*expect);

This is wrong. Instead of allocating 3x512 bytes it's now only allocating 512 bytes, so we get OOB below with this change. 'expect' is a pointer to a 3-dimensional array of 512-char arrays (matching observed.lines).

author
#2 lore raw
Quoted 39 lines · Marco Elver
Quoted 38 lines · Kees Cook

Instead of depending on the implicit case between a pointer to pointers and pointer to arrays, use the assigned variable type for the allocation type so they correctly match. Solves the following build error:

../kernel/kcsan/kcsan_test.c: In function '__report_matches':
../kernel/kcsan/kcsan_test.c:171:16: error: assignment to 'char (*)[512]' from incompatible pointer type 'char (*)[3][512]' [-Wincompatible-pointer-types]
171 | expect = kmalloc_obj(observed.lines);
| ^

Tested with:

$ ./tools/testing/kunit/kunit.py run \
        --kconfig_add CONFIG_DEBUG_KERNEL=y \
        --kconfig_add CONFIG_KCSAN=y \
        --kconfig_add CONFIG_KCSAN_KUNIT_TEST=y \
        --arch=x86_64 --qemu_args '-smp 2' kcsan
Fixes 69050f8d6d07 ("treewide: Replace kmalloc with kmalloc_obj for non-scalar types")

---
Cc: Marco Elver <[email protected]>
Cc: Dmitry Vyukov <[email protected]>
Cc: <[email protected]>

---
 kernel/kcsan/kcsan_test.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/kcsan/kcsan_test.c +0 -0
index 79e655ea4ca1..056fa859ad9a 100644
@@ -168,7 +168,7 @@ static bool __report_matches(const struct expect_report *r)
        if (!report_available())
                return false;
 
Quoted 7 lines

kernel/kcsan/kcsan_test.c static bool __report_matches(const struct expect_report *r) · line 171

Quoted 2 lines
kernel/kcsan/kcsan_test.c +1 -1
-       expect = kmalloc_obj(observed.lines);
+       expect = kmalloc_obj(*expect);

This is wrong. Instead of allocating 3x512 bytes it's now only allocating 512 bytes, so we get OOB below with this change. 'expect' is a pointer to a 3-dimensional array of 512-char arrays (matching observed.lines).

Why did running the kunit test not trip over this? :(

Hmpf, getting arrays allocated without an explicit cast seems to be impossible. How about this:

kernel/kcsan/kcsan_test.c +1 -1
index 056fa859ad9a..ae758150ccb9 100644
@@ -168,7 +168,7 @@ static bool __report_matches(const struct expect_report *r)
 	if (!report_available())
 		return false;
 
-	expect = kmalloc_obj(*expect);
+	expect = (typeof(expect))kmalloc_obj(observed.lines);
 	if (WARN_ON(!expect))
 		return false;
 
Signature · 1 line
Kees Cook
maintainer
#3 lore raw
Quoted 60 lines · Kees Cook
Quoted 39 lines · Marco Elver
Quoted 38 lines · Kees Cook

Instead of depending on the implicit case between a pointer to pointers and pointer to arrays, use the assigned variable type for the allocation type so they correctly match. Solves the following build error:

../kernel/kcsan/kcsan_test.c: In function '__report_matches':
../kernel/kcsan/kcsan_test.c:171:16: error: assignment to 'char (*)[512]' from incompatible pointer type 'char (*)[3][512]' [-Wincompatible-pointer-types]
171 | expect = kmalloc_obj(observed.lines);
| ^

Tested with:

$ ./tools/testing/kunit/kunit.py run \
        --kconfig_add CONFIG_DEBUG_KERNEL=y \
        --kconfig_add CONFIG_KCSAN=y \
        --kconfig_add CONFIG_KCSAN_KUNIT_TEST=y \
        --arch=x86_64 --qemu_args '-smp 2' kcsan
Fixes 69050f8d6d07 ("treewide: Replace kmalloc with kmalloc_obj for non-scalar types")

---
Cc: Marco Elver <[email protected]>
Cc: Dmitry Vyukov <[email protected]>
Cc: <[email protected]>

---
 kernel/kcsan/kcsan_test.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/kcsan/kcsan_test.c +0 -0
index 79e655ea4ca1..056fa859ad9a 100644
@@ -168,7 +168,7 @@ static bool __report_matches(const struct expect_report *r)
        if (!report_available())
                return false;
 
Quoted 7 lines

kernel/kcsan/kcsan_test.c static bool __report_matches(const struct expect_report *r) · line 171

Quoted 2 lines
kernel/kcsan/kcsan_test.c +1 -1
-       expect = kmalloc_obj(observed.lines);
+       expect = kmalloc_obj(*expect);

This is wrong. Instead of allocating 3x512 bytes it's now only allocating 512 bytes, so we get OOB below with this change. 'expect' is a pointer to a 3-dimensional array of 512-char arrays (matching observed.lines).

Why did running the kunit test not trip over this? :(

Hmpf, getting arrays allocated without an explicit cast seems to be impossible. How about this:

kernel/kcsan/kcsan_test.c +0 -0
index 056fa859ad9a..ae758150ccb9 100644

kernel/kcsan/kcsan_test.c static bool __report_matches(const struct expect_report *r) · line 171

Quoted 5 lines
kernel/kcsan/kcsan_test.c +1 -1
@@ -168,7 +168,7 @@ static bool __report_matches(const struct expect_report *r)
        if (!report_available())
                return false;
 
-       expect = kmalloc_obj(*expect);
+       expect = (typeof(expect))kmalloc_obj(observed.lines);

That works - or why not revert it back to normal kmalloc? There's marginal benefit for kmalloc_obj() in this case, and this really is just a bunch of char buffers - not a complex object. If there's still a benefit to be had from kmalloc_obj() here, I'm fine with the typeof cast.

Thanks,
-- Marco

author
#4 lore raw
Quoted 64 lines · Marco Elver
Quoted 63 lines · Kees Cook
Quoted 39 lines · Marco Elver
Quoted 38 lines · Kees Cook

Instead of depending on the implicit case between a pointer to pointers and pointer to arrays, use the assigned variable type for the allocation type so they correctly match. Solves the following build error:

../kernel/kcsan/kcsan_test.c: In function '__report_matches':
../kernel/kcsan/kcsan_test.c:171:16: error: assignment to 'char (*)[512]' from incompatible pointer type 'char (*)[3][512]' [-Wincompatible-pointer-types]
171 | expect = kmalloc_obj(observed.lines);
| ^

Tested with:

$ ./tools/testing/kunit/kunit.py run \
        --kconfig_add CONFIG_DEBUG_KERNEL=y \
        --kconfig_add CONFIG_KCSAN=y \
        --kconfig_add CONFIG_KCSAN_KUNIT_TEST=y \
        --arch=x86_64 --qemu_args '-smp 2' kcsan
Fixes 69050f8d6d07 ("treewide: Replace kmalloc with kmalloc_obj for non-scalar types")

---
Cc: Marco Elver <[email protected]>
Cc: Dmitry Vyukov <[email protected]>
Cc: <[email protected]>

---
 kernel/kcsan/kcsan_test.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/kcsan/kcsan_test.c +0 -0
index 79e655ea4ca1..056fa859ad9a 100644
@@ -168,7 +168,7 @@ static bool __report_matches(const struct expect_report *r)
        if (!report_available())
                return false;
 
Quoted 7 lines

kernel/kcsan/kcsan_test.c static bool __report_matches(const struct expect_report *r) · line 171

Quoted 2 lines
kernel/kcsan/kcsan_test.c +1 -1
-       expect = kmalloc_obj(observed.lines);
+       expect = kmalloc_obj(*expect);

This is wrong. Instead of allocating 3x512 bytes it's now only allocating 512 bytes, so we get OOB below with this change. 'expect' is a pointer to a 3-dimensional array of 512-char arrays (matching observed.lines).

Why did running the kunit test not trip over this? :(

Hmpf, getting arrays allocated without an explicit cast seems to be impossible. How about this:

kernel/kcsan/kcsan_test.c +0 -0
index 056fa859ad9a..ae758150ccb9 100644
@@ -168,7 +168,7 @@ static bool __report_matches(const struct expect_report *r)
        if (!report_available())
                return false;
 
Quoted 8 lines

kernel/kcsan/kcsan_test.c static bool __report_matches(const struct expect_report *r) · line 171

Quoted 2 lines
kernel/kcsan/kcsan_test.c +1 -1
-       expect = kmalloc_obj(*expect);
+       expect = (typeof(expect))kmalloc_obj(observed.lines);

That works - or why not revert it back to normal kmalloc? There's marginal benefit for kmalloc_obj() in this case, and this really is just a bunch of char buffers - not a complex object. If there's still a benefit to be had from kmalloc_obj() here, I'm fine with the typeof cast.

Honestly... it's because I can't figure out how to make a exclusion for this (nor how to get multidimensional array types) in Coccinelle to avoid this case. (So re-running the conversion script will keep trying to change this case.) And it's the only place in the kernel doing this kind of thing. :P

I've sent v2 with the cast and a better commit log describing what's happening.

Signature · 1 line
Kees Cook
author
#5 lore raw
In reply to Kees Cook
Quoted 59 lines · Kees Cook
Quoted 39 lines · Marco Elver
Quoted 38 lines · Kees Cook

Instead of depending on the implicit case between a pointer to pointers and pointer to arrays, use the assigned variable type for the allocation type so they correctly match. Solves the following build error:

../kernel/kcsan/kcsan_test.c: In function '__report_matches':
../kernel/kcsan/kcsan_test.c:171:16: error: assignment to 'char (*)[512]' from incompatible pointer type 'char (*)[3][512]' [-Wincompatible-pointer-types]
171 | expect = kmalloc_obj(observed.lines);
| ^

Tested with:

$ ./tools/testing/kunit/kunit.py run \
        --kconfig_add CONFIG_DEBUG_KERNEL=y \
        --kconfig_add CONFIG_KCSAN=y \
        --kconfig_add CONFIG_KCSAN_KUNIT_TEST=y \
        --arch=x86_64 --qemu_args '-smp 2' kcsan
Fixes 69050f8d6d07 ("treewide: Replace kmalloc with kmalloc_obj for non-scalar types")

---
Cc: Marco Elver <[email protected]>
Cc: Dmitry Vyukov <[email protected]>
Cc: <[email protected]>

---
 kernel/kcsan/kcsan_test.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/kcsan/kcsan_test.c +0 -0
index 79e655ea4ca1..056fa859ad9a 100644
@@ -168,7 +168,7 @@ static bool __report_matches(const struct expect_report *r)
        if (!report_available())
                return false;
 
Quoted 7 lines

kernel/kcsan/kcsan_test.c static bool __report_matches(const struct expect_report *r) · line 171

Quoted 2 lines
kernel/kcsan/kcsan_test.c +1 -1
-       expect = kmalloc_obj(observed.lines);
+       expect = kmalloc_obj(*expect);

This is wrong. Instead of allocating 3x512 bytes it's now only allocating 512 bytes, so we get OOB below with this change. 'expect' is a pointer to a 3-dimensional array of 512-char arrays (matching observed.lines).

Why did running the kunit test not trip over this? :(

Hmpf, getting arrays allocated without an explicit cast seems to be impossible. How about this:

kernel/kcsan/kcsan_test.c +0 -0
index 056fa859ad9a..ae758150ccb9 100644

kernel/kcsan/kcsan_test.c static bool __report_matches(const struct expect_report *r) · line 173

Quoted 7 lines
kernel/kcsan/kcsan_test.c +1 -1
@@ -168,7 +168,7 @@ static bool __report_matches(const struct expect_report *r)
 	if (!report_available())
 		return false;
 
-	expect = kmalloc_obj(*expect);
+	expect = (typeof(expect))kmalloc_obj(observed.lines);
 	if (WARN_ON(!expect))
 		return false;

Or:

	expect = kmalloc_objs(*observed.lines, ARRAY_SIZE(observed.lines));

I think the quoted cast is probably better...

Signature · 1 line
Kees Cook
maintainer
#6 lore raw
Quoted 71 lines · Kees Cook
Quoted 59 lines · Kees Cook
Quoted 39 lines · Marco Elver
Quoted 38 lines · Kees Cook

Instead of depending on the implicit case between a pointer to pointers and pointer to arrays, use the assigned variable type for the allocation type so they correctly match. Solves the following build error:

../kernel/kcsan/kcsan_test.c: In function '__report_matches':
../kernel/kcsan/kcsan_test.c:171:16: error: assignment to 'char (*)[512]' from incompatible pointer type 'char (*)[3][512]' [-Wincompatible-pointer-types]
171 | expect = kmalloc_obj(observed.lines);
| ^

Tested with:

$ ./tools/testing/kunit/kunit.py run \
        --kconfig_add CONFIG_DEBUG_KERNEL=y \
        --kconfig_add CONFIG_KCSAN=y \
        --kconfig_add CONFIG_KCSAN_KUNIT_TEST=y \
        --arch=x86_64 --qemu_args '-smp 2' kcsan
Fixes 69050f8d6d07 ("treewide: Replace kmalloc with kmalloc_obj for non-scalar types")

---
Cc: Marco Elver <[email protected]>
Cc: Dmitry Vyukov <[email protected]>
Cc: <[email protected]>

---
 kernel/kcsan/kcsan_test.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/kcsan/kcsan_test.c +0 -0
index 79e655ea4ca1..056fa859ad9a 100644
@@ -168,7 +168,7 @@ static bool __report_matches(const struct expect_report *r)
        if (!report_available())
                return false;
 
Quoted 7 lines

kernel/kcsan/kcsan_test.c static bool __report_matches(const struct expect_report *r) · line 171

Quoted 2 lines
kernel/kcsan/kcsan_test.c +1 -1
-       expect = kmalloc_obj(observed.lines);
+       expect = kmalloc_obj(*expect);

This is wrong. Instead of allocating 3x512 bytes it's now only allocating 512 bytes, so we get OOB below with this change. 'expect' is a pointer to a 3-dimensional array of 512-char arrays (matching observed.lines).

Why did running the kunit test not trip over this? :(

Hmpf, getting arrays allocated without an explicit cast seems to be impossible. How about this:

kernel/kcsan/kcsan_test.c +0 -0
index 056fa859ad9a..ae758150ccb9 100644

kernel/kcsan/kcsan_test.c static bool __report_matches(const struct expect_report *r) · line 173

Quoted 7 lines
kernel/kcsan/kcsan_test.c +1 -1
@@ -168,7 +168,7 @@ static bool __report_matches(const struct expect_report *r)
      if (!report_available())
              return false;
 
-     expect = kmalloc_obj(*expect);
+     expect = (typeof(expect))kmalloc_obj(observed.lines);
      if (WARN_ON(!expect))
              return false;

Or:

Quoted 3 lines
        expect = kmalloc_objs(*observed.lines, ARRAY_SIZE(observed.lines));

I think the quoted cast is probably better...

The cast is easier to read (no indirection needed to understand it's just allocating same size as observed.lines).