* [PATCH net] tipc: fix UAF in tipc_buf_append via tipc_msg_validate
@ 2026-03-30 20:53 nicholas
2026-03-31 9:38 ` Tung Quang Nguyen
0 siblings, 1 reply; 2+ messages in thread
From: nicholas @ 2026-03-30 20:53 UTC (permalink / raw)
To: netdev; +Cc: Jon Maloy, Nicholas Carlini, stable
From: Nicholas Carlini <nicholas@carlini.com>
tipc_buf_append() passes the address of a local variable `head` to
tipc_msg_validate(). When the flow-control ratio check in
tipc_msg_validate() fires, it frees the original skb and updates
*_skb to point to a new copy -- but this only updates the local
`head`, not *headbuf. If validation subsequently fails (e.g. the
reassembled message has an invalid TIPC version), the err path
calls kfree_skb(*headbuf) on the already-freed skb. The replacement
skb is also leaked.
A remote attacker with an established TIPC link over a UDP bearer
can trigger this by sending a sequence of MSG_FRAGMENTER packets
crafted to inflate the reassembled skb's truesize relative to its
length past the ratio threshold, with an invalid version field in
the inner message.
Fix by passing headbuf directly to tipc_msg_validate() so the
pointer update propagates correctly.
Fixes: d618d09a68e4 ("tipc: enforce valid ratio between skb truesize and contents")
Cc: stable@vger.kernel.org
Signed-off-by: Nicholas Carlini <nicholas@carlini.com>
---
net/tipc/msg.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index 76284fc53..9f4f612ee 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -177,8 +177,9 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
if (fragid == LAST_FRAGMENT) {
TIPC_SKB_CB(head)->validated = 0;
- if (unlikely(!tipc_msg_validate(&head)))
+ if (unlikely(!tipc_msg_validate(headbuf)))
goto err;
+ head = *headbuf;
*buf = head;
TIPC_SKB_CB(head)->tail = NULL;
*headbuf = NULL;
--
2.43.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* RE: [PATCH net] tipc: fix UAF in tipc_buf_append via tipc_msg_validate
2026-03-30 20:53 [PATCH net] tipc: fix UAF in tipc_buf_append via tipc_msg_validate nicholas
@ 2026-03-31 9:38 ` Tung Quang Nguyen
0 siblings, 0 replies; 2+ messages in thread
From: Tung Quang Nguyen @ 2026-03-31 9:38 UTC (permalink / raw)
To: nicholas@carlini.com
Cc: Jon Maloy, stable@vger.kernel.org, netdev@vger.kernel.org
>Subject: [PATCH net] tipc: fix UAF in tipc_buf_append via tipc_msg_validate
Please remove "via tipc_msg_validate". It gives wrong impression that the fix could be done in tipc_msg_validate().
>
>From: Nicholas Carlini <nicholas@carlini.com>
>
>tipc_buf_append() passes the address of a local variable `head` to
>tipc_msg_validate(). When the flow-control ratio check in
>tipc_msg_validate() fires, it frees the original skb and updates *_skb to point to
>a new copy -- but this only updates the local `head`, not *headbuf. If validation
>subsequently fails (e.g. the reassembled message has an invalid TIPC version),
>the err path calls kfree_skb(*headbuf) on the already-freed skb. The
>replacement skb is also leaked.
>
>A remote attacker with an established TIPC link over a UDP bearer can trigger
>this by sending a sequence of MSG_FRAGMENTER packets crafted to inflate the
>reassembled skb's truesize relative to its length past the ratio threshold, with
>an invalid version field in the inner message.
>
>Fix by passing headbuf directly to tipc_msg_validate() so the pointer update
>propagates correctly.
>
>Fixes: d618d09a68e4 ("tipc: enforce valid ratio between skb truesize and
>contents")
>Cc: stable@vger.kernel.org
>Signed-off-by: Nicholas Carlini <nicholas@carlini.com>
>---
> net/tipc/msg.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
>diff --git a/net/tipc/msg.c b/net/tipc/msg.c index 76284fc53..9f4f612ee 100644
>--- a/net/tipc/msg.c
>+++ b/net/tipc/msg.c
>@@ -177,8 +177,9 @@ int tipc_buf_append(struct sk_buff **headbuf, struct
>sk_buff **buf)
>
> if (fragid == LAST_FRAGMENT) {
> TIPC_SKB_CB(head)->validated = 0;
>- if (unlikely(!tipc_msg_validate(&head)))
>+ if (unlikely(!tipc_msg_validate(headbuf)))
> goto err;
>+ head = *headbuf;
This fix is not optimal because it adds overhead to normal path. This patch is better, I think:
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index 76284fc538eb..01a693559589 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -177,8 +177,19 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
if (fragid == LAST_FRAGMENT) {
TIPC_SKB_CB(head)->validated = 0;
- if (unlikely(!tipc_msg_validate(&head)))
+ if (unlikely(!tipc_msg_validate(&head))) {
+ /* reassembled skb has been freed in
+ * tipc_msg_validate() because of invalid truesize.
+ * head now points to newly-allocated reassembled skb
+ * while *headbuf points to freed reassembled skb.
+ * So, correct *headbuf for freeing newly-allocated
+ * reassembled skb later.
+ */
+ if (head != *headbuf)
+ *headbuf = head;
+
goto err;
+ }
*buf = head;
TIPC_SKB_CB(head)->tail = NULL;
*headbuf = NULL;
> *buf = head;
> TIPC_SKB_CB(head)->tail = NULL;
> *headbuf = NULL;
>--
>2.43.0
>
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-03-31 9:38 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-30 20:53 [PATCH net] tipc: fix UAF in tipc_buf_append via tipc_msg_validate nicholas
2026-03-31 9:38 ` Tung Quang Nguyen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox