* [PATCH] net: wwan: iosm: fix NULL skb deref in ul_td_process
@ 2026-10-20 10:11 liuc63
2026-10-20 10:14 ` netdev-bot+sinfo
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: liuc63 @ 2026-10-20 10:11 UTC (permalink / raw)
To: M Chetan Kumar
Cc: Loic Poulain, Sergey Ryazanov, Johannes Berg, Guanglei Zhu,
netdev, linux-kernel, Liu Chao, stable
From: Liu Chao <liuc63@xiaopeng.com>
ipc_protocol_ul_td_process() fetches the skb for the current tail
entry and then dereferences IPC_CB(skb) when comparing the TD buffer
address against the skb DMA mapping. If the skb slot is NULL (e.g.
the entry was never populated or was already consumed), this results
in a NULL pointer dereference.
Validate skb before dereferencing it, mirroring the existing check on
p_td->buffer.address. Return NULL and log the error when the skb is
missing so the caller can handle the malformed descriptor.
Fixes: 64516f633bfd ("net: iosm: protocol operations")
Cc: stable@vger.kernel.org
Reviewed-by: Guanglei Zhu <zhugl3@xiaopeng.com>
Signed-off-by: Liu Chao <liuc63@xiaopeng.com>
---
drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c b/drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c
index f2f86f41fd10..dee2e6607f77 100644
--- a/drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c
+++ b/drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c
@@ -302,6 +302,11 @@ struct sk_buff *ipc_protocol_ul_td_process(struct iosm_protocol *ipc_protocol,
if (pipe->old_tail >= pipe->nr_of_entries)
pipe->old_tail = 0;
+ if (!skb) {
+ dev_err(ipc_protocol->dev, "skb is null");
+ return NULL;
+ }
+
if (!p_td->buffer.address) {
dev_err(ipc_protocol->dev, "Td buffer address is NULL");
return NULL;
--
2.50.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] net: wwan: iosm: fix NULL skb deref in ul_td_process
2026-10-20 10:11 [PATCH] net: wwan: iosm: fix NULL skb deref in ul_td_process liuc63
@ 2026-10-20 10:14 ` netdev-bot+sinfo
2026-10-20 10:21 ` Loic Poulain
2026-10-22 4:14 ` netdev-bot+sashiko
2 siblings, 0 replies; 4+ messages in thread
From: netdev-bot+sinfo @ 2026-10-20 10:14 UTC (permalink / raw)
To: liuc63
Cc: M Chetan Kumar, Loic Poulain, Sergey Ryazanov, Johannes Berg,
Guanglei Zhu, netdev, linux-kernel, stable
Hi!
This is an automated message. This series looks like a fix, but its
commit messages seem to be missing some information:
- How the issue was discovered, e.g. hit in production, hit during
development, syzbot report, manual code inspection, LLM or static
analysis tool scan.
- Whether the issue was actually triggered, or is only theoretical
(e.g. found by code inspection). If it was triggered please include
the symptoms, like the stack trace or error messages.
Please do not repost the series just to address the above. Instead,
reply to this email with the missing information, so that reviewers
can take it into account. If the series needs another revision for
other reasons, please include the information in the commit messages
then.
The evaluation is done by an LLM so it may be wrong, if you think
that is the case please reply and explain.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] net: wwan: iosm: fix NULL skb deref in ul_td_process
2026-10-20 10:11 [PATCH] net: wwan: iosm: fix NULL skb deref in ul_td_process liuc63
2026-10-20 10:14 ` netdev-bot+sinfo
@ 2026-10-20 10:21 ` Loic Poulain
2026-10-22 4:14 ` netdev-bot+sashiko
2 siblings, 0 replies; 4+ messages in thread
From: Loic Poulain @ 2026-10-20 10:21 UTC (permalink / raw)
To: liuc63
Cc: M Chetan Kumar, Sergey Ryazanov, Johannes Berg, Guanglei Zhu,
netdev, linux-kernel, stable
On Tue, Oct 20, 2026 at 12:11 PM liuc63 <liuc63@xiaopeng.com> wrote:
>
> From: Liu Chao <liuc63@xiaopeng.com>
>
> ipc_protocol_ul_td_process() fetches the skb for the current tail
> entry and then dereferences IPC_CB(skb) when comparing the TD buffer
> address against the skb DMA mapping. If the skb slot is NULL (e.g.
> the entry was never populated or was already consumed), this results
> in a NULL pointer dereference.
>
> Validate skb before dereferencing it, mirroring the existing check on
> p_td->buffer.address. Return NULL and log the error when the skb is
> missing so the caller can handle the malformed descriptor.
>
> Fixes: 64516f633bfd ("net: iosm: protocol operations")
> Cc: stable@vger.kernel.org
> Reviewed-by: Guanglei Zhu <zhugl3@xiaopeng.com>
> Signed-off-by: Liu Chao <liuc63@xiaopeng.com>
> ---
> drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c b/drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c
> index f2f86f41fd10..dee2e6607f77 100644
> --- a/drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c
> +++ b/drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c
> @@ -302,6 +302,11 @@ struct sk_buff *ipc_protocol_ul_td_process(struct iosm_protocol *ipc_protocol,
> if (pipe->old_tail >= pipe->nr_of_entries)
> pipe->old_tail = 0;
>
> + if (!skb) {
> + dev_err(ipc_protocol->dev, "skb is null");
> + return NULL;
Look like the caller(s) already check/report for null skb, so instead
of adding another print here, maybe it would be simpler to check for
skb in the condition where IPC_CB(skb) is used:
`if (skb && p_td->buffer.address != IPC_CB(skb)->mapping)`
> +
> if (!p_td->buffer.address) {
> dev_err(ipc_protocol->dev, "Td buffer address is NULL");
> return NULL;
> --
> 2.50.1
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] net: wwan: iosm: fix NULL skb deref in ul_td_process
2026-10-20 10:11 [PATCH] net: wwan: iosm: fix NULL skb deref in ul_td_process liuc63
2026-10-20 10:14 ` netdev-bot+sinfo
2026-10-20 10:21 ` Loic Poulain
@ 2026-10-22 4:14 ` netdev-bot+sashiko
2 siblings, 0 replies; 4+ messages in thread
From: netdev-bot+sashiko @ 2026-10-22 4:14 UTC (permalink / raw)
To: liuc63
Cc: m.chetan.kumar, loic.poulain, ryazanov.s.a, johannes, zhugl3,
netdev, linux-kernel, stable, kuba
Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider.
Critical: 0 · High: 1 (1) · Medium: 0 · Low: 0
If you believe none of the issues are legitimate, please reply to each
issue of Medium severity or higher and explain why the AI is wrong.
If any of them are legitimate and you plan to respin, please let patchwork
know by including "pw-bot: cr" as a separate line at the end of your reply
(one such reply per series is enough).
- [High] The fix does not handle the 'already consumed' case that its
commit message says it covers.
Pre-existing issues:
- [High] This problem wasn't introduced by this patch, but UL completion
processing in the IRQ tasklet is not synchronized with pipe teardown.
--
net: wwan: iosm: fix NULL skb deref in ul_td_process
This commit adds a NULL check on the skb taken from the UL ring slot in
ipc_protocol_ul_td_process() before IPC_CB(skb) is dereferenced. The
goal is to avoid a NULL pointer dereference when the slot was never
populated or has already been consumed.
> diff --git a/drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c b/drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c
> index f2f86f41fd10..dee2e6607f77 100644
> --- a/drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c
> +++ b/drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c
> @@ -302,6 +302,11 @@ struct sk_buff *ipc_protocol_ul_td_process(struct iosm_protocol *ipc_protocol,
> if (pipe->old_tail >= pipe->nr_of_entries)
> pipe->old_tail = 0;
>
> + if (!skb) {
> + dev_err(ipc_protocol->dev, "skb is null");
> + return NULL;
> + }
> +
[Severity: High]
Does this check catch the "already consumed" case that the commit message
mentions?
The UL path never resets the ring slot after taking the skb:
drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c:ipc_protocol_ul_td_process() {
struct ipc_protocol_td *p_td = &pipe->tdr_start[pipe->old_tail];
struct sk_buff *skb = pipe->skbr_start[pipe->old_tail];
pipe->nr_of_queued_entries--;
pipe->old_tail++;
...
}
The DL sibling does reset it, so a NULL there really does mean "already
consumed":
drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c:ipc_protocol_dl_td_process() {
...
/* Reset the ring elements. */
pipe->skbr_start[pipe->old_tail] = NULL;
...
}
The only place that writes a UL slot is ipc_protocol_ul_td_send(). It
also sets td->buffer.address = IPC_CB(skb)->mapping, and nothing clears
that field on completion. The caller, ipc_imem_ul_pipe_process(), then
frees each returned skb with ipc_pcie_kfree_skb() or passes it to
ipc_mux_ul_encoded_process().
So a consumed UL slot keeps a stale, non-NULL skb pointer and a non-zero
TD address. If the slot is processed again, the new !skb check passes.
IPC_CB(skb)->mapping is then read from freed memory. If the stale mapping
still matches the stale TD address, the freed skb is returned and freed a
second time.
Slots can be processed again because the loop count in
ipc_imem_ul_pipe_process() comes straight from the device-written tail:
if (pipe->old_tail != tail) {
if (pipe->old_tail < tail)
cnt = tail - pipe->old_tail;
else
cnt = pipe->nr_of_entries - pipe->old_tail + tail;
}
cnt is never checked against nr_of_queued_entries. A misbehaving
endpoint, which is the case this patch is meant to guard against, can
reach this path.
Would it be better to clear pipe->skbr_start[pipe->old_tail] after
reading it, the way the DL path does, and/or to cap cnt by
pipe->nr_of_queued_entries?
[Severity: High]
This is a pre-existing issue and was not introduced by this patch, but
the new check does not protect against it. Is UL completion processing in
the IRQ tasklet synchronized with pipe teardown?
ipc_imem_handle_irq() checks is_open without holding a lock:
if (ul_pipe->is_open)
ipc_imem_ul_pipe_process(ipc_imem, ul_pipe);
It then goes on into ipc_protocol_ul_td_process(), which reads
pipe->tdr_start[] and pipe->skbr_start[].
ipc_imem_sys_devlink_close() runs in process context. It waits on
ul_pend_sem with a timeout but never sets app_notify_ul_pend, so the wait
just times out. It then frees the pipes directly:
ipc_imem_pipe_cleanup(ipc_imem, &channel->ul_pipe);
ipc_imem_pipe_cleanup(ipc_imem, &channel->dl_pipe);
ipc_protocol_pipe_cleanup() frees the in-flight skbs, kfree()s
skbr_start and dma_free_coherent()s tdr_start. No lock or tasklet
quiescing waits for a tasklet that has already passed the is_open check.
ipc_imem_cleanup() has the same ordering:
ipc_imem_channel_reset(ipc_imem);
ipc_protocol_deinit(ipc_imem->ipc_protocol);
ipc_task_deinit(ipc_imem->ipc_task);
Here the channels are freed before tasklet_kill() in ipc_task_deinit(),
and the IRQ is still live until ipc_pcie_cleanup() runs afterwards.
Can a running tasklet then dereference freed or NULL tdr_start and
skbr_start, or free the same skb that the cleanup loop frees? The local
skb pointer it holds would be non-NULL, so the new !skb check would not
catch it.
> if (!p_td->buffer.address) {
> dev_err(ipc_protocol->dev, "Td buffer address is NULL");
> return NULL;
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261020101150.16967-1-liuc63%40xiaopeng.com
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-10-22 4:14 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-20 10:11 [PATCH] net: wwan: iosm: fix NULL skb deref in ul_td_process liuc63
2026-10-20 10:14 ` netdev-bot+sinfo
2026-10-20 10:21 ` Loic Poulain
2026-10-22 4:14 ` netdev-bot+sashiko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®