* [PATCH v4 1/4] thunderbolt: property: reject u32 wrap in tb_property_entry_valid()
2026-05-10 23:16 ` [PATCH v4 0/4] thunderbolt: harden " Michael Bommarito
@ 2026-05-10 23:16 ` Michael Bommarito
2026-05-10 23:16 ` [PATCH v4 2/4] thunderbolt: property: reject dir_len < 4 to prevent size_t underflow Michael Bommarito
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Michael Bommarito @ 2026-05-10 23:16 UTC (permalink / raw)
To: Mika Westerberg, linux-usb
Cc: Andreas Noever, Yehezkel Bernat, Andy Shevchenko, Michael Jamet,
Greg Kroah-Hartman, linux-kernel, stable
entry->value is u32 and entry->length is u16; the sum is performed in
u32 and wraps. A malicious XDomain peer can pick
value = 0xffffff00, length = 0x100 so the sum 0x100000000 wraps to 0
and passes the > block_len check. tb_property_parse() then passes
entry->value to parse_dwdata() as a dword offset into the property
block, reading attacker-directed memory far past the allocation.
For TEXT-typed entries with the "deviceid" or "vendorid" keys this
lands in xd->device_name / xd->vendor_name and is readable back via
the per-XDomain device_name / vendor_name sysfs attributes; the leak
is NUL-bounded (kstrdup() stops at the first zero byte) and
untargeted (the attacker picks a delta, not an absolute address).
DATA-typed entries are parsed into property->value.data but not
generically surfaced to userspace.
Use check_add_overflow() so a wrapped sum is rejected.
Fixes: cdae7c07e3e3 ("thunderbolt: Add support for XDomain properties")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-6
Assisted-by: Codex:gpt-5-4
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
drivers/thunderbolt/property.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/thunderbolt/property.c b/drivers/thunderbolt/property.c
index 50cbfc92fe65..29cd60c11ac4 100644
--- a/drivers/thunderbolt/property.c
+++ b/drivers/thunderbolt/property.c
@@ -8,6 +8,7 @@
*/
#include <linux/err.h>
+#include <linux/overflow.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/uuid.h>
@@ -52,13 +53,16 @@ static inline void format_dwdata(void *dst, const void *src, size_t dwords)
static bool tb_property_entry_valid(const struct tb_property_entry *entry,
size_t block_len)
{
+ u32 end;
+
switch (entry->type) {
case TB_PROPERTY_TYPE_DIRECTORY:
case TB_PROPERTY_TYPE_DATA:
case TB_PROPERTY_TYPE_TEXT:
if (entry->length > block_len)
return false;
- if (entry->value + entry->length > block_len)
+ if (check_add_overflow(entry->value, entry->length, &end) ||
+ end > block_len)
return false;
break;
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v4 2/4] thunderbolt: property: reject dir_len < 4 to prevent size_t underflow
2026-05-10 23:16 ` [PATCH v4 0/4] thunderbolt: harden " Michael Bommarito
2026-05-10 23:16 ` [PATCH v4 1/4] thunderbolt: property: reject u32 wrap in tb_property_entry_valid() Michael Bommarito
@ 2026-05-10 23:16 ` Michael Bommarito
2026-05-10 23:16 ` [PATCH v4 3/4] thunderbolt: property: cap recursion depth in __tb_property_parse_dir() Michael Bommarito
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Michael Bommarito @ 2026-05-10 23:16 UTC (permalink / raw)
To: Mika Westerberg, linux-usb
Cc: Andreas Noever, Yehezkel Bernat, Andy Shevchenko, Michael Jamet,
Greg Kroah-Hartman, linux-kernel, stable
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.
Fixes: cdae7c07e3e3 ("thunderbolt: Add support for XDomain properties")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-6
Assisted-by: Codex:gpt-5-4
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
drivers/thunderbolt/property.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/thunderbolt/property.c b/drivers/thunderbolt/property.c
index 29cd60c11ac4..74c92f9801ff 100644
--- a/drivers/thunderbolt/property.c
+++ b/drivers/thunderbolt/property.c
@@ -174,10 +174,16 @@ static struct tb_property_dir *__tb_property_parse_dir(const u32 *block,
if (!dir)
return NULL;
+ INIT_LIST_HEAD(&dir->properties);
+
if (is_root) {
content_offset = dir_offset + 2;
content_len = dir_len;
} else {
+ if (dir_len < 4) {
+ tb_property_free_dir(dir);
+ return NULL;
+ }
dir->uuid = kmemdup(&block[dir_offset], sizeof(*dir->uuid),
GFP_KERNEL);
if (!dir->uuid) {
@@ -191,8 +197,6 @@ static struct tb_property_dir *__tb_property_parse_dir(const u32 *block,
entries = (const struct tb_property_entry *)&block[content_offset];
nentries = content_len / (sizeof(*entries) / 4);
- INIT_LIST_HEAD(&dir->properties);
-
for (i = 0; i < nentries; i++) {
struct tb_property *property;
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v4 3/4] thunderbolt: property: cap recursion depth in __tb_property_parse_dir()
2026-05-10 23:16 ` [PATCH v4 0/4] thunderbolt: harden " Michael Bommarito
2026-05-10 23:16 ` [PATCH v4 1/4] thunderbolt: property: reject u32 wrap in tb_property_entry_valid() Michael Bommarito
2026-05-10 23:16 ` [PATCH v4 2/4] thunderbolt: property: reject dir_len < 4 to prevent size_t underflow Michael Bommarito
@ 2026-05-10 23:16 ` Michael Bommarito
2026-05-10 23:16 ` [PATCH v4 4/4] thunderbolt: test: add KUnit regression tests for XDomain property parser Michael Bommarito
2026-05-11 9:37 ` [PATCH v4 0/4] thunderbolt: harden " Mika Westerberg
4 siblings, 0 replies; 8+ messages in thread
From: Michael Bommarito @ 2026-05-10 23:16 UTC (permalink / raw)
To: Mika Westerberg, linux-usb
Cc: Andreas Noever, Yehezkel Bernat, Andy Shevchenko, Michael Jamet,
Greg Kroah-Hartman, linux-kernel, stable
A DIRECTORY entry's value field is used as the dir_offset for a
recursive call into __tb_property_parse_dir() with no depth counter.
A crafted peer that chains DIRECTORY entries into a back-reference
loop drives the parser until the kernel stack is exhausted and the
guard page fires. Any untrusted XDomain peer (cable, dock, in-line
inspector, adjacent host) that reaches the PROPERTIES_REQUEST
control-plane exchange can trigger this without authentication.
Thread a depth counter through tb_property_parse() and
__tb_property_parse_dir(), and reject blocks that exceed
TB_PROPERTY_MAX_DEPTH = 8. That is comfortably larger than any
observed legitimate XDomain layout.
Operators who do not need XDomain host-to-host discovery can disable
the path entirely with thunderbolt.xdomain=0 on the kernel command
line.
Fixes: cdae7c07e3e3 ("thunderbolt: Add support for XDomain properties")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-6
Assisted-by: Codex:gpt-5-4
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
drivers/thunderbolt/property.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/drivers/thunderbolt/property.c b/drivers/thunderbolt/property.c
index 74c92f9801ff..da2c59a17db5 100644
--- a/drivers/thunderbolt/property.c
+++ b/drivers/thunderbolt/property.c
@@ -35,10 +35,11 @@ struct tb_property_dir_entry {
};
#define TB_PROPERTY_ROOTDIR_MAGIC 0x55584401
+#define TB_PROPERTY_MAX_DEPTH 8
static struct tb_property_dir *__tb_property_parse_dir(const u32 *block,
size_t block_len, unsigned int dir_offset, size_t dir_len,
- bool is_root);
+ bool is_root, unsigned int depth);
static inline void parse_dwdata(void *dst, const void *src, size_t dwords)
{
@@ -97,7 +98,8 @@ tb_property_alloc(const char *key, enum tb_property_type type)
}
static struct tb_property *tb_property_parse(const u32 *block, size_t block_len,
- const struct tb_property_entry *entry)
+ const struct tb_property_entry *entry,
+ unsigned int depth)
{
char key[TB_PROPERTY_KEY_SIZE + 1];
struct tb_property *property;
@@ -118,7 +120,7 @@ static struct tb_property *tb_property_parse(const u32 *block, size_t block_len,
switch (property->type) {
case TB_PROPERTY_TYPE_DIRECTORY:
dir = __tb_property_parse_dir(block, block_len, entry->value,
- entry->length, false);
+ entry->length, false, depth + 1);
if (!dir) {
kfree(property);
return NULL;
@@ -163,13 +165,17 @@ static struct tb_property *tb_property_parse(const u32 *block, size_t block_len,
}
static struct tb_property_dir *__tb_property_parse_dir(const u32 *block,
- size_t block_len, unsigned int dir_offset, size_t dir_len, bool is_root)
+ size_t block_len, unsigned int dir_offset, size_t dir_len, bool is_root,
+ unsigned int depth)
{
const struct tb_property_entry *entries;
size_t i, content_len, nentries;
unsigned int content_offset;
struct tb_property_dir *dir;
+ if (depth > TB_PROPERTY_MAX_DEPTH)
+ return NULL;
+
dir = kzalloc_obj(*dir);
if (!dir)
return NULL;
@@ -200,7 +206,7 @@ static struct tb_property_dir *__tb_property_parse_dir(const u32 *block,
for (i = 0; i < nentries; i++) {
struct tb_property *property;
- property = tb_property_parse(block, block_len, &entries[i]);
+ property = tb_property_parse(block, block_len, &entries[i], depth);
if (!property) {
tb_property_free_dir(dir);
return NULL;
@@ -239,7 +245,7 @@ struct tb_property_dir *tb_property_parse_dir(const u32 *block,
return NULL;
return __tb_property_parse_dir(block, block_len, 0, rootdir->length,
- true);
+ true, 0);
}
/**
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v4 4/4] thunderbolt: test: add KUnit regression tests for XDomain property parser
2026-05-10 23:16 ` [PATCH v4 0/4] thunderbolt: harden " Michael Bommarito
` (2 preceding siblings ...)
2026-05-10 23:16 ` [PATCH v4 3/4] thunderbolt: property: cap recursion depth in __tb_property_parse_dir() Michael Bommarito
@ 2026-05-10 23:16 ` Michael Bommarito
2026-05-11 9:37 ` [PATCH v4 0/4] thunderbolt: harden " Mika Westerberg
4 siblings, 0 replies; 8+ messages in thread
From: Michael Bommarito @ 2026-05-10 23:16 UTC (permalink / raw)
To: Mika Westerberg, linux-usb
Cc: Andreas Noever, Yehezkel Bernat, Andy Shevchenko, Michael Jamet,
Greg Kroah-Hartman, linux-kernel, stable
Add three KUnit cases that exercise the defects fixed by the sibling
commits in this series by feeding crafted XDomain property blocks to
tb_property_parse_dir():
tb_test_property_parse_u32_wrap - entry->value = 0xffffff00 and
entry->length = 0x100 so their u32 sum 0x100000000 wraps to 0
under the block_len guard; without the fix the subsequent
parse_dwdata() reads attacker-directed OOB memory.
tb_test_property_parse_recursion - two DIRECTORY entries pointing
at each other, driving __tb_property_parse_dir() recursion;
without the fix the kernel stack is exhausted.
tb_test_property_parse_dir_len_underflow - a DIRECTORY entry with
length < 4 placed near the end of the block so the non-root UUID
kmemdup of 4 dwords from dir_offset reads OOB before the later
content_len = dir_len - 4 underflow path is reached.
Each test asserts tb_property_parse_dir() returns NULL on the
crafted input. With CONFIG_KASAN=y, running these on the pre-fix
kernel produces an oops inside __tb_property_parse_dir or its
callees: u32_wrap takes a page fault on the KASAN shadow lookup for
the wild ~16 GiB OOB offset; recursion trips a KASAN out-of-bounds
report in __unwind_start as the per-task kernel stack is consumed;
dir_len_underflow trips a KASAN slab-out-of-bounds report in
kmemdup_noprof reading 16 bytes past the 28-byte block. Post-fix
they pass cleanly.
The crafted blocks are populated by writing u32 dwords directly,
matching the existing root_directory[] style used elsewhere in
this file rather than imposing a private struct overlay.
Run with:
./tools/testing/kunit/kunit.py run --arch=x86_64 \
--kconfig_add CONFIG_PCI=y --kconfig_add CONFIG_NVMEM=y \
--kconfig_add CONFIG_USB4=y --kconfig_add CONFIG_USB4_KUNIT_TEST=y \
--kconfig_add CONFIG_KASAN=y 'thunderbolt.tb_test_property_parse_*'
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
drivers/thunderbolt/test.c | 126 +++++++++++++++++++++++++++++++++++++
1 file changed, 126 insertions(+)
diff --git a/drivers/thunderbolt/test.c b/drivers/thunderbolt/test.c
index 1f4318249c22..f41fabf15456 100644
--- a/drivers/thunderbolt/test.c
+++ b/drivers/thunderbolt/test.c
@@ -2852,7 +2852,133 @@ static void tb_test_property_copy(struct kunit *test)
tb_property_free_dir(src);
}
+/*
+ * Reproducers for three memory-safety defects in
+ * drivers/thunderbolt/property.c reached from a crafted XDomain
+ * PROPERTIES_RESPONSE payload. Without the fix these trip KASAN or
+ * smash the kernel stack; with the fix each returns NULL cleanly.
+ *
+ * The on-wire entry layout matches struct tb_property_entry in
+ * property.c (private to that translation unit): u32 key_hi, u32
+ * key_lo, then a packed u32 = (type << 24) | (reserved << 16) |
+ * length, then u32 value. Each entry is 4 dwords.
+ */
+
+static void tb_test_property_parse_u32_wrap(struct kunit *test)
+{
+ /*
+ * 0x102 dwords: enough for the entry's length field (0x100) to
+ * pass the "entry->length > block_len" gate so the wrap check
+ * is actually exercised. parse_dwdata's downstream OOB read
+ * lands ~16 GiB past the allocation regardless.
+ */
+ u32 *block = kunit_kzalloc(test, 0x102 * sizeof(u32), GFP_KERNEL);
+ struct tb_property_dir *dir;
+
+ KUNIT_ASSERT_NOT_NULL(test, block);
+
+ block[0] = 0x55584401; /* "UXD" v1 magic */
+ block[1] = 0x00000004; /* Root directory length: one entry */
+
+ /*
+ * DATA entry whose value 0xffffff00 + length 0x100 wrap to 0
+ * in u32, passing the sum <= block_len guard even though the
+ * real offset is far past the allocation.
+ */
+ block[2] = 0x61616161; /* key_hi */
+ block[3] = 0x61616161; /* key_lo */
+ block[4] = 0x64000100; /* type=DATA, reserved=0, length=0x100 */
+ block[5] = 0xffffff00; /* value */
+
+ dir = tb_property_parse_dir(block, 0x102);
+ KUNIT_EXPECT_NULL(test, dir);
+ tb_property_free_dir(dir);
+}
+
+static void tb_test_property_parse_recursion(struct kunit *test)
+{
+ /*
+ * 10 dwords: rootdir header (2) + parent DIRECTORY entry (4) +
+ * the child entry that lives at dir_offset(2) + UUID(4) = 6,
+ * occupying block[6..9]. Each recursive level re-reads the
+ * same block[6..9] as its first child entry, which is itself
+ * a DIRECTORY pointing at offset 2.
+ */
+ u32 *block = kunit_kzalloc(test, 10 * sizeof(u32), GFP_KERNEL);
+ struct tb_property_dir *dir;
+
+ KUNIT_ASSERT_NOT_NULL(test, block);
+
+ block[0] = 0x55584401; /* "UXD" v1 magic */
+ block[1] = 0x00000004; /* Root directory length: one entry */
+
+ /*
+ * DIRECTORY entry pointing at dir_offset = 2 with length = 8.
+ * Non-root parse derives content_offset = 6, content_len = 4,
+ * nentries = 1. block[6..9] is read both as the parent's UUID
+ * (kmemdup'd into dir->uuid) and as the single child entry --
+ * which is itself a DIRECTORY pointing at offset 2, so the
+ * recursion never terminates and the kernel stack is exhausted.
+ */
+ block[2] = 0x61616161; /* key_hi */
+ block[3] = 0x61616161; /* key_lo */
+ block[4] = 0x44000008; /* type=DIRECTORY, reserved=0, length=8 */
+ block[5] = 0x00000002; /* value = dir_offset */
+
+ block[6] = 0x62626262; /* doubles as UUID dword 0 / child key_hi */
+ block[7] = 0x62626262; /* doubles as UUID dword 1 / child key_lo */
+ block[8] = 0x44000008; /* type=DIRECTORY, reserved=0, length=8 */
+ block[9] = 0x00000002; /* value = dir_offset (back at parent) */
+
+ dir = tb_property_parse_dir(block, 10);
+ KUNIT_EXPECT_NULL(test, dir);
+ tb_property_free_dir(dir);
+}
+
+static void tb_test_property_parse_dir_len_underflow(struct kunit *test)
+{
+ /*
+ * Allocate exactly 7 dwords (28 bytes) so the kmalloc-32 chunk
+ * leaves a 4-byte slab redzone tail that KASAN-Generic can flag.
+ * With block_len = 7, dir_offset = 4, dir_len = 3, the non-root
+ * UUID kmemdup reads 16 bytes from byte 16, so bytes 28..31 fall
+ * in the redzone and trip a KASAN slab-out-of-bounds report on
+ * the pre-fix kernel. Sizing the buffer at a power of two (32,
+ * 64, ...) puts the over-read into the slab cache tail where
+ * KASAN's generic shadow does not flag it, and the test reduces
+ * to the downstream content_len = dir_len - 4 underflow path
+ * which also returns NULL.
+ */
+ u32 *block = kunit_kzalloc(test, 7 * sizeof(u32), GFP_KERNEL);
+ struct tb_property_dir *dir;
+
+ KUNIT_ASSERT_NOT_NULL(test, block);
+
+ block[0] = 0x55584401; /* "UXD" v1 magic */
+ block[1] = 0x00000004; /* Root directory length: one entry */
+
+ /*
+ * DIRECTORY entry with length = 3 pointing at dir_offset = 4.
+ * tb_property_entry_valid() permits value(4) + length(3) <=
+ * block_len(7). Non-root parse begins with a kmemdup of 4
+ * dwords from dir_offset for the UUID; that read runs past the
+ * 28-byte allocation before the dir_len < 4 reject would fire.
+ */
+ block[2] = 0x61616161; /* key_hi */
+ block[3] = 0x61616161; /* key_lo */
+ block[4] = 0x44000003; /* type=DIRECTORY, reserved=0, length=3 */
+ block[5] = 0x00000004; /* value = dir_offset */
+ /* block[6] is the start of the four UUID dwords; block[7..] is OOB. */
+
+ dir = tb_property_parse_dir(block, 7);
+ KUNIT_EXPECT_NULL(test, dir);
+ tb_property_free_dir(dir);
+}
+
static struct kunit_case tb_test_cases[] = {
+ KUNIT_CASE(tb_test_property_parse_u32_wrap),
+ KUNIT_CASE(tb_test_property_parse_recursion),
+ KUNIT_CASE(tb_test_property_parse_dir_len_underflow),
KUNIT_CASE(tb_test_path_basic),
KUNIT_CASE(tb_test_path_not_connected_walk),
KUNIT_CASE(tb_test_path_single_hop_walk),
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v4 0/4] thunderbolt: harden XDomain property parser
2026-05-10 23:16 ` [PATCH v4 0/4] thunderbolt: harden " Michael Bommarito
` (3 preceding siblings ...)
2026-05-10 23:16 ` [PATCH v4 4/4] thunderbolt: test: add KUnit regression tests for XDomain property parser Michael Bommarito
@ 2026-05-11 9:37 ` Mika Westerberg
4 siblings, 0 replies; 8+ messages in thread
From: Mika Westerberg @ 2026-05-11 9:37 UTC (permalink / raw)
To: Michael Bommarito
Cc: Mika Westerberg, linux-usb, Andreas Noever, Yehezkel Bernat,
Andy Shevchenko, Michael Jamet, Greg Kroah-Hartman, linux-kernel,
stable
Hi Michael,
On Sun, May 10, 2026 at 07:16:55PM -0400, Michael Bommarito wrote:
> Style cleanups only on top of v3. Andy's three nits on 1/4, 2/4,
> 3/4 are applied; Mika's request to drop the duplicated on-wire
> entry struct in 4/4 is applied. No behavioural change to any
> patch; the bug analysis and the gating in patches 1-3 are
> unchanged.
>
> Three independent memory-safety defects in drivers/thunderbolt/property.c
> are reachable when an untrusted Thunderbolt/USB4 XDomain peer responds
> to a PROPERTIES_REQUEST during host-to-host discovery. The peer
> supplies up to TB_XDP_PROPERTIES_MAX_LENGTH (500) dwords of attacker-
> controlled property block which the local host passes to
> tb_property_parse_dir() as part of the control-plane exchange that
> runs before any tunnels are set up.
>
> Patches 1-3 are one bug per patch: u32 overflow in
> tb_property_entry_valid(), short-dir_len OOB+underflow in
> __tb_property_parse_dir(), and unbounded recursion in the same.
> Patch 4 is three KUnit regression cases exercising all three.
>
> All three defects are OOB-read or DoS at worst. No controlled OOB
> write is reachable through the parser; parse_dwdata()'s destination
> is a freshly kcalloc'd buffer sized by entry->length.
>
> Operators who do not need XDomain host-to-host discovery can disable
> the path entirely with thunderbolt.xdomain=0 on the kernel command
> line.
>
> Reproduced on v7.0-rc7 + CONFIG_KASAN=y + CONFIG_USB4_KUNIT_TEST=y
> via the KUnit suite in patch 4. Pre-fix on a v7.0-rc7 + patch 4
> kernel: u32_wrap fails with a KASAN use-after-free trace in
> __tb_property_parse_dir() (the parser reads ~16 GiB past the
> block); recursion fails with KASAN + an Oops on RIP=0 as the
> parser exhausts its guard page. dir_len_underflow returns NULL
> on pre-fix because the downstream content_len = dir_len - 4
> underflow makes the entry walk bail at tb_property_entry_valid();
> the UUID kmemdup over-read is silent here because KASAN-Generic's
> slab redzones do not flag a 4-byte over-read into the
> kmalloc-chunk tail. Treat dir_len_underflow as the post-fix
> invariant pin; u32_wrap and recursion are the active pre-fix
> detectors.
Applied 1-3 to thunderbolt.git/fixes and the last one to
thunderbolt.git/next. Thanks a lot!
^ permalink raw reply [flat|nested] 8+ messages in thread