* [PATCH 1/2] vfs: Annotate struct fdtable's fd field with __counted_by_ptr [not found] <20260810204118.1981755-1-morbo@google.com> @ 2026-08-10 20:41 ` Bill Wendling 2026-08-11 0:18 ` Kees Cook 2026-08-10 20:41 ` [PATCH 2/2] vfs: Add KUnit tests for fdtable Bill Wendling 1 sibling, 1 reply; 6+ messages in thread From: Bill Wendling @ 2026-08-10 20:41 UTC (permalink / raw) Cc: Bill Wendling, codemender-patching+linux, Alexander Viro, Christian Brauner, Jan Kara, Kees Cook, Gustavo A. R. Silva, linux-kernel, linux-fsdevel, linux-hardening The 'struct fdtable' holds the file descriptor table information, including the current file descriptor array 'fd' and its size 'max_fds'. To harden the kernel against out-of-bounds accesses, we can annotate the 'fd' pointer field with the '__counted_by_ptr' attribute, referencing 'max_fds'. The compiler uses the '__counted_by_ptr' attribute to track the size of the memory allocated for the pointer field, enabling runtime bounds checks under KASAN and fortified functions. There are three places where a 'struct fdtable' is initialized, and in all of them, 'max_fds' is set before the 'fd' pointer is accessed or assigned in all allocation and initialization places. No accesses to 'fd' occur before 'max_fds' is set, preventing any potential runtime false-positives or panics due to uninitialized count fields. This patch was generated by CodeMender and checked by submitter. Cc: codemender-patching+linux@google.com Signed-off-by: Bill Wendling <morbo@google.com> --- Cc: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Christian Brauner <brauner@kernel.org> Cc: Jan Kara <jack@suse.cz> Cc: Kees Cook <kees@kernel.org> Cc: "Gustavo A. R. Silva" <gustavoars@kernel.org> Cc: linux-kernel@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org Cc: linux-hardening@vger.kernel.org --- include/linux/fdtable.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h index c45306a9f007..3a5c88291125 100644 --- a/include/linux/fdtable.h +++ b/include/linux/fdtable.h @@ -25,7 +25,7 @@ struct fdtable { unsigned int max_fds; - struct file __rcu **fd; /* current fd array */ + struct file __rcu **fd __counted_by_ptr(max_fds); /* current fd array */ unsigned long *close_on_exec; unsigned long *open_fds; unsigned long *full_fds_bits; -- 2.55.0.679.g6767b8d81c-goog ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] vfs: Annotate struct fdtable's fd field with __counted_by_ptr 2026-08-10 20:41 ` [PATCH 1/2] vfs: Annotate struct fdtable's fd field with __counted_by_ptr Bill Wendling @ 2026-08-11 0:18 ` Kees Cook 0 siblings, 0 replies; 6+ messages in thread From: Kees Cook @ 2026-08-11 0:18 UTC (permalink / raw) To: Bill Wendling Cc: codemender-patching+linux, Alexander Viro, Christian Brauner, Jan Kara, Gustavo A. R. Silva, linux-kernel, linux-fsdevel, linux-hardening On Mon, Aug 10, 2026 at 08:41:12PM +0000, Bill Wendling wrote: > The 'struct fdtable' holds the file descriptor table information, > including the current file descriptor array 'fd' and its size 'max_fds'. > To harden the kernel against out-of-bounds accesses, we can annotate the > 'fd' pointer field with the '__counted_by_ptr' attribute, referencing > 'max_fds'. > > The compiler uses the '__counted_by_ptr' attribute to track the > size of the memory allocated for the pointer field, enabling > runtime bounds checks under KASAN and fortified functions. There are > three places where a 'struct fdtable' is initialized, and in all of > them, 'max_fds' is set before the 'fd' pointer is accessed or assigned > in all allocation and initialization places. > > No accesses to 'fd' occur before 'max_fds' is set, preventing any > potential runtime false-positives or panics due to uninitialized count > fields. > > This patch was generated by CodeMender and checked by submitter. > > Cc: codemender-patching+linux@google.com > Signed-off-by: Bill Wendling <morbo@google.com> > --- > Cc: Alexander Viro <viro@zeniv.linux.org.uk> > Cc: Christian Brauner <brauner@kernel.org> > Cc: Jan Kara <jack@suse.cz> > Cc: Kees Cook <kees@kernel.org> > Cc: "Gustavo A. R. Silva" <gustavoars@kernel.org> > Cc: linux-kernel@vger.kernel.org > Cc: linux-fsdevel@vger.kernel.org > Cc: linux-hardening@vger.kernel.org > --- > include/linux/fdtable.h | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h > index c45306a9f007..3a5c88291125 100644 > --- a/include/linux/fdtable.h > +++ b/include/linux/fdtable.h > @@ -25,7 +25,7 @@ > > struct fdtable { > unsigned int max_fds; > - struct file __rcu **fd; /* current fd array */ > + struct file __rcu **fd __counted_by_ptr(max_fds); /* current fd array */ > unsigned long *close_on_exec; > unsigned long *open_fds; > unsigned long *full_fds_bits; I see the alloc_fdtable test, that's one max_fds assignment, but I also see dup_fd(), which does the assignment after the newf allocation, so that looks safe too, but it might be nice to add that allocation path to the tests too? -- Kees Cook ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/2] vfs: Add KUnit tests for fdtable [not found] <20260810204118.1981755-1-morbo@google.com> 2026-08-10 20:41 ` [PATCH 1/2] vfs: Annotate struct fdtable's fd field with __counted_by_ptr Bill Wendling @ 2026-08-10 20:41 ` Bill Wendling 2026-08-11 0:16 ` Kees Cook 1 sibling, 1 reply; 6+ messages in thread From: Bill Wendling @ 2026-08-10 20:41 UTC (permalink / raw) Cc: Bill Wendling, codemender-patching+linux, Alexander Viro, Christian Brauner, Jan Kara, Kees Cook, Gustavo A. R. Silva, linux-kernel, linux-fsdevel, linux-hardening This adds a KUnit test suite for fdtable to verify correct allocation, max_fds initialization, and dynamic object size of the fd array under __counted_by_ptr when CONFIG_CC_HAS_COUNTED_BY_PTR is enabled. This patch was generated by CodeMender and checked by submitter. Cc: codemender-patching+linux@google.com Signed-off-by: Bill Wendling <morbo@google.com> --- Cc: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Christian Brauner <brauner@kernel.org> Cc: Jan Kara <jack@suse.cz> Cc: Kees Cook <kees@kernel.org> Cc: "Gustavo A. R. Silva" <gustavoars@kernel.org> Cc: linux-kernel@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org Cc: linux-hardening@vger.kernel.org --- fs/Kconfig | 8 ++++++++ fs/file.c | 4 ++++ fs/tests/.kunitconfig | 2 ++ fs/tests/fdtable_kunit.c | 40 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+) create mode 100644 fs/tests/.kunitconfig create mode 100644 fs/tests/fdtable_kunit.c diff --git a/fs/Kconfig b/fs/Kconfig index cf6ae64776e6..f4b9235ab883 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -423,4 +423,12 @@ source "fs/unicode/Kconfig" config IO_WQ bool +config FDTABLE_KUNIT_TEST + bool "KUnit test for fdtable" if !KUNIT_ALL_TESTS + depends on KUNIT=y + default KUNIT_ALL_TESTS + help + This builds the fdtable KUnit tests, which tests various aspects + of the fdtable structure and allocation. + endmenu diff --git a/fs/file.c b/fs/file.c index 628ca07dc4b1..9c7001b901cf 100644 --- a/fs/file.c +++ b/fs/file.c @@ -1529,3 +1529,7 @@ int iterate_fd(struct files_struct *files, unsigned n, return res; } EXPORT_SYMBOL(iterate_fd); + +#ifdef CONFIG_FDTABLE_KUNIT_TEST +#include "tests/fdtable_kunit.c" +#endif diff --git a/fs/tests/.kunitconfig b/fs/tests/.kunitconfig new file mode 100644 index 000000000000..de67125a9421 --- /dev/null +++ b/fs/tests/.kunitconfig @@ -0,0 +1,2 @@ +CONFIG_KUNIT=y +CONFIG_FDTABLE_KUNIT_TEST=y diff --git a/fs/tests/fdtable_kunit.c b/fs/tests/fdtable_kunit.c new file mode 100644 index 000000000000..41bae6b7400f --- /dev/null +++ b/fs/tests/fdtable_kunit.c @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include <kunit/test.h> +#include <linux/fdtable.h> +#include <linux/file.h> + +static void fdtable_test_alloc(struct kunit *test) +{ + struct fdtable *fdt; + unsigned int slots = 64; + + fdt = alloc_fdtable(slots); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fdt); + + /* Check that max_fds is set correctly and is >= slots */ + KUNIT_EXPECT_GE(test, fdt->max_fds, slots); + + /* Check that fd is allocated */ + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, fdt->fd); + + /* Check dynamic object size of fdt->fd if compiler supports __counted_by_ptr */ +#ifdef CONFIG_CC_HAS_COUNTED_BY_PTR + KUNIT_EXPECT_EQ(test, __builtin_dynamic_object_size(fdt->fd, 0), + fdt->max_fds * sizeof(struct file *)); +#endif + + /* Free the fdtable */ + __free_fdtable(fdt); +} + +static struct kunit_case fdtable_test_cases[] = { + KUNIT_CASE(fdtable_test_alloc), + {} +}; + +static struct kunit_suite fdtable_test_suite = { + .name = "fdtable", + .test_cases = fdtable_test_cases, +}; + +kunit_test_suite(fdtable_test_suite); -- 2.55.0.679.g6767b8d81c-goog ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] vfs: Add KUnit tests for fdtable 2026-08-10 20:41 ` [PATCH 2/2] vfs: Add KUnit tests for fdtable Bill Wendling @ 2026-08-11 0:16 ` Kees Cook 2026-08-11 15:42 ` Jann Horn 0 siblings, 1 reply; 6+ messages in thread From: Kees Cook @ 2026-08-11 0:16 UTC (permalink / raw) To: Bill Wendling Cc: codemender-patching+linux, Alexander Viro, Christian Brauner, Jan Kara, Gustavo A. R. Silva, linux-kernel, linux-fsdevel, linux-hardening On Mon, Aug 10, 2026 at 08:41:13PM +0000, Bill Wendling wrote: > +static void fdtable_test_alloc(struct kunit *test) > +{ > + struct fdtable *fdt; > + unsigned int slots = 64; > + > + fdt = alloc_fdtable(slots); > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fdt); > + > + /* Check that max_fds is set correctly and is >= slots */ > + KUNIT_EXPECT_GE(test, fdt->max_fds, slots); > + > + /* Check that fd is allocated */ > + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, fdt->fd); Nice to add these tests! Can you add one for each of the conditionals in alloc_fdtable (e.g. ENOMEM, EMFILE, and the power-of-two rounding-up logic, etc)? -Kees -- Kees Cook ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] vfs: Add KUnit tests for fdtable 2026-08-11 0:16 ` Kees Cook @ 2026-08-11 15:42 ` Jann Horn 2026-08-12 0:22 ` Kees Cook 0 siblings, 1 reply; 6+ messages in thread From: Jann Horn @ 2026-08-11 15:42 UTC (permalink / raw) To: Kees Cook Cc: Bill Wendling, codemender-patching+linux, Alexander Viro, Christian Brauner, Jan Kara, Gustavo A. R. Silva, linux-kernel, linux-fsdevel, linux-hardening On Tue, Aug 11, 2026 at 2:16 AM Kees Cook <kees@kernel.org> wrote: > On Mon, Aug 10, 2026 at 08:41:13PM +0000, Bill Wendling wrote: > > +static void fdtable_test_alloc(struct kunit *test) > > +{ > > + struct fdtable *fdt; > > + unsigned int slots = 64; > > + > > + fdt = alloc_fdtable(slots); > > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fdt); > > + > > + /* Check that max_fds is set correctly and is >= slots */ > > + KUNIT_EXPECT_GE(test, fdt->max_fds, slots); > > + > > + /* Check that fd is allocated */ > > + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, fdt->fd); > > Nice to add these tests! Can you add one for each of the conditionals > in alloc_fdtable (e.g. ENOMEM, EMFILE, and the power-of-two rounding-up > logic, etc)? Wouldn't tests for stuff like the rounding-up logic get into implementation details too much, and break if implementation choices change? ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] vfs: Add KUnit tests for fdtable 2026-08-11 15:42 ` Jann Horn @ 2026-08-12 0:22 ` Kees Cook 0 siblings, 0 replies; 6+ messages in thread From: Kees Cook @ 2026-08-12 0:22 UTC (permalink / raw) To: Jann Horn Cc: Bill Wendling, codemender-patching+linux, Alexander Viro, Christian Brauner, Jan Kara, Gustavo A. R. Silva, linux-kernel, linux-fsdevel, linux-hardening On Tue, Aug 11, 2026 at 05:42:05PM +0200, Jann Horn wrote: > On Tue, Aug 11, 2026 at 2:16 AM Kees Cook <kees@kernel.org> wrote: > > On Mon, Aug 10, 2026 at 08:41:13PM +0000, Bill Wendling wrote: > > > +static void fdtable_test_alloc(struct kunit *test) > > > +{ > > > + struct fdtable *fdt; > > > + unsigned int slots = 64; > > > + > > > + fdt = alloc_fdtable(slots); > > > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fdt); > > > + > > > + /* Check that max_fds is set correctly and is >= slots */ > > > + KUNIT_EXPECT_GE(test, fdt->max_fds, slots); > > > + > > > + /* Check that fd is allocated */ > > > + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, fdt->fd); > > > > Nice to add these tests! Can you add one for each of the conditionals > > in alloc_fdtable (e.g. ENOMEM, EMFILE, and the power-of-two rounding-up > > logic, etc)? > > Wouldn't tests for stuff like the rounding-up logic get into > implementation details too much, and break if implementation choices > change? It seemed to me like we'd want to notice if that behavior changed? -- Kees Cook ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-08-12 0:22 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20260810204118.1981755-1-morbo@google.com>
2026-08-10 20:41 ` [PATCH 1/2] vfs: Annotate struct fdtable's fd field with __counted_by_ptr Bill Wendling
2026-08-11 0:18 ` Kees Cook
2026-08-10 20:41 ` [PATCH 2/2] vfs: Add KUnit tests for fdtable Bill Wendling
2026-08-11 0:16 ` Kees Cook
2026-08-11 15:42 ` Jann Horn
2026-08-12 0:22 ` Kees Cook
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox