Re: [PATCH] kunit/fortify: Validate __alloc_size attribute results

From: David Gow
Date: Wed Oct 19 2022 - 02:30:12 EST


On Wed, Oct 19, 2022 at 1:45 PM Kees Cook <keescook@xxxxxxxxxxxx> wrote:
>
> On Wed, Oct 19, 2022 at 11:35:40AM +0800, David Gow wrote:
> > On Tue, Oct 18, 2022 at 4:27 PM Kees Cook <keescook@xxxxxxxxxxxx> wrote:
> > >
> > > Validate the effect of the __alloc_size attribute on allocators. If the
> > > compiler doesn't support __builtin_dynamic_object_size(), skip the test.
> > >
> > > Cc: linux-hardening@xxxxxxxxxxxxxxx
> > > Signed-off-by: Kees Cook <keescook@xxxxxxxxxxxx>
> > > ---
> > > To pass this depends on the following patches:
> > > https://lore.kernel.org/lkml/20221018073430.never.551-kees@xxxxxxxxxx/
> > > https://lore.kernel.org/lkml/20221018082232.never.213-kees@xxxxxxxxxx/
> > > To not be skipped, either GCC 12 or Clang is needed.
> > > ---
> >
> > While this _looks_ good, I can't actually get the tests to pass on my
> > machine, with the following all having a
> > __builtin_dynamic_object_size() of -1:
> > - kmalloc_node(size++, gfp, NUMA_NO_NODE)
> > - kzalloc(size++, gfp)
> > - kzalloc_node(size++, gfp, NUMA_NO_NODE)
> > - kcalloc(1, size++, gfp)
> > - kcalloc_node(1, size++, gfp, NUMA_NO_NODE)
> > - kmalloc_array(1, size++, gfp)
> > - kmalloc_array_node(1, size++, gfp, NUMA_NO_NODE)
> >
> > I've been using the following command to run the tests:
> > ./tools/testing/kunit/kunit.py run --kconfig_add CONFIG_FORTIFY_SOURCE=y
> >
> > And I've also tried it on x86_64 and arm64 under qemu, with both gcc
> > 12.2.0 and clang 14.0.6-2, with the same failures.
> >
> > Is there a dependency somewhere I've missed? (I've tried it on the
> > ksefltest/kunit branch, with the mentioned dependencies applied, and
> > also on your for-next/hardening branch, with the missing patches
> > applied.)
>
> I would expect this to pass with v6.1-rc1 when used with the above two
> patches added, but it seems those _did_ pass, but not the k*alloc()
> helpers for you? That is curious. Here's my testing:
>
> $ ./tools/testing/kunit/kunit.py run --arch x86_64 \
> --kconfig_add CONFIG_FORTIFY_SOURCE=y --make_options LLVM=1 fortify
> ...
> [22:43:32] =================== fortify (3 subtests) ===================
> [22:43:32] [PASSED] known_sizes_test
> [22:43:32] [PASSED] control_flow_split_test
> [22:43:32] [PASSED] alloc_size_test
> [22:43:32] ===================== [PASSED] fortify =====================
> [22:43:32] ============================================================
> [22:43:32] Testing complete. Ran 3 tests: passed: 3
> [22:43:32] Elapsed time: 33.210s total, 3.369s configuring, 28.367s
> building, 0.799s running
>
> $ clang --version
> ClangBuiltLinux clang version 16.0.0 (https://github.com/llvm/llvm-project.git 3291eac12340f465084f347720d99352241f621c)
>
>

Running the exact same command here gives the following output (spam incoming):
[13:55:34] Configuring KUnit Kernel ...
[13:55:34] Building KUnit Kernel ...
Populating config with:
$ make ARCH=x86_64 O=.kunit olddefconfig LLVM=1
Building with:
$ make ARCH=x86_64 O=.kunit --jobs=48 LLVM=1
[13:55:43] Starting KUnit Kernel (1/1)...
[13:55:43] ============================================================
Running tests with:
$ qemu-system-x86_64 -nodefaults -m 1024 -kernel
.kunit/arch/x86/boot/bzImage -append 'kunit.filter_glob=fortify
kunit.enable=1 console=ttyS0 kunit_shutdown=reboot' -no-reboot
-nographic -serial stdio
[13:55:44] =================== fortify (3 subtests) ===================
[13:55:44] [PASSED] known_sizes_test
[13:55:44] [PASSED] control_flow_split_test
[13:55:44] # alloc_size_test: EXPECTATION FAILED at lib/fortify_kunit.c:91
[13:55:44] Expected __builtin_dynamic_object_size(p, 1) == expected, but
[13:55:44] __builtin_dynamic_object_size(p, 1) == -1
[13:55:44] expected == 51
[13:55:44] __alloc_size() not working with kmalloc_node(size++, gfp,
NUMA_NO_NODE)
[13:55:44] # alloc_size_test: EXPECTATION FAILED at lib/fortify_kunit.c:92
[13:55:44] Expected __builtin_dynamic_object_size(p, 1) == expected, but
[13:55:44] __builtin_dynamic_object_size(p, 1) == -1
[13:55:44] expected == 52
[13:55:44] __alloc_size() not working with kzalloc(size++, gfp)
[13:55:44] # alloc_size_test: EXPECTATION FAILED at lib/fortify_kunit.c:93
[13:55:44] Expected __builtin_dynamic_object_size(p, 1) == expected, but
[13:55:44] __builtin_dynamic_object_size(p, 1) == -1
[13:55:44] expected == 53
[13:55:44] __alloc_size() not working with kzalloc_node(size++, gfp,
NUMA_NO_NODE)
[13:55:44] # alloc_size_test: EXPECTATION FAILED at lib/fortify_kunit.c:94
[13:55:44] Expected __builtin_dynamic_object_size(p, 1) == expected, but
[13:55:44] __builtin_dynamic_object_size(p, 1) == -1
[13:55:44] expected == 54
[13:55:44] __alloc_size() not working with kcalloc(1, size++, gfp)
[13:55:44] # alloc_size_test: EXPECTATION FAILED at lib/fortify_kunit.c:95
[13:55:44] Expected __builtin_dynamic_object_size(p, 1) == expected, but
[13:55:44] __builtin_dynamic_object_size(p, 1) == -1
[13:55:44] expected == 55
[13:55:44] __alloc_size() not working with kcalloc_node(1, size++,
gfp, NUMA_NO_NODE)
[13:55:44] # alloc_size_test: EXPECTATION FAILED at lib/fortify_kunit.c:96
[13:55:44] Expected __builtin_dynamic_object_size(p, 1) == expected, but
[13:55:44] __builtin_dynamic_object_size(p, 1) == -1
[13:55:44] expected == 56
[13:55:44] __alloc_size() not working with kmalloc_array(1, size++, gfp)
[13:55:44] # alloc_size_test: EXPECTATION FAILED at lib/fortify_kunit.c:97
[13:55:44] Expected __builtin_dynamic_object_size(p, 1) == expected, but
[13:55:44] __builtin_dynamic_object_size(p, 1) == -1
[13:55:44] expected == 57
[13:55:44] __alloc_size() not working with kmalloc_array_node(1,
size++, gfp, NUMA_NO_NODE)
[13:55:44] not ok 3 - alloc_size_test
[13:55:44] [FAILED] alloc_size_test
[13:55:44] # Subtest: fortify
[13:55:44] 1..3
[13:55:44] # fortify: pass:2 fail:1 skip:0 total:3
[13:55:44] # Totals: pass:2 fail:1 skip:0 total:3
[13:55:44] not ok 1 - fortify
[13:55:44] ===================== [FAILED] fortify =====================
[13:55:44] ============================================================
[13:55:44] Testing complete. Ran 3 tests: passed: 2, failed: 1
[13:55:45] Elapsed time: 10.424s total, 0.002s configuring, 8.950s
building, 0.835s running

With:
clang --version
Debian clang version 14.0.6-2
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

Same thing with gcc:
gcc (Debian 12.2.0-1) 12.2.0
Copyright (C) 2022 Free Software Foundation, Inc.

I can also reproduce it on a different machine, running openSUSE
Tumbleweed's gcc 12.2 and clang 15.0.2.

It also fails the same way with just the mentioned patches, applied to
torvalds/master at aae803b02f92.

Do you have a specific working tree somewhere public I should try?

-- David