Re: [PATCH v3 2/4] thunderbolt: property: reject dir_len < 4 to prevent size_t underflow

From: Andy Shevchenko

Date: Mon May 04 2026 - 05:02:53 EST


On Sun, May 03, 2026 at 10:15:06AM -0400, Michael Bommarito wrote:
> On the non-root path, __tb_property_parse_dir() takes dir_len from
> entry->length (u16 widened to size_t). Two distinct OOB conditions
> follow when entry->length < 4:
>
> 1. The non-root path begins with kmemdup(&block[dir_offset],
> sizeof(*dir->uuid), ...) which always reads 4 dwords from
> dir_offset. tb_property_entry_valid() only enforces
> dir_offset + entry->length <= block_len, so a crafted entry
> with dir_offset close to the end of the property block and
> entry->length in 0..3 passes that gate but lets the UUID copy
> run off the block (e.g. dir_offset = 497, dir_len = 3 in a
> 500-dword block reads block[497..501]).
>
> 2. After the kmemdup, content_len = dir_len - 4 underflows size_t
> to ~SIZE_MAX, nentries becomes SIZE_MAX / 4, and the entry
> walk runs OOB on each iteration until an entry fails
> validation or the kernel oopses on an unmapped page.
>
> Reject dir_len < 4 on the non-root path *before* the UUID kmemdup,
> which closes both holes.
>
> Also move INIT_LIST_HEAD(&dir->properties) up to immediately after
> the dir allocation so the new error-return path (and the existing
> uuid-alloc failure path) calling tb_property_free_dir() sees a
> walkable list rather than the zero-initialized NULL next/prev that
> list_for_each_entry_safe() would oops on.

...

> dir = kzalloc_obj(*dir);
> if (!dir)
> return NULL;

+ blank line.

> + INIT_LIST_HEAD(&dir->properties);
>

--
With Best Regards,
Andy Shevchenko